365302: made map of loggers concurrent and shared in abstract

This commit is contained in:
Greg Wilkins 2012-01-12 20:39:24 +11:00
parent 08f4b79a66
commit 564cf7329c
16 changed files with 185 additions and 120 deletions

View File

@ -5,6 +5,6 @@ contexts:MMBean: Deployed Contexts
appProviders:MMBean: Application Providers
getApps(java.lang.String):MBean:ACTION: List apps that are located at specified App LifeCycle node
getApps(java.lang.String)[0]:nodeName: Name of the App LifeCycle node
requestAppGoal(java.lang.String,java.lang.String) ACTION: Request the app to be moved to the specified App LifeCycle node
requestAppGoal(java.lang.String,java.lang.String):ACTION: Request the app to be moved to the specified App LifeCycle node
requestAppGoal(java.lang.String,java.lang.String)[0]:appId:App identifier
requestAppGoal(java.lang.String,java.lang.String)[1]:nodeName:Name of the App LifeCycle node
requestAppGoal(java.lang.String,java.lang.String)[1]:nodeName:Name of the App LifeCycle node

View File

@ -48,11 +48,10 @@
</Call>
<!-- Add the static log -->
<Get id="Logger" class="org.eclipse.jetty.util.log.Log" name="log" />
<Ref id="MBeanContainer">
<Call name="addBean">
<Arg>
<Ref id="Logger" />
<New class="org.eclipse.jetty.util.log.Log"/>
</Arg>
</Call>
</Ref>

View File

@ -0,0 +1,48 @@
// ========================================================================
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.util.log.jmx;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.jmx.ObjectMBean;
import org.eclipse.jetty.util.log.Log;
/* ------------------------------------------------------------ */
/**
*/
public class LogMBean extends ObjectMBean
{
public LogMBean(Object managedObject)
{
super(managedObject);
}
public List<String> getLoggers()
{
List<String> keySet = new ArrayList<String>(Log.getLoggers().keySet());
return keySet;
}
public boolean isDebugEnabled(String logger)
{
return Log.getLogger(logger).isDebugEnabled();
}
public void setDebugEnabled(String logger, Boolean enabled)
{
Log.getLogger(logger).setDebugEnabled(enabled);
}
}

View File

@ -0,0 +1,8 @@
Log: Jetty Logging implementaton
loggers:MBean: List of all instantiated loggers
debugEnabled:RW: True if debug enabled for root logger Log.LOG
isDebugEnabled(java.lang.String):MBean:INFO: True if debug is enabled for the given logger
isDebugEnabled(java.lang.String)[0]:loggerName: Name of the logger to return isDebugEnabled for
setDebugEnabled(java.lang.String,java.lang.Boolean):MBean:ACTION: Set debug enabled for the given logger
setDebugEnabled(java.lang.String,java.lang.Boolean)[0]:loggerName: Name of the logger to set debug enabled
setDebugEnabled(java.lang.String,java.lang.Boolean)[1]:enabled: true to enable debug, false otherwise

View File

@ -1,3 +0,0 @@
Logger: Jetty Logging implementaton
debugEnabled: True if debug enabled
name: Logger name

View File

@ -1,2 +1 @@
ThreadMonitor: Detect and report spinning and deadlocked threads

View File

@ -3,4 +3,3 @@ name: RO:Name
displayName: RO:Display Name
className: RO:Class Name
initParameters: RO:Initial parameters

View File

@ -0,0 +1,59 @@
package org.eclipse.jetty.util.log;
/* ------------------------------------------------------------ */
/** Abstract Logger.
* Manages the atomic registration of the logger by name.
*/
public abstract class AbstractLogger implements Logger
{
public final Logger getLogger(String name)
{
if (isBlank(name))
return this;
final String basename = getName();
final String fullname = (isBlank(basename) || Log.getRootLogger()==this)?name:(basename + "." + name);
Logger logger = Log.getLoggers().get(fullname);
if (logger == null)
{
Logger newlog = newLogger(fullname);
logger = Log.getMutableLoggers().putIfAbsent(fullname,newlog);
if (logger == null)
logger=newlog;
}
return logger;
}
protected abstract Logger newLogger(String fullname);
/**
* A more robust form of name blank test. Will return true for null names, and names that have only whitespace
*
* @param name
* the name to test
* @return true for null or blank name, false if any non-whitespace character is found.
*/
private static boolean isBlank(String name)
{
if (name == null)
{
return true;
}
int size = name.length();
char c;
for (int i = 0; i < size; i++)
{
c = name.charAt(i);
if (!Character.isWhitespace(c))
{
return false;
}
}
return true;
}
}

View File

@ -28,7 +28,7 @@ import java.util.logging.Level;
* standard java.util.logging configuration</a>.
* </p>
*/
public class JavaUtilLog implements Logger
public class JavaUtilLog extends AbstractLogger
{
private Level configuredLevel;
private java.util.logging.Logger _logger;
@ -116,9 +116,12 @@ public class JavaUtilLog implements Logger
_logger.log(Level.FINE, msg, thrown);
}
public Logger getLogger(String name)
/**
* Create a Child Logger of this Logger.
*/
protected Logger newLogger(String fullname)
{
return new JavaUtilLog(name);
return new JavaUtilLog(fullname);
}
public void ignore(Throwable ignored)

View File

@ -19,10 +19,14 @@ import java.lang.reflect.Method;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.Loader;
@ -61,7 +65,11 @@ public class Log
*/
public static boolean __ignored;
public static Map<String, Logger> __loggers = new HashMap<String, Logger>();
/**
* Hold loggers only.
*/
private final static ConcurrentMap<String, Logger> __loggers = new ConcurrentHashMap<String, Logger>();
static
{
@ -427,14 +435,16 @@ public class Log
Logger logger = __loggers.get(name);
if(logger==null)
{
logger = LOG.getLogger(name);
__loggers.put(name,logger);
}
return logger;
}
static ConcurrentMap<String, Logger> getMutableLoggers()
{
return __loggers;
}
/**
* Get a map of all configured {@link Logger} instances.
*
@ -442,6 +452,6 @@ public class Log
*/
public static Map<String, Logger> getLoggers()
{
return __loggers;
return Collections.unmodifiableMap(__loggers);
}
}

View File

@ -18,7 +18,7 @@ import java.lang.reflect.Method;
/**
*
*/
public class LoggerLog implements Logger
public class LoggerLog extends AbstractLogger
{
private final Object _logger;
private final Method _debugMT;
@ -189,11 +189,14 @@ public class LoggerLog implements Logger
}
}
public Logger getLogger(String name)
/**
* Create a Child Logger of this Logger.
*/
protected Logger newLogger(String fullname)
{
try
{
Object logger=_getLoggerN.invoke(_logger, name);
Object logger=_getLoggerN.invoke(_logger, fullname);
return new LoggerLog(logger);
}
catch (Exception e)

View File

@ -18,7 +18,7 @@ package org.eclipse.jetty.util.log;
/**
* Slf4jLog Logger
*/
public class Slf4jLog implements Logger
public class Slf4jLog extends AbstractLogger
{
private final org.slf4j.Logger _logger;
@ -114,9 +114,12 @@ public class Slf4jLog implements Logger
warn("setDebugEnabled not implemented",null,null);
}
public Logger getLogger(String name)
/**
* Create a Child Logger of this Logger.
*/
protected Logger newLogger(String fullname)
{
return new Slf4jLog(name);
return new Slf4jLog(fullname);
}
public void ignore(Throwable ignored)

View File

@ -35,7 +35,7 @@ import org.eclipse.jetty.util.DateCache;
* used for logging. For named debuggers, the system property name+".LONG" is checked. If it is not not set, then
* "org.eclipse.jetty.util.log.LONG" is used as the default.
*/
public class StdErrLog implements Logger
public class StdErrLog extends AbstractLogger
{
private static final String EOL = System.getProperty("line.separator");
private static DateCache _dateCache;
@ -45,11 +45,6 @@ public class StdErrLog implements Logger
Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.SOURCE","false")));
private final static boolean __long = Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.LONG","false"));
/**
* Tracking for child loggers only.
*/
private final static ConcurrentMap<String, StdErrLog> __loggers = new ConcurrentHashMap<String, StdErrLog>();
static
{
String deprecatedProperties[] =
@ -332,28 +327,22 @@ public class StdErrLog implements Logger
{
if (enabled)
{
synchronized (__loggers)
{
this._level = LEVEL_DEBUG;
this._level = LEVEL_DEBUG;
// Boot stomp all cached log levels to DEBUG
for(StdErrLog log: __loggers.values())
{
log._level = LEVEL_DEBUG;
}
for (Logger log : Log.getLoggers().values())
{
if (log instanceof StdErrLog)
((StdErrLog)log).setLevel(LEVEL_DEBUG);
}
}
else
{
synchronized (__loggers)
this._level = this._configuredLevel;
for (Logger log : Log.getLoggers().values())
{
this._level = this._configuredLevel;
// restore all cached log configured levels
for(StdErrLog log: __loggers.values())
{
log._level = log._configuredLevel;
}
if (log instanceof StdErrLog)
((StdErrLog)log).setLevel(((StdErrLog)log)._configuredLevel);
}
}
}
@ -570,67 +559,18 @@ public class StdErrLog implements Logger
}
}
/**
* A more robust form of name blank test. Will return true for null names, and names that have only whitespace
*
* @param name
* the name to test
* @return true for null or blank name, false if any non-whitespace character is found.
*/
private static boolean isBlank(String name)
{
if (name == null)
{
return true;
}
int size = name.length();
char c;
for (int i = 0; i < size; i++)
{
c = name.charAt(i);
if (!Character.isWhitespace(c))
{
return false;
}
}
return true;
}
/**
* Get a Child Logger relative to this Logger.
*
* @param name
* the child name
* @return the appropriate child logger (if name specified results in a new unique child)
* Create a Child Logger of this Logger.
*/
public Logger getLogger(String name)
protected Logger newLogger(String fullname)
{
if (isBlank(name))
{
return this;
}
String fullname = name;
if (!isBlank(_name))
{
fullname = _name + "." + name;
}
StdErrLog logger = __loggers.get(fullname);
if (logger == null)
{
StdErrLog sel = new StdErrLog(fullname);
// Preserve configuration for new loggers configuration
sel.setPrintLongNames(_printLongNames);
// Let Level come from configured Properties instead - sel.setLevel(_level);
sel.setSource(_source);
sel._stderr = this._stderr;
logger = __loggers.putIfAbsent(fullname,sel);
if (logger == null)
{
logger = sel;
}
}
StdErrLog logger = new StdErrLog(fullname);
// Preserve configuration for new loggers configuration
logger.setPrintLongNames(_printLongNames);
// Let Level come from configured Properties instead - sel.setLevel(_level);
logger.setSource(_source);
logger._stderr = this._stderr;
return logger;
}

View File

@ -15,6 +15,9 @@ package org.eclipse.jetty.util.log;
import static org.hamcrest.Matchers.is;
import java.util.HashMap;
import java.util.Map;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
@ -23,18 +26,23 @@ import org.junit.Test;
public class LogTest
{
private static Logger originalLogger;
private static Map<String,Logger> originalLoggers;
@SuppressWarnings("deprecation")
@BeforeClass
public static void rememberOriginalLogger()
{
originalLogger = Log.getLog();
originalLoggers = new HashMap<String, Logger>(Log.getLoggers());
Log.getMutableLoggers().clear();
}
@AfterClass
public static void restoreOriginalLogger()
{
Log.setLog(originalLogger);
Log.getMutableLoggers().clear();
Log.getMutableLoggers().putAll(originalLoggers);
}
@Test

View File

@ -1,26 +1,9 @@
package org.eclipse.jetty.util.log;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class NamedLogTest
{
private static Logger originalLogger;
@SuppressWarnings("deprecation")
@BeforeClass
public static void rememberOriginalLogger()
{
originalLogger = Log.getLog();
}
@AfterClass
public static void restoreOriginalLogger()
{
Log.setLog(originalLogger);
}
@Test
public void testNamedLogging()
{
@ -37,7 +20,7 @@ public class NamedLogTest
red.generateLogs();
green.generateLogs();
blue.generateLogs();
output.assertContains(Red.class.getName());
output.assertContains(Green.class.getName());
output.assertContains(Blue.class.getName());

View File

@ -43,4 +43,10 @@ public class StdErrCapture
String output = new String(test.toByteArray());
Assert.assertThat(output,not(containsString(unexpectedString)));
}
public String toString()
{
err.flush();
return new String(test.toByteArray());
}
}