log4j2 - Syslog 附加程序和 PatternLayout

Posted

技术标签:

【中文标题】log4j2 - Syslog 附加程序和 PatternLayout【英文标题】:log4j2 - Syslog appender and PatternLayout 【发布时间】:2013-07-30 15:13:44 【问题描述】:

我需要将事件记录到系统日志中。 我使用 lo4j2 和 syslog appender。 我在 log4j2.xml 中的 appenders 块看起来像这样:

<appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%dHH:mm:ss.SSS [%t] %-5level %logger36 - %msg%n"/>
        </Console>
        <Syslog name="syslog" host="localhost" port="514" protocol="UDP" charset="ISO-8859-1">
        </Syslog>
        <RollingFile name="AppLog" fileName="/var/log/app.log"
                     filePattern="/var/log/$$date:yyyy-MM/app-%dMM-dd-yyyy-%i.log.gz">
            <PatternLayout pattern="%dHH:mm:ss.SSS [%t] %-5level %logger36 - %msg%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
            </Policies>
        </RollingFile>          
    </appenders>

如您所见,我有一个带有特定 PatternLayout 的 Console appender 和 RollingFile appender。 我想为 Syslog appender 使用相同的 PatternLayout。 但是,syslog 中的日志消息似乎总是使用预定义的布局。 我尝试执行以下操作:

<Syslog name="syslog" host="localhost" port="514" protocol="UDP" charset="ISO-8859-1">
    <PatternLayout pattern="%dHH:mm:ss.SSS [%t] %-5level %logger36 - %msg%n"/>
</Syslog>

但这没有任何效果。系统日志消息仍然具有相同的预定义格式。

如何确定进入 syslog 的日志消息的格式?

【问题讨论】:

【参考方案1】:

正如log4j2 bug report 中所述,log4j2 的开发人员将SyslogAppender 编码为SocketAppender,硬连线为SyslogLayout

因为它旨在符合原始系统日志格式或 RFC 5424。不应允许其他布局。

不幸的是,他们没有意识到 RFC 5424 规范并未对日志中包含的消息强制执行任何特定格式,在 Log4j2 实现中只有日志的 %m 部分。

为了解决这个问题,一个解决方案(在同一个错误报告中建议)是在 SocketAppender 中使用 PatternLayout 重现 syslog 格式,就像这样

<Socket name="SYSLOG" host="localhost" port="514" protocol="UDP">
  <PatternLayout
    pattern="&lt;1&gt;%dMMM dd HH:mm:ss $hostName appName: 
      &quot;host&quot;:&quot;$hostName&quot;,
      &quot;thread&quot;:&quot;%t&quot;,
      &quot;level&quot;:&quot;%p&quot;,
      &quot;logger&quot;:&quot;%c1&quot;,
      &quot;line&quot;:%L,
      &quot;message&quot;:&quot;%enc%m&quot;,
      &quot;exception&quot;:&quot;%exception&quot;
      %n"
  />
</Socket>

这将通过 UDP 将格式正确的 RFC5424 日志写入本地 514 端口。以下是示例日志输出:

Sep 14 10:40:50 app-hostname app-name:  "host":"host-name-01", "thread":"http-nio-8080-exec-4", "level":"DEBUG", "logger":"ExecuteTimeInterceptor", "line":52, "message":"GET &#x2F;health 200 served in 3", "exception":"" 

【讨论】:

这不允许将消息写入自定义设施,例如 local4。【参考方案2】:

我不相信您可以在基本的 Syslog 附加程序上使用模式。

从文档中指出

“SyslogAppender 是一个 SocketAppender,它以符合 BSD Syslog 格式或 RFC 5424 的格式将其输出写入由主机和端口指定的远程目标” http://logging.apache.org/log4j/2.x/manual/appenders.html#SyslogAppender

但是,它确实允许您指定“格式 = RFC 5424”

如果您使用 RFC 5424

然后你可以在loggerFields参数中放一个PatterLayout。 见http://logging.apache.org/log4j/2.x/manual/layouts.html#RFC5424Layout

希望有帮助!

【讨论】:

这似乎是正确的方向,但我不太明白如何在我的log4j2.xml 中使用&lt;loggerFields&gt; 标签。我应该在“关键”属性中添加什么?一个例子会很有用。 @conornicol,我相信你误解了 PatternLayout 部分。到目前为止,不可能将自定义 PatternLayout 注入 RFC-5424 布局。您正在影响的是 [] 中的部分。您不会影响该布局的消息部分。【参考方案3】:

您可以使用 LoggerFields 标记向 RFC5424 格式的 SyslogAppender 消息添加其他元素,如下所示:

<LoggerFields>
  <KeyValuePair key="thread" value="%t"/>
  <KeyValuePair key="priority" value="%p"/>
  <KeyValuePair key="category" value="%c"/>
  <KeyValuePair key="exception" value="%ex"/>
</LoggerFields>

然后我使用 rsyslog 的 RFC5424 解析模块 mmpstrucdata 将这些提取出来,以创建 json 树。用于访问它们的 rsyslog.conf 模板如下所示:

template(name="jsondump" type="string" string="'%$!rfc5424-sd!mdc@18060!thread%', '%$!rfc5424-sd!mdc@18060!priority%', '%$!rfc5424-sd!mdc@18060!category%', '%$!rfc5424-sd!mdc@18060!exception%'")

我只是尝试做同样的事情,并认为我会分享对我有用的方法。 - 山姆

【讨论】:

有没有办法在 log4j2.properties 文件中添加这些 LoggerFields。我想为 elasticsearch 5x 做它,它只支持 log4j.properties 不支持 log4j2.xml,我在网上看不到任何示例,在属性文件中看不到 LoggerFields 的文档 将此添加到属性文件不起作用 appender.sumo_syslog.loggerFields='key' : 'priority', 'value' : '%p' 您还需要加载正确的 rsyslog 模块才能解析 RFC5424 结构:module(load="mmpstrucdata") action(type="mmpstrucdata")【参考方案4】:

您可以使用 SocketAppender 和 PatternLayout 来格式化 syslog (syslog-ng) 消息。 为了支持具有固定设施的动态严重性(例如:“用户级消息” - 请参阅 RFC5424),模式应如下所示:

<Socket name="SYSLOG" host="$env:INTERFACE" port="514" protocol="UDP">
   <PatternLayout pattern="&lt;%levelTRACE=15, DEBUG=15, INFO=14, WARN=12, ERROR=11, Fatal=11,&gt;%replace$env:APPLICATION_NAME\r[%XPID] %t(%T) %c10 - %m%n"/>
</Socket>
要计算设施“用户级消息”和严重性“信息性消息”的优先级值 (PRIVAL) - 请参阅 [RFC5424](https://www.rfc-editor.org/rfc/rfc5424/))以下示例可能帮助:
Syslog:          Facility  | Severity
Numerical Code:      1          6
Bin:             0 0 0 0 1 |  1 1 0
Dec:                 8     +    6    =  14

log4j2syslog-ngsocketappenderpatternlayout

【讨论】:

【参考方案5】:

我使用了config posted by butcher82,但必须对其进行一些更改才能产生我需要的结果。

我最终得到的是一条具有正确优先级、时间戳(几天没有前导零)、主机和消息部分的消息。 syslog 和 log4J 级别之间的映射按照 org.apache.log4j.Level 中的定义使用,并且该工具设置为 1(用户级别消息),以简化优先级计算。

此模式应与 RFC-3164 兼容:

<Socket name="SysLogAppender" host="localhost" port="514" protocol="UDP">
    <PatternLayout pattern="&lt;%levelTRACE=7, DEBUG=7, INFO=6, WARN=4, ERROR=3, Fatal=0&gt;%dMMM d hh:mm:ss $hostName %m%n"/>
</Socket>

下面是生成的输出:

<3>Dec 15 09:59:16 foo.bar.hostname this is a test message

注意:可以在主机名之后添加应用程序名称或 pid。

【讨论】:

以上是关于log4j2 - Syslog 附加程序和 PatternLayout的主要内容,如果未能解决你的问题,请参考以下文章

log4j2 syslog 数据报大小超过 UDP 的限制

Mac 上的 Log4j2 Syslog Appender 格式

通过 syslog 发送 log4j2 堆栈跟踪

将 Apache Storm Log4j2 syslog appender 从 UDP 更改为 TCP

Log4j2 Syslog Appender 添加垃圾字段

如何以编程方式在运行时添加 Log4J2 附加程序?