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 org.apache.logging.log4j.Level;
020import org.apache.logging.log4j.Marker;
021import org.apache.logging.log4j.ThreadContext.ContextStack;
022import org.apache.logging.log4j.core.ContextDataInjector;
023import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory;
024import org.apache.logging.log4j.util.StringMap;
025import org.apache.logging.log4j.message.Message;
026
027import com.lmax.disruptor.EventTranslator;
028
029/**
030 * This class is responsible for writing elements that make up a log event into
031 * the ringbuffer {@code RingBufferLogEvent}. After this translator populated
032 * the ringbuffer event, the disruptor will update the sequence number so that
033 * the event can be consumed by another thread.
034 */
035public class RingBufferLogEventTranslator implements
036        EventTranslator<RingBufferLogEvent> {
037
038    private final ContextDataInjector injector = ContextDataInjectorFactory.createInjector();
039    private AsyncLogger asyncLogger;
040    String loggerName;
041    protected Marker marker;
042    protected String fqcn;
043    protected Level level;
044    protected Message message;
045    protected Throwable thrown;
046    private ContextStack contextStack;
047    private long threadId = Thread.currentThread().getId();
048    private String threadName = Thread.currentThread().getName();
049    private int threadPriority = Thread.currentThread().getPriority();
050    private StackTraceElement location;
051    private long currentTimeMillis;
052    private long nanoTime;
053
054    // @Override
055    @Override
056    public void translateTo(final RingBufferLogEvent event, final long sequence) {
057
058        event.setValues(asyncLogger, loggerName, marker, fqcn, level, message, thrown,
059                // config properties are taken care of in the EventHandler thread
060                // in the AsyncLogger#actualAsyncLog method
061                injector.injectContextData(null, (StringMap) event.getContextData()), contextStack,
062                threadId, threadName, threadPriority, location, currentTimeMillis, nanoTime);
063
064        clear(); // clear the translator
065    }
066
067    /**
068     * Release references held by this object to allow objects to be garbage-collected.
069     */
070    private void clear() {
071        setBasicValues(null, // asyncLogger
072                null, // loggerName
073                null, // marker
074                null, // fqcn
075                null, // level
076                null, // data
077                null, // t
078                null, // contextStack
079                null, // location
080                0, // currentTimeMillis
081                0 // nanoTime
082        );
083    }
084
085    public void setBasicValues(final AsyncLogger anAsyncLogger, final String aLoggerName, final Marker aMarker,
086            final String theFqcn, final Level aLevel, final Message msg, final Throwable aThrowable,
087            final ContextStack aContextStack, final StackTraceElement aLocation,
088            final long aCurrentTimeMillis, final long aNanoTime) {
089        this.asyncLogger = anAsyncLogger;
090        this.loggerName = aLoggerName;
091        this.marker = aMarker;
092        this.fqcn = theFqcn;
093        this.level = aLevel;
094        this.message = msg;
095        this.thrown = aThrowable;
096        this.contextStack = aContextStack;
097        this.location = aLocation;
098        this.currentTimeMillis = aCurrentTimeMillis;
099        this.nanoTime = aNanoTime;
100    }
101
102    public void updateThreadValues() {
103        final Thread currentThread = Thread.currentThread();
104        this.threadId = currentThread.getId();
105        this.threadName = currentThread.getName();
106        this.threadPriority = currentThread.getPriority();
107    }
108}