Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make log4j syslog appender write a stack trace in one line?

Tags:

java

log4j

syslog

I am using log4j syslog appender and notice that when an exception occurs the appender writes every entry in the stack trace as a new line.

Is there a way to configure it so that the entire stack trace will go as one line instead of multiple lines?

like image 841
Joly Avatar asked Jul 20 '16 16:07

Joly


2 Answers

I'm using the following log4j2 configuration which is working well sending to syslog and doesn't require code changes to convert all those exceptions to strings. It's just replacing the default linesep with a pipe on exceptions.

    <Syslog name="SYSLOG" host="127.0.0.1" port="515" protocol="TCP" charset="UTF-8"
            immediateFail="false" ignoreExceptions="true" reconnectionDelayMillis="250">
        <PatternLayout pattern="[%d] %-5p %m%n %throwable{separator(|)}"></PatternLayout>
    </Syslog>
like image 90
james Avatar answered Sep 25 '22 13:09

james


Log4j2

See james' answer.

Log4j v1

By default, the syslog appender will send the formatted log as well as each line of the stack trace as separate log entries in syslog. Because syslog uses UDP, the lines may be out of order.

If that's the problem you're trying to solve, then as james mentioned the best way to do this is to use a pattern layout with the %throwable conversion character. He documented how to do it for log4j2. For log4j1, it requires the EnhancedPatternLayout:

<appender name="syslog" class="org.apache.log4j.net.SyslogAppender">
  <param name="SyslogHost" value="127.0.0.1:514"/>
  <layout class="org.apache.log4j.EnhancedPatternLayout">
    <param name="ConversionPattern" value="[%d] %-5p %m%n%throwable"/>
  </layout>
</appender>

Note that the above solution will still use newline characters to separate the individual lines of the stack trace, but it will solve the problem of the stack trace lines being sent as separate log entries in syslog.

If you really want the stack trace on one line, a quick fix is to use the above example with %throwable{short} or %throwable{1}, which will only include the first line of the stack trace.

If you want the entire stack trace in one line, you may prefer to use a custom ThrowableRenderer as proposed by davidxxx. (Note that this will still send the formatted log to syslog separately from the stack trace, so to avoid that you can combine this solution with the one above.)

For example:

import org.apache.log4j.DefaultThrowableRenderer;
import org.apache.log4j.spi.ThrowableRenderer;

import java.util.ArrayList;
import java.util.Arrays;

public class CustomThrowableRenderer implements ThrowableRenderer {
    private final DefaultThrowableRenderer defaultRenderer = new DefaultThrowableRenderer();

    @Override
    public String[] doRender(Throwable throwable) {
        String[] defaultRepresentation = defaultRenderer.doRender(throwable);
        String[] newRepresentation = {String.join("|", Arrays.asList(defaultRepresentation))};

        return newRepresentation;
    }
}

And then in your log4j.xml:

<throwableRenderer class="CustomThrowableRenderer"/>
like image 42
bmaupin Avatar answered Sep 23 '22 13:09

bmaupin