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

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

<appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %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-%d{MM-dd-yyyy}-%i.log.gz">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %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="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Syslog>

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

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

【问题讨论】:

    标签: java log4j syslog log4j2


    【解决方案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;%d{MMM 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;%c{1}&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;%level{TRACE=15, DEBUG=15, INFO=14, WARN=12, ERROR=11, Fatal=11,&gt;%replace{${env:APPLICATION_NAME}}{\r}{}[%X{PID}] %t(%T) %c{10} - %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
    

    【讨论】:

      【解决方案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;%level{TRACE=7, DEBUG=7, INFO=6, WARN=4, ERROR=3, Fatal=0}&gt;%d{MMM d hh:mm:ss} ${hostName} %m%n"/>
      </Socket>
      

      下面是生成的输出:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多