Log4j 如何与 Logstash 集成(Java 日志进 ELK)?
Log4j/Log4j2 与 Logstash 集成:Logback 可用 logstash-logback-encoder,Log4j2 使用自身 SocketAppender;也可写文件由 Filebeat 采集。Log4j1 已废弃不建议新项目使用。本文对比各方案。
三种集成方式:一、Socket Appender 经 TCP/UDP 直发 Logstash;二、写日志文件,Filebeat 采集转发(可缓冲临时后端故障);三、Log4j2 的 SocketAppender 配合 Logstash tcp input。新项目建议用 Log4j2 或 Logback,Log4j1 早已停止维护。
方案一:Logback/Log4j2 TCP 直发(JSON)
Logback 项目用 logstash-logback-encoder,不适用于 Log4j2 后端;示例 7.4 要求 Logback 1.3+,需核对项目依赖兼容性:
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>7.4</version>
</dependency>
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>logstash-host:5000</destination>
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>
Logstash 侧:
input {
tcp {
port => 5000
codec => json_lines
}
}
方案二:写文件 + Filebeat 采集(生产推荐)
应用正常写日志文件,Filebeat 读取并转发:
filebeat.inputs:
- type: filestream
id: myapp-logs
paths: [/var/log/myapp/*.log]
output.logstash:
hosts: ["logstash-host:5044"]
优点:应用与日志后端解耦;临时故障可由仍保留的文件缓冲,但磁盘满、文件过早轮转删除、主机丢失等仍会丢数据。5044 端需配置 Logstash beats input,不能用上面的原始 TCP input;JSON 或多行解析按实际文件格式配置。
方案三:Log4j2 SocketAppender
<Socket name="logstash" host="logstash-host" port="5000" protocol="TCP">
<JsonLayout compact="true" eventEol="true" properties="true"/>
</Socket>
上述 Socket 片段放在 Appenders 中,并在对应 Logger 下添加 AppenderRef;JsonLayout 还需文档要求的 Jackson 运行时依赖。
常见问题(FAQ)
Q:Log4j1 还能用吗?
A:Log4j1 已于 2015 年停止维护,且存在已知安全问题。新项目用 Log4j2 或 Logback。
Q:TCP 直发会阻塞应用吗?
A:Log4j2 同步 SocketAppender 可能等待或失败;异步队列需考虑满队列策略。Logback 的 LogstashTcpSocketAppender 已内置异步,无需重复包装,也可采用文件采集。
Q:JSON 里想带 TraceID?
A:Logback/SLF4J 把 TraceID 放进 MDC(MDC.put("traceId", ...)),LogstashEncoder 可包含这些字段;Log4j2 API 使用 ThreadContext,并启用相应布局字段,任务结束时清理或恢复上下文。接入追踪时,应按所用探针与日志框架的配置注入标识,并检查上下游日志中的值是否一致。