log4j支持Syslog-ng的改造

来源:互联网 发布:公共基础知识软件下载 编辑:程序博客网 时间:2024/05/29 05:57

log4j本身是支持syslog的,但是有很多不足,所以需要改造。

 

1.log4j在支持syslog时,默认同Msg大小是1024,这也是syslog的RFC3164标准。但是对于在实际应用中超过1024的MSG,我们还是

希望能完整地log下来,所以log4j对大于1024的MSG进行拆包。

这一拆就带来了麻烦。

 

因为priority,tag这些syslog标准的属性都是包含在MSG本身而当不是专门的字段,所以在拆包时只能拆在第一条,而后面的MSG就失去了这些关键属性。比如:

 

Apr 28 10:22:59 myhost myapp:<INFO> msgdetailxxxxxxxxxxxxxxxxxxxxxxxxxx.

实际的MSG是"myapp:<INFO> msgdetailxxxxxxxxxxxxxxxxxxxxxxxxxx",如果要拆成两条记录,则:

 

Apr 28 10:22:59 myhost myapp:<INFO> msgdetailxxxxx

Apr 28 10:22:59 myhost xxxxxxxxxxxxxx

第二条以后的记录就失去了tag和priority,文档分类就不知道把这条消息放在哪个文件档中了。所以要么我们自己手工分割消息,将分割后小于1024的消息传给log4j,这样它会作为多条消息处理,就不会把关键属性去掉。

 

这条路还是走不通,因为MSG拆分后,UDP传输不可能保证消息顺序和完整,消息并不是按你拆开的顺序完整地发送给syslog.那么也就不能保证被还原。即使加上序列ID也难以保证。

 


2.所以我尽量能寻找支持1024以上消息长度的方案。一开始,我的测试环境是log4j加ubuntu下的syslogd(sysklogd).我修改了log4j的源码,从UDP层取消1024的限制,但是消息发送到syslogd后,被服务端截断。即syslogd也按照RFC3164标准将消息裁断了。但UDP协议是可以发送大于1024的消息的。

 

3.后来改用syslog-ng,修改了相关参数,出现一个惊喜,可以发送64K的消息,这已经是UDP包的限制了。当然一条日志超过64K就不叫日志了。

 

 

现在就是修改log4j的appender了。这个工作主要是重新实现SyslogAppender中UDP发送。

如果把它们重新分发到我们自己的包中需要修改三个类,主要实现SyslogWriter,然后是SyslogAppender,让他调用我们自己的SyslogQuiteWriter,然后在SyslogQuiteWriter中调用修改过的SyslogWriter。

 

如果要增加一些控制,比如增加字符集,因为SyslogWriter默认getBytes是没有字符集参数,使用系统默认字符集,有可能不是我们

想要的结果,所以如果增加配置项,需要先在SyslogAppender中增加setter方法,LoggerFactory中初始化时是读一个配置项然后

反射调用appender的set方法,比如你配置了log4j.appender.syslog.axman=12345

那么初始化时会反射调用SyslogAppender的setAxman方法把配置项注入进去而不是放在一个数据结构中的。

 

这样经过修改后,只要将log4j.appender.syslog指向我们的SyslogAppender:

log4j.appender.syslog=com.axman.SyslogAppender,并且com.axman.SyslogAppender在classpath中就可以正确地工作。其它的没有任何影响,这时如果你把ConversionPattern配置成 myapp:<%p> 其它选项......%m%n

就可以把日志按myapp,priority来分到不同文件中,特别是按$LEVEL来分档,可以把fatal(对应syslog是emerg)的日志先发给监控处理而info的可以发给其它业务处理,非常方便。