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