diff --git a/slf4j-api/src/main/java/org/slf4j/event/LoggingEvent.java b/slf4j-api/src/main/java/org/slf4j/event/LoggingEvent.java index 27bdf3e27..434b2d18b 100755 --- a/slf4j-api/src/main/java/org/slf4j/event/LoggingEvent.java +++ b/slf4j-api/src/main/java/org/slf4j/event/LoggingEvent.java @@ -23,6 +23,10 @@ public interface LoggingEvent { Object[] getArgumentArray(); + /** + * List of markers in the event, might be null. + * @return markers in the event, might be null. + */ List getMarkers(); List getKeyValuePairs(); diff --git a/slf4j-api/src/main/java/org/slf4j/spi/DefaultLoggingEventBuilder.java b/slf4j-api/src/main/java/org/slf4j/spi/DefaultLoggingEventBuilder.java index d2cd1cccd..548022f9c 100755 --- a/slf4j-api/src/main/java/org/slf4j/spi/DefaultLoggingEventBuilder.java +++ b/slf4j-api/src/main/java/org/slf4j/spi/DefaultLoggingEventBuilder.java @@ -1,7 +1,7 @@ /** * Copyright (c) 2004-2022 QOS.ch * All rights reserved. - * + *

* Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -9,10 +9,10 @@ * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: - * + *

* The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. - * + *

* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -20,10 +20,10 @@ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * */ package org.slf4j.spi; +import java.util.List; import java.util.function.Supplier; import org.slf4j.Logger; @@ -42,11 +42,11 @@ */ public class DefaultLoggingEventBuilder implements LoggingEventBuilder, CallerBoundaryAware { - + // The caller boundary when the log() methods are invoked, is this class itself. - + static String DLEB_FQCN = DefaultLoggingEventBuilder.class.getName(); - + protected DefaultLoggingEvent loggingEvent; protected Logger logger; @@ -57,7 +57,7 @@ public DefaultLoggingEventBuilder(Logger logger, Level level) { /** * Add a marker to the current logging event being built. - * + *

* It is possible to add multiple markers to the same logging event. * * @param marker the marker to add @@ -76,85 +76,112 @@ public LoggingEventBuilder setCause(Throwable t) { @Override public LoggingEventBuilder addArgument(Object p) { - loggingEvent.addArgument(p); + this.loggingEvent.addArgument(p); return this; } @Override public LoggingEventBuilder addArgument(Supplier objectSupplier) { - loggingEvent.addArgument(objectSupplier.get()); + this.loggingEvent.addArgument(objectSupplier.get()); + return this; + } + + @Override + public LoggingEventBuilder addKeyValue(String key, Object value) { + loggingEvent.addKeyValue(key, value); + return this; + } + + @Override + public LoggingEventBuilder addKeyValue(String key, Supplier value) { + loggingEvent.addKeyValue(key, value.get()); return this; } @Override public void setCallerBoundary(String fqcn) { - loggingEvent.setCallerBoundary(fqcn); + this.loggingEvent.setCallerBoundary(fqcn); } @Override public void log() { - log(loggingEvent); + log(this.loggingEvent); } @Override public LoggingEventBuilder setMessage(String message) { - loggingEvent.setMessage(message); + this.loggingEvent.setMessage(message); return this; } + @Override public LoggingEventBuilder setMessage(Supplier messageSupplier) { - loggingEvent.setMessage(messageSupplier.get()); + this.loggingEvent.setMessage(messageSupplier.get()); return this; } @Override public void log(String message) { - loggingEvent.setMessage(message); - log(loggingEvent); + this.loggingEvent.setMessage(message); + log(this.loggingEvent); } @Override public void log(String message, Object arg) { - loggingEvent.setMessage(message); - loggingEvent.addArgument(arg); - log(loggingEvent); + this.loggingEvent.setMessage(message); + this.loggingEvent.addArgument(arg); + log(this.loggingEvent); } @Override public void log(String message, Object arg0, Object arg1) { - loggingEvent.setMessage(message); - loggingEvent.addArgument(arg0); - loggingEvent.addArgument(arg1); - log(loggingEvent); + this.loggingEvent.setMessage(message); + this.loggingEvent.addArgument(arg0); + this.loggingEvent.addArgument(arg1); + log(this.loggingEvent); } @Override public void log(String message, Object... args) { - loggingEvent.setMessage(message); - loggingEvent.addArguments(args); + this.loggingEvent.setMessage(message); + this.loggingEvent.addArguments(args); - log(loggingEvent); + log(this.loggingEvent); } @Override public void log(Supplier messageSupplier) { - if (messageSupplier == null) { + if(messageSupplier == null) { log((String) null); } else { log(messageSupplier.get()); } } - + protected void log(LoggingEvent aLoggingEvent) { - setCallerBoundary(DLEB_FQCN); - if (logger instanceof LoggingEventAware) { + if(aLoggingEvent.getCallerBoundary() == null) { + setCallerBoundary(DLEB_FQCN); + } + + if(logger instanceof LoggingEventAware) { ((LoggingEventAware) logger).log(aLoggingEvent); + } else if(logger instanceof LocationAwareLogger) { + logViaLocationAwareLoggerAPI((LocationAwareLogger) logger, aLoggingEvent); } else { logViaPublicSLF4JLoggerAPI(aLoggingEvent); } } + private void logViaLocationAwareLoggerAPI(LocationAwareLogger locationAwareLogger, LoggingEvent aLoggingEvent) { + String msg = aLoggingEvent.getMessage(); + List markerList = aLoggingEvent.getMarkers(); + String mergedMessage = mergeMarkersAndKeyValuePairsAndMessage(aLoggingEvent); + locationAwareLogger.log(null, aLoggingEvent.getCallerBoundary(), aLoggingEvent.getLevel().toInt(), + mergedMessage, + aLoggingEvent.getArgumentArray(), aLoggingEvent.getThrowable()); + } + private void logViaPublicSLF4JLoggerAPI(LoggingEvent aLoggingEvent) { Object[] argArray = aLoggingEvent.getArgumentArray(); int argLen = argArray == null ? 0 : argArray.length; @@ -162,71 +189,84 @@ private void logViaPublicSLF4JLoggerAPI(LoggingEvent aLoggingEvent) { Throwable t = aLoggingEvent.getThrowable(); int tLen = t == null ? 0 : 1; - String msg = aLoggingEvent.getMessage(); - Object[] combinedArguments = new Object[argLen + tLen]; - if (argArray != null) { + if(argArray != null) { System.arraycopy(argArray, 0, combinedArguments, 0, argLen); } - if (t != null) { + if(t != null) { combinedArguments[argLen] = t; } - msg = mergeMarkersAndKeyValuePairs(aLoggingEvent, msg); - - switch (aLoggingEvent.getLevel()) { - case TRACE: - logger.trace(msg, combinedArguments); - break; - case DEBUG: - logger.debug(msg, combinedArguments); - break; - case INFO: - logger.info(msg, combinedArguments); - break; - case WARN: - logger.warn(msg, combinedArguments); - break; - case ERROR: - logger.error(msg, combinedArguments); - break; + String mergedMessage = mergeMarkersAndKeyValuePairsAndMessage(aLoggingEvent); + + + switch(aLoggingEvent.getLevel()) { + case TRACE: + logger.trace(mergedMessage, combinedArguments); + break; + case DEBUG: + logger.debug(mergedMessage, combinedArguments); + break; + case INFO: + logger.info(mergedMessage, combinedArguments); + break; + case WARN: + logger.warn(mergedMessage, combinedArguments); + break; + case ERROR: + logger.error(mergedMessage, combinedArguments); + break; } - } + /** * Prepend markers and key-value pairs to the message. - * + * * @param aLoggingEvent - * @param msg + * * @return */ - private String mergeMarkersAndKeyValuePairs(LoggingEvent aLoggingEvent, String msg) { + private String mergeMarkersAndKeyValuePairsAndMessage(LoggingEvent aLoggingEvent) { + StringBuilder sb = mergeMarkers(aLoggingEvent.getMarkers(), null); + sb = mergeKeyValuePairs(aLoggingEvent.getKeyValuePairs(), sb); + final String mergedMessage = mergeMessage(aLoggingEvent.getMessage(), sb); + return mergedMessage; + } - StringBuilder sb = null; + private StringBuilder mergeMarkers(List markerList, StringBuilder sb) { + if(markerList == null || markerList.isEmpty()) + return sb; - if (aLoggingEvent.getMarkers() != null) { + if(sb == null) sb = new StringBuilder(); - for (Marker marker : aLoggingEvent.getMarkers()) { - sb.append(marker); - sb.append(' '); - } + + for(Marker marker : markerList) { + sb.append(marker); + sb.append(' '); } + return sb; + } + + private StringBuilder mergeKeyValuePairs(List keyValuePairList, StringBuilder sb) { + if(keyValuePairList == null || keyValuePairList.isEmpty()) + return sb; + + if(sb == null) + sb = new StringBuilder(); - if (aLoggingEvent.getKeyValuePairs() != null) { - if (sb == null) { - sb = new StringBuilder(); - } - for (KeyValuePair kvp : aLoggingEvent.getKeyValuePairs()) { - sb.append(kvp.key); - sb.append('='); - sb.append(kvp.value); - sb.append(' '); - } + for(KeyValuePair kvp : keyValuePairList) { + sb.append(kvp.key); + sb.append('='); + sb.append(kvp.value); + sb.append(' '); } + return sb; + } - if (sb != null) { + private String mergeMessage(String msg, StringBuilder sb) { + if(sb != null) { sb.append(msg); return sb.toString(); } else { @@ -236,16 +276,7 @@ private String mergeMarkersAndKeyValuePairs(LoggingEvent aLoggingEvent, String m - @Override - public LoggingEventBuilder addKeyValue(String key, Object value) { - loggingEvent.addKeyValue(key, value); - return this; - } - @Override - public LoggingEventBuilder addKeyValue(String key, Supplier value) { - loggingEvent.addKeyValue(key, value.get()); - return this; - } + } diff --git a/slf4j-jdk14/src/test/java/org/slf4j/issue/CallerInfoTest.java b/slf4j-jdk14/src/test/java/org/slf4j/issue/CallerInfoTest.java index 303ec31e5..82d873c5a 100755 --- a/slf4j-jdk14/src/test/java/org/slf4j/issue/CallerInfoTest.java +++ b/slf4j-jdk14/src/test/java/org/slf4j/issue/CallerInfoTest.java @@ -20,6 +20,8 @@ import org.slf4j.helpers.SubstituteServiceProvider; import org.slf4j.jul.JDK14LoggerAdapter; import org.slf4j.jul.ListHandler; +import org.slf4j.spi.CallerBoundaryAware; +import org.slf4j.spi.LoggingEventBuilder; public class CallerInfoTest { Level oldLevel; @@ -78,6 +80,22 @@ public void testCallerInfoWithFluentAPI() { assertEquals(this.getClass().getName(), logRecod.getSourceClassName()); } + @Test + public void testCallerInfoWithFluentAPIAndAWrapper() { + Logger logger = LoggerFactory.getLogger("bla"); + LoggingWrapper wrappedLogger = new LoggingWrapper(logger); + + wrappedLogger.logWithEvent("hello"); + + List recordList = listHandler.recordList; + + assertEquals(1, recordList.size()); + + LogRecord logRecod = recordList.get(0); + assertEquals(this.getClass().getName(), logRecod.getSourceClassName()); + } + + @Test public void testPostInitializationCallerInfoWithSubstituteLogger() { Logger logger = LoggerFactory.getLogger("bla"); @@ -121,4 +139,22 @@ public void testIntraInitializationCallerInfoWithSubstituteLogger() throws Inter assertEquals(EventConstants.NA_SUBST, logRecod.getSourceClassName()); } + static class LoggingWrapper { + + Logger underlyingLogger; + + LoggingWrapper(Logger aLogger) { + this.underlyingLogger = aLogger; + } + public void logWithEvent(String msg) { + LoggingEventBuilder lev = underlyingLogger.atInfo(); + // setting the caller boundary to LoggingWrapper + if(lev instanceof CallerBoundaryAware) { + // builder is CallerBoundaryAware + ((CallerBoundaryAware) lev).setCallerBoundary(LoggingWrapper.class.getName()); + } + lev.log(msg); + } + } + }