Issue #4567 - StdErrLog cleanup and final Arg Throwable support

Checkstyle fixes ...
+ Log.__loggers now Log.LOGGERS
+ Log.__props now Log.PROPS
+ StdErrLog.__tagpad now StdErrLog.THREADNAME_PADDING
+ StdErrLog.__source now StdErrLog.SOURCE
+ StdErrLog.__long now StdErrLog.LONG_CLASSNAMES
+ StdErrLog.__escape now StdErrLog.ESCAPE_CONTROL_CHARS
+ Removed redundant "public" modifier on Log interface methods

New code ...
+ New Log.getProperty(String key, String defaultValue)
  Used by JavaUtilLog, JettyLogHandler, and StdErrLog
+ New StdErrLog.getConfiguredLevel()
+ New StrErrLog.println(String) used to write StringBuilder
  to configured PrintStream

Removed code ...
+ Removed deprecated prop check in StdErrLog initialization

Cleanup and Corrected code ...
+ StdErrLog.setDebugEnabled(boolean) cleanup
+ StdErrLog._stderr is now used and is never null
+ Only one StdErrLog.format() method entry point
+ StdErrLog.format(StringBuilder, Throwable) now called .formatCause(StringBuilder, Throwable, String)

Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
This commit is contained in:
Joakim Erdfelt 2020-02-13 13:00:24 -06:00
parent 3c9c506644
commit 3f3eaf2182
No known key found for this signature in database
GPG Key ID: 2D0E1FB8FE4B68B4
6 changed files with 197 additions and 174 deletions

View File

@ -65,8 +65,8 @@ public class JavaUtilLog extends AbstractLogger
{ {
private static final String THIS_CLASS = JavaUtilLog.class.getName(); private static final String THIS_CLASS = JavaUtilLog.class.getName();
private static final boolean __source = private static final boolean __source =
Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.SOURCE", Boolean.parseBoolean(Log.getProperty("org.eclipse.jetty.util.log.SOURCE",
Log.__props.getProperty("org.eclipse.jetty.util.log.javautil.SOURCE", "true"))); Log.getProperty("org.eclipse.jetty.util.log.javautil.SOURCE", "true")));
private static boolean _initialized = false; private static boolean _initialized = false;
@ -86,7 +86,7 @@ public class JavaUtilLog extends AbstractLogger
{ {
_initialized = true; _initialized = true;
final String properties = Log.__props.getProperty("org.eclipse.jetty.util.log.javautil.PROPERTIES", null); final String properties = Log.getProperty("org.eclipse.jetty.util.log.javautil.PROPERTIES", null);
if (properties != null) if (properties != null)
{ {
AccessController.doPrivileged(new PrivilegedAction<Object>() AccessController.doPrivileged(new PrivilegedAction<Object>()
@ -115,7 +115,7 @@ public class JavaUtilLog extends AbstractLogger
_logger = java.util.logging.Logger.getLogger(name); _logger = java.util.logging.Logger.getLogger(name);
switch (lookupLoggingLevel(Log.__props, name)) switch (lookupLoggingLevel(Log.getProperties(), name))
{ {
case LEVEL_ALL: case LEVEL_ALL:
_logger.setLevel(Level.ALL); _logger.setLevel(Level.ALL);

View File

@ -59,12 +59,12 @@ public class JettyLogHandler extends java.util.logging.Handler
public JettyLogHandler() public JettyLogHandler()
{ {
if (Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.DEBUG", "false"))) if (Boolean.parseBoolean(Log.getProperty("org.eclipse.jetty.util.log.DEBUG", "false")))
{ {
setLevel(Level.FINEST); setLevel(Level.FINEST);
} }
if (Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.IGNORED", "false"))) if (Boolean.parseBoolean(Log.getProperty("org.eclipse.jetty.util.log.IGNORED", "false")))
{ {
setLevel(Level.ALL); setLevel(Level.ALL);
} }

View File

@ -67,8 +67,8 @@ public class Log
/** /**
* Logging Configuration Properties * Logging Configuration Properties
*/ */
protected static final Properties __props = new Properties(); protected static final Properties PROPS = new Properties();
private static final ConcurrentMap<String, Logger> __loggers = new ConcurrentHashMap<>(); private static final ConcurrentMap<String, Logger> LOGGERS = new ConcurrentHashMap<>();
private static boolean __initialized; private static boolean __initialized;
private static Logger LOG; private static Logger LOG;
@ -83,7 +83,7 @@ public class Log
// * This is an optional feature used by embedded mode use, and test cases to allow for early // * This is an optional feature used by embedded mode use, and test cases to allow for early
// * configuration of the Log class in situations where access to the System.properties are // * configuration of the Log class in situations where access to the System.properties are
// * either too late or just impossible. // * either too late or just impossible.
loadProperties("jetty-logging.properties", __props); loadProperties("jetty-logging.properties", PROPS);
// Next see if an OS specific jetty-logging.properties object exists in the classpath. // Next see if an OS specific jetty-logging.properties object exists in the classpath.
// This really for setting up test specific logging behavior based on OS. // This really for setting up test specific logging behavior based on OS.
@ -92,7 +92,7 @@ public class Log
{ {
// NOTE: cannot use jetty-util's StringUtil.replace() as it may initialize logging itself. // NOTE: cannot use jetty-util's StringUtil.replace() as it may initialize logging itself.
osName = osName.toLowerCase(Locale.ENGLISH).replace(' ', '-'); osName = osName.toLowerCase(Locale.ENGLISH).replace(' ', '-');
loadProperties("jetty-logging-" + osName + ".properties", __props); loadProperties("jetty-logging-" + osName + ".properties", PROPS);
} }
// Now load the System.properties as-is into the __props, // Now load the System.properties as-is into the __props,
@ -105,12 +105,12 @@ public class Log
String val = System.getProperty(key); String val = System.getProperty(key);
// Protect against application code insertion of non-String values (returned as null). // Protect against application code insertion of non-String values (returned as null).
if (val != null) if (val != null)
__props.setProperty(key, val); PROPS.setProperty(key, val);
} }
// Now use the configuration properties to configure the Log statics. // Now use the configuration properties to configure the Log statics.
__logClass = __props.getProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.Slf4jLog"); __logClass = PROPS.getProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.Slf4jLog");
__ignored = Boolean.parseBoolean(__props.getProperty("org.eclipse.jetty.util.log.IGNORED", "false")); __ignored = Boolean.parseBoolean(PROPS.getProperty("org.eclipse.jetty.util.log.IGNORED", "false"));
return null; return null;
} }
}); });
@ -148,7 +148,7 @@ public class Log
return; return;
__initialized = true; __initialized = true;
boolean announce = Boolean.parseBoolean(__props.getProperty("org.eclipse.jetty.util.log.announce", "true")); boolean announce = Boolean.parseBoolean(PROPS.getProperty("org.eclipse.jetty.util.log.announce", "true"));
try try
{ {
Class<?> logClass = Loader.loadClass(Log.class, __logClass); Class<?> logClass = Loader.loadClass(Log.class, __logClass);
@ -278,7 +278,7 @@ public class Log
if (name == null) if (name == null)
return LOG; return LOG;
Logger logger = __loggers.get(name); Logger logger = LOGGERS.get(name);
if (logger == null) if (logger == null)
logger = LOG.getLogger(name); logger = LOG.getLogger(name);
@ -287,7 +287,7 @@ public class Log
static ConcurrentMap<String, Logger> getMutableLoggers() static ConcurrentMap<String, Logger> getMutableLoggers()
{ {
return __loggers; return LOGGERS;
} }
/** /**
@ -298,11 +298,16 @@ public class Log
@ManagedAttribute("list of all instantiated loggers") @ManagedAttribute("list of all instantiated loggers")
public static Map<String, Logger> getLoggers() public static Map<String, Logger> getLoggers()
{ {
return Collections.unmodifiableMap(__loggers); return Collections.unmodifiableMap(LOGGERS);
} }
public static Properties getProperties() public static Properties getProperties()
{ {
return __props; return PROPS;
}
public static String getProperty(String key, String defaultValue)
{
return PROPS.getProperty(key, defaultValue);
} }
} }

View File

@ -26,7 +26,7 @@ public interface Logger
/** /**
* @return the name of this logger * @return the name of this logger
*/ */
public String getName(); String getName();
/** /**
* Formats and logs at warn level. * Formats and logs at warn level.
@ -34,14 +34,14 @@ public interface Logger
* @param msg the formatting string * @param msg the formatting string
* @param args the optional arguments * @param args the optional arguments
*/ */
public void warn(String msg, Object... args); void warn(String msg, Object... args);
/** /**
* Logs the given Throwable information at warn level * Logs the given Throwable information at warn level
* *
* @param thrown the Throwable to log * @param thrown the Throwable to log
*/ */
public void warn(Throwable thrown); void warn(Throwable thrown);
/** /**
* Logs the given message at warn level, with Throwable information. * Logs the given message at warn level, with Throwable information.
@ -49,7 +49,7 @@ public interface Logger
* @param msg the message to log * @param msg the message to log
* @param thrown the Throwable to log * @param thrown the Throwable to log
*/ */
public void warn(String msg, Throwable thrown); void warn(String msg, Throwable thrown);
/** /**
* Formats and logs at info level. * Formats and logs at info level.
@ -57,14 +57,14 @@ public interface Logger
* @param msg the formatting string * @param msg the formatting string
* @param args the optional arguments * @param args the optional arguments
*/ */
public void info(String msg, Object... args); void info(String msg, Object... args);
/** /**
* Logs the given Throwable information at info level * Logs the given Throwable information at info level
* *
* @param thrown the Throwable to log * @param thrown the Throwable to log
*/ */
public void info(Throwable thrown); void info(Throwable thrown);
/** /**
* Logs the given message at info level, with Throwable information. * Logs the given message at info level, with Throwable information.
@ -72,19 +72,19 @@ public interface Logger
* @param msg the message to log * @param msg the message to log
* @param thrown the Throwable to log * @param thrown the Throwable to log
*/ */
public void info(String msg, Throwable thrown); void info(String msg, Throwable thrown);
/** /**
* @return whether the debug level is enabled * @return whether the debug level is enabled
*/ */
public boolean isDebugEnabled(); boolean isDebugEnabled();
/** /**
* Mutator used to turn debug on programmatically. * Mutator used to turn debug on programmatically.
* *
* @param enabled whether to enable the debug level * @param enabled whether to enable the debug level
*/ */
public void setDebugEnabled(boolean enabled); void setDebugEnabled(boolean enabled);
/** /**
* Formats and logs at debug level. * Formats and logs at debug level.
@ -92,7 +92,7 @@ public interface Logger
* @param msg the formatting string * @param msg the formatting string
* @param args the optional arguments * @param args the optional arguments
*/ */
public void debug(String msg, Object... args); void debug(String msg, Object... args);
/** /**
* Formats and logs at debug level. * Formats and logs at debug level.
@ -101,14 +101,14 @@ public interface Logger
* @param msg the formatting string * @param msg the formatting string
* @param value long value * @param value long value
*/ */
public void debug(String msg, long value); void debug(String msg, long value);
/** /**
* Logs the given Throwable information at debug level * Logs the given Throwable information at debug level
* *
* @param thrown the Throwable to log * @param thrown the Throwable to log
*/ */
public void debug(Throwable thrown); void debug(Throwable thrown);
/** /**
* Logs the given message at debug level, with Throwable information. * Logs the given message at debug level, with Throwable information.
@ -116,13 +116,13 @@ public interface Logger
* @param msg the message to log * @param msg the message to log
* @param thrown the Throwable to log * @param thrown the Throwable to log
*/ */
public void debug(String msg, Throwable thrown); void debug(String msg, Throwable thrown);
/** /**
* @param name the name of the logger * @param name the name of the logger
* @return a logger with the given name * @return a logger with the given name
*/ */
public Logger getLogger(String name); Logger getLogger(String name);
/** /**
* Ignore an exception. * Ignore an exception.
@ -130,5 +130,5 @@ public interface Logger
* *
* @param ignored the throwable to log as ignored * @param ignored the throwable to log as ignored
*/ */
public void ignore(Throwable ignored); void ignore(Throwable ignored);
} }

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.util.log;
import java.io.PrintStream; import java.io.PrintStream;
import java.security.AccessControlException; import java.security.AccessControlException;
import java.util.Properties; import java.util.Properties;
import java.util.function.Function;
import org.eclipse.jetty.util.DateCache; import org.eclipse.jetty.util.DateCache;
import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedAttribute;
@ -92,30 +93,20 @@ import org.eclipse.jetty.util.annotation.ManagedObject;
@ManagedObject("Jetty StdErr Logging Implementation") @ManagedObject("Jetty StdErr Logging Implementation")
public class StdErrLog extends AbstractLogger public class StdErrLog extends AbstractLogger
{ {
private static final String EOL = System.getProperty("line.separator"); private static final String EOL = System.lineSeparator();
private static final Object[] EMPTY_ARGS = new Object[0];
// Do not change output format lightly, people rely on this output format now. // Do not change output format lightly, people rely on this output format now.
private static int __tagpad = Integer.parseInt(Log.__props.getProperty("org.eclipse.jetty.util.log.StdErrLog.TAG_PAD", "0")); private static int THREADNAME_PADDING = Integer.parseInt(Log.getProperty("org.eclipse.jetty.util.log.StdErrLog.TAG_PAD", "0"));
private static DateCache _dateCache; private static DateCache _dateCache;
private static final boolean __source = Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.SOURCE", private static final boolean SOURCE = Boolean.parseBoolean(
Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.SOURCE", "false"))); Log.getProperty("org.eclipse.jetty.util.log.SOURCE",
private static final boolean __long = Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.LONG", "false")); Log.getProperty("org.eclipse.jetty.util.log.stderr.SOURCE", "false")));
private static final boolean __escape = Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.ESCAPE", "true")); private static final boolean LONG_CLASSNAMES = Boolean.parseBoolean(Log.getProperty("org.eclipse.jetty.util.log.stderr.LONG", "false"));
private static final boolean ESCAPE_CONTROL_CHARS = Boolean.parseBoolean(Log.getProperty("org.eclipse.jetty.util.log.stderr.ESCAPE", "true"));
static static
{ {
String[] deprecatedProperties =
{"DEBUG", "org.eclipse.jetty.util.log.DEBUG", "org.eclipse.jetty.util.log.stderr.DEBUG"};
// Toss a message to users about deprecated system properties
for (String deprecatedProp : deprecatedProperties)
{
if (System.getProperty(deprecatedProp) != null)
{
System.err.printf("System Property [%s] has been deprecated! (Use org.eclipse.jetty.LEVEL=DEBUG instead)%n", deprecatedProp);
}
}
try try
{ {
_dateCache = new DateCache("yyyy-MM-dd HH:mm:ss"); _dateCache = new DateCache("yyyy-MM-dd HH:mm:ss");
@ -128,19 +119,19 @@ public class StdErrLog extends AbstractLogger
public static void setTagPad(int pad) public static void setTagPad(int pad)
{ {
__tagpad = pad; THREADNAME_PADDING = pad;
} }
private int _level = LEVEL_INFO; private int _level = LEVEL_INFO;
// Level that this Logger was configured as (remembered in special case of .setDebugEnabled()) // Level that this Logger was configured as (remembered in special case of .setDebugEnabled())
private int _configuredLevel; private int _configuredLevel;
private PrintStream _stderr = null; private PrintStream _stderr = System.err;
private boolean _source = __source; private boolean _source = SOURCE;
// Print the long form names, otherwise use abbreviated // Print the long form names, otherwise use abbreviated
private boolean _printLongNames = __long; private boolean _printLongNames = LONG_CLASSNAMES;
// The full log name, as provided by the system. // The full log name, as provided by the system.
private final String _name; private final String _name;
// The abbreviated log name (used by default, unless _long is specified) // The abbreviated log name (used by default, unless _printLongNames is specified)
protected final String _abbrevname; protected final String _abbrevname;
private boolean _hideStacks = false; private boolean _hideStacks = false;
@ -204,28 +195,28 @@ public class StdErrLog extends AbstractLogger
public StdErrLog(String name, Properties props) public StdErrLog(String name, Properties props)
{ {
@SuppressWarnings("ReferenceEquality") @SuppressWarnings("ReferenceEquality")
boolean sameObject = (props != Log.__props); boolean sameObject = (props != Log.PROPS);
if (props != null && sameObject) if (props != null && sameObject)
Log.__props.putAll(props); Log.PROPS.putAll(props);
_name = name == null ? "" : name; _name = name == null ? "" : name;
_abbrevname = condensePackageString(this._name); _abbrevname = condensePackageString(this._name);
_level = getLoggingLevel(Log.__props, this._name); _level = getLoggingLevel(Log.PROPS, this._name);
_configuredLevel = _level; _configuredLevel = _level;
try try
{ {
String source = getLoggingProperty(Log.__props, _name, "SOURCE"); String source = getLoggingProperty(Log.PROPS, _name, "SOURCE");
_source = source == null ? __source : Boolean.parseBoolean(source); _source = source == null ? SOURCE : Boolean.parseBoolean(source);
} }
catch (AccessControlException ace) catch (AccessControlException ace)
{ {
_source = __source; _source = SOURCE;
} }
try try
{ {
// allow stacktrace display to be controlled by properties as well // allow stacktrace display to be controlled by properties as well
String stacks = getLoggingProperty(Log.__props, _name, "STACKS"); String stacks = getLoggingProperty(Log.PROPS, _name, "STACKS");
_hideStacks = stacks == null ? false : !Boolean.parseBoolean(stacks); _hideStacks = stacks == null ? false : !Boolean.parseBoolean(stacks);
} }
catch (AccessControlException ignore) catch (AccessControlException ignore)
@ -285,9 +276,9 @@ public class StdErrLog extends AbstractLogger
{ {
if (_level <= LEVEL_WARN) if (_level <= LEVEL_WARN)
{ {
StringBuilder buffer = new StringBuilder(64); StringBuilder builder = new StringBuilder(64);
format(buffer, ":WARN:", msg, args); format(builder, ":WARN:", msg, args);
(_stderr == null ? System.err : _stderr).println(buffer); println(builder);
} }
} }
@ -302,9 +293,9 @@ public class StdErrLog extends AbstractLogger
{ {
if (_level <= LEVEL_WARN) if (_level <= LEVEL_WARN)
{ {
StringBuilder buffer = new StringBuilder(64); StringBuilder builder = new StringBuilder(64);
format(buffer, ":WARN:", msg, thrown); format(builder, ":WARN:", msg, thrown);
(_stderr == null ? System.err : _stderr).println(buffer); println(builder);
} }
} }
@ -313,9 +304,9 @@ public class StdErrLog extends AbstractLogger
{ {
if (_level <= LEVEL_INFO) if (_level <= LEVEL_INFO)
{ {
StringBuilder buffer = new StringBuilder(64); StringBuilder builder = new StringBuilder(64);
format(buffer, ":INFO:", msg, args); format(builder, ":INFO:", msg, args);
(_stderr == null ? System.err : _stderr).println(buffer); println(builder);
} }
} }
@ -330,9 +321,9 @@ public class StdErrLog extends AbstractLogger
{ {
if (_level <= LEVEL_INFO) if (_level <= LEVEL_INFO)
{ {
StringBuilder buffer = new StringBuilder(64); StringBuilder builder = new StringBuilder(64);
format(buffer, ":INFO:", msg, thrown); format(builder, ":INFO:", msg, thrown);
(_stderr == null ? System.err : _stderr).println(buffer); println(builder);
} }
} }
@ -350,28 +341,35 @@ public class StdErrLog extends AbstractLogger
@Override @Override
public void setDebugEnabled(boolean enabled) public void setDebugEnabled(boolean enabled)
{ {
Function<StdErrLog, Integer> lvlFunc;
if (enabled) if (enabled)
{ {
this._level = LEVEL_DEBUG; lvlFunc = (logger) -> LEVEL_DEBUG;
for (Logger log : Log.getLoggers().values())
{
if (log.getName().startsWith(getName()) && log instanceof StdErrLog)
((StdErrLog)log).setLevel(LEVEL_DEBUG);
}
} }
else else
{ {
this._level = this._configuredLevel; lvlFunc = (logger) -> logger.getConfiguredLevel();
}
for (Logger log : Log.getLoggers().values()) this.setLevel(lvlFunc.apply(this));
String name = getName();
for (Logger log : Log.getLoggers().values())
{
if (log.getName().startsWith(name) && log instanceof StdErrLog)
{ {
if (log.getName().startsWith(getName()) && log instanceof StdErrLog) StdErrLog logger = (StdErrLog)log;
((StdErrLog)log).setLevel(((StdErrLog)log)._configuredLevel); logger.setLevel(lvlFunc.apply(logger));
} }
} }
} }
private int getConfiguredLevel()
{
return _configuredLevel;
}
public int getLevel() public int getLevel()
{ {
return _level; return _level;
@ -392,17 +390,24 @@ public class StdErrLog extends AbstractLogger
public void setStdErrStream(PrintStream stream) public void setStdErrStream(PrintStream stream)
{ {
this._stderr = stream == System.err ? null : stream; if (stream == null)
{
this._stderr = System.err;
}
else
{
this._stderr = stream;
}
} }
@Override @Override
public void debug(String msg, Object... args) public void debug(String msg, Object... args)
{ {
if (_level <= LEVEL_DEBUG) if (isDebugEnabled())
{ {
StringBuilder buffer = new StringBuilder(64); StringBuilder builder = new StringBuilder(64);
format(buffer, ":DBUG:", msg, args); format(builder, ":DBUG:", msg, args);
(_stderr == null ? System.err : _stderr).println(buffer); println(builder);
} }
} }
@ -411,9 +416,9 @@ public class StdErrLog extends AbstractLogger
{ {
if (isDebugEnabled()) if (isDebugEnabled())
{ {
StringBuilder buffer = new StringBuilder(64); StringBuilder builder = new StringBuilder(64);
format(buffer, ":DBUG:", msg, arg); format(builder, ":DBUG:", msg, arg);
(_stderr == null ? System.err : _stderr).println(buffer); println(builder);
} }
} }
@ -426,50 +431,57 @@ public class StdErrLog extends AbstractLogger
@Override @Override
public void debug(String msg, Throwable thrown) public void debug(String msg, Throwable thrown)
{ {
if (_level <= LEVEL_DEBUG) if (isDebugEnabled())
{ {
StringBuilder buffer = new StringBuilder(64); StringBuilder builder = new StringBuilder(64);
format(buffer, ":DBUG:", msg, thrown); format(builder, ":DBUG:", msg, thrown);
(_stderr == null ? System.err : _stderr).println(buffer); println(builder);
} }
} }
private void format(StringBuilder buffer, String level, String msg, Object... args) private void println(StringBuilder builder)
{
_stderr.println(builder);
}
private void format(StringBuilder builder, String level, String msg, Object... inArgs)
{ {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
int ms = (int)(now % 1000); int ms = (int)(now % 1000);
String d = _dateCache.formatNow(now); String d = _dateCache.formatNow(now);
tag(buffer, d, ms, level); tag(builder, d, ms, level);
format(buffer, msg, args);
}
private void format(StringBuilder buffer, String level, String msg, Throwable thrown) Object[] msgArgs = EMPTY_ARGS;
{ int msgArgsLen = 0;
format(buffer, level, msg); Throwable cause = null;
if (isHideStacks())
{ if (inArgs != null)
format(buffer, ": " + String.valueOf(thrown)); {
} msgArgs = inArgs;
else msgArgsLen = inArgs.length;
{ if (msgArgsLen > 0)
format(buffer, thrown); {
} if (inArgs[msgArgsLen - 1] instanceof Throwable)
} {
cause = (Throwable)inArgs[msgArgsLen - 1];
msgArgsLen--;
}
}
}
private void format(StringBuilder builder, String msg, Object... args)
{
if (msg == null) if (msg == null)
{ {
msg = ""; msg = "";
for (int i = 0; i < args.length; i++) for (int i = 0; i < msgArgsLen; i++)
{ {
msg += "{} "; msg += "{} ";
} }
} }
String braces = "{}"; String braces = "{}";
int start = 0; int start = 0;
for (Object arg : args) for (int i = 0; i < msgArgsLen; i++)
{ {
Object arg = msgArgs[i];
int bracesIndex = msg.indexOf(braces, start); int bracesIndex = msg.indexOf(braces, start);
if (bracesIndex < 0) if (bracesIndex < 0)
{ {
@ -481,57 +493,57 @@ public class StdErrLog extends AbstractLogger
else else
{ {
escape(builder, msg.substring(start, bracesIndex)); escape(builder, msg.substring(start, bracesIndex));
builder.append(String.valueOf(arg)); builder.append(arg);
start = bracesIndex + braces.length(); start = bracesIndex + braces.length();
} }
} }
escape(builder, msg.substring(start)); escape(builder, msg.substring(start));
}
protected void format(StringBuilder buffer, Throwable thrown) if (cause != null)
{
format(buffer, thrown, "");
}
protected void format(StringBuilder buffer, Throwable thrown, String indent)
{
if (thrown == null)
{ {
buffer.append("null"); if (isHideStacks())
}
else
{
buffer.append(EOL).append(indent);
format(buffer, thrown.toString());
StackTraceElement[] elements = thrown.getStackTrace();
for (int i = 0; elements != null && i < elements.length; i++)
{ {
buffer.append(EOL).append(indent).append("\tat "); builder.append(": " + cause);
format(buffer, elements[i].toString());
} }
else
for (Throwable suppressed : thrown.getSuppressed())
{ {
buffer.append(EOL).append(indent).append("Suppressed: "); formatCause(builder, cause, "");
format(buffer, suppressed, "\t|" + indent);
}
Throwable cause = thrown.getCause();
if (cause != null && cause != thrown)
{
buffer.append(EOL).append(indent).append("Caused by: ");
format(buffer, cause, indent);
} }
} }
} }
private void escape(StringBuilder builder, String string) private void formatCause(StringBuilder builder, Throwable cause, String indent)
{ {
if (__escape) builder.append(EOL).append(indent);
escape(builder, cause.toString());
StackTraceElement[] elements = cause.getStackTrace();
for (int i = 0; elements != null && i < elements.length; i++)
{ {
for (int i = 0; i < string.length(); ++i) builder.append(EOL).append(indent).append("\tat ");
escape(builder, elements[i].toString());
}
for (Throwable suppressed : cause.getSuppressed())
{
builder.append(EOL).append(indent).append("Suppressed: ");
formatCause(builder, suppressed, "\t|" + indent);
}
Throwable by = cause.getCause();
if (by != null && by != cause)
{
builder.append(EOL).append(indent).append("Caused by: ");
formatCause(builder, by, indent);
}
}
private void escape(StringBuilder builder, String str)
{
if (ESCAPE_CONTROL_CHARS)
{
for (int i = 0; i < str.length(); ++i)
{ {
char c = string.charAt(i); char c = str.charAt(i);
if (Character.isISOControl(c)) if (Character.isISOControl(c))
{ {
if (c == '\n') if (c == '\n')
@ -554,35 +566,35 @@ public class StdErrLog extends AbstractLogger
} }
} }
else else
builder.append(string); builder.append(str);
} }
private void tag(StringBuilder buffer, String d, int ms, String tag) private void tag(StringBuilder builder, String d, int ms, String tag)
{ {
buffer.setLength(0); builder.setLength(0);
buffer.append(d); builder.append(d);
if (ms > 99) if (ms > 99)
{ {
buffer.append('.'); builder.append('.');
} }
else if (ms > 9) else if (ms > 9)
{ {
buffer.append(".0"); builder.append(".0");
} }
else else
{ {
buffer.append(".00"); builder.append(".00");
} }
buffer.append(ms).append(tag); builder.append(ms).append(tag);
String name = _printLongNames ? _name : _abbrevname; String name = _printLongNames ? _name : _abbrevname;
String tname = Thread.currentThread().getName(); String tname = Thread.currentThread().getName();
int p = __tagpad > 0 ? (name.length() + tname.length() - __tagpad) : 0; int p = THREADNAME_PADDING > 0 ? (name.length() + tname.length() - THREADNAME_PADDING) : 0;
if (p < 0) if (p < 0)
{ {
buffer builder
.append(name) .append(name)
.append(':') .append(':')
.append(" ", 0, -p) .append(" ", 0, -p)
@ -590,9 +602,9 @@ public class StdErrLog extends AbstractLogger
} }
else if (p == 0) else if (p == 0)
{ {
buffer.append(name).append(':').append(tname); builder.append(name).append(':').append(tname);
} }
buffer.append(':'); builder.append(':');
if (_source) if (_source)
{ {
@ -608,23 +620,23 @@ public class StdErrLog extends AbstractLogger
} }
if (!_printLongNames && clazz.startsWith("org.eclipse.jetty.")) if (!_printLongNames && clazz.startsWith("org.eclipse.jetty."))
{ {
buffer.append(condensePackageString(clazz)); builder.append(condensePackageString(clazz));
} }
else else
{ {
buffer.append(clazz); builder.append(clazz);
} }
buffer.append('#').append(frame.getMethodName()); builder.append('#').append(frame.getMethodName());
if (frame.getFileName() != null) if (frame.getFileName() != null)
{ {
buffer.append('(').append(frame.getFileName()).append(':').append(frame.getLineNumber()).append(')'); builder.append('(').append(frame.getFileName()).append(':').append(frame.getLineNumber()).append(')');
} }
buffer.append(':'); builder.append(':');
break; break;
} }
} }
buffer.append(' '); builder.append(' ');
} }
/** /**
@ -678,9 +690,9 @@ public class StdErrLog extends AbstractLogger
{ {
if (_level <= LEVEL_ALL) if (_level <= LEVEL_ALL)
{ {
StringBuilder buffer = new StringBuilder(64); StringBuilder builder = new StringBuilder(64);
format(buffer, ":IGNORED:", "", ignored); format(builder, ":IGNORED:", "", ignored);
(_stderr == null ? System.err : _stderr).println(buffer); println(builder);
} }
} }
} }

View File

@ -149,6 +149,12 @@ public class StdErrLogTest
log.warn("ex", th); log.warn("ex", th);
output.assertContains(ths); output.assertContains(ths);
Throwable thr = new Throwable("Reasons Explained");
log.warn("Ex {}", "Reasons", thr);
output.assertContains("Reasons");
output.assertContains(thr.toString());
th = new Throwable("Message with \033 escape"); th = new Throwable("Message with \033 escape");
log.warn("ex", th); log.warn("ex", th);