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 java.net.URI;
020import java.util.concurrent.TimeUnit;
021
022import org.apache.logging.log4j.core.Logger;
023import org.apache.logging.log4j.core.LoggerContext;
024import org.apache.logging.log4j.core.config.Configuration;
025import org.apache.logging.log4j.core.config.DefaultConfiguration;
026import org.apache.logging.log4j.core.jmx.RingBufferAdmin;
027import org.apache.logging.log4j.message.MessageFactory;
028import org.apache.logging.log4j.status.StatusLogger;
029
030/**
031 * {@code LoggerContext} that creates {@code AsyncLogger} objects.
032 */
033public class AsyncLoggerContext extends LoggerContext {
034
035    private final AsyncLoggerDisruptor loggerDisruptor;
036
037    public AsyncLoggerContext(final String name) {
038        super(name);
039        loggerDisruptor = new AsyncLoggerDisruptor(name);
040    }
041
042    public AsyncLoggerContext(final String name, final Object externalContext) {
043        super(name, externalContext);
044        loggerDisruptor = new AsyncLoggerDisruptor(name);
045    }
046
047    public AsyncLoggerContext(final String name, final Object externalContext, final URI configLocn) {
048        super(name, externalContext, configLocn);
049        loggerDisruptor = new AsyncLoggerDisruptor(name);
050    }
051
052    public AsyncLoggerContext(final String name, final Object externalContext, final String configLocn) {
053        super(name, externalContext, configLocn);
054        loggerDisruptor = new AsyncLoggerDisruptor(name);
055    }
056
057    @Override
058    protected Logger newInstance(final LoggerContext ctx, final String name, final MessageFactory messageFactory) {
059        return new AsyncLogger(ctx, name, messageFactory, loggerDisruptor);
060    }
061
062    @Override
063    public void setName(final String name) {
064        super.setName("AsyncContext[" + name + "]");
065        loggerDisruptor.setContextName(name);
066    }
067
068    /*
069     * (non-Javadoc)
070     *
071     * @see org.apache.logging.log4j.core.LoggerContext#start()
072     */
073    @Override
074    public void start() {
075        loggerDisruptor.start();
076        super.start();
077    }
078
079    /*
080     * (non-Javadoc)
081     *
082     * @see org.apache.logging.log4j.core.LoggerContext#start(org.apache.logging.log4j.core.config.Configuration)
083     */
084    @Override
085    public void start(final Configuration config) {
086        maybeStartHelper(config);
087        super.start(config);
088    }
089
090    private void maybeStartHelper(final Configuration config) {
091        // If no log4j configuration was found, there are no loggers
092        // and there is no point in starting the disruptor (which takes up
093        // significant memory and starts a thread).
094        if (config instanceof DefaultConfiguration) {
095            StatusLogger.getLogger().debug("[{}] Not starting Disruptor for DefaultConfiguration.", getName());
096        } else {
097            loggerDisruptor.start();
098        }
099    }
100
101    @Override
102    public boolean stop(final long timeout, final TimeUnit timeUnit) {
103        setStopping();
104        // first stop Disruptor
105        loggerDisruptor.stop(timeout, timeUnit);
106        super.stop(timeout, timeUnit);
107        return true;
108    }
109
110    /**
111     * Creates and returns a new {@code RingBufferAdmin} that instruments the ringbuffer of the {@code AsyncLogger}
112     * objects in this {@code LoggerContext}.
113     *
114     * @return a new {@code RingBufferAdmin} that instruments the ringbuffer
115     */
116    public RingBufferAdmin createRingBufferAdmin() {
117        return loggerDisruptor.createRingBufferAdmin(getName());
118    }
119
120    /**
121     * Signals this context whether it is allowed to use ThreadLocal objects for efficiency.
122     * @param useThreadLocals whether this context is allowed to use ThreadLocal objects
123     */
124    public void setUseThreadLocals(final boolean useThreadLocals) {
125        loggerDisruptor.setUseThreadLocals(useThreadLocals);
126    }
127}