I have a logger that send log to a log server storage. This work fine but the patternlayout isn't used. With or without that doesn't change anything. I believe remember to read somewhere that socketappender use is own pattern and not others.
<appender name="LOGSTASH" class="org.apache.log4j.net.SocketAppender">
<param name="Port" value="5000"/>
<param name="RemoteHost" value="192.168.81.131"/>
<param name="ReconnectionDelay" value="5000"/>
<param name="LocationInfo" value="true" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n" />
</layout>
</appender>
But on this documentation (and a few other) thay use this. Example from this doc :
<appender name="A1" class="org.apache.log4j.net.SocketAppender">
<param name="RemoteHost" value="localhost"/>
<param name="Port" value="5000"/>
<param name="LocationInfo" value="true"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%t %-5p %c{2} - %m%n"/>
</layout>
</appender>
So is it impossible to use personnal pattern with socketappender or is it my fault?
If it's impossible is there an alternative appender for tcp logging with custom pattern?
It seems that SocketAppender don't use a layout.
SocketAppenders do not use a layout. They ship a serialized LoggingEvent object to the server side.
So I use a SyslogAppender to replace. It's not perfect because of unused possibilies (like facility and priority) but works fine.
As a workaround,
- For Log4j 1.x
- Copy SocketAppender code to your local project
Change, "requiresLayout" method as
public boolean requiresLayout() { return true; }
Change append method as ;
public void append(LoggingEvent event) { ///...... event.getThrowableStrRep(); if (this.layout == null) { errorHandler.error("No layout for appender " + name, null, ErrorCode.MISSING_LAYOUT); return; } String message = this.layout.format(event); oos.writeObject(message); ///...... }
Set this class as your appender.
- Now on, you can set any layout to this appender.
Hope it helps.
Workaround that @myuce posted is working, but you also need to replace ObjectOutputStream (OOS) within "standard" OutputStream (OS).
You can check inside OOS - it's prepending output with some additional stuff for "the receiver".
??t?{"@timestamp":"2018-03-27T14...
So... I've just replaced (it's scala in my case):
oos = new ObjectOutputStream(new Socket(address, port).getOutputStream());
and
oos = new ObjectOutputStream(socket.getOutputStream());
within:
stream = new Socket(address, port).getOutputStream
and stream = socket.getOutputStream
(and variable name [of course every occurrence;] for clarity).
来源:https://stackoverflow.com/questions/27230778/socketappender-and-patternlayout