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 */ 039public class DefaultLoggingEventBuilder implements LoggingEventBuilder, CallerBoundaryAware { 040 041 042 // The caller boundary when the log() methods are invoked, is this class itself. 043 044 static String DLEB_FQCN = DefaultLoggingEventBuilder.class.getName(); 045 046 protected DefaultLoggingEvent loggingEvent; 047 protected Logger logger; 048 049 public DefaultLoggingEventBuilder(Logger logger, Level level) { 050 this.logger = logger; 051 loggingEvent = new DefaultLoggingEvent(level, logger); 052 } 053 054 /** 055 * Add a marker to the current logging event being built. 056 * 057 * It is possible to add multiple markers to the same logging event. 058 * 059 * @param marker the marker to add 060 */ 061 @Override 062 public LoggingEventBuilder addMarker(Marker marker) { 063 loggingEvent.addMarker(marker); 064 return this; 065 } 066 067 @Override 068 public LoggingEventBuilder setCause(Throwable t) { 069 loggingEvent.setThrowable(t); 070 return this; 071 } 072 073 @Override 074 public LoggingEventBuilder addArgument(Object p) { 075 loggingEvent.addArgument(p); 076 return this; 077 } 078 079 @Override 080 public LoggingEventBuilder addArgument(Supplier<?> objectSupplier) { 081 loggingEvent.addArgument(objectSupplier.get()); 082 return this; 083 } 084 085 @Override 086 public void setCallerBoundary(String fqcn) { 087 loggingEvent.setCallerBoundary(fqcn); 088 } 089 090 @Override 091 public void log() { 092 log(loggingEvent); 093 } 094 095 @Override 096 public LoggingEventBuilder setMessage(String message) { 097 loggingEvent.setMessage(message); 098 return this; 099 } 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}