跳转到正文

日志存储

日志存储模块接收 Component 生成的 SystemLog。应用可以选择一个后端,也可以让一条日志同时保存到多个位置。

本页以已完成基础接入为前提。所有存储坐标的 groupId 为 com.own.business,artifactId 为 springboot-business-system-log-persistence-<backend>

文件开关和 Java 包名的升级映射见接入调整

选择存储后端

backend保存位置查询能力历史迁移
rdbmsown_system_log 表及部署配置的分表分页、详情、链路源与目标
mongodbown_system_log 集合分页、详情、链路源与目标
elasticsystem-log 索引分页、详情、链路、统计源与目标
clickhouseown_system_log 专用列式表分页、详情、链路源与目标
file-json按日期追加完整日志 JSON Lines仅目标,须有完整快照
file-csv按日期追加 CSV仅目标
file-rdbms按日期追加 SQL,可压缩为 ZIP仅目标

数据库后端需要配置对应连接和存储结构;文件后端无需数据库连接。RDBMS 与 ClickHouse 的初始化脚本分别位于其源码模块的 database/own_system_log.sql,二者表结构不同。

七种存储都可参与实时保存和 MQ 消费;历史迁移需另外引入对应的 migration 模块;JSON 迁移要求源记录有完整 extra.systemLog 快照。

数据库、CSV 和 SQL 将日志映射为各自的存储模型,完整原始记录位于 extra.systemLog。JSON Lines 每行直接保存一个 SystemLog,原始事件 ID 就是顶层 id,不增加这层包装。

JSON Lines 文件

添加 springboot-business-system-log-persistence-file-json 后配置:

yaml
own:
  system-log:
    file-json:
      save-path: ./logs/system-log/json
      file-prefix: system-log
      write-batch-size: 32
      persistence: true

配置前缀为 own.system-log.file-jsonsave-path 必须在非空输入写入前配置;file-prefix 默认 system-log,仅允许字母、数字、下划线和连字符;write-batch-size 默认 32,必须大于零;保存器默认启用。

快速开始的接口示例触发采集后,日志会追加到 system-log_yyyy-MM-dd.jsonl。文件日期取 operation.startedAt 在 Asia/Shanghai 时区对应的日期,每个物理行是一个完整 SystemLog,以 LF 结束。文件没有表头、数组括号或记录间逗号,应逐行解析。

原始事件 ID、身份、服务名、操作、响应及快照状态直接保留。时间使用 ISO-8601,保留原始 Instant 精度;字段中的引号和换行正常转义,字段命名与时间格式不受应用自定义 ObjectMapper 配置影响。

下面展开一条日志以便阅读,实际文件仍每行保存一条。事件 ID、身份和时间为示例值,响应对应快速开始中的 R.success("pong")

查看完整记录示例
json
{
  "id": "log-001",
  "operator": {
    "type": "ANONYMOUS",
    "id": null,
    "name": null,
    "client": "web",
    "ip": "127.0.0.1"
  },
  "operation": {
    "module": "日志演示",
    "name": "测试日志",
    "code": "log.demo.ping",
    "requestMethod": "GET",
    "requestPath": "/log-demo/ping",
    "startedAt": "2026-09-09T01:00:00Z",
    "requestParams": {
      "json": "null",
      "status": "OMITTED",
      "reason": "DISABLED"
    },
    "authenticatedUserId": null
  },
  "response": {
    "httpStatus": 200,
    "code": "00000",
    "message": "请求成功",
    "data": {
      "json": "\"pong\"",
      "status": "CAPTURED",
      "reason": null
    },
    "success": true,
    "completedAt": "2026-09-09T01:00:00.012Z"
  },
  "traceId": "trace-001",
  "serviceName": "log-demo",
  "durationMillis": 12,
  "extra": {
    "json": "null",
    "status": "OMITTED",
    "reason": "NOT_PROVIDED"
  }
}

JsonSnapshot.json 是快照文本,嵌入外层 JSON 时正常转义。读取行对象后,可按需再次解析;例如上面的 response.data.json 再解析后得到字符串 pong

显式保存

模块自动注册 SystemLogFileJsonService 和保存器。已有完整日志时,可注入 com.own.business.system.log.persistence.file.json.service.SystemLogFileJsonService,调用 save(SystemLog)save(Collection<SystemLog>)save(Iterable<SystemLog>)

集合或迭代源为 null 或为空时不创建文件;单条日志不能为空。每条记录须有非空白 ID、发起人对象、操作开始时间和响应完成时间,文件端不生成替代身份或时间。

显式调用服务不经过 Component 记录器,不应用采集开关或重新限制快照。关闭 file-json.persistence 后服务仍可注入,但不再参与实时分发或 MQ 消费;作为 MQ 保存目标时须保留该开关。

JSON 文件不提供查询、读取 API 或压缩。历史迁移需额外引入 springboot-business-system-log-migration-file-json,以 FILE_JSON 作为目标;接入与快照要求见迁移到 JSON Lines 文件FILE_JSON 不能用作查询来源。

CSV 文件

添加 springboot-business-system-log-persistence-file-csv 后配置:

yaml
own:
  system-log:
    file-csv:
      save-path: ./logs/system-log/csv
      file-prefix: system-log
      write-batch-size: 32
      persistence: true
配置默认值说明
save-path必须配置;不存在时自动创建目录
file-prefixsystem-log字母、数字、下划线和连字符
write-batch-size32每批追加条数,必须大于零
persistencetrue注册保存器,参与实时分发或 MQ 消费

文件按请求日期命名为 system-log_yyyy-MM-dd.csv,使用 UTF-8。首次写入固定表头,共 26 列;字段中的引号、逗号和换行按 CSV 规则保留,结构化数据写为 JSON。

CSV 保留原字符串 ID 和已有时间;缺少 ID 时生成 UUID。完整采集内容保存在 extra.systemLog。该模块提供文件写入,不提供 CSV 读取、查询或压缩。

SQL 文件

添加 springboot-business-system-log-persistence-file-rdbms 后配置:

yaml
own:
  system-log:
    file-rdbms:
      save-path: ./logs/system-log/sql
      file-prefix: system-log
      write-batch-size: 32
      persistence: true
      compress:
        enable: false
        is-delete-origin: false

目录、前缀、批次和保存器开关的默认值与 CSV 一致,两项压缩开关默认均为 false

文件名为 system-log_yyyy-MM-dd.sql,逐条追加 MySQL 风格的 INSERT IGNORE。模块只生成语句,不执行 SQL、不创建表,也不要求数据库连接。

目标表由实体分片决定:空分片写 own_system_log,非空写 own_system_log_<sharding>。实时保存器和迁移适配器默认按 yyyyQQ 生成季度后缀,例如 2026 年第三季度为 202603。导入前须准备对应表并核对数据库方言。

通过 SystemLogFileRdbmsService.compress() 显式压缩,或在文件迁移成功结束时压缩。启用后生成 .sql.zip;仅 is-delete-origin=true 时删除原 SQL。实时保存不会自动触发压缩,应在停止向目标文件写入后安排压缩。

ClickHouse

添加 springboot-business-system-log-persistence-clickhouse,使用该模块的建表脚本准备数据库和表,然后配置:

yaml
own:
  system-log:
    clickhouse:
      url: jdbc:clickhouse:http://localhost:8123/default
      username: default
      password: ${CLICKHOUSE_PASSWORD:}
      table: own_system_log
      query-timeout-seconds: 30
      batch-size: 1000
      persistence:
        enabled: true
      driver-properties:
        connection_timeout: "10000"
        socket_timeout: "30000"

配置 url 后装配专用 JDBC 保存和查询能力。它不注册应用通用 DataSourceJdbcTemplate,不共享业务事务。连接使用 HTTP 8123 或 HTTPS 8443 端口。

表采用 ReplacingMergeTree,排序键为 (request_time, id),查询使用 FINAL。重复投递同一事件时须保留原请求时间;同 ID 不同请求时间仍是不同排序键。

同时保存到多个位置

例如同时引入 persistence-mongodbpersistence-file-csvpersistence-file-json(完整 artifactId 使用本页开头的前缀),配置 MongoDB 连接后使用:

yaml
own:
  system-log:
    enabled: true
    service-name: account-service
    mongodb:
      persistence:
        enabled: true
    file-json:
      save-path: ./logs/system-log/json
      persistence: true
    file-csv:
      save-path: ./logs/system-log/csv
      persistence: true

一次采集会调用三个保存器,无需开启迁移。文件后端设为 persistence=false,数据库后端设为 persistence.enabled=false,可让对应后端退出实时分发,同时保留该模块已有的查询或显式保存服务;文件模块本身仍不提供查询。

默认记录器按 Spring Order 依次调用后端,单个后端异常后仍尝试其余后端。没有跨后端事务或自动重试,已成功的写入不会回滚;各后端需配置自身 I/O 超时。

查询来源单独配置,见日志查询。多处保存不会自动合并查询结果。

文件写入约定

JSON、CSV 和 SQL 都向文件末尾追加,不加载或重写历史文件。保存服务按 write-batch-size 消费当前批次,支持单条、集合和惰性 Iterable;追加使用进程内锁和文件锁。每批处理完才读取下一批,内存仍受当前批次和单条日志大小影响。

JSON 文件追加前只读取最后一个字节,缺少 LF 时保留原文件并拒绝追加,需先核对并处理不完整尾行。此检查不解析历史 JSON,也不会自动修复文件。每批追加完成后强制刷写文件内容,所有写入方应遵守同一文件锁协议。

写入或输入迭代异常会传播给调用方,已经追加的部分不会回滚;磁盘故障或进程中断仍可能留下部分内容。重复提交或 MQ 重投可能重复追加;JSON、CSV、SQL 作为迁移目标时,迁移重跑也可能产生重复内容。文件层不自动去重。