外观
日志存储
日志存储模块接收 Component 生成的 SystemLog。应用可以选择一个后端,也可以让一条日志同时保存到多个位置。
本页以已完成基础接入为前提。所有存储坐标的 groupId 为 com.own.business,artifactId 为 springboot-business-system-log-persistence-<backend>。
文件开关和 Java 包名的升级映射见接入调整。
选择存储后端
| backend | 保存位置 | 查询能力 | 历史迁移 |
|---|---|---|---|
rdbms | own_system_log 表及部署配置的分表 | 分页、详情、链路 | 源与目标 |
mongodb | own_system_log 集合 | 分页、详情、链路 | 源与目标 |
elastic | system-log 索引 | 分页、详情、链路、统计 | 源与目标 |
clickhouse | own_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-json。save-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-prefix | system-log | 字母、数字、下划线和连字符 |
write-batch-size | 32 | 每批追加条数,必须大于零 |
persistence | true | 注册保存器,参与实时分发或 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 保存和查询能力。它不注册应用通用 DataSource 或 JdbcTemplate,不共享业务事务。连接使用 HTTP 8123 或 HTTPS 8443 端口。
表采用 ReplacingMergeTree,排序键为 (request_time, id),查询使用 FINAL。重复投递同一事件时须保留原请求时间;同 ID 不同请求时间仍是不同排序键。
同时保存到多个位置
例如同时引入 persistence-mongodb、persistence-file-csv 和 persistence-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 作为迁移目标时,迁移重跑也可能产生重复内容。文件层不自动去重。