Details
-
Improvement
-
Resolution: Unresolved
-
Major
-
None
-
1.7.24
-
None
-
any
-
enhancement
Description
The SLF4JBridgeHandler is currently dropping some log record info while bridging to slf4j.
The reason for this is that java.util.logging logger names are different beasts than slf4j ones. While it is a very common convention that an slf4j logger name equals the class name it's responsible for, this isn't necessarily the case for java.util.logging.
That's why LogRecord contains sourceClassName and sourceMethodName fields that are populated by Logger.entering, Logger.exiting, Logger.throwing and the general logp/logrb methods.
That info is crucial to the point where the log records are relatively useless without it.
Example:
Logger.entering("SourceClass","sourceMethod") will result in an event that simply says ENTRY.
Furthermore, jul allows for custom Level instances with a name and an arbitrary intValue(). While losing those is way less critical since they are already mapped to slf4j levels in a reasonable way, I think it would still be worthwhile to keep that info around.
I'd suggest to add the following to SLF4JBridgeHandler:
private static final String LEVEL_MDC_KEY = "JUL-Level"; private static final String LEVEL_VALUE_MDC_KEY = "JUL-Level-Value"; private static final String SOURCE_CLASS_NAME_MDC_KEY = "JUL-SourceClassName"; private static final String SOURCE_METHOD_NAME_MDC_KEY = "JUL-SourceMethodName"; private static void initMDC(LogRecord record) { Level julLevel = record.getLevel(); MDC.put(LEVEL_MDC_KEY, julLevel.getName()); MDC.put(LEVEL_VALUE_MDC_KEY, Integer.toString(julLevel.intValue())); String sourceClassName = record.getSourceClassName(); if(sourceClassName != null) { MDC.put(SOURCE_CLASS_NAME_MDC_KEY, sourceClassName); } String sourceMethodName = record.getSourceMethodName(); if(sourceMethodName != null) { MDC.put(SOURCE_METHOD_NAME_MDC_KEY, sourceMethodName); } } private static void clearMDC() { MDC.remove(LEVEL_MDC_KEY); MDC.remove(LEVEL_VALUE_MDC_KEY); MDC.remove(SOURCE_CLASS_NAME_MDC_KEY); MDC.remove(SOURCE_METHOD_NAME_MDC_KEY); }
Those methods would then be used in publish(LogRecord record):
initMDC(record); try { if (slf4jLogger instanceof LocationAwareLogger) { callLocationAwareLogger((LocationAwareLogger) slf4jLogger, record); } else { callPlainSLF4JLogger(slf4jLogger, record); } } finally { clearMDC(); }