一次接入,统一应用日志、访问日志与审计日志。
UniLog 是面向企业级 Spring Boot 应用的统一日志框架。它通过一个 Starter
收敛日志后端、结构化字段、请求关联、安全脱敏、文件滚动和采集规范,让业务团队
不再为每个项目重复维护 logback.xml、log4j2.xml 与日志平台适配代码。
项目覆盖两条兼容线:
| 兼容线 | Java | Spring Boot 基线 | Logback | Log4j2 | 推荐用途 |
|---|---|---|---|---|---|
| Legacy | 8 | 2.7.18 | 支持 | 支持 | 仅用于存量系统治理与迁移过渡 |
| Modern | 17+ | 3.5.16、4.1.0 | 支持 | 支持 | 新系统默认选择 |
两条线共享 unilog-core:业务代码只依赖 SLF4J 和统一 API,不直接依赖 Logback、Log4j2,也不需要因升级 Java 改写日志调用。
- 生产格式:单行 UTF-8 ECS JSON(NDJSON),本地开发使用可读文本。
- 三类物理通道:
application、access、audit,分别检索、滚动、限额和授权。 - 关联字段:
trace.id、span.id、request.id;自动桥接 Spring/Micrometer 常见的traceId、spanId。 - 文件滚动:UTC 按天 + 按大小双触发,GZIP 压缩,186 天时间窗,另设总容量上限。
- 容器:只写 stdout,由 Filebeat/Fluent Bit 采集,集中平台执行 186 天生命周期。
- 虚机/物理机:应用内滚动,禁止再用 logrotate 重命名同一活动文件。
- 普通日志与访问日志:有界异步、队列满时阻塞,不静默丢弃。
- 审计日志:同步、立即刷新、独立文件;强合规场景还必须进入不可变集中存储。
- 安全:控制字符中和、敏感键自动掩码、字段和值长度上限、禁止默认调用任意对象
toString()。 - 治理:字段保留区、稳定事件名、错误码命名空间、Semgrep 规则、验收脚本、容量计算器。
flowchart LR
A["Spring Boot 业务应用"] --> B["UniLog Starter"]
B --> C["application<br/>业务事件"]
B --> D["access<br/>HTTP 访问"]
B --> E["audit<br/>审计事件"]
C --> F{"输出模式"}
D --> F
E --> F
F -->|console| G["容器 stdout"]
F -->|file| H["滚动 JSON 文件"]
G --> I["Filebeat / Fluent Bit"]
H --> I
I --> J["Elasticsearch / OpenSearch"]
UniLog 负责应用侧“生成一致、可关联、可治理的日志”;采集、索引生命周期、访问控制 和不可变归档由平台侧负责。两者共同构成完整的生产日志链路。
先把本项目发布到你的 Maven 仓库,并在业务项目中导入 BOM:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.flyfish</groupId>
<artifactId>unilog-bom</artifactId>
<version>2.0.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement><dependency>
<groupId>dev.flyfish</groupId>
<artifactId>unilog-spring-boot2-starter-logback</artifactId>
</dependency>先从所有 Spring Boot starter 中排除 spring-boot-starter-logging,再引入:
<dependency>
<groupId>dev.flyfish</groupId>
<artifactId>unilog-spring-boot2-starter-log4j2</artifactId>
</dependency><dependency>
<groupId>dev.flyfish</groupId>
<artifactId>unilog-spring-boot3-starter-logback</artifactId>
</dependency><dependency>
<groupId>dev.flyfish</groupId>
<artifactId>unilog-spring-boot3-starter-log4j2</artifactId>
</dependency>最小配置:
spring:
application:
name: order-service
flyfish:
unilog:
mode: console # local | console | file | both | auto
environment: prod
retention-days: 186业务日志:
private final StructuredLogger log;
public OrderService(StructuredLoggerFactory factory) {
this.log = factory.getLogger(OrderService.class);
}
public void create(String orderId) {
log.info(
"order.created",
LogOutcome.SUCCESS,
LogFields.of("business.order.id", orderId, "business.channel", "web")
);
}异常只在处理边界记录一次:
log.error(
"order.creation.failed",
"ORDER-1007",
LogFields.of("business.order.id", orderId),
exception
);审计日志:
auditLogger.log(
AuditEvent.builder("permission.granted")
.category("iam")
.outcome(LogOutcome.SUCCESS)
.actor("user", operatorId)
.target("role", "finance-admin")
.reason(ticketNo)
.changeSummary("grant role finance-admin")
.build()
);| 模式 | 输出 | 使用场景 |
|---|---|---|
local |
可读文本 stdout | 本地开发;不得用于生产采集 |
console |
ECS JSON stdout | Kubernetes、Docker、云原生,生产默认 |
file |
ECS JSON 文件 | 虚机、物理机、纯内网部署 |
both |
stdout + 文件 | 迁移期;长期使用会导致双份成本 |
auto |
dev/local/test→local,其余→console | 默认行为 |
unilog-core/ Java 8 字节码;统一 API、上下文、安全与领域策略
unilog-logback-support/ Java 8 字节码;受控 MDC 的 ECS Logback 编码器
unilog-log4j2-support/ Java 8 字节码;受控 MDC 的 ECS Log4j2 序列化器
unilog-spring-boot2-autoconfigure/ javax.servlet;Spring Boot 2.7
unilog-spring-boot3-autoconfigure/ jakarta.servlet;Spring Boot 3/4
unilog-*-starter-logback/ Logback 一键依赖
unilog-*-starter-log4j2/ Log4j2 一键依赖
examples/ 六套完整示例
ops/ Filebeat、Fluent Bit、ILM/ISM、K8s、systemd
policies/ Semgrep、Maven Enforcer 治理模板
tools/ 架构、文档、Schema、安全与兼容性检查
scripts/ 全量构建与示例启动脚本
docs/ 架构、规范、迁移、运维与推广手册
业务服务应优先只导入 dev.flyfish.unilog.api。bootstrap、context、http、security、spring.*、logback 与 log4j2 包属于框架扩展或适配层;除明确扩展点外,不建议在业务代码中直接依赖。Java 源码禁止内联完全限定类名,统一使用显式 import;日志 XML 中的实现类名是框架插件实例化语法,不适用 Java 导入规则。
bash scripts/verify-distribution.sh
./mvnw -B -ntp clean verify
bash scripts/check-dependency-tree.sh
bash scripts/smoke-examples.shJava 8 运行时单独验证:
./mvnw -B -ntp \
-pl examples/java8-logback-demo,examples/java8-log4j2-demo \
-am verify- 在 Maven 私服中发布并锁定
dev.flyfish:unilog-bom版本,禁止业务项目直接漂移子模块版本。 - 根据真实峰值计算总容量上限;容量上限小于 186 天日志量时,会提前删除旧文件。
- 容器生产必须配置集中日志平台的 186 天生命周期,不把容器节点磁盘当长期留存介质。
- 审计日志必须进入独立索引、独立权限和不可变归档;同步本地文件不等于不可抵赖。
- Log4j2 项目必须彻底排除默认 Logback,启动时检测到双后端会直接失败。
- 生产禁止记录请求/响应正文、Cookie、Authorization、令牌、密码、身份证、银行卡等原始敏感值。
- 自动 HTTP access 日志适配 Spring MVC Servlet 栈:Boot 2 使用
javax.servlet,Boot 3/4 使用jakarta.servlet。 - WebFlux、网关自定义 Netty 管线、消息消费、批处理和定时任务仍可直接使用
unilog-core,但不会自动生成 Servlet access 事件;应在各自处理边界显式记录完成事件。 - 框架不记录请求体、响应体、SQL 参数、完整查询串或认证凭据;确有审计需求时,应先完成字段级数据分级、脱敏和审批。
- 本地文件的
totalSizeCap优先保护磁盘。当容量不足以容纳 186 天数据时,旧文件会早于 186 天删除;严格留存必须由 Elasticsearch/OpenSearch 生命周期和归档存储共同保证。 mvnw/mvnw.cmd是安全启动器,调用已安装且受信任的 Maven,不会自动下载 Maven Wrapper 二进制。CI 或开发机需预装 Maven 3.8.6+。
| 文档 | 内容 |
|---|---|
| 执行摘要 | 管理层决策、双版本基线与推广目标 |
| 架构与兼容矩阵 | 模块边界、Java/Spring Boot/Servlet 兼容关系 |
| 日志输出规范 | JSON 格式、事件名、字段与示例 |
| 级别与粒度 | TRACE/DEBUG/INFO/WARN/ERROR 使用边界 |
| 接入指南 | Maven、Gradle、配置和业务代码接入 |
| 完整配置参考 | 全量配置项、优先级、环境模板和文件布局 |
| 运维与留存 | 186 天、容量、滚动、采集与故障处理 |
| 安全与审计 | 敏感数据、日志注入、审计事件与权限 |
| 可观测性集成 | Trace、Metric、Elastic/OpenSearch 对接 |
| 迁移指南 | 存量 Logback/Log4j2 项目迁移步骤 |
| 故障排查 | 双绑定、配置未生效、磁盘与异步问题 |
| 字段字典 | 公司字段注册和 ECS 映射 |
| 推广治理 | 试点、版本治理、门禁与责任分工 |
| 验收清单 | 发布前技术、运行与合规验收 |
| 代码架构与约定 | 包边界、设计模式、API 与代码门禁 |
| 1.x → 2.x 迁移 | 坐标、包名、配置前缀和运维模板迁移 |
| 文件文档策略 | 各类文件注释与机器可读格式例外 |
| 运行时安全边界 | 可信代理、MDC、审计、失败策略与非目标 |
UniLog 采用 Apache License 2.0 开源。欢迎通过 Issue 反馈问题、通过 Pull Request 提交改进;提交前请阅读 CONTRIBUTING.md。安全漏洞不要公开披露,请按照 SECURITY.md 使用 GitHub 私密漏洞报告。
当前源码已完成 71 项离线结构与策略检查、包含 16 个模块和 23 项测试的 Maven 全量 构建、真实 JDK 8 Legacy 构建,以及六套示例的 JDK 8/21 端到端 NDJSON 冒烟测试。 CI/发布门禁可复现这些检查:
bash scripts/verify-distribution.sh
bash scripts/build-legacy-java8.sh
bash scripts/build-modern-java17.sh
JAVA8_HOME=/path/to/jdk8 JAVA17_HOME=/path/to/jdk17 bash scripts/smoke-examples.sh详细结果见 交付验证报告。