ch.qos.logback.classic.net.SyslogAppender Maven / Gradle / Ivy
/**
* Logback: the reliable, generic, fast and flexible logging framework.
* Copyright (C) 1999-2015, QOS.ch. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
*/
package ch.qos.logback.classic.net;
import java.io.IOException;
import java.io.OutputStream;
import java.net.SocketException;
import java.net.UnknownHostException;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.pattern.SyslogStartConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.StackTraceElementProxy;
import ch.qos.logback.classic.util.LevelToSyslogSeverity;
import ch.qos.logback.core.CoreConstants;
import ch.qos.logback.core.Layout;
import ch.qos.logback.core.net.SyslogAppenderBase;
import ch.qos.logback.core.net.SyslogOutputStream;
/**
* This appender can be used to send messages to a remote syslog daemon.
*
* For more information about this appender, please refer to the online manual
* at http://logback.qos.ch/manual/appenders.html#SyslogAppender
*
* @author Ceki Gülcü
*/
public class SyslogAppender extends SyslogAppenderBase {
static final public String DEFAULT_SUFFIX_PATTERN = "[%thread] %logger %msg";
static final public String DEFAULT_STACKTRACE_PATTERN = "" + CoreConstants.TAB;
PatternLayout stackTraceLayout = new PatternLayout();
String stackTracePattern = DEFAULT_STACKTRACE_PATTERN;
boolean throwableExcluded = false;
public void start() {
super.start();
setupStackTraceLayout();
}
String getPrefixPattern() {
return "%syslogStart{" + getFacility() + "}%nopex{}";
}
@Override
public SyslogOutputStream createOutputStream() throws SocketException, UnknownHostException {
return new SyslogOutputStream(getSyslogHost(), getPort());
}
/**
* Convert a level to equivalent syslog severity. Only levels for printing
* methods i.e. DEBUG, WARN, INFO and ERROR are converted.
*
* @see ch.qos.logback.core.net.SyslogAppenderBase#getSeverityForEvent(java.lang.Object)
*/
@Override
public int getSeverityForEvent(Object eventObject) {
ILoggingEvent event = (ILoggingEvent) eventObject;
return LevelToSyslogSeverity.convert(event);
}
@Override
protected void postProcess(Object eventObject, OutputStream sw) {
if (throwableExcluded)
return;
ILoggingEvent event = (ILoggingEvent) eventObject;
IThrowableProxy tp = event.getThrowableProxy();
if (tp == null)
return;
String stackTracePrefix = stackTraceLayout.doLayout(event);
boolean isRootException = true;
while (tp != null) {
StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray();
try {
handleThrowableFirstLine(sw, tp, stackTracePrefix, isRootException);
isRootException = false;
for (StackTraceElementProxy step : stepArray) {
StringBuilder sb = new StringBuilder();
sb.append(stackTracePrefix).append(step);
sw.write(sb.toString().getBytes());
sw.flush();
}
} catch (IOException e) {
break;
}
tp = tp.getCause();
}
}
// LOGBACK-411 and LOGBACK-750
private void handleThrowableFirstLine(OutputStream sw, IThrowableProxy tp, String stackTracePrefix,
boolean isRootException) throws IOException {
StringBuilder sb = new StringBuilder().append(stackTracePrefix);
if (!isRootException) {
sb.append(CoreConstants.CAUSED_BY);
}
sb.append(tp.getClassName()).append(": ").append(tp.getMessage());
sw.write(sb.toString().getBytes());
sw.flush();
}
boolean stackTraceHeaderLine(StringBuilder sb, boolean topException) {
return false;
}
public Layout buildLayout() {
PatternLayout layout = new PatternLayout();
layout.getInstanceConverterMap().put("syslogStart", SyslogStartConverter::new);
if (suffixPattern == null) {
suffixPattern = DEFAULT_SUFFIX_PATTERN;
}
layout.setPattern(getPrefixPattern() + suffixPattern);
layout.setContext(getContext());
layout.start();
return layout;
}
private void setupStackTraceLayout() {
stackTraceLayout.getInstanceConverterMap().put("syslogStart", SyslogStartConverter::new);
stackTraceLayout.setPattern(getPrefixPattern() + stackTracePattern);
stackTraceLayout.setContext(getContext());
stackTraceLayout.start();
}
public boolean isThrowableExcluded() {
return throwableExcluded;
}
/**
* Setting throwableExcluded to true causes no Throwable's stack trace data to
* be sent to the syslog daemon. By default, stack trace data is sent to syslog
* daemon.
*
* @param throwableExcluded
* @since 1.0.4
*/
public void setThrowableExcluded(boolean throwableExcluded) {
this.throwableExcluded = throwableExcluded;
}
/**
* See {@link #setStackTracePattern(String).
*
* @return the stackTraceSuffixPattern
* @since 1.0.4
*/
public String getStackTracePattern() {
return stackTracePattern;
}
/**
* Stack trace lines are sent to the syslog server separately from the main
* message For stack trace lines, the stackTracePattern is used instead of
* {@link #suffixPattern}. The stackTracePattern option allows
* specification of a separate format for the non-standardized part of stack
* trace lines.
*
* @param stackTracePattern
* @since 1.0.4
*/
public void setStackTracePattern(String stackTracePattern) {
this.stackTracePattern = stackTracePattern;
}
}