2016-11-08 10 views
1

Я пытаюсь записывать трассировки стека в Logstash.Отправить трассировку стека log4j2 по syslog

Стек протоколирования - ELK (ElasticSearch, Logstash, Kibana).

Журналы, производящие приложения, представляют собой приложение Java, используя slf4j в качестве интерфейса ведения журнала и log4j2 в качестве реализации ведения журнала.

log4j2.xml объявляет эту syslog Appender, с форматом RFC5424:

<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> 

Я вхожу Throwable из приложения Java, как так:

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

Когда исключение регистрируется, Logstash отслеживает что-то вроде этого, чтобы показать мне, что он сохраняется:

{ 
    "@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 [[email protected] category=\"exception_test\" exception=\"java.lang.RuntimeException: Exception message", 
    "type":"syslog", 
    "tags":[ 
     "_grokparsefailure" 
    ] 
} 

И я подтверждаю, что Kibana отображает точно такой же JSON в поле _source одной из своих записей в журнале.

Здесь есть проблема: трассировка стека не сохраняется. И сообщение «Ошибки тестирования» теряется.

"tags":["_grokparsefailure"] несчастливо, но не имеет отношения к этому вопросу.


Я попытался добавить <ExceptionPattern/>, чтобы увидеть, если это изменит что-нибудь:

<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. Но это дает мне название класса и номер строки:

{ 
    "@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" 
    ] 
} 

Снова: нет трассировки стека. И снова: сообщение «Ошибки тестирования» теряется.


Как я могу использовать log4j2 войти трассировки стека в Logstash? Мне необязательно использовать приложение syslog.

По существу ограничения:

  • Не быть заблокирован в какой-либо конкретной лесозаготовительной инфраструктуры (именно поэтому я использовал системный журнал)
  • стек Многоканальный прослеживает нужно понимать как единый журнал запись. Нежелательно, чтобы «каждая строка трассировки стека» была «отдельным сообщением журнала»
  • Следы стека должны быть подвергнуты фильтрам. Типичное исключение моей может иметь трассировку стека страниц. Я хочу отфильтровать рамки, такие как Spring.

ответ

1

Log4j 2.5 SyslogAppender может отправлять только трассировки стека по 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"] начинают работать в качестве решений для многопоточных трассировки стека.

Это то, что logstash печатает, когда я послал исключение через UDP через системный журнал:

{ 
    "@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 [[email protected] 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" 
    ] 
} 

Внутри [[email protected] exception=\"…\"] мы получим трассировки стека LoggerFields.KeyValuePair["exception"].

В дополнение к этому: трассировка стека вставлена ​​в само регистрируемое сообщение, благодаря ExceptionPattern.


Для справки: это то, что logstash печатает, когда я посылаю исключение над TCP через системный журнал (то есть один и тот же SyslogAppender, как описано выше, но с protocol="TCP" вместо этого):

{ 
    "@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 [[email protected] 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 действительно «работает», но разбивает одно сообщение журнала на много сообщений syslog (например, когда встречается \n).

 Смежные вопросы

  • Нет связанных вопросов^_^