View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.core.async;
18  
19  import java.util.HashMap;
20  import java.util.Map;
21  
22  import org.apache.logging.log4j.Level;
23  import org.apache.logging.log4j.Marker;
24  import org.apache.logging.log4j.ThreadContext.ContextStack;
25  import org.apache.logging.log4j.core.LogEvent;
26  import org.apache.logging.log4j.core.config.Property;
27  import org.apache.logging.log4j.core.lookup.StrSubstitutor;
28  import org.apache.logging.log4j.message.Message;
29  import org.apache.logging.log4j.message.SimpleMessage;
30  import org.apache.logging.log4j.message.TimestampMessage;
31  
32  import com.lmax.disruptor.EventFactory;
33  
34  /**
35   * When the Disruptor is started, the RingBuffer is populated with event
36   * objects. These objects are then re-used during the life of the RingBuffer.
37   */
38  public class RingBufferLogEvent implements LogEvent {
39      private static final long serialVersionUID = 8462119088943934758L;
40  
41      /**
42       * Creates the events that will be put in the RingBuffer.
43       */
44      private static class Factory implements EventFactory<RingBufferLogEvent> {
45      
46          @Override
47          public RingBufferLogEvent newInstance() {
48              return new RingBufferLogEvent();
49          }
50      }
51  
52      /** The {@code EventFactory} for {@code RingBufferLogEvent}s. */
53      public static final Factory FACTORY = new Factory();
54  
55      private AsyncLogger asyncLogger;
56      private String loggerName;
57      private Marker marker;
58      private String fqcn;
59      private Level level;
60      private Message message;
61      private Throwable thrown;
62      private Map<String, String> contextMap;
63      private ContextStack contextStack;
64      private String threadName;
65      private StackTraceElement location;
66      private long currentTimeMillis;
67      private boolean endOfBatch;
68      private boolean includeLocation;
69  
70      public void setValues(final AsyncLogger asyncLogger,
71              final String loggerName, final Marker marker, final String fqcn,
72              final Level level, final Message data, final Throwable t,
73              final Map<String, String> map, final ContextStack contextStack,
74              final String threadName, final StackTraceElement location,
75              final long currentTimeMillis) {
76          this.asyncLogger = asyncLogger;
77          this.loggerName = loggerName;
78          this.marker = marker;
79          this.fqcn = fqcn;
80          this.level = level;
81          this.message = data;
82          this.thrown = t;
83          this.contextMap = map;
84          this.contextStack = contextStack;
85          this.threadName = threadName;
86          this.location = location;
87          this.currentTimeMillis = currentTimeMillis;
88      }
89  
90      /**
91       * Event processor that reads the event from the ringbuffer can call this
92       * method.
93       *
94       * @param endOfBatch flag to indicate if this is the last event in a batch
95       *            from the RingBuffer
96       */
97      public void execute(final boolean endOfBatch) {
98          this.endOfBatch = endOfBatch;
99          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 }