View Javadoc
1   /**
2    * Copyright (c) 2004-2022 QOS.ch
3    * All rights reserved.
4    *
5    * Permission is hereby granted, free  of charge, to any person obtaining
6    * a  copy  of this  software  and  associated  documentation files  (the
7    * "Software"), to  deal in  the Software without  restriction, including
8    * without limitation  the rights to  use, copy, modify,  merge, publish,
9    * distribute,  sublicense, and/or sell  copies of  the Software,  and to
10   * permit persons to whom the Software  is furnished to do so, subject to
11   * the following conditions:
12   *
13   * The  above  copyright  notice  and  this permission  notice  shall  be
14   * included in all copies or substantial portions of the Software.
15   *
16   * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
17   * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
18   * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
19   * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20   * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21   * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
22   * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23   *
24   */
25  package org.slf4j.spi;
26  
27  import java.util.function.Supplier;
28  
29  import org.slf4j.Logger;
30  import org.slf4j.Marker;
31  import org.slf4j.event.DefaultLoggingEvent;
32  import org.slf4j.event.KeyValuePair;
33  import org.slf4j.event.Level;
34  import org.slf4j.event.LoggingEvent;
35  
36  /**
37   * Default implementation of {@link LoggingEventBuilder}
38   */
39  public class DefaultLoggingEventBuilder implements LoggingEventBuilder, CallerBoundaryAware {
40  
41      
42      // The caller boundary when the log() methods are invoked, is this class itself.
43      
44      static String DLEB_FQCN = DefaultLoggingEventBuilder.class.getName();
45      
46      protected DefaultLoggingEvent loggingEvent;
47      protected Logger logger;
48  
49      public DefaultLoggingEventBuilder(Logger logger, Level level) {
50          this.logger = logger;
51          loggingEvent = new DefaultLoggingEvent(level, logger);
52      }
53  
54      /**
55       * Add a marker to the current logging event being built.
56       * 
57       * It is possible to add multiple markers to the same logging event.
58       *
59       * @param marker the marker to add
60       */
61      @Override
62      public LoggingEventBuilder addMarker(Marker marker) {
63          loggingEvent.addMarker(marker);
64          return this;
65      }
66  
67      @Override
68      public LoggingEventBuilder setCause(Throwable t) {
69          loggingEvent.setThrowable(t);
70          return this;
71      }
72  
73      @Override
74      public LoggingEventBuilder addArgument(Object p) {
75          loggingEvent.addArgument(p);
76          return this;
77      }
78  
79      @Override
80      public LoggingEventBuilder addArgument(Supplier<?> objectSupplier) {
81          loggingEvent.addArgument(objectSupplier.get());
82          return this;
83      }
84  
85      @Override
86      public void setCallerBoundary(String fqcn) {
87          loggingEvent.setCallerBoundary(fqcn);
88      }
89  
90      @Override
91      public void log() {
92          log(loggingEvent);
93      }
94  
95      @Override
96      public LoggingEventBuilder setMessage(String message) {
97          loggingEvent.setMessage(message);
98          return this;
99      }
100     @Override
101     public LoggingEventBuilder setMessage(Supplier<String> messageSupplier) {
102         loggingEvent.setMessage(messageSupplier.get());
103         return this;
104     }
105 
106     @Override
107     public void log(String message) {
108         loggingEvent.setMessage(message);
109         log(loggingEvent);
110     }
111 
112     @Override
113     public void log(String message, Object arg) {
114         loggingEvent.setMessage(message);
115         loggingEvent.addArgument(arg);
116         log(loggingEvent);
117     }
118 
119     @Override
120     public void log(String message, Object arg0, Object arg1) {
121         loggingEvent.setMessage(message);
122         loggingEvent.addArgument(arg0);
123         loggingEvent.addArgument(arg1);
124         log(loggingEvent);
125     }
126 
127     @Override
128     public void log(String message, Object... args) {
129         loggingEvent.setMessage(message);
130         loggingEvent.addArguments(args);
131 
132         log(loggingEvent);
133     }
134 
135     @Override
136     public void log(Supplier<String> messageSupplier) {
137         if (messageSupplier == null) {
138             log((String) null);
139         } else {
140             log(messageSupplier.get());
141         }
142     }
143     
144     protected void log(LoggingEvent aLoggingEvent) {
145         setCallerBoundary(DLEB_FQCN);
146         if (logger instanceof LoggingEventAware) {
147             ((LoggingEventAware) logger).log(aLoggingEvent);
148         } else {
149             logViaPublicSLF4JLoggerAPI(aLoggingEvent);
150         }
151     }
152 
153     private void logViaPublicSLF4JLoggerAPI(LoggingEvent aLoggingEvent) {
154         Object[] argArray = aLoggingEvent.getArgumentArray();
155         int argLen = argArray == null ? 0 : argArray.length;
156 
157         Throwable t = aLoggingEvent.getThrowable();
158         int tLen = t == null ? 0 : 1;
159 
160         String msg = aLoggingEvent.getMessage();
161 
162         Object[] combinedArguments = new Object[argLen + tLen];
163 
164         if (argArray != null) {
165             System.arraycopy(argArray, 0, combinedArguments, 0, argLen);
166         }
167         if (t != null) {
168             combinedArguments[argLen] = t;
169         }
170 
171         msg = mergeMarkersAndKeyValuePairs(aLoggingEvent, msg);
172 
173         switch (aLoggingEvent.getLevel()) {
174         case TRACE:
175             logger.trace(msg, combinedArguments);
176             break;
177         case DEBUG:
178             logger.debug(msg, combinedArguments);
179             break;
180         case INFO:
181             logger.info(msg, combinedArguments);
182             break;
183         case WARN:
184             logger.warn(msg, combinedArguments);
185             break;
186         case ERROR:
187             logger.error(msg, combinedArguments);
188             break;
189         }
190 
191     }
192 
193     /**
194      * Prepend markers and key-value pairs to the message.
195      * 
196      * @param aLoggingEvent
197      * @param msg
198      * @return
199      */
200     private String mergeMarkersAndKeyValuePairs(LoggingEvent aLoggingEvent, String msg) {
201 
202         StringBuilder sb = null;
203 
204         if (aLoggingEvent.getMarkers() != null) {
205             sb = new StringBuilder();
206             for (Marker marker : aLoggingEvent.getMarkers()) {
207                 sb.append(marker);
208                 sb.append(' ');
209             }
210         }
211 
212         if (aLoggingEvent.getKeyValuePairs() != null) {
213             if (sb == null) {
214                 sb = new StringBuilder();
215             }
216             for (KeyValuePair kvp : aLoggingEvent.getKeyValuePairs()) {
217                 sb.append(kvp.key);
218                 sb.append('=');
219                 sb.append(kvp.value);
220                 sb.append(' ');
221             }
222         }
223 
224         if (sb != null) {
225             sb.append(msg);
226             return sb.toString();
227         } else {
228             return msg;
229         }
230     }
231 
232 
233 
234     @Override
235     public LoggingEventBuilder addKeyValue(String key, Object value) {
236         loggingEvent.addKeyValue(key, value);
237         return this;
238     }
239 
240     @Override
241     public LoggingEventBuilder addKeyValue(String key, Supplier<Object> value) {
242         loggingEvent.addKeyValue(key, value.get());
243         return this;
244     }
245 
246 }