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  
31  import com.lmax.disruptor.EventFactory;
32  
33  /**
34   * When the Disruptor is started, the RingBuffer is populated with event
35   * objects. These objects are then re-used during the life of the RingBuffer.
36   */
37  public class RingBufferLogEvent implements LogEvent {
38      private static final long serialVersionUID = 8462119088943934758L;
39  
40      /**
41       * Creates the events that will be put in the RingBuffer.
42       */
43      private static class Factory implements EventFactory<RingBufferLogEvent> {
44          // @Override
45          @Override
46          public RingBufferLogEvent newInstance() {
47              return new RingBufferLogEvent();
48          }
49      }
50  
51      /** The {@code EventFactory} for {@code RingBufferLogEvent}s. */
52      public static final Factory FACTORY = new Factory();
53  
54      private AsyncLogger asyncLogger;
55      private String loggerName;
56      private Marker marker;
57      private String fqcn;
58      private Level level;
59      private Message message;
60      private Throwable thrown;
61      private Map<String, String> contextMap;
62      private ContextStack contextStack;
63      private String threadName;
64      private StackTraceElement location;
65      private long currentTimeMillis;
66      private boolean endOfBatch;
67      private boolean includeLocation;
68  
69      public void setValues(final AsyncLogger asyncLogger,
70              final String loggerName, final Marker marker, final String fqcn,
71              final Level level, final Message data, final Throwable t,
72              final Map<String, String> map, final ContextStack contextStack,
73              final String threadName, final StackTraceElement location,
74              final long currentTimeMillis) {
75          this.asyncLogger = asyncLogger;
76          this.loggerName = loggerName;
77          this.marker = marker;
78          this.fqcn = fqcn;
79          this.level = level;
80          this.message = data;
81          this.thrown = t;
82          this.contextMap = map;
83          this.contextStack = contextStack;
84          this.threadName = threadName;
85          this.location = location;
86          this.currentTimeMillis = currentTimeMillis;
87      }
88  
89      /**
90       * Event processor that reads the event from the ringbuffer can call this
91       * method.
92       *
93       * @param endOfBatch flag to indicate if this is the last event in a batch
94       *            from the RingBuffer
95       */
96      public void execute(final boolean endOfBatch) {
97          this.endOfBatch = endOfBatch;
98          asyncLogger.actualAsyncLog(this);
99      }
100 
101     /**
102      * Returns {@code true} if this event is the end of a batch, {@code false}
103      * otherwise.
104      *
105      * @return {@code true} if this event is the end of a batch, {@code false}
106      *         otherwise
107      */
108     @Override
109     public boolean isEndOfBatch() {
110         return endOfBatch;
111     }
112 
113     @Override
114     public void setEndOfBatch(final boolean endOfBatch) {
115         this.endOfBatch = endOfBatch;
116     }
117 
118     @Override
119     public boolean isIncludeLocation() {
120         return includeLocation;
121     }
122 
123     @Override
124     public void setIncludeLocation(final boolean includeLocation) {
125         this.includeLocation = includeLocation;
126     }
127 
128     @Override
129     public String getLoggerName() {
130         return loggerName;
131     }
132 
133     @Override
134     public Marker getMarker() {
135         return marker;
136     }
137 
138     @Override
139     public String getFQCN() {
140         return fqcn;
141     }
142 
143     @Override
144     public Level getLevel() {
145         return level;
146     }
147 
148     @Override
149     public Message getMessage() {
150         if (message == null) {
151             message = new SimpleMessage("");
152         }
153         return message;
154     }
155 
156     @Override
157     public Throwable getThrown() {
158         return thrown;
159     }
160 
161     @Override
162     public Map<String, String> getContextMap() {
163         return contextMap;
164     }
165 
166     @Override
167     public ContextStack getContextStack() {
168         return contextStack;
169     }
170 
171     @Override
172     public String getThreadName() {
173         return threadName;
174     }
175 
176     @Override
177     public StackTraceElement getSource() {
178         return location;
179     }
180 
181     @Override
182     public long getMillis() {
183         return currentTimeMillis;
184     }
185 
186     /**
187      * Merges the contents of the specified map into the contextMap, after
188      * replacing any variables in the property values with the
189      * StrSubstitutor-supplied actual values.
190      *
191      * @param properties configured properties
192      * @param strSubstitutor used to lookup values of variables in properties
193      */
194     public void mergePropertiesIntoContextMap(
195             final Map<Property, Boolean> properties,
196             final StrSubstitutor strSubstitutor) {
197         if (properties == null) {
198             return; // nothing to do
199         }
200 
201         final Map<String, String> map = (contextMap == null) ? new HashMap<String, String>()
202                 : new HashMap<String, String>(contextMap);
203 
204         for (final Map.Entry<Property, Boolean> entry : properties.entrySet()) {
205             final Property prop = entry.getKey();
206             if (map.containsKey(prop.getName())) {
207                 continue; // contextMap overrides config properties
208             }
209             final String value = entry.getValue() ? strSubstitutor.replace(prop
210                     .getValue()) : prop.getValue();
211             map.put(prop.getName(), value);
212         }
213         contextMap = map;
214     }
215 
216     /**
217      * Release references held by ring buffer to allow objects to be
218      * garbage-collected.
219      */
220     public void clear() {
221         setValues(null, // asyncLogger
222                 null, // loggerName
223                 null, // marker
224                 null, // fqcn
225                 null, // level
226                 null, // data
227                 null, // t
228                 null, // map
229                 null, // contextStack
230                 null, // threadName
231                 null, // location
232                 0 // currentTimeMillis
233         );
234     }
235 }