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            public RingBufferLogEvent newInstance() {
046                return new RingBufferLogEvent();
047            }
048        }
049    
050        /** The {@code EventFactory} for {@code RingBufferLogEvent}s. */
051        public static final Factory FACTORY = new Factory();
052    
053        private AsyncLogger asyncLogger;
054        private String loggerName;
055        private Marker marker;
056        private String fqcn;
057        private Level level;
058        private Message message;
059        private Throwable thrown;
060        private Map<String, String> contextMap;
061        private ContextStack contextStack;
062        private String threadName;
063        private StackTraceElement location;
064        private long currentTimeMillis;
065        private boolean endOfBatch;
066        private boolean includeLocation;
067    
068        public void setValues(AsyncLogger asyncLogger, String loggerName,
069                Marker marker, String fqcn, Level level, Message data, Throwable t,
070                Map<String, String> map, ContextStack contextStack,
071                String threadName, StackTraceElement location,
072                long currentTimeMillis) {
073            this.asyncLogger = asyncLogger;
074            this.loggerName = loggerName;
075            this.marker = marker;
076            this.fqcn = fqcn;
077            this.level = level;
078            this.message = data;
079            this.thrown = t;
080            this.contextMap = map;
081            this.contextStack = contextStack;
082            this.threadName = threadName;
083            this.location = location;
084            this.currentTimeMillis = currentTimeMillis;
085        }
086    
087        /**
088         * Event processor that reads the event from the ringbuffer can call this
089         * method.
090         * 
091         * @param endOfBatch flag to indicate if this is the last event in a batch
092         *            from the RingBuffer
093         */
094        public void execute(boolean endOfBatch) {
095            this.endOfBatch = endOfBatch;
096            asyncLogger.actualAsyncLog(this);
097        }
098    
099        /**
100         * Returns {@code true} if this event is the end of a batch, {@code false}
101         * otherwise.
102         * 
103         * @return {@code true} if this event is the end of a batch, {@code false}
104         *         otherwise
105         */
106        public boolean isEndOfBatch() {
107            return endOfBatch;
108        }
109    
110        public void setEndOfBatch(boolean endOfBatch) {
111            this.endOfBatch = endOfBatch;
112        }
113    
114        public boolean isIncludeLocation() {
115            return includeLocation;
116        }
117    
118        public void setIncludeLocation(boolean includeLocation) {
119            this.includeLocation = includeLocation;
120        }
121    
122        // @Override
123        public String getLoggerName() {
124            return loggerName;
125        }
126    
127        // @Override
128        public Marker getMarker() {
129            return marker;
130        }
131    
132        // @Override
133        public String getFQCN() {
134            return fqcn;
135        }
136    
137        // @Override
138        public Level getLevel() {
139            return level;
140        }
141    
142        // @Override
143        public Message getMessage() {
144            if (message == null) {
145                message = new SimpleMessage("");
146            }
147            return message;
148        }
149    
150        // @Override
151        public Throwable getThrown() {
152            return thrown;
153        }
154    
155        // @Override
156        public Map<String, String> getContextMap() {
157            return contextMap;
158        }
159    
160        // @Override
161        public ContextStack getContextStack() {
162            return contextStack;
163        }
164    
165        // @Override
166        public String getThreadName() {
167            return threadName;
168        }
169    
170        // @Override
171        public StackTraceElement getSource() {
172            return location;
173        }
174    
175        // @Override
176        public long getMillis() {
177            return currentTimeMillis;
178        }
179    
180        /**
181         * Merges the contents of the specified map into the contextMap, after
182         * replacing any variables in the property values with the
183         * StrSubstitutor-supplied actual values.
184         * 
185         * @param properties configured properties
186         * @param strSubstitutor used to lookup values of variables in properties
187         */
188        public void mergePropertiesIntoContextMap(
189                Map<Property, Boolean> properties, StrSubstitutor strSubstitutor) {
190            if (properties == null) {
191                return; // nothing to do
192            }
193    
194            Map<String, String> map = (contextMap == null) ? new HashMap<String, String>()
195                    : new HashMap<String, String>(contextMap);
196    
197            for (Map.Entry<Property, Boolean> entry : properties.entrySet()) {
198                Property prop = entry.getKey();
199                if (map.containsKey(prop.getName())) {
200                    continue; // contextMap overrides config properties
201                }
202                String value = entry.getValue() ? strSubstitutor.replace(prop
203                        .getValue()) : prop.getValue();
204                map.put(prop.getName(), value);
205            }
206            contextMap = map;
207        }
208    }