2424 */
2525package org .slf4j .jul ;
2626
27+ import java .util .List ;
2728import java .util .logging .Level ;
2829import java .util .logging .LogRecord ;
2930
3031import org .slf4j .Logger ;
3132import org .slf4j .Marker ;
3233import org .slf4j .event .EventConstants ;
34+ import org .slf4j .event .KeyValuePair ;
3335import org .slf4j .event .LoggingEvent ;
3436import org .slf4j .helpers .AbstractLogger ;
3537import org .slf4j .helpers .FormattingTuple ;
3638import org .slf4j .helpers .LegacyAbstractLogger ;
3739import org .slf4j .helpers .MessageFormatter ;
3840import org .slf4j .helpers .NormalizedParameters ;
39- import org .slf4j .helpers .SubstituteLogger ;
40- import org .slf4j .spi .DefaultLoggingEventBuilder ;
4141import org .slf4j .spi .LocationAwareLogger ;
42+ import org .slf4j .spi .LoggingEventAware ;
4243
4344/**
4445 * A wrapper over {@link java.util.logging.Logger java.util.logging.Logger} in
4950 * @author Ceki Gülcü
5051 * @author Peter Royal
5152 */
52- public final class JDK14LoggerAdapter extends LegacyAbstractLogger implements LocationAwareLogger {
53+ public final class JDK14LoggerAdapter extends LegacyAbstractLogger implements LocationAwareLogger , LoggingEventAware {
5354
5455 private static final long serialVersionUID = -8053026990503422791L ;
5556
@@ -139,7 +140,8 @@ public boolean isErrorEnabled() {
139140 */
140141 @ Override
141142 protected void handleNormalizedLoggingCall (org .slf4j .event .Level level , Marker marker , String msg , Object [] args , Throwable throwable ) {
142- innerNormalizedLoggingCallHandler (getFullyQualifiedCallerName (), level , marker , msg , args , throwable );
143+ // AbstractLogger is the entry point of all classic API calls
144+ innerNormalizedLoggingCallHandler (SUPER_OF_SUPER , level , marker , msg , args , throwable );
143145 }
144146
145147 private void innerNormalizedLoggingCallHandler (String fqcn , org .slf4j .event .Level level , Marker marker , String msg , Object [] args , Throwable throwable ) {
@@ -180,13 +182,28 @@ public void log(Marker marker, String callerFQCN, int slf4jLevelInt, String mess
180182 *
181183 * @param record The record to update
182184 */
183- final private void fillCallerData (String callerFQCN , LogRecord record ) {
185+ private void fillCallerData (String callerFQCN , LogRecord record ) {
184186 StackTraceElement [] steArray = new Throwable ().getStackTrace ();
187+ // Find the first stack trace element matching the caller boundary
188+ int selfIndex = NOT_FOUND ;
189+ for (int i = 0 ; i < steArray .length ; i ++) {
190+ final String className = steArray [i ].getClassName ();
191+ if (className .equals (callerFQCN )) {
192+ selfIndex = i ;
193+ break ;
194+ }
195+ }
196+ // Find the first stack trace element after the caller boundary
197+ int found = NOT_FOUND ;
198+ for (int i = selfIndex + 1 ; i < steArray .length ; i ++) {
199+ final String className = steArray [i ].getClassName ();
200+ if (!(className .equals (callerFQCN ))) {
201+ found = i ;
202+ break ;
203+ }
204+ }
185205
186- int furthestIndex = findFurthestIndex (callerFQCN , steArray );
187-
188- if (furthestIndex != NOT_FOUND ) {
189- int found = furthestIndex +1 ;
206+ if (found != NOT_FOUND ) {
190207 StackTraceElement ste = steArray [found ];
191208 // setting the class name has the side effect of setting
192209 // the needToInferCaller variable to false.
@@ -195,42 +212,9 @@ final private void fillCallerData(String callerFQCN, LogRecord record) {
195212 }
196213 }
197214
198- // find the furthest index which matches any of the barrier classes
199- // We assume that the actual caller is at most MAX_SEARCH_DEPTH calls away
200- private int findFurthestIndex (String callerFQCN , StackTraceElement [] steArray ) {
201-
202- final int maxIndex = Math .min (MAX_SEARCH_DEPTH , steArray .length );
203- int furthestIndex = NOT_FOUND ;
204-
205- for (int i = 0 ; i < maxIndex ; i ++) {
206- final String className = steArray [i ].getClassName ();
207- if (barrierMatch (callerFQCN , className )) {
208- furthestIndex = i ;
209- }
210- }
211- return furthestIndex ;
212- }
213-
214- static final int MAX_SEARCH_DEPTH = 12 ;
215- static String SELF = JDK14LoggerAdapter .class .getName ();
215+ static String SELF = JDK14LoggerAdapter .class .getName ();
216216
217- static String SUPER = LegacyAbstractLogger .class .getName ();
218217 static String SUPER_OF_SUPER = AbstractLogger .class .getName ();
219- static String SUBSTITUE = SubstituteLogger .class .getName ();
220- static String FLUENT = DefaultLoggingEventBuilder .class .getName ();
221-
222- static String [] BARRIER_CLASSES = new String [] { SUPER_OF_SUPER , SUPER , SELF , SUBSTITUE , FLUENT };
223-
224- private boolean barrierMatch (String callerFQCN , String candidateClassName ) {
225- if (candidateClassName .equals (callerFQCN ))
226- return true ;
227- for (String barrierClassName : BARRIER_CLASSES ) {
228- if (barrierClassName .equals (candidateClassName )) {
229- return true ;
230- }
231- }
232- return false ;
233- }
234218
235219 private static Level slf4jLevelIntToJULLevel (int levelInt ) {
236220 org .slf4j .event .Level slf4jLevel = org .slf4j .event .Level .intToLevel (levelInt );
@@ -264,12 +248,15 @@ private static Level slf4jLevelToJULLevel(org.slf4j.event.Level slf4jLevel) {
264248 /**
265249 * @since 1.7.15
266250 */
251+ @ Override
267252 public void log (LoggingEvent event ) {
268253 // assumes that the invocation is made from a substitute logger
269254 // this assumption might change in the future with the advent of a fluent API
270255 Level julLevel = slf4jLevelToJULLevel (event .getLevel ());
271256 if (logger .isLoggable (julLevel )) {
272257 LogRecord record = eventToRecord (event , julLevel );
258+ String callerBoundary = event .getCallerBoundary ();
259+ fillCallerData (callerBoundary != null ? callerBoundary : SELF , record );
273260 logger .log (record );
274261 }
275262 }
@@ -279,16 +266,18 @@ private LogRecord eventToRecord(LoggingEvent event, Level julLevel) {
279266 Object [] arguments = event .getArgumentArray ();
280267 FormattingTuple ft = MessageFormatter .arrayFormat (format , arguments );
281268 if (ft .getThrowable () != null && event .getThrowable () != null ) {
282- throw new IllegalArgumentException ("both last element in argument array and last argument are of type Throwable" );
269+ throw new IllegalArgumentException (
270+ "both last element in argument array and last argument are of type Throwable" );
283271 }
284272
285273 Throwable t = event .getThrowable ();
286- if (ft .getThrowable () != null ) {
274+ if (t == null && ft .getThrowable () != null ) {
287275 t = ft .getThrowable ();
288- throw new IllegalStateException ("fix above code" );
289276 }
290277
291- LogRecord record = new LogRecord (julLevel , ft .getMessage ());
278+ LogRecord record = new LogRecord (
279+ julLevel ,
280+ prependMarkersAndKeyValuePairs (event .getMarkers (), event .getKeyValuePairs (), ft .getMessage ()));
292281 record .setLoggerName (event .getLoggerName ());
293282 record .setMillis (event .getTimeStamp ());
294283 record .setSourceClassName (EventConstants .NA_SUBST );
@@ -298,4 +287,31 @@ private LogRecord eventToRecord(LoggingEvent event, Level julLevel) {
298287 return record ;
299288 }
300289
290+ private String prependMarkersAndKeyValuePairs (
291+ List <Marker > markers , List <KeyValuePair > KeyValuePairs , String message ) {
292+ boolean hasMarkers = isNotEmpty (markers );
293+ boolean hasKeyValuePairs = isNotEmpty (KeyValuePairs );
294+ if (!hasMarkers && !hasKeyValuePairs ) {
295+ return message ;
296+ }
297+ StringBuilder sb = new StringBuilder (message .length ());
298+ if (hasMarkers ) {
299+ for (Marker marker : markers ) {
300+ sb .append (marker ).append (' ' );
301+ }
302+ }
303+ if (hasKeyValuePairs ) {
304+ for (KeyValuePair keyValuePair : KeyValuePairs ) {
305+ sb .append (keyValuePair .key )
306+ .append ('=' )
307+ .append (keyValuePair .value )
308+ .append (' ' );
309+ }
310+ }
311+ return sb .append (message ).toString ();
312+ }
313+
314+ private boolean isNotEmpty (List <?> list ) {
315+ return list != null && !list .isEmpty ();
316+ }
301317}
0 commit comments