🌟 Spring Boot + Filebeat + ELK 实现日志在线展示全流程(含Docker部署与完整源码)

🚀 适用版本:Spring Boot 3.x + ELK 8.x
🧩 适用场景:日志监控 / 异常分析 / 实时日志面板展示


🧭 一、为什么要用 ELK 收集日志?

在微服务架构下,每个服务都会产生日志。
传统方案查看日志要登录多台服务器,非常麻烦;而 ELK(Elasticsearch + Logstash + Kibana) 提供了一套高效的日志采集、分析与可视化方案。

ELK 日志链路:

Spring Boot → Filebeat → Logstash → Elasticsearch → Kibana

作用说明:

组件 作用
Spring Boot 产生日志(logback 输出文件)
Filebeat 轻量级日志收集器,实时监听日志文件
Logstash 对日志进行过滤、解析、清洗
Elasticsearch 存储与索引日志
Kibana 可视化展示与检索界面

Docker Compose 安装ELK


🏗️ 二、整体架构图

采集日志
转换与过滤
存储索引
Spring Boot 日志输出 - logback
Filebeat 轻量级日志收集器
Logstash 日志清洗与结构化
Elasticsearch 搜索分析引擎
Kibana Web 可视化展示

📊 说明:

  • Spring Boot:产生日志(logback 输出文件)
  • Filebeat:采集日志文件并发送到 Logstash
  • Logstash:解析日志、结构化清洗
  • Elasticsearch:存储与索引
  • Kibana:日志可视化展示

⚙️ 三、Spring Boot 日志配置(logback-spring.xml)

src/main/resources/logback-spring.xml 添加以下配置,让日志同时输出到控制台和文件。

<configuration>
    <!-- 定义 JSON 日志文件输出 -->
    <appender name="JSON_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>/opt/logs/filebeat-demo.log</file>

        <!-- 每天生成一个新文件 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>/opt/logs/filebeat-demo-%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>14</maxHistory>
        </rollingPolicy>

        <!-- 输出为 JSON 格式 -->
        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp>
                    <timeZone>Asia/Shanghai</timeZone>
                </timestamp>
                <pattern>
                    <pattern>
                        {
                        "timestamp": "%d{yyyy-MM-dd HH:mm:ss.SSS}",
                        "level": "%level",
                        "thread": "%thread",
                        "logger": "%logger",
                        "message": "%msg",
                        "exception": "%ex"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
    </appender>

    <!-- 控制台输出(方便本地调试) -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="JSON_FILE"/>
        <appender-ref ref="CONSOLE"/>
    </root>
</configuration>


🧩 四、Filebeat 配置(filebeat.yml)

Filebeat 用来采集 Spring Boot 日志文件并发送给 Logstash。

filebeat.inputs:
  - type: log
    enabled: true
    paths:
      - /opt/logs/filebeat-demo.log   # ✅ 容器挂载路径
    json.keys_under_root: true
    json.add_error_key: true
    json.message_key: message
    multiline.pattern: '^{'
    multiline.negate: true
    multiline.match: after

output.logstash:
  hosts: ["logstash:5044"]

关键点说明

  • paths:Spring Boot 日志文件路径。
  • multiline:避免多行堆栈日志被拆分。
  • output.logstash:日志最终发往 Logstash。

🔧 五、Logstash 配置(pipeline/logstash.conf)

Logstash 接收 Filebeat 的数据,清洗并存入 Elasticsearch。

#################################################
# Logstash Pipeline 配置文件(生产推荐版)
# 功能:Filebeat -> Logstash -> Elasticsearch
# 支持:Spring Boot JSON / 系统日志 / DNF / 通用 App 日志
#################################################

input {
  #################################################
  # Filebeat 输入
  # Filebeat 会通过 beats 协议推送日志
  #################################################
  beats {
    port => 5044
  }
}

filter {
  #################################################
  # 1️⃣ 提取 Filebeat 自定义字段(例如 appname)
  #################################################
  mutate {
    add_field => { "appname" => "%{[fields][appname]}" }
  }

  #################################################
  # 2️⃣ 解析 Spring Boot JSON 格式日志(最推荐)
  # 示例:
  # {"@timestamp":"2025-10-09T15:30:02.331+08:00","level":"INFO","logger":"com.example.FilebeatDemo","message":"启动成功"}
  #################################################
  if [appname] == "filebeat-demo" or [fileset][module] == "springboot" {
    json {
      source => "message"
      target => "json"
    }

    mutate {
      rename => { "[json][message]" => "msg" }
      rename => { "[json][level]" => "log.level" }
      rename => { "[json][logger]" => "logger" }
      rename => { "[json][@timestamp]" => "@timestamp" }
      remove_field => [ "json" ]
    }
  }

  #################################################
  # 3️⃣ DNF 日志(Linux 软件包管理日志)
  # 示例:
  # 2025-09-28T08:53:19+0800 DDEBUG Plugins were unloaded.
  #################################################
  else if [appname] == "dnf" {
    grok {
      match => { "message" => "%{TIMESTAMP_ISO8601:logtime}\s+%{WORD:log.level}\s+%{GREEDYDATA:msg}" }
    }
    date {
      match => ["logtime", "yyyy-MM-dd'T'HH:mm:ssZ"]
      target => "@timestamp"
    }
  }

  #################################################
  # 4️⃣ 系统日志 (/var/log/messages)
  # 示例:
  # Sep 28 09:02:08 localhost NetworkManager[753]: <info> ...
  #################################################
  else if [appname] == "system" {
    grok {
      match => {
        "message" => "%{SYSLOGTIMESTAMP:logtime} %{HOSTNAME:host} %{DATA:program}(?:\[%{POSINT:pid}\])?: %{GREEDYDATA:msg}"
      }
    }

    date {
      match => ["logtime", "MMM  d HH:mm:ss", "MMM dd HH:mm:ss"]
      target => "@timestamp"
      timezone => "Asia/Shanghai"
    }

    # ruby 动态提取日志级别(info/warn/err/crit)
    ruby {
      code => '
        msg = event.get("msg")
        level = "INFO"
        if msg
          m = msg.match(/<(info|err|warn|crit|alert|emerg)>/i)
          if m
            case m[1].downcase
            when "err" then level = "ERROR"
            when "warn" then level = "WARN"
            when "crit", "alert", "emerg" then level = "FATAL"
            end
          end
        end
        event.set("log.level", level)
      '
    }
  }

  #################################################
  # 5️⃣ 其他通用应用日志
  # 示例:
  # [ERROR] something bad happened
  #################################################
  else {
    grok {
      match => { "message" => "\[%{LOGLEVEL:log.level}\]\s+%{GREEDYDATA:msg}" }
      overwrite => [ "log.level" ]
    }
  }

  #################################################
  # 6️⃣ 清理无用字段
  #################################################
  mutate {
    remove_field => ["logtime", "ecs", "agent", "input", "host", "[fields]", "[@version]"]
  }
}

#################################################
# 输出部分:生产建议使用 Elasticsearch
# 支持用户认证
#################################################
output {
  elasticsearch {
    hosts => ["http://elasticsearch:9200"]
    user => "elastic"          # ← 修改为你的账户
    password => "changeme"     # ← 修改为你的密码
    index => "filebeat-logs-%{+YYYY.MM.dd}"
    ilm_enabled => false       # 若不启用索引生命周期管理
  }

  #################################################
  # 控制台输出(仅开发调试)
  #################################################
  stdout {
    codec => rubydebug
  }
}


🐳 六、Docker Compose 一键启动环境

新建文件 docker-compose.yml

version: '3.9'  # 使用新版本 Compose 文件格式

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
      - ES_JAVA_OPTS=-Xms1g -Xmx1g
      - xpack.security.enabled=true
      - ELASTIC_PASSWORD=changeme
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - ./es_data:/usr/share/elasticsearch/data  # 数据持久化
      - ./elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro  # 可选 ES 配置
    ports:
      - "9200:9200"

  logstash:
    image: docker.elastic.co/logstash/logstash:8.15.0
    container_name: logstash
    volumes:
      - ./pipeline/:/usr/share/logstash/pipeline/:ro  # 挂载目录而不是单文件
    ports:
      - "5044:5044"  # Beats input 默认端口
    depends_on:
      - elasticsearch

  kibana:
    image: docker.elastic.co/kibana/kibana:8.15.0
    container_name: kibana
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
      - SERVER_NAME=kibana
      - I18N_LOCALE=zh-CN    # 设置中文界面
      - ELASTICSEARCH_USERNAME=kibana_user
      - ELASTICSEARCH_PASSWORD=kibanapwd
    ports:
      - "5601:5601"
    volumes:
      - ./kibana/data:/usr/share/kibana/data
    depends_on:
      - elasticsearch

  filebeat:
    image: docker.elastic.co/beats/filebeat:8.15.0
    container_name: filebeat
    user: root
    volumes:
      - ./filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro  # 映射修改后的配置文件
      - /var/log:/var/log:ro                # 采集宿主机日志
      - /opt/logs:/opt/logs:ro     # ✅ 挂载 Spring Boot 日志路径
    depends_on:
      - logstash
    command: ["/usr/share/filebeat/filebeat", "-e", "-d", "*"]  # 显式指定文件路径和命令

执行命令启动:

docker compose up -d

💻 七、Spring Boot 示例代码

@RestController
@RequestMapping("/log")
public class DemoController {

    private static final Logger logger = LoggerFactory.getLogger(DemoController.class);

    @GetMapping("/test")
    public String test() {
        logger.info("访问 /log/test 成功!");
        logger.warn("这是一个警告日志");
        logger.error("这是一个错误日志,用于测试 ELK 采集");
        return "日志已写入!";
    }
}

打包上传到服务器,启动

nohup java -jar Spring-Boot-ELK-0.0.1-SNAPSHOT.jar > /opt/logs/filebeat-demo.log 2>&1 &

访问接口:

http://服务器ip:8080/log/test

💡 稍等几秒钟,就能在 Kibana 的 Discover 面板 实时看到日志。


📊 八、Kibana 可视化仪表板

  1. 打开浏览器访问:http://localhost:5601
  2. 进入 Stack Management → Index Patterns
  3. 新建索引模式:filebeat-logs-*
  4. 时间字段选择:@timestamp

创建完成后,即可在 Kibana → Discover 页面实时查看日志。

推荐 Dashboard 组件

类型 字段 功能
饼图 level.keyword 查看 INFO/WARN/ERROR 比例
折线图 @timestamp 查看日志趋势
表格 logger, msg 查看最新日志
过滤 app.keyword, env.keyword 多应用环境筛选

🚀 九、进阶优化建议

功能 实现方式
🔁 结构化日志 使用 logstash-logback-encoder 输出 JSON 格式日志
🔒 安全认证 开启 Elasticsearch + Kibana xpack 安全机制
📦 多应用接入 每个服务输出独立索引:appname-%{+YYYY.MM.dd}
🔍 异常追踪整合 结合 SkyWalking / Zipkin / Sentry,实现链路日志分析
☁️ 云原生部署 ELK 可部署在 K8s 集群中,通过 Helm 一键安装

🏁 十、总结

通过本篇教程,你可以:

✅ 使用 Docker 快速搭建完整 ELK 环境
✅ 利用 Filebeat 自动采集 Spring Boot 日志
✅ 在 Kibana 上实时查看、分析日志
✅ 支持多服务、多环境扩展

从此告别 SSH 登录查日志的痛苦,ELK 让日志监控更智能、更直观!


📦 项目结构总览

springboot-elk-demo/
├── docker-compose.yml
├── filebeat.yml
├── pipeline/
│   └── logstash.conf
├── logs/
├── src/
│   └── main/
│       ├── java/com/example/elk/
│       │   ├── DemoController.java
│       └── resources/
│           ├── application.yml
│           └── logback-spring.xml
├── pom.yml

📚 附录:完整源码

pom.yml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springboot-elk-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Spring-Boot-ELK</name>
    <description>Spring-Boot-ELK</description>

    <properties>
        <java.version>17</java.version>
        <spring.boot.version>3.2.5</spring.boot.version>
    </properties>

    <dependencies>
        <!-- Spring Boot 基础 Web 模块 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- JSON 日志输出(Logstash Encoder) -->
        <dependency>
            <groupId>net.logstash.logback</groupId>
            <artifactId>logstash-logback-encoder</artifactId>
            <version>7.4</version>
        </dependency>

        <!-- 单元测试 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>


Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐