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 */ 017 package org.apache.logging.log4j.core.async; 018 019 import java.util.HashMap; 020 import java.util.Map; 021 022 import org.apache.logging.log4j.Level; 023 import org.apache.logging.log4j.Marker; 024 import org.apache.logging.log4j.ThreadContext.ContextStack; 025 import org.apache.logging.log4j.core.LogEvent; 026 import org.apache.logging.log4j.core.config.Property; 027 import org.apache.logging.log4j.core.lookup.StrSubstitutor; 028 import org.apache.logging.log4j.message.Message; 029 import org.apache.logging.log4j.message.SimpleMessage; 030 031 import com.lmax.disruptor.EventFactory; 032 033 /** 034 * When the Disruptor is started, the RingBuffer is populated with event 035 * objects. These objects are then re-used during the life of the RingBuffer. 036 */ 037 public class RingBufferLogEvent implements LogEvent { 038 private static final long serialVersionUID = 8462119088943934758L; 039 040 /** 041 * Creates the events that will be put in the RingBuffer. 042 */ 043 private static class Factory implements EventFactory<RingBufferLogEvent> { 044 // @Override 045 @Override 046 public RingBufferLogEvent newInstance() { 047 return new RingBufferLogEvent(); 048 } 049 } 050 051 /** The {@code EventFactory} for {@code RingBufferLogEvent}s. */ 052 public static final Factory FACTORY = new Factory(); 053 054 private AsyncLogger asyncLogger; 055 private String loggerName; 056 private Marker marker; 057 private String fqcn; 058 private Level level; 059 private Message message; 060 private Throwable thrown; 061 private Map<String, String> contextMap; 062 private ContextStack contextStack; 063 private String threadName; 064 private StackTraceElement location; 065 private long currentTimeMillis; 066 private boolean endOfBatch; 067 private boolean includeLocation; 068 069 public void setValues(AsyncLogger asyncLogger, String loggerName, 070 Marker marker, String fqcn, Level level, Message data, Throwable t, 071 Map<String, String> map, ContextStack contextStack, 072 String threadName, StackTraceElement location, 073 long currentTimeMillis) { 074 this.asyncLogger = asyncLogger; 075 this.loggerName = loggerName; 076 this.marker = marker; 077 this.fqcn = fqcn; 078 this.level = level; 079 this.message = data; 080 this.thrown = t; 081 this.contextMap = map; 082 this.contextStack = contextStack; 083 this.threadName = threadName; 084 this.location = location; 085 this.currentTimeMillis = currentTimeMillis; 086 } 087 088 /** 089 * Event processor that reads the event from the ringbuffer can call this 090 * method. 091 * 092 * @param endOfBatch flag to indicate if this is the last event in a batch 093 * from the RingBuffer 094 */ 095 public void execute(boolean endOfBatch) { 096 this.endOfBatch = endOfBatch; 097 asyncLogger.actualAsyncLog(this); 098 } 099 100 /** 101 * Returns {@code true} if this event is the end of a batch, {@code false} 102 * otherwise. 103 * 104 * @return {@code true} if this event is the end of a batch, {@code false} 105 * otherwise 106 */ 107 @Override 108 public boolean isEndOfBatch() { 109 return endOfBatch; 110 } 111 112 @Override 113 public void setEndOfBatch(boolean endOfBatch) { 114 this.endOfBatch = endOfBatch; 115 } 116 117 @Override 118 public boolean isIncludeLocation() { 119 return includeLocation; 120 } 121 122 @Override 123 public void setIncludeLocation(boolean includeLocation) { 124 this.includeLocation = includeLocation; 125 } 126 127 // @Override 128 @Override 129 public String getLoggerName() { 130 return loggerName; 131 } 132 133 // @Override 134 @Override 135 public Marker getMarker() { 136 return marker; 137 } 138 139 // @Override 140 @Override 141 public String getFQCN() { 142 return fqcn; 143 } 144 145 // @Override 146 @Override 147 public Level getLevel() { 148 return level; 149 } 150 151 // @Override 152 @Override 153 public Message getMessage() { 154 if (message == null) { 155 message = new SimpleMessage(""); 156 } 157 return message; 158 } 159 160 // @Override 161 @Override 162 public Throwable getThrown() { 163 return thrown; 164 } 165 166 // @Override 167 @Override 168 public Map<String, String> getContextMap() { 169 return contextMap; 170 } 171 172 // @Override 173 @Override 174 public ContextStack getContextStack() { 175 return contextStack; 176 } 177 178 // @Override 179 @Override 180 public String getThreadName() { 181 return threadName; 182 } 183 184 // @Override 185 @Override 186 public StackTraceElement getSource() { 187 return location; 188 } 189 190 // @Override 191 @Override 192 public long getMillis() { 193 return currentTimeMillis; 194 } 195 196 /** 197 * Merges the contents of the specified map into the contextMap, after 198 * replacing any variables in the property values with the 199 * StrSubstitutor-supplied actual values. 200 * 201 * @param properties configured properties 202 * @param strSubstitutor used to lookup values of variables in properties 203 */ 204 public void mergePropertiesIntoContextMap( 205 Map<Property, Boolean> properties, StrSubstitutor strSubstitutor) { 206 if (properties == null) { 207 return; // nothing to do 208 } 209 210 Map<String, String> map = (contextMap == null) ? new HashMap<String, String>() 211 : new HashMap<String, String>(contextMap); 212 213 for (Map.Entry<Property, Boolean> entry : properties.entrySet()) { 214 Property prop = entry.getKey(); 215 if (map.containsKey(prop.getName())) { 216 continue; // contextMap overrides config properties 217 } 218 String value = entry.getValue() ? strSubstitutor.replace(prop 219 .getValue()) : prop.getValue(); 220 map.put(prop.getName(), value); 221 } 222 contextMap = map; 223 } 224 }