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 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
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
066        clear(); // clear the translator
067    }
068
069    /**
070     * Release references held by this object to allow objects to be garbage-collected.
071     */
072    private void clear() {
073        setBasicValues(null, // asyncLogger
074                null, // loggerName
075                null, // marker
076                null, // fqcn
077                null, // level
078                null, // data
079                null, // t
080                null, // contextStack
081                null, // location
082                null, // clock
083                null // nanoClock
084        );
085    }
086
087    public void setBasicValues(final AsyncLogger anAsyncLogger, final String aLoggerName, final Marker aMarker,
088                               final String theFqcn, final Level aLevel, final Message msg, final Throwable aThrowable,
089                               final ContextStack aContextStack, final StackTraceElement aLocation,
090                               final Clock aClock, final NanoClock aNanoClock) {
091        this.asyncLogger = anAsyncLogger;
092        this.loggerName = aLoggerName;
093        this.marker = aMarker;
094        this.fqcn = theFqcn;
095        this.level = aLevel;
096        this.message = msg;
097        this.thrown = aThrowable;
098        this.contextStack = aContextStack;
099        this.location = aLocation;
100        this.clock = aClock;
101        this.nanoClock = aNanoClock;
102    }
103
104    public void updateThreadValues() {
105        final Thread currentThread = Thread.currentThread();
106        this.threadId = currentThread.getId();
107        this.threadName = currentThread.getName();
108        this.threadPriority = currentThread.getPriority();
109    }
110}