001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017package org.apache.logging.log4j.core.async; 018 019import java.util.HashMap; 020import java.util.Map; 021 022import org.apache.logging.log4j.Level; 023import org.apache.logging.log4j.Marker; 024import org.apache.logging.log4j.ThreadContext.ContextStack; 025import org.apache.logging.log4j.core.LogEvent; 026import org.apache.logging.log4j.core.config.Property; 027import org.apache.logging.log4j.core.lookup.StrSubstitutor; 028import org.apache.logging.log4j.message.Message; 029import org.apache.logging.log4j.message.SimpleMessage; 030import org.apache.logging.log4j.message.TimestampMessage; 031 032import com.lmax.disruptor.EventFactory; 033 034/** 035 * When the Disruptor is started, the RingBuffer is populated with event 036 * objects. These objects are then re-used during the life of the RingBuffer. 037 */ 038public class RingBufferLogEvent implements LogEvent { 039 private static final long serialVersionUID = 8462119088943934758L; 040 041 /** 042 * Creates the events that will be put in the RingBuffer. 043 */ 044 private static class Factory implements EventFactory<RingBufferLogEvent> { 045 046 @Override 047 public RingBufferLogEvent newInstance() { 048 return new RingBufferLogEvent(); 049 } 050 } 051 052 /** The {@code EventFactory} for {@code RingBufferLogEvent}s. */ 053 public static final Factory FACTORY = new Factory(); 054 055 private AsyncLogger asyncLogger; 056 private String loggerName; 057 private Marker marker; 058 private String fqcn; 059 private Level level; 060 private Message message; 061 private Throwable thrown; 062 private Map<String, String> contextMap; 063 private ContextStack contextStack; 064 private String threadName; 065 private StackTraceElement location; 066 private long currentTimeMillis; 067 private boolean endOfBatch; 068 private boolean includeLocation; 069 070 public void setValues(final AsyncLogger asyncLogger, 071 final String loggerName, final Marker marker, final String fqcn, 072 final Level level, final Message data, final Throwable t, 073 final Map<String, String> map, final ContextStack contextStack, 074 final String threadName, final StackTraceElement location, 075 final long currentTimeMillis) { 076 this.asyncLogger = asyncLogger; 077 this.loggerName = loggerName; 078 this.marker = marker; 079 this.fqcn = fqcn; 080 this.level = level; 081 this.message = data; 082 this.thrown = t; 083 this.contextMap = map; 084 this.contextStack = contextStack; 085 this.threadName = threadName; 086 this.location = location; 087 this.currentTimeMillis = currentTimeMillis; 088 } 089 090 /** 091 * Event processor that reads the event from the ringbuffer can call this 092 * method. 093 * 094 * @param endOfBatch flag to indicate if this is the last event in a batch 095 * from the RingBuffer 096 */ 097 public void execute(final boolean endOfBatch) { 098 this.endOfBatch = endOfBatch; 099 asyncLogger.actualAsyncLog(this); 100 } 101 102 /** 103 * Returns {@code true} if this event is the end of a batch, {@code false} 104 * otherwise. 105 * 106 * @return {@code true} if this event is the end of a batch, {@code false} 107 * otherwise 108 */ 109 @Override 110 public boolean isEndOfBatch() { 111 return endOfBatch; 112 } 113 114 @Override 115 public void setEndOfBatch(final boolean endOfBatch) { 116 this.endOfBatch = endOfBatch; 117 } 118 119 @Override 120 public boolean isIncludeLocation() { 121 return includeLocation; 122 } 123 124 @Override 125 public void setIncludeLocation(final boolean includeLocation) { 126 this.includeLocation = includeLocation; 127 } 128 129 @Override 130 public String getLoggerName() { 131 return loggerName; 132 } 133 134 @Override 135 public Marker getMarker() { 136 return marker; 137 } 138 139 @Override 140 public String getFQCN() { 141 return fqcn; 142 } 143 144 @Override 145 public Level getLevel() { 146 if (level == null) { 147 level = Level.OFF; // LOG4J2-462, LOG4J2-465 148 } 149 return level; 150 } 151 152 @Override 153 public Message getMessage() { 154 if (message == null) { 155 message = new SimpleMessage(""); 156 } 157 return message; 158 } 159 160 @Override 161 public Throwable getThrown() { 162 return thrown; 163 } 164 165 @Override 166 public Map<String, String> getContextMap() { 167 return contextMap; 168 } 169 170 @Override 171 public ContextStack getContextStack() { 172 return contextStack; 173 } 174 175 @Override 176 public String getThreadName() { 177 return threadName; 178 } 179 180 @Override 181 public StackTraceElement getSource() { 182 return location; 183 } 184 185 @Override 186 public long getMillis() { 187 Message msg = getMessage(); 188 if (msg instanceof TimestampMessage) { // LOG4J2-455 189 return ((TimestampMessage) msg).getTimestamp(); 190 } 191 return currentTimeMillis; 192 } 193 194 /** 195 * Merges the contents of the specified map into the contextMap, after 196 * replacing any variables in the property values with the 197 * StrSubstitutor-supplied actual values. 198 * 199 * @param properties configured properties 200 * @param strSubstitutor used to lookup values of variables in properties 201 */ 202 public void mergePropertiesIntoContextMap( 203 final Map<Property, Boolean> properties, 204 final StrSubstitutor strSubstitutor) { 205 if (properties == null) { 206 return; // nothing to do 207 } 208 209 final Map<String, String> map = (contextMap == null) ? new HashMap<String, String>() 210 : new HashMap<String, String>(contextMap); 211 212 for (final Map.Entry<Property, Boolean> entry : properties.entrySet()) { 213 final Property prop = entry.getKey(); 214 if (map.containsKey(prop.getName())) { 215 continue; // contextMap overrides config properties 216 } 217 final String value = entry.getValue() ? strSubstitutor.replace(prop 218 .getValue()) : prop.getValue(); 219 map.put(prop.getName(), value); 220 } 221 contextMap = map; 222 } 223 224 /** 225 * Release references held by ring buffer to allow objects to be 226 * garbage-collected. 227 */ 228 public void clear() { 229 setValues(null, // asyncLogger 230 null, // loggerName 231 null, // marker 232 null, // fqcn 233 null, // level 234 null, // data 235 null, // t 236 null, // map 237 null, // contextStack 238 null, // threadName 239 null, // location 240 0 // currentTimeMillis 241 ); 242 } 243}