?? asyncappender.java
字號:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */// Contibutors: Aaron Greenhouse <aarong@cs.cmu.edu>// Thomas Tuft Muller <ttm@online.no>package org.apache.log4j;import org.apache.log4j.helpers.AppenderAttachableImpl;import org.apache.log4j.spi.AppenderAttachable;import org.apache.log4j.spi.LoggingEvent;import java.text.MessageFormat;import java.util.ArrayList;import java.util.Enumeration;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;/** * The AsyncAppender lets users log events asynchronously. * <p/> * <p/> * The AsyncAppender will collect the events sent to it and then dispatch them * to all the appenders that are attached to it. You can attach multiple * appenders to an AsyncAppender. * </p> * <p/> * <p/> * The AsyncAppender uses a separate thread to serve the events in its buffer. * </p> * <p/> * <b>Important note:</b> The <code>AsyncAppender</code> can only be script * configured using the {@link org.apache.log4j.xml.DOMConfigurator}. * </p> * * @author Ceki Gülcü * @author Curt Arnold * @since 0.9.1 */public class AsyncAppender extends AppenderSkeleton implements AppenderAttachable { /** * The default buffer size is set to 128 events. */ public static final int DEFAULT_BUFFER_SIZE = 128; /** * Event buffer, also used as monitor to protect itself and * discardMap from simulatenous modifications. */ private final List buffer = new ArrayList(); /** * Map of DiscardSummary objects keyed by logger name. */ private final Map discardMap = new HashMap(); /** * Buffer size. */ private int bufferSize = DEFAULT_BUFFER_SIZE; /** Nested appenders. */ AppenderAttachableImpl aai; /** * Nested appenders. */ private final AppenderAttachableImpl appenders; /** * Dispatcher. */ private final Thread dispatcher; /** * Should location info be included in dispatched messages. */ private boolean locationInfo = false; /** * Does appender block when buffer is full. */ private boolean blocking = true; /** * Create new instance. */ public AsyncAppender() { appenders = new AppenderAttachableImpl(); // // only set for compatibility aai = appenders; dispatcher = new Thread(new Dispatcher(this, buffer, discardMap, appenders)); // It is the user's responsibility to close appenders before // exiting. dispatcher.setDaemon(true); // set the dispatcher priority to lowest possible value // dispatcher.setPriority(Thread.MIN_PRIORITY); dispatcher.setName("Dispatcher-" + dispatcher.getName()); dispatcher.start(); } /** * Add appender. * * @param newAppender appender to add, may not be null. */ public void addAppender(final Appender newAppender) { synchronized (appenders) { appenders.addAppender(newAppender); } } /** * {@inheritDoc} */ public void append(final LoggingEvent event) { // // if dispatcher thread has died then // append subsequent events synchronously // See bug 23021 if ((dispatcher == null) || !dispatcher.isAlive() || (bufferSize <= 0)) { synchronized (appenders) { appenders.appendLoopOnAppenders(event); } return; } // Set the NDC and thread name for the calling thread as these // LoggingEvent fields were not set at event creation time. event.getNDC(); event.getThreadName(); // Get a copy of this thread's MDC. event.getMDCCopy(); if (locationInfo) { event.getLocationInformation(); } synchronized (buffer) { while (true) { int previousSize = buffer.size(); if (previousSize < bufferSize) { buffer.add(event); // // if buffer had been empty // signal all threads waiting on buffer // to check their conditions. // if (previousSize == 0) { buffer.notifyAll(); } break; } // // Following code is only reachable if buffer is full // // // if blocking and thread is not already interrupted // and not the dispatcher then // wait for a buffer notification boolean discard = true; if (blocking && !Thread.interrupted() && Thread.currentThread() != dispatcher) { try { buffer.wait(); discard = false; } catch (InterruptedException e) { // // reset interrupt status so // calling code can see interrupt on // their next wait or sleep. Thread.currentThread().interrupt(); } } // // if blocking is false or thread has been interrupted // add event to discard map. // if (discard) { String loggerName = event.getLoggerName(); DiscardSummary summary = (DiscardSummary) discardMap.get(loggerName); if (summary == null) { summary = new DiscardSummary(event); discardMap.put(loggerName, summary); } else { summary.add(event); } break; } } } } /** * Close this <code>AsyncAppender</code> by interrupting the dispatcher * thread which will process all pending events before exiting. */ public void close() { /** * Set closed flag and notify all threads to check their conditions. * Should result in dispatcher terminating. */ synchronized (buffer) { closed = true; buffer.notifyAll(); } try { dispatcher.join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); org.apache.log4j.helpers.LogLog.error( "Got an InterruptedException while waiting for the " + "dispatcher to finish.", e); } // // close all attached appenders. // synchronized (appenders) { Enumeration iter = appenders.getAllAppenders(); if (iter != null) { while (iter.hasMoreElements()) { Object next = iter.nextElement(); if (next instanceof Appender) { ((Appender) next).close(); } } } } } /** * Get iterator over attached appenders. * @return iterator or null if no attached appenders. */ public Enumeration getAllAppenders() { synchronized (appenders) { return appenders.getAllAppenders(); } } /** * Get appender by name. * * @param name name, may not be null. * @return matching appender or null. */ public Appender getAppender(final String name) { synchronized (appenders) { return appenders.getAppender(name); } } /** * Gets whether the location of the logging request call * should be captured. * * @return the current value of the <b>LocationInfo</b> option. */ public boolean getLocationInfo() { return locationInfo; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -