com.netflix.blitz4j.NFAppenderAttachableImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.netflix.blitz4j.NFAppenderAttachableImpl.java

Source

/*
 * Copyright 2012 Netflix, Inc.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.netflix.blitz4j;

import java.util.AbstractQueue;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.apache.commons.collections.iterators.IteratorEnumeration;
import org.apache.log4j.Appender;
import org.apache.log4j.helpers.AppenderAttachableImpl;
import org.apache.log4j.spi.AppenderAttachable;
import org.apache.log4j.spi.LoggingEvent;

/**
 * This class overrides log4j implementation to provide appender with less
 * multi-threaded contention.
 * 
 * @author Karthik Ranganathan
 * 
 */
public class NFAppenderAttachableImpl extends AppenderAttachableImpl implements AppenderAttachable {

    protected AbstractQueue<Appender> appenderList = new ConcurrentLinkedQueue<Appender>();
    private AbstractQueue<String> configuredAppenderList = new ConcurrentLinkedQueue<String>();

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.log4j.helpers.AppenderAttachableImpl#addAppender(org.apache
     * .log4j.Appender)
     */
    @Override
    public void addAppender(Appender newAppender) {
        // Null values for newAppender parameter are strictly forbidden.
        if (newAppender == null) {
            return;
        }
        // If the appender is already there, add this one to the end before
        // removing the
        // previous one
        boolean isAppenderPresent = appenderList.contains(newAppender);
        if (isAppenderPresent) {
            appenderList.add(newAppender);
            for (Iterator<Appender> it = appenderList.iterator(); it.hasNext();) {
                Appender appender = it.next();
                if (newAppender.equals(appender)) {
                    appender.close();
                    it.remove();
                    return;
                }
            }
        } else {
            appenderList.add(newAppender);
        }
        configuredAppenderList.add(newAppender.getName());
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.log4j.helpers.AppenderAttachableImpl#appendLoopOnAppenders
     * (org.apache.log4j.spi.LoggingEvent)
     */
    @Override
    public int appendLoopOnAppenders(LoggingEvent event) {
        int size = 0;
        Appender appender;
        if (appenderList != null) {
            size = appenderList.size();
            Iterator<Appender> it = appenderList.iterator();
            while (it.hasNext()) {
                appender = (Appender) it.next();
                appender.doAppend(event);
            }
        }
        return size;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.log4j.helpers.AppenderAttachableImpl#getAllAppenders()
     */
    @Override
    public Enumeration getAllAppenders() {
        if (appenderList == null)
            return null;
        else {
            Iterator<Appender> it = appenderList.iterator();
            return new IteratorEnumeration(it);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.log4j.helpers.AppenderAttachableImpl#getAppender(java.lang
     * .String)
     */
    @Override
    public Appender getAppender(String name) {
        if (appenderList == null || name == null)
            return null;
        Appender appender;
        Iterator<Appender> it = appenderList.iterator();
        while (it.hasNext()) {
            appender = (Appender) it.next();
            if (name.equals(appender.getName())) {
                return appender;
            }
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.log4j.helpers.AppenderAttachableImpl#isAttached(org.apache
     * .log4j.Appender)
     */
    @Override
    public boolean isAttached(Appender appender) {
        if (appenderList == null || appender == null)
            return false;
        Appender a;
        Iterator<Appender> it = appenderList.iterator();
        while (it.hasNext()) {
            a = (Appender) it.next();
            if (a == appender) {
                return true;
            }
        }
        return false;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.log4j.helpers.AppenderAttachableImpl#removeAllAppenders()
     */
    @Override
    public void removeAllAppenders() {
        this.configuredAppenderList.clear();
        if (appenderList != null) {
            Iterator<Appender> it = appenderList.iterator();
            while (it.hasNext()) {
                Appender a = (Appender) it.next();
                String[] asyncAppenders = LoggingConfiguration.getInstance().getConfiguration()
                        .getAsyncAppenderImplementationNames();
                // For AsyncAppenders, we won't remove appenders.
                // This call is primarily made during dynamic log4 reconfiguration and we will
                // retain the ability to queue the messages.
                for (String asyncAppender : asyncAppenders) {
                    if (!(asyncAppender.equals(a.getClass().getName()))) {
                        a.close();
                        it.remove();
                    }
                }
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.log4j.helpers.AppenderAttachableImpl#removeAppender(org.apache
     * .log4j.Appender)
     */
    @Override
    public void removeAppender(Appender appender) {
        if (appender == null || appenderList == null)
            return;
        appenderList.remove(appender);
        configuredAppenderList.remove(appender.getName());
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.apache.log4j.helpers.AppenderAttachableImpl#removeAppender(java.lang
     * .String)
     */
    @Override
    public void removeAppender(String name) {
        if (name == null || appenderList == null)
            return;
        Iterator<Appender> it = appenderList.iterator();
        while (it.hasNext()) {
            Appender a = (Appender) it.next();
            if (name.equals(a.getName())) {
                it.remove();
                configuredAppenderList.remove(a.getName());
                break;
            }
        }
    }

    /**
     * Reconciles the appender list after configuration to ensure that the asynchrnous
     * appenders are not left over after the configuration.  This is needed because the
     * appenders are not cleaned out completely during configuration for it to retain the
     * ability to not messages.
     */
    public void reconcileAppenders() {
        for (Appender appender : appenderList) {
            if (!configuredAppenderList.contains(appender.getName())) {
                appender.close();
                appenderList.remove(appender);
            }
        }
    }
}