All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.logstash.logback.appender.DelegatingAsyncDisruptorAppender Maven / Gradle / Ivy

Go to download

Provides logback encoders, layouts, and appenders to log in JSON and other formats supported by Jackson

There is a newer version: 8.0
Show newest version
/**
 * 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 net.logstash.logback.appender;

import java.io.Flushable;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;

import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.RingBuffer;

import ch.qos.logback.access.spi.IAccessEvent;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.AsyncAppenderBase;
import ch.qos.logback.core.OutputStreamAppender;
import ch.qos.logback.core.spi.AppenderAttachable;
import ch.qos.logback.core.spi.AppenderAttachableImpl;
import ch.qos.logback.core.spi.DeferredProcessingAware;
import net.logstash.logback.appender.listener.AppenderListener;

/**
 * An {@link AsyncDisruptorAppender} that delegates appending of an event
 * to delegate {@link #appenders}.
 * 
 * This is very similar to logback's {@link AsyncAppenderBase}, except that:
 * 
    *
  • it uses a {@link RingBuffer} instead of a {@link BlockingQueue}
  • *
  • it allows any number of delegate appenders, instead of just one
  • *
  • it flushes appenders of type {@link OutputStreamAppender} or {@link Flushable} at the end of a batch
  • *
  • it is resilient to exceptions and guarantees that all appenders are invoked
  • *
* * @param type of event ({@link ILoggingEvent} or {@link IAccessEvent}). */ public abstract class DelegatingAsyncDisruptorAppender> extends AsyncDisruptorAppender implements AppenderAttachable { /** * The delegate appenders. */ private final AppenderAttachableImpl appenders = new AppenderAttachableImpl(); private class DelegatingEventHandler implements EventHandler> { /** * Whether exceptions should be reported with a error status or not. */ private boolean silentError; @Override public void onEvent(LogEvent logEvent, long sequence, boolean endOfBatch) throws Exception { boolean exceptionThrown = false; for(Iterator> it=appenders.iteratorForAppenders(); it.hasNext(); ) { Appender appender = it.next(); try { appender.doAppend(logEvent.event); /* * Optimization: * * If any of the delegate appenders are instances of OutputStreamAppender or Flushable, * then flush them at the end of the batch. */ if (endOfBatch) { flushAppender(appender); } } catch(Exception e) { exceptionThrown = true; if (!this.silentError) { addError(String.format("Unable to forward event to appender [%s]: %s", appender.getName(), e.getMessage()), e); } } } this.silentError = exceptionThrown; } private void flushAppender(Appender appender) throws IOException { // Similar to #doAppend() - don't flush if appender is stopped if (!appender.isStarted()) { return; } if (appender instanceof Flushable) { flushAppender((Flushable)appender); } else if (appender instanceof OutputStreamAppender) { flushAppender((OutputStreamAppender)appender); } } private void flushAppender(OutputStreamAppender appender) throws IOException { if (!appender.isImmediateFlush()) { OutputStream os = appender.getOutputStream(); if (os != null) { os.flush(); } } } private void flushAppender(Flushable appender) throws IOException { appender.flush(); } } public DelegatingAsyncDisruptorAppender() { super(); setEventHandler(new DelegatingEventHandler()); } @Override public void start() { startDelegateAppenders(); super.start(); } @Override public void stop() { if (!isStarted()) { return; } super.stop(); stopDelegateAppenders(); } private void startDelegateAppenders() { for (Iterator> appenderIter = appenders.iteratorForAppenders(); appenderIter.hasNext();) { Appender appender = appenderIter.next(); if (appender.getContext() == null) { appender.setContext(getContext()); } if (!appender.isStarted()) { appender.start(); } } } private void stopDelegateAppenders() { for (Iterator> appenderIter = appenders.iteratorForAppenders(); appenderIter.hasNext();) { Appender appender = appenderIter.next(); if (appender.isStarted()) { appender.stop(); } } } @Override public void addAppender(Appender newAppender) { appenders.addAppender(newAppender); } @Override public Iterator> iteratorForAppenders() { return appenders.iteratorForAppenders(); } @Override public Appender getAppender(String name) { return appenders.getAppender(name); } @Override public boolean isAttached(Appender appender) { return appenders.isAttached(appender); } @Override public void detachAndStopAllAppenders() { appenders.detachAndStopAllAppenders(); } @Override public boolean detachAppender(Appender appender) { return appenders.detachAppender(appender); } @Override public boolean detachAppender(String name) { return appenders.detachAppender(name); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy