syslog転送のログは下記のようにPRIとHEADERが先頭に記述されています。
<14>1 2018-10-29T08:31:37.341536+00:00 loggregator 05ad060f-ae0b-44c3-b9e8-091ad9f70878 [APP/PROC/WEB] - - 2018-10-29 08:31:37.331 hostname WARN Log4j2DemoApplication: - Hey, This is a warning!
このログでのjavaのスタックトレースを含んでいる場合は下記のような形で転送されてきます。
<14>1 2018-10-29T08:31:37.341536+00:00 loggregator 05ad060f-ae0b-44c3-b9e8-091ad9f70878 [APP/PROC/WEB] - - 2018-10-29 08:31:37.331 hostname WARN Log4j2DemoApplication: - Hey, This is a warning! <14>1 2018-10-29T08:31:37.348936+00:00 loggregator 05ad060f-ae0b-44c3-b9e8-091ad9f70878 [APP/PROC/WEB] - - at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:771) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE] <14>1 2018-10-29T08:31:37.348946+00:00 loggregator 05ad060f-ae0b-44c3-b9e8-091ad9f70878 [APP/PROC/WEB] - - at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
ログの先頭をヘッダー込みの日付でパターンを指定する必要があるためinputを下記のように記述します。
input { tcp { port => 51000 codec => multiline { pattern => "<%{POSINT}>%{POSINT}%{SPACE}%{SYSLOGTIMESTAMP}|%{SPACE}%{SYSLOGHOST}%{SPACE}[0-9a-f\-]+%{SPACE}\[[A-Z/]+\]%{SPACE}-%{SPACE}-%{SPACE}%{TIMESTAMP_ISO8601}" negate => true what => "previous" } } }
しかし、これだけだとスタックトレースの部分がそのまま末尾に追記されるためヘッダーが残ってしまいます。
下記のように残ったヘッダをフィルタで削除します。
filter { mutate { gsub => [ "message", "[0-9]+ <[0-9]+>[0-9]+ [0-9TZ:.+-]+ [a-zA-Z_-]+ [0-9a-f-]+ \[[A-Z/]+\] - - ", "" ] } }
これでsyslog転送したファイルもマルチラインでの取り込みが可能となります。
やや力技ですが他に良い方法は見つかりませんでした。
なお、下記のstackoverflowのQAを参考にしています。
https://stackoverflow.com/questions/28433265/logstash-multiline-with-syslog
今回、javaのログに対してlogstashでタグ付けしてDatadogに格納したいという要望がありましたので無理やり設定方法を捜しました。
そもそも今回のようにjavaのログをテキストで出力して転送しているのが間違いかもしれません。
logstashを使用する想定であればjsonで出力して連携すればこの問題は発生しません。