001/** 002 * Copyright (c) 2004-2022 QOS.ch 003 * All rights reserved. 004 * 005 * Permission is hereby granted, free of charge, to any person obtaining 006 * a copy of this software and associated documentation files (the 007 * "Software"), to deal in the Software without restriction, including 008 * without limitation the rights to use, copy, modify, merge, publish, 009 * distribute, sublicense, and/or sell copies of the Software, and to 010 * permit persons to whom the Software is furnished to do so, subject to 011 * the following conditions: 012 * 013 * The above copyright notice and this permission notice shall be 014 * included in all copies or substantial portions of the Software. 015 * 016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 017 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 018 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 019 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 020 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 021 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 022 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 023 * 024 */ 025package org.slf4j.spi; 026 027import java.util.function.Supplier; 028 029import org.slf4j.Logger; 030import org.slf4j.Marker; 031import org.slf4j.event.DefaultLoggingEvent; 032import org.slf4j.event.KeyValuePair; 033import org.slf4j.event.Level; 034import org.slf4j.event.LoggingEvent; 035 036/** 037 * Default implementation of {@link LoggingEventBuilder}. 038 * 039 * <p>It is assumed that when </p> 040 * 041 * @since 2.0.0 042 */ 043public class DefaultLoggingEventBuilder implements LoggingEventBuilder, CallerBoundaryAware { 044 045 046 // The caller boundary when the log() methods are invoked, is this class itself. 047 048 static String DLEB_FQCN = DefaultLoggingEventBuilder.class.getName(); 049 050 protected DefaultLoggingEvent loggingEvent; 051 protected Logger logger; 052 053 public DefaultLoggingEventBuilder(Logger logger, Level level) { 054 this.logger = logger; 055 loggingEvent = new DefaultLoggingEvent(level, logger); 056 } 057 058 /** 059 * Add a marker to the current logging event being built. 060 * 061 * It is possible to add multiple markers to the same logging event. 062 * 063 * @param marker the marker to add 064 */ 065 @Override 066 public LoggingEventBuilder addMarker(Marker marker) { 067 loggingEvent.addMarker(marker); 068 return this; 069 } 070 071 @Override 072 public LoggingEventBuilder setCause(Throwable t) { 073 loggingEvent.setThrowable(t); 074 return this; 075 } 076 077 @Override 078 public LoggingEventBuilder addArgument(Object p) { 079 loggingEvent.addArgument(p); 080 return this; 081 } 082 083 084 @Override 085 public LoggingEventBuilder addArgument(Supplier<?> objectSupplier) { 086 loggingEvent.addArgument(objectSupplier.get()); 087 return this; 088 } 089 090 @Override 091 public void setCallerBoundary(String fqcn) { 092 loggingEvent.setCallerBoundary(fqcn); 093 } 094 095 @Override 096 public void log() { 097 log(loggingEvent); 098 } 099 100 @Override 101 public LoggingEventBuilder setMessage(String message) { 102 loggingEvent.setMessage(message); 103 return this; 104 } 105 @Override 106 public LoggingEventBuilder setMessage(Supplier<String> messageSupplier) { 107 loggingEvent.setMessage(messageSupplier.get()); 108 return this; 109 } 110 111 @Override 112 public void log(String message) { 113 loggingEvent.setMessage(message); 114 log(loggingEvent); 115 } 116 117 @Override 118 public void log(String message, Object arg) { 119 loggingEvent.setMessage(message); 120 loggingEvent.addArgument(arg); 121 log(loggingEvent); 122 } 123 124 @Override 125 public void log(String message, Object arg0, Object arg1) { 126 loggingEvent.setMessage(message); 127 loggingEvent.addArgument(arg0); 128 loggingEvent.addArgument(arg1); 129 log(loggingEvent); 130 } 131 132 @Override 133 public void log(String message, Object... args) { 134 loggingEvent.setMessage(message); 135 loggingEvent.addArguments(args); 136 137 log(loggingEvent); 138 } 139 140 @Override 141 public void log(Supplier<String> messageSupplier) { 142 if (messageSupplier == null) { 143 log((String) null); 144 } else { 145 log(messageSupplier.get()); 146 } 147 } 148 149 protected void log(LoggingEvent aLoggingEvent) { 150 setCallerBoundary(DLEB_FQCN); 151 if (logger instanceof LoggingEventAware) { 152 ((LoggingEventAware) logger).log(aLoggingEvent); 153 } else { 154 logViaPublicSLF4JLoggerAPI(aLoggingEvent); 155 } 156 } 157 158 private void logViaPublicSLF4JLoggerAPI(LoggingEvent aLoggingEvent) { 159 Object[] argArray = aLoggingEvent.getArgumentArray(); 160 int argLen = argArray == null ? 0 : argArray.length; 161 162 Throwable t = aLoggingEvent.getThrowable(); 163 int tLen = t == null ? 0 : 1; 164 165 String msg = aLoggingEvent.getMessage(); 166 167 Object[] combinedArguments = new Object[argLen + tLen]; 168 169 if (argArray != null) { 170 System.arraycopy(argArray, 0, combinedArguments, 0, argLen); 171 } 172 if (t != null) { 173 combinedArguments[argLen] = t; 174 } 175 176 msg = mergeMarkersAndKeyValuePairs(aLoggingEvent, msg); 177 178 switch (aLoggingEvent.getLevel()) { 179 case TRACE: 180 logger.trace(msg, combinedArguments); 181 break; 182 case DEBUG: 183 logger.debug(msg, combinedArguments); 184 break; 185 case INFO: 186 logger.info(msg, combinedArguments); 187 break; 188 case WARN: 189 logger.warn(msg, combinedArguments); 190 break; 191 case ERROR: 192 logger.error(msg, combinedArguments); 193 break; 194 } 195 196 } 197 198 /** 199 * Prepend markers and key-value pairs to the message. 200 * 201 * @param aLoggingEvent 202 * @param msg 203 * @return 204 */ 205 private String mergeMarkersAndKeyValuePairs(LoggingEvent aLoggingEvent, String msg) { 206 207 StringBuilder sb = null; 208 209 if (aLoggingEvent.getMarkers() != null) { 210 sb = new StringBuilder(); 211 for (Marker marker : aLoggingEvent.getMarkers()) { 212 sb.append(marker); 213 sb.append(' '); 214 } 215 } 216 217 if (aLoggingEvent.getKeyValuePairs() != null) { 218 if (sb == null) { 219 sb = new StringBuilder(); 220 } 221 for (KeyValuePair kvp : aLoggingEvent.getKeyValuePairs()) { 222 sb.append(kvp.key); 223 sb.append('='); 224 sb.append(kvp.value); 225 sb.append(' '); 226 } 227 } 228 229 if (sb != null) { 230 sb.append(msg); 231 return sb.toString(); 232 } else { 233 return msg; 234 } 235 } 236 237 238 239 @Override 240 public LoggingEventBuilder addKeyValue(String key, Object value) { 241 loggingEvent.addKeyValue(key, value); 242 return this; 243 } 244 245 @Override 246 public LoggingEventBuilder addKeyValue(String key, Supplier<Object> value) { 247 loggingEvent.addKeyValue(key, value.get()); 248 return this; 249 } 250 251}