Skip to content

ELK 日志平台:日志收集与分析

日志是排查生产问题的第一手资料。

但单机日志有个问题:服务器多了,日志散落在各个机器上,查一个问题要登录多台机器、用 grep 翻日志...这是运维的噩梦。

ELK 就是来解决这个问题的。

ELK 是什么

ELK 是 Elasticsearch + Logstash + Kibana 三件套的合称:

组件作用
Elasticsearch日志存储和搜索引擎,支持全文检索
Logstash日志收集、处理、转发
Kibana可视化界面,查询和分析日志

架构图:

应用 → Filebeat → Logstash → Elasticsearch ← Kibana

Filebeat 负责从各个机器收集日志,Logstash 做解析处理,Elasticsearch 存储,Kibana 展示。

Logback 配置

把日志发送到 Logstash:

xml
<!-- logback.xml -->

<!-- TCP 方式发送到 Logstash -->
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
    <destination>logstash.example.com:5000</destination>
    <encoder class="net.logstash.logback.encoder.LogstashEncoder">
        <!-- 添加服务标识,方便过滤 -->
        <customFields>{"service":"user-service","env":"prod"}</customFields>
    </encoder>
</appender>

<!-- 文件输出(本地留存)-->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logs/application.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>logs/application.%d{yyyy-MM-dd}.log</fileNamePattern>
        <maxHistory>30</maxHistory>
    </rollingPolicy>
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

<!-- 生产环境同时输出到文件和 ELK -->
<springProfile name="prod">
    <root level="INFO">
        <appender-ref ref="FILE"/>
        <appender-ref ref="LOGSTASH"/>
    </root>
</springProfile>

JSON 格式日志

ELK 最适合处理 JSON 格式的日志:

xml
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
    <customFields>{"service":"user-service"}</customFields>
    <includeMdcKeyName>traceId</includeMdcKeyName>
    <includeMdcKeyName>userId</includeMdcKeyName>
</encoder>

输出的 JSON 日志:

json
{
  "@timestamp": "2026-03-22T10:30:00.000Z",
  "level": "INFO",
  "logger": "com.example.UserService",
  "message": "用户注册成功",
  "traceId": "abc123",
  "userId": "10001",
  "service": "user-service"
}

异步日志

日志发送到 Logstash 会增加 IO 开销,用异步 appender 来解耦:

xml
<appender name="ASYNC_LOGSTASH" class="ch.qos.logback.classic.AsyncAppender">
    <queueSize>512</queueSize>
    <discardingThreshold>0</discardingThreshold>
    <appender-ref ref="LOGSTASH"/>
</appender>
  • queueSize:队列大小,队列满了会丢弃日志
  • discardingThreshold:队列满到多少比例时丢弃,设为 0 表示队列满就丢弃

总结

  1. 架构选型:Filebeat + Elasticsearch 是中小型系统的主流选择,比 Logstash 更轻量
  2. 异步写入:不要让日志发送阻塞主线程
  3. 结构化日志:用 JSON 格式,方便检索和分析
  4. 关键字段:traceId、userId、service 这些字段对排查问题很有用

日志不是越多越好,结构清晰比数量多更重要。

基于 VitePress 构建