如何通过Log4j2配置将Elasticsearch多行堆栈日志转为单行?
问题
需要将Elasticsearch日志推送至rsyslog,再转发到Fluentd,要求错误堆栈日志为单行格式。此前日志为多行形式(示例如下):
443 [2022-08-05T07:45:38,068][ERROR][o.e.i.g.GeoIpDownloader ] [techsrv01] exception during geoip databases update 444 org.elasticsearch.ElasticsearchException: not all primary shards of [.geoip_databases] index are active 445 at org.elasticsearch.ingest.geoip.GeoIpDownloader.updateDatabases(GeoIpDownloader.java:137) ~[ingest-geoip-7.17.5.jar:7.17.5] 446 at org.elasticsearch.ingest.geoip.GeoIpDownloader.runDownloader(GeoIpDownloader.java:284) [ingest-geoip-7.17.5.jar:7.17.5] 447 at org.elasticsearch.ingest.geoip.GeoIpDownloaderTaskExecutor.nodeOperation(GeoIpDownloaderTaskExecutor.java:100) [ingest-geoip-7.17.5.jar:7.17.5] 448 at org.elasticsearch.ingest.geoip.GeoIpDownloaderTaskExecutor.nodeOperation(GeoIpDownloaderTaskExecutor.java:46) [ingest-geoip-7.17.5.jar:7.17.5] 449 at org.elasticsearch.persistent.NodePersistentTasksExecutor$1.doRun(NodePersistentTasksExecutor.java:42) [elasticsearch-7.17.5.jar:7.17.5] 450 at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:777) [elasticsearch-7.17.5.jar:7.17.5] 451 at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:26) [elasticsearch-7.17.5.jar:7.17.5] 452 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?] 453 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?] 454 at java.lang.Thread.run(Thread.java:833) [?:?]
修改log4j2.properties中的pattern layout为以下格式后,日志变为两行,无法合并为单行:
appender.rolling_old.layout.pattern =
[%d{ISO8601}][%-5p][%-25c{1.}][%node_name] %marker %m %n
%throwable{separator(|)}
修改后的日志示例:
2028 [2022-08-05T11:04:40,810][ERROR][o.e.i.g.GeoIpDownloader ][techsrv01] exception during geoip databases update 2029 ElasticsearchException[not all primary shards of [.geoip_databases] index are active]| at org.elasticsearch.ingest.geoip.GeoIpDownloader.updateDatabases(GeoIpDownloader.java:137)| at org.elasticsearch.ingest.geoip.GeoIpDownloader.runDownloader(GeoIpDownloader.java:284)| at org.elasticsearch.ingest.geoip.GeoIpDownloaderTaskExecutor.nodeOperation(GeoIpDownloaderTaskExecutor.java:100)| at org.elasticsearch.ingest.geoip.GeoIpDownloaderTaskExecutor.nodeOperation(GeoIpDownloaderTaskExecutor.java:46)| at org.elasticsearch.persistent.NodePersistentTasksExecutor$1.doRun(NodePersistentTasksExecutor.java:42)| at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:777)| at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:26)| at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)| at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)| at java.base/java.lang.Thread.run(Thread.java:833)[2022-08-05T11:04:41,171][INFO ][o.e.c.r.a.AllocationService][techsrv01] Cluster health status changed from [RED] to [GREEN] (reason: [shards started [[.ds-ilm-history-5-2022.07.18-000001][0], [.kibana-event-log-7.17.5-000001][0], [.geoip_databases][0], [.ds-.logs-deprecation.elasticsearch-default-2022.07.18-000001][0]]]).
解决方案
问题出在当前pattern里的%n会在日志消息末尾插入换行符,导致堆栈信息被分到下一行。要实现单行日志,需要调整pattern的结构:
修改后的log4j2 pattern配置如下:
appender.rolling_old.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}][%node_name] %marker %m%throwable{separator(|)}%n
配置说明:
- 移除原配置中
%m后的%n,避免日志消息和堆栈信息之间出现换行 - 将
%throwable{separator(|)}直接紧跟在%m之后,让堆栈信息直接拼接在日志消息末尾 - 只保留最后一个
%n,用于分隔不同的日志条目,确保每条完整日志结束后换行,不会和下一条日志粘连
这样配置后,包含堆栈的错误日志会完全变为单行,满足rsyslog和Fluentd的处理要求。
内容的提问来源于stack exchange,提问作者Gautam
相关产品推荐
相关产品推荐

