通过syslog发送log4j2堆栈跟踪 [英] Send log4j2 stack traces over syslog

查看:119
本文介绍了通过syslog发送log4j2堆栈跟踪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将堆栈跟踪记录到Logstash中.

I am trying to log stack traces into Logstash.

日志记录堆栈是ELK(ElasticSearch,Logstash,Kibana).

The logging stack is ELK (ElasticSearch, Logstash, Kibana).

产生日志的应用程序是一个Java应用程序,使用slf4j作为日志记录接口,并使用log4j2作为日志记录实现.

The application producing logs is a Java application, using slf4j as a logging interface, and log4j2 as the logging implementation.

log4j2.xml使用RFC5424格式声明此syslog Appender:

The log4j2.xml declares this syslog Appender, with the RFC5424 format:

<Appenders>
  <Syslog name="RFC5424" format="RFC5424" host="localhost" port="8514"
          protocol="TCP" appName="MyApp" includeMDC="true" mdcId="mdc"
          facility="LOCAL0" enterpriseNumber="18060" newLine="true"
          messageId="Audit" id="App">
    <LoggerFields>
      <KeyValuePair key="thread" value="%t"/>
      <KeyValuePair key="priority" value="%p"/>
      <KeyValuePair key="category" value="%c"/>
      <KeyValuePair key="exception" value="%ex{full}"/>
    </LoggerFields>
  </Syslog>
</Appenders>

我从Java应用程序中记录一个Throwable,如下所示:

I log a Throwable from the Java application like so:

org.slf4j.LoggerFactory.getLogger("exception_test").error("Testing errors", new RuntimeException("Exception message"));


记录到异常后,Logstash会跟踪这样的内容以向我显示其持续存在的原因:


When an exception is logged, Logstash traces something like this to show me what it persists:

{
   "@timestamp":"2016-11-08T11:08:10.387Z",
   "port":60397,
   "@version":"1",
   "host":"127.0.0.1",
   "message":"<131>1 2016-11-08T11:08:10.386Z MyComputer.local MyApp - Audit [mdc@18060 category=\"exception_test\" exception=\"java.lang.RuntimeException: Exception message",
   "type":"syslog",
   "tags":[
      "_grokparsefailure"
   ]
}

我确认Kibana在其日志条目之一的_source字段中显示了完全相同的JSON.

And I confirm that Kibana displays exactly the same JSON within the _source field of one of its log entries.

这里有一个问题:没有保存堆栈跟踪.并且测试错误"消息丢失了.

There's a problem here: no stack trace is saved. And the message, "Testing errors", is lost.

不幸的是,"tags":["_grokparsefailure"]却与此问题无关..

The "tags":["_grokparsefailure"] is unfortunate but not related to this question.

我尝试添加<ExceptionPattern/>来查看它是否会更改任何内容:

I tried adding <ExceptionPattern/> to see if it would change anything:

<Syslog name="RFC5424" format="RFC5424" host="localhost" port="8514"
        protocol="TCP" appName="MyApp" includeMDC="true" mdcId="mdc"
        facility="LOCAL0" enterpriseNumber="18060" newLine="true"
        messageId="Audit" id="App">
  <LoggerFields>
    <KeyValuePair key="thread" value="%t"/>
    <KeyValuePair key="priority" value="%p"/>
    <KeyValuePair key="category" value="%c"/>
    <KeyValuePair key="exception" value="%ex{full}"/>
  </LoggerFields>
  <ExceptionPattern>%ex{full}</ExceptionPattern>
</Syslog>

<ExceptionPattern/>替换日志消息,并且(很遗憾)忽略了所有loggerFields.但这确实给了我一个类名和行号:

<ExceptionPattern/> replaces the log message, and also (sadly) omits all loggerFields. But it does give me a class name and line number:

{
   "@timestamp":"2016-11-08T11:54:03.835Z",
   "port":60397,
   "@version":"1",
   "host":"127.0.0.1",
   "message":"at com.stackoverflow.LogTest.throw(LogTest.java:149)",
   "type":"syslog",
   "tags":[
      "_grokparsefailure"
   ]
}

再次:没有堆栈跟踪.再说一次:测试错误"消息丢失了.

Again: no stack trace. And again: the message, "Testing errors", is lost.

如何使用log4j2将堆栈跟踪记录到Logstash中?我不一定必须使用syslog附加程序.

How can I use log4j2 to log stack traces into Logstash? I don't necessarily have to use the syslog appender.

基本上,约束是:

  • 不锁定任何特定的日志记录基础结构(这就是为什么我使用syslog的原因)
  • 多行堆栈跟踪需要理解为单个日志条目. 堆栈跟踪的每一行"都不是单独的日志消息"
  • 堆栈跟踪必须能够经过过滤器.我的一个典型的例外可能是长达一整页的堆栈跟踪.我想过滤掉像Spring这样的框架.
  • Not be locked in to any particular logging infrastructure (this is why I used syslog)
  • Multi-line stack traces need to be understood as being a single log entry. It's undesirable for "each line of the stack trace" to be "a separate log message"
  • Stack traces must be able to be subjected to filters. A typical exception of mine can have a page-long stack trace. I want to filter out frames like Spring.

推荐答案

Log4j 2.5的SyslogAppender只能通过UDP发送堆栈跟踪.

Log4j 2.5's SyslogAppender can only send stack traces over UDP.

<Syslog name="RFC5424" format="RFC5424" host="localhost" port="8514"
        protocol="UDP" appName="MyApp" includeMDC="true" mdcId="mdc"
        facility="LOCAL0" enterpriseNumber="18060" newLine="true"
        messageId="LogTest" id="App">
  <LoggerFields>
    <KeyValuePair key="thread" value="%t"/>
    <KeyValuePair key="priority" value="%p"/>
    <KeyValuePair key="category" value="%c"/>
    <KeyValuePair key="exception" value="%ex{full}"/>
  </LoggerFields>
  <ExceptionPattern>%ex{full}</ExceptionPattern>
</Syslog>

使用UDP:ExceptionPattern LoggerFields.KeyValuePair["exception"]都开始作为多行堆栈跟踪的解决方案.

With UDP: both ExceptionPattern and LoggerFields.KeyValuePair["exception"] start working as solutions for multiline stack traces.

当我通过syslog通过 UDP 发送异常时,这是logstash打印的内容:

This is what logstash prints when I sent an exception over UDP via syslog:

{
    "@timestamp" => 2016-11-14T13:23:38.304Z,
      "@version" => "1",
          "host" => "127.0.0.1",
       "message" => "<131>1 2016-11-14T13:23:38.302Z BirchBox.local MyApp - LogTest [mdc@18060 category=\"com.stackoverflow.Deeply\" exception=\"java.lang.RuntimeException: Exception message\n\tat com.stackoverflow.Deeply.complain(Deeply.java:10)\n\tat com.stackoverflow.Nested.complain(Nested.java:8)\n\tat com.stackoverflow.Main.main(Main.java:20)\n\" priority=\"ERROR\" thread=\"main\"] Example error\njava.lang.RuntimeException: Exception message\n\tat com.stackoverflow.Deeply.complain(Deeply.java:10)\n\tat com.stackoverflow.Nested.complain(Nested.java:8)\n\tat com.stackoverflow.Main.main(Main.java:20)",
          "type" => "syslog",
          "tags" => [
        [0] "_grokparsefailure"
    ]
}

[mdc@18060 exception=\"…\"]内部,我们获得了 LoggerFields.KeyValuePair["exception"] 堆栈跟踪.

Inside [mdc@18060 exception=\"…\"] we get the LoggerFields.KeyValuePair["exception"] stack trace.

此外,由于ExceptionPattern,堆栈跟踪已插入到已记录的消息本身中.

In addition to this: the stack trace is inserted into the logged message itself, thanks to ExceptionPattern.

供参考:当我通过syslog通过 TCP 发送异常时,这是logstash打印的内容(即与上述相同的SyslogAppender,但使用protocol="TCP"):

For reference: this is what logstash prints when I send the exception over TCP via syslog (i.e. the same SyslogAppender as described above, but with protocol="TCP" instead):

{
    "@timestamp" => 2016-11-14T19:56:30.293Z,
          "port" => 63179,
      "@version" => "1",
          "host" => "127.0.0.1",
       "message" => "<131>1 2016-11-14T19:56:30.277Z BirchBox.local MyApp - Audit [mdc@18060 category=\"com.stackoverflow.Deeply\" exception=\"java.lang.RuntimeException: Exception message",
          "type" => "syslog",
          "tags" => [
        [0] "_grokparsefailure"
    ]
}
{
    "@timestamp" => 2016-11-14T19:56:30.296Z,
          "port" => 63179,
      "@version" => "1",
          "host" => "127.0.0.1",
       "message" => "at com.stackoverflow.Deeply.complain(Deeply.java:10)",
          "type" => "syslog",
          "tags" => [
        [0] "_grokparsefailure"
    ]
}
{
    "@timestamp" => 2016-11-14T19:56:30.296Z,
          "port" => 63179,
      "@version" => "1",
          "host" => "127.0.0.1",
       "message" => "at com.stackoverflow.Nested.complain(Nested.java:8)",
          "type" => "syslog",
          "tags" => [
        [0] "_grokparsefailure"
    ]
}
{
    "@timestamp" => 2016-11-14T19:56:30.296Z,
          "port" => 63179,
      "@version" => "1",
          "host" => "127.0.0.1",
       "message" => "at com.stackoverflow.Main.main(Main.java:20)",
          "type" => "syslog",
          "tags" => [
        [0] "_grokparsefailure"
    ]
}
{
    "@timestamp" => 2016-11-14T19:56:30.296Z,
          "port" => 63179,
      "@version" => "1",
          "host" => "127.0.0.1",
       "message" => "\" priority=\"ERROR\" thread=\"main\"] Example error",
          "type" => "syslog",
          "tags" => [
        [0] "_grokparsefailure"
    ]
}
{
    "@timestamp" => 2016-11-14T19:56:30.296Z,
          "port" => 63179,
      "@version" => "1",
          "host" => "127.0.0.1",
       "message" => "java.lang.RuntimeException: Exception message",
          "type" => "syslog",
          "tags" => [
        [0] "_grokparsefailure"
    ]
}
{
    "@timestamp" => 2016-11-14T19:56:30.297Z,
          "port" => 63179,
      "@version" => "1",
          "host" => "127.0.0.1",
       "message" => "at com.stackoverflow.Deeply.complain(Deeply.java:10)",
          "type" => "syslog",
          "tags" => [
        [0] "_grokparsefailure"
    ]
}
{
    "@timestamp" => 2016-11-14T19:56:30.298Z,
          "port" => 63179,
      "@version" => "1",
          "host" => "127.0.0.1",
       "message" => "at com.stackoverflow.Nested.complain(Nested.java:8)",
          "type" => "syslog",
          "tags" => [
        [0] "_grokparsefailure"
    ]
}
{
    "@timestamp" => 2016-11-14T19:56:30.298Z,
          "port" => 63179,
      "@version" => "1",
          "host" => "127.0.0.1",
       "message" => "at com.stackoverflow.Main.main(Main.java:20)",
          "type" => "syslog",
          "tags" => [
        [0] "_grokparsefailure"
    ]
}
{
    "@timestamp" => 2016-11-14T19:56:30.299Z,
          "port" => 63179,
      "@version" => "1",
          "host" => "127.0.0.1",
       "message" => "",
          "type" => "syslog",
          "tags" => [
        [0] "_grokparsefailure"
    ]
}

看起来TCP实际上确实在起作用",但是将单个日志消息拆分为许多个系统日志消息(例如,遇到\n时).

It looks like TCP does actually "work", but splits the single log message into many syslog messages (for example when \n is encountered).

这篇关于通过syslog发送log4j2堆栈跟踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆