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 boolean __source =
Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.SOURCE",
Log.__props.getProperty("org.eclipse.jetty.util.log.javautil.SOURCE", "true")));
Boolean.parseBoolean(Log.getProperty("org.eclipse.jetty.util.log.SOURCE",
Log.getProperty("org.eclipse.jetty.util.log.javautil.SOURCE", "true")));
private static boolean _initialized = false;
@ -86,7 +86,7 @@ public class JavaUtilLog extends AbstractLogger
{
_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)
{
AccessController.doPrivileged(new PrivilegedAction<Object>()
@ -115,7 +115,7 @@ public class JavaUtilLog extends AbstractLogger
_logger = java.util.logging.Logger.getLogger(name);
switch (lookupLoggingLevel(Log.__props, name))
switch (lookupLoggingLevel(Log.getProperties(), name))
{
case LEVEL_ALL:
_logger.setLevel(Level.ALL);

View File

@ -59,12 +59,12 @@ public class JettyLogHandler extends java.util.logging.Handler
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);
}
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);
}

View File

@ -67,8 +67,8 @@ public class Log
/**
* Logging Configuration Properties
*/
protected static final Properties __props = new Properties();
private static final ConcurrentMap<String, Logger> __loggers = new ConcurrentHashMap<>();
protected static final Properties PROPS = new Properties();
private static final ConcurrentMap<String, Logger> LOGGERS = new ConcurrentHashMap<>();
private static boolean __initialized;
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
// * configuration of the Log class in situations where access to the System.properties are
// * 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.
// 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.
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,
@ -105,12 +105,12 @@ public class Log
String val = System.getProperty(key);
// Protect against application code insertion of non-String values (returned as null).
if (val != null)
__props.setProperty(key, val);
PROPS.setProperty(key, val);
}
// 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");
__ignored = Boolean.parseBoolean(__props.getProperty("org.eclipse.jetty.util.log.IGNORED", "false"));
__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"));
return null;
}
});
@ -148,7 +148,7 @@ public class Log
return;
__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
{
Class<?> logClass = Loader.loadClass(Log.class, __logClass);
@ -278,7 +278,7 @@ public class Log
if (name == null)
return LOG;
Logger logger = __loggers.get(name);
Logger logger = LOGGERS.get(name);
if (logger == null)
logger = LOG.getLogger(name);
@ -287,7 +287,7 @@ public class Log
static ConcurrentMap<String, Logger> getMutableLoggers()
{
return __loggers;
return LOGGERS;
}
/**
@ -298,11 +298,16 @@ public class Log
@ManagedAttribute("list of all instantiated loggers")
public static Map<String, Logger> getLoggers()
{
return Collections.unmodifiableMap(__loggers);
return Collections.unmodifiableMap(LOGGERS);
}
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
*/
public String getName();
String getName();
/**
* Formats and logs at warn level.
@ -34,14 +34,14 @@ public interface Logger
* @param msg the formatting string
* @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
*
* @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.
@ -49,7 +49,7 @@ public interface Logger
* @param msg the message 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.
@ -57,14 +57,14 @@ public interface Logger
* @param msg the formatting string
* @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
*
* @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.
@ -72,19 +72,19 @@ public interface Logger
* @param msg the message 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
*/
public boolean isDebugEnabled();
boolean isDebugEnabled();
/**
* Mutator used to turn debug on programmatically.
*
* @param enabled whether to enable the debug level
*/
public void setDebugEnabled(boolean enabled);
void setDebugEnabled(boolean enabled);
/**
* Formats and logs at debug level.
@ -92,7 +92,7 @@ public interface Logger
* @param msg the formatting string
* @param args the optional arguments
*/
public void debug(String msg, Object... args);
void debug(String msg, Object... args);
/**
* Formats and logs at debug level.
@ -101,14 +101,14 @@ public interface Logger
* @param msg the formatting string
* @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
*
* @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.
@ -116,13 +116,13 @@ public interface Logger
* @param msg the message 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
* @return a logger with the given name
*/
public Logger getLogger(String name);
Logger getLogger(String name);
/**
* Ignore an exception.
@ -130,5 +130,5 @@ public interface Logger
*
* @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.security.AccessControlException;
import java.util.Properties;
import java.util.function.Function;
import org.eclipse.jetty.util.DateCache;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
@ -92,30 +93,20 @@ import org.eclipse.jetty.util.annotation.ManagedObject;
@ManagedObject("Jetty StdErr Logging Implementation")
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.
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 final boolean __source = Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.SOURCE",
Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.SOURCE", "false")));
private static final boolean __long = Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.LONG", "false"));
private static final boolean __escape = Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.ESCAPE", "true"));
private static final boolean SOURCE = Boolean.parseBoolean(
Log.getProperty("org.eclipse.jetty.util.log.SOURCE",
Log.getProperty("org.eclipse.jetty.util.log.stderr.SOURCE", "false")));
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
{
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
{
_dateCache = new DateCache("yyyy-MM-dd HH:mm:ss");
@ -128,19 +119,19 @@ public class StdErrLog extends AbstractLogger
public static void setTagPad(int pad)
{
__tagpad = pad;
THREADNAME_PADDING = pad;
}
private int _level = LEVEL_INFO;
// Level that this Logger was configured as (remembered in special case of .setDebugEnabled())
private int _configuredLevel;
private PrintStream _stderr = null;
private boolean _source = __source;
private PrintStream _stderr = System.err;
private boolean _source = SOURCE;
// 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.
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;
private boolean _hideStacks = false;
@ -204,28 +195,28 @@ public class StdErrLog extends AbstractLogger
public StdErrLog(String name, Properties props)
{
@SuppressWarnings("ReferenceEquality")
boolean sameObject = (props != Log.__props);
boolean sameObject = (props != Log.PROPS);
if (props != null && sameObject)
Log.__props.putAll(props);
Log.PROPS.putAll(props);
_name = name == null ? "" : name;
_abbrevname = condensePackageString(this._name);
_level = getLoggingLevel(Log.__props, this._name);
_level = getLoggingLevel(Log.PROPS, this._name);
_configuredLevel = _level;
try
{
String source = getLoggingProperty(Log.__props, _name, "SOURCE");
_source = source == null ? __source : Boolean.parseBoolean(source);
String source = getLoggingProperty(Log.PROPS, _name, "SOURCE");
_source = source == null ? SOURCE : Boolean.parseBoolean(source);
}
catch (AccessControlException ace)
{
_source = __source;
_source = SOURCE;
}
try
{
// 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);
}
catch (AccessControlException ignore)
@ -285,9 +276,9 @@ public class StdErrLog extends AbstractLogger
{
if (_level <= LEVEL_WARN)
{
StringBuilder buffer = new StringBuilder(64);
format(buffer, ":WARN:", msg, args);
(_stderr == null ? System.err : _stderr).println(buffer);
StringBuilder builder = new StringBuilder(64);
format(builder, ":WARN:", msg, args);
println(builder);
}
}
@ -302,9 +293,9 @@ public class StdErrLog extends AbstractLogger
{
if (_level <= LEVEL_WARN)
{
StringBuilder buffer = new StringBuilder(64);
format(buffer, ":WARN:", msg, thrown);
(_stderr == null ? System.err : _stderr).println(buffer);
StringBuilder builder = new StringBuilder(64);
format(builder, ":WARN:", msg, thrown);
println(builder);
}
}
@ -313,9 +304,9 @@ public class StdErrLog extends AbstractLogger
{
if (_level <= LEVEL_INFO)
{
StringBuilder buffer = new StringBuilder(64);
format(buffer, ":INFO:", msg, args);
(_stderr == null ? System.err : _stderr).println(buffer);
StringBuilder builder = new StringBuilder(64);
format(builder, ":INFO:", msg, args);
println(builder);
}
}
@ -330,9 +321,9 @@ public class StdErrLog extends AbstractLogger
{
if (_level <= LEVEL_INFO)
{
StringBuilder buffer = new StringBuilder(64);
format(buffer, ":INFO:", msg, thrown);
(_stderr == null ? System.err : _stderr).println(buffer);
StringBuilder builder = new StringBuilder(64);
format(builder, ":INFO:", msg, thrown);
println(builder);
}
}
@ -350,28 +341,35 @@ public class StdErrLog extends AbstractLogger
@Override
public void setDebugEnabled(boolean enabled)
{
Function<StdErrLog, Integer> lvlFunc;
if (enabled)
{
this._level = LEVEL_DEBUG;
for (Logger log : Log.getLoggers().values())
{
if (log.getName().startsWith(getName()) && log instanceof StdErrLog)
((StdErrLog)log).setLevel(LEVEL_DEBUG);
}
lvlFunc = (logger) -> LEVEL_DEBUG;
}
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)log).setLevel(((StdErrLog)log)._configuredLevel);
StdErrLog logger = (StdErrLog)log;
logger.setLevel(lvlFunc.apply(logger));
}
}
}
private int getConfiguredLevel()
{
return _configuredLevel;
}
public int getLevel()
{
return _level;
@ -392,17 +390,24 @@ public class StdErrLog extends AbstractLogger
public void setStdErrStream(PrintStream stream)
{
this._stderr = stream == System.err ? null : stream;
if (stream == null)
{
this._stderr = System.err;
}
else
{
this._stderr = stream;
}
}
@Override
public void debug(String msg, Object... args)
{
if (_level <= LEVEL_DEBUG)
if (isDebugEnabled())
{
StringBuilder buffer = new StringBuilder(64);
format(buffer, ":DBUG:", msg, args);
(_stderr == null ? System.err : _stderr).println(buffer);
StringBuilder builder = new StringBuilder(64);
format(builder, ":DBUG:", msg, args);
println(builder);
}
}
@ -411,9 +416,9 @@ public class StdErrLog extends AbstractLogger
{
if (isDebugEnabled())
{
StringBuilder buffer = new StringBuilder(64);
format(buffer, ":DBUG:", msg, arg);
(_stderr == null ? System.err : _stderr).println(buffer);
StringBuilder builder = new StringBuilder(64);
format(builder, ":DBUG:", msg, arg);
println(builder);
}
}
@ -426,50 +431,57 @@ public class StdErrLog extends AbstractLogger
@Override
public void debug(String msg, Throwable thrown)
{
if (_level <= LEVEL_DEBUG)
if (isDebugEnabled())
{
StringBuilder buffer = new StringBuilder(64);
format(buffer, ":DBUG:", msg, thrown);
(_stderr == null ? System.err : _stderr).println(buffer);
StringBuilder builder = new StringBuilder(64);
format(builder, ":DBUG:", msg, thrown);
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();
int ms = (int)(now % 1000);
String d = _dateCache.formatNow(now);
tag(buffer, d, ms, level);
format(buffer, msg, args);
}
tag(builder, d, ms, level);
private void format(StringBuilder buffer, String level, String msg, Throwable thrown)
{
format(buffer, level, msg);
if (isHideStacks())
{
format(buffer, ": " + String.valueOf(thrown));
}
else
{
format(buffer, thrown);
}
}
Object[] msgArgs = EMPTY_ARGS;
int msgArgsLen = 0;
Throwable cause = null;
if (inArgs != null)
{
msgArgs = inArgs;
msgArgsLen = inArgs.length;
if (msgArgsLen > 0)
{
if (inArgs[msgArgsLen - 1] instanceof Throwable)
{
cause = (Throwable)inArgs[msgArgsLen - 1];
msgArgsLen--;
}
}
}
private void format(StringBuilder builder, String msg, Object... args)
{
if (msg == null)
{
msg = "";
for (int i = 0; i < args.length; i++)
for (int i = 0; i < msgArgsLen; i++)
{
msg += "{} ";
}
}
String braces = "{}";
int start = 0;
for (Object arg : args)
for (int i = 0; i < msgArgsLen; i++)
{
Object arg = msgArgs[i];
int bracesIndex = msg.indexOf(braces, start);
if (bracesIndex < 0)
{
@ -481,57 +493,57 @@ public class StdErrLog extends AbstractLogger
else
{
escape(builder, msg.substring(start, bracesIndex));
builder.append(String.valueOf(arg));
builder.append(arg);
start = bracesIndex + braces.length();
}
}
escape(builder, msg.substring(start));
}
protected void format(StringBuilder buffer, Throwable thrown)
{
format(buffer, thrown, "");
}
protected void format(StringBuilder buffer, Throwable thrown, String indent)
{
if (thrown == null)
if (cause != null)
{
buffer.append("null");
}
else
{
buffer.append(EOL).append(indent);
format(buffer, thrown.toString());
StackTraceElement[] elements = thrown.getStackTrace();
for (int i = 0; elements != null && i < elements.length; i++)
if (isHideStacks())
{
buffer.append(EOL).append(indent).append("\tat ");
format(buffer, elements[i].toString());
builder.append(": " + cause);
}
for (Throwable suppressed : thrown.getSuppressed())
else
{
buffer.append(EOL).append(indent).append("Suppressed: ");
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);
formatCause(builder, cause, "");
}
}
}
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 (c == '\n')
@ -554,35 +566,35 @@ public class StdErrLog extends AbstractLogger
}
}
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);
buffer.append(d);
builder.setLength(0);
builder.append(d);
if (ms > 99)
{
buffer.append('.');
builder.append('.');
}
else if (ms > 9)
{
buffer.append(".0");
builder.append(".0");
}
else
{
buffer.append(".00");
builder.append(".00");
}
buffer.append(ms).append(tag);
builder.append(ms).append(tag);
String name = _printLongNames ? _name : _abbrevname;
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)
{
buffer
builder
.append(name)
.append(':')
.append(" ", 0, -p)
@ -590,9 +602,9 @@ public class StdErrLog extends AbstractLogger
}
else if (p == 0)
{
buffer.append(name).append(':').append(tname);
builder.append(name).append(':').append(tname);
}
buffer.append(':');
builder.append(':');
if (_source)
{
@ -608,23 +620,23 @@ public class StdErrLog extends AbstractLogger
}
if (!_printLongNames && clazz.startsWith("org.eclipse.jetty."))
{
buffer.append(condensePackageString(clazz));
builder.append(condensePackageString(clazz));
}
else
{
buffer.append(clazz);
builder.append(clazz);
}
buffer.append('#').append(frame.getMethodName());
builder.append('#').append(frame.getMethodName());
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;
}
}
buffer.append(' ');
builder.append(' ');
}
/**
@ -678,9 +690,9 @@ public class StdErrLog extends AbstractLogger
{
if (_level <= LEVEL_ALL)
{
StringBuilder buffer = new StringBuilder(64);
format(buffer, ":IGNORED:", "", ignored);
(_stderr == null ? System.err : _stderr).println(buffer);
StringBuilder builder = new StringBuilder(64);
format(builder, ":IGNORED:", "", ignored);
println(builder);
}
}
}

View File

@ -149,6 +149,12 @@ public class StdErrLogTest
log.warn("ex", th);
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");
log.warn("ex", th);