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 DefaultLoggingEventBuilder(Logger logger, Level level)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 addMarker(Marker marker)62 public LoggingEventBuilder addMarker(Marker marker) { 63 loggingEvent.addMarker(marker); 64 return this; 65 } 66 67 @Override setCause(Throwable t)68 public LoggingEventBuilder setCause(Throwable t) { 69 loggingEvent.setThrowable(t); 70 return this; 71 } 72 73 @Override addArgument(Object p)74 public LoggingEventBuilder addArgument(Object p) { 75 loggingEvent.addArgument(p); 76 return this; 77 } 78 79 @Override addArgument(Supplier<?> objectSupplier)80 public LoggingEventBuilder addArgument(Supplier<?> objectSupplier) { 81 loggingEvent.addArgument(objectSupplier.get()); 82 return this; 83 } 84 85 @Override setCallerBoundary(String fqcn)86 public void setCallerBoundary(String fqcn) { 87 loggingEvent.setCallerBoundary(fqcn); 88 } 89 90 @Override log()91 public void log() { 92 log(loggingEvent); 93 } 94 95 @Override setMessage(String message)96 public LoggingEventBuilder setMessage(String message) { 97 loggingEvent.setMessage(message); 98 return this; 99 } 100 @Override setMessage(Supplier<String> messageSupplier)101 public LoggingEventBuilder setMessage(Supplier<String> messageSupplier) { 102 loggingEvent.setMessage(messageSupplier.get()); 103 return this; 104 } 105 106 @Override log(String message)107 public void log(String message) { 108 loggingEvent.setMessage(message); 109 log(loggingEvent); 110 } 111 112 @Override log(String message, Object arg)113 public void log(String message, Object arg) { 114 loggingEvent.setMessage(message); 115 loggingEvent.addArgument(arg); 116 log(loggingEvent); 117 } 118 119 @Override log(String message, Object arg0, Object arg1)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 log(String message, Object... args)128 public void log(String message, Object... args) { 129 loggingEvent.setMessage(message); 130 loggingEvent.addArguments(args); 131 132 log(loggingEvent); 133 } 134 135 @Override log(Supplier<String> messageSupplier)136 public void log(Supplier<String> messageSupplier) { 137 if (messageSupplier == null) { 138 log((String) null); 139 } else { 140 log(messageSupplier.get()); 141 } 142 } 143 log(LoggingEvent aLoggingEvent)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 logViaPublicSLF4JLoggerAPI(LoggingEvent aLoggingEvent)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 */ mergeMarkersAndKeyValuePairs(LoggingEvent aLoggingEvent, String msg)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 addKeyValue(String key, Object value)235 public LoggingEventBuilder addKeyValue(String key, Object value) { 236 loggingEvent.addKeyValue(key, value); 237 return this; 238 } 239 240 @Override addKeyValue(String key, Supplier<Object> value)241 public LoggingEventBuilder addKeyValue(String key, Supplier<Object> value) { 242 loggingEvent.addKeyValue(key, value.get()); 243 return this; 244 } 245 246 } 247