外观
日志业务重点文件与方法
Java 包名及文件开关的升级映射见接入调整。
重点覆盖跨后端查询门面、MQ 协议与投递、JSON Lines 保存以及迁移编排。采集上下文和记录器见 Component 日志方法,具体后端选择见日志存储。
本页按重点文件查阅方法;表内方法名可打开源码。重载共享的约束写在表前,差异在各行说明。源码链接固定到核对版本,接入前提见快速开始。
SystemLogQueryService
查询门面。每次调用从 ObjectProvider 按 own.system-log.query.backend 选择唯一候选;未设置 backend 时也必须恰好只有一个 Provider,否则抛业务异常。构造器由 Lombok 生成,参数是 ObjectProvider<SystemLogQueryProvider> 和 SystemLogQueryProperty。
| 方法 / 重载 | 用途、参数与返回值 | 注意事项 |
|---|---|---|
| page(SystemLogQuery query) | 委托选定后端分页,返回 PageModel<SystemLogVo>。 | query 非 null,不自动限定当前用户。 |
| pageForUser(SystemLogQuery query, Long userId) | 覆盖 query.userId 后分页。 | userId 非 null;会修改 Query,不可在多个用户请求间共享。 |
| getById(String id) | 按字符串 ID 查询,向 Provider 传 userId=null。 | 不限制用户;是否缺失返回 null 由 Provider 处理。 |
| getByIdForUser(String id, Long userId) | 将 ID 与非 null 用户 ID 一同交给 Provider。 | id 是后端统一 String,不要求都可转 Long。 |
| getByTraceId(String traceId) | 按 TraceId 返回单条 VO。 | 不是整个链路列表,TraceId 不一定唯一。 |
| getByTraceIdForUser(String traceId, Long userId) | 按 TraceId 与非 null 用户 ID 查询。 | 必须让后端在选择记录时限定用户,不能先随意取一条再当完整结果。 |
| statsForTimeRange(SystemLogStatsTimeRangeQuery query) | 返回时间统计分组 List<ChildrenItemModel<ItemCountModel,ItemCountModel>>。 | 仅支持统计的 Provider 可用,不自动当前用户过滤。 |
| statsForUserTimeRange(SystemLogStatsTimeRangeQuery query) | 返回用户与时间分组统计 List<ChildrenItemModel<ItemCountModel,ItemLongCountModel>>。 | 字段和时间口径以统计后端为准。 |
| statsForUserCountTimeRange(SystemLogStatsTimeRangeQuery query) | 返回用户数量统计 List<ItemCountModel>。 | 不等于日志条数;onlyApp 等条件看实现。 |
| statsForDeviceCountTimeRange(SystemLogStatsTimeRangeQuery query) | 返回设备统计分组 List<ChildrenItemModel<ItemCountModel,ItemCountModel>>。 | 无统计能力的 Provider 抛“不支持统计查询”,不是空列表。 |
SystemLogQueryProvider
后端实现的公共契约。RDBMS、MongoDB、ClickHouse、Elasticsearch 的 Query→原生条件映射并不完全相同。新增 Provider 要明确空结果、时间时区、ID 和用户隔离语义。
| 方法 / 重载 | 用途、参数与返回值 | 注意事项 |
|---|---|---|
| backend() | 返回 SystemLogQueryBackendEnum,用于门面选取。 | 相同 backend 多 Bean 会导致候选不唯一。 |
| page(SystemLogQuery query) | 实现分页并转成公共 PageModel<SystemLogVo>。 | 仅映射实际支持条件,不能忽略 userId 隔离。 |
| getById(String id, Long userId) | 按 ID 查单条;userId=null 表示管理范围,否则限定归属。 | 不要把无法转换的 ID 无条件当成数据库异常。 |
| getByTraceId(String traceId, Long userId) | 按链路和可选用户取一条。 | TraceId 不是权限凭证;多条时选择策略需明确。 |
| statsForTimeRange(SystemLogStatsTimeRangeQuery query) | 扩展时间分组统计;默认抛 BusinessSimpleException。 | 当前只有 Elasticsearch Provider 覆盖统计,不能据接口存在推断所有后端支持。 |
| statsForUserTimeRange(SystemLogStatsTimeRangeQuery query) | 扩展用户时间分组统计;默认抛 BusinessSimpleException。 | 当前只有 Elasticsearch Provider 覆盖统计,不能据接口存在推断所有后端支持。 |
| statsForUserCountTimeRange(SystemLogStatsTimeRangeQuery query) | 扩展用户数量统计;默认抛 BusinessSimpleException。 | 当前只有 Elasticsearch Provider 覆盖统计,不能据接口存在推断所有后端支持。 |
| statsForDeviceCountTimeRange(SystemLogStatsTimeRangeQuery query) | 扩展设备分组统计;默认抛 BusinessSimpleException。 | 当前只有 Elasticsearch Provider 覆盖统计,不能据接口存在推断所有后端支持。 |
在已注入 SystemLogQueryService logs 的可信后台方法中,按当前用户查询应传独立 Query。import 为 com.own.business.system.log.entity.query.SystemLogQuery:
java
var query = new SystemLogQuery();
var page = logs.pageForUser(query, authenticatedUserId);
// authenticatedUserId 取自已认证身份,不能直接采用请求中任意 userId。SystemLogMqMessageCodec
MQ 使用 UTF-8 JSON,type=own.system-log.v1。只校验协议所需结构和大小,不自动执行采集快照的脱敏/限深规则。
| 方法 / 重载 | 用途、参数与返回值 | 注意事项 |
|---|---|---|
| encode(SystemLog log) | 验证 ID、operator、operation/startedAt、response/completedAt,序列化为 byte[],再检查最大 65536 字节。 | 缺结构抛 IllegalArgumentException;序列化可抛 IOException;没有创建 Exchange 或发送消息。 |
| decode(byte[] bytes) | 先检查非空及 <=65536 字节,再解析 SystemLog 并验证完整性。 | 禁止尾随 JSON token;结构/大小异常与 JSON 解析异常分别传播。 |
RabbitProducerSystemLogPersistence
源码:RabbitProducerSystemLogPersistence。
作为转发保存器实现 SystemLogForwardingPersistence。Lombok 构造器接收专用 RabbitTemplate 与 producer 配置;声明 AutoCloseable 管理该模板资源。
| 方法 / 重载 | 用途、参数与返回值 | 注意事项 |
|---|---|---|
| save(SystemLog log) | 编码后发送持久化消息,设置 type/contentType/messageId/TraceId,等待 correlated confirm。 | nack、returned、超时均失败;确认成功只表示 Broker 接收,不等于消费者已保存。中断恢复标记。 |
| close() | 调用 template.destroy 释放专用模板。 | 生命周期结束使用,不在每条消息后调用;不要传共享模板再随意销毁。 |
SystemLogRabbitConsumerListener
源码:SystemLogRabbitConsumerListener。
同步消费后分发实际保存器。构造时排除 SystemLogForwardingPersistence,防止再投递回 MQ;必须至少一个实际保存器。
| 方法 / 重载 | 用途、参数与返回值 | 注意事项 |
|---|---|---|
| SystemLogRabbitConsumerListener(List<SystemLogPersistence> persistences) | 过滤转发器并固定实际保存器列表。 | 空列表/仅转发器会构造失败,不能只装 consumer 没有存储实现。 |
| receive(Message message) | 验证 type/contentType 与 JSON;暂设日志 TraceId,逐个同步保存,最后恢复原 MDC。 | 任一后端失败仍继续其他后端,最终拒绝且不重新入队;之前成功的后端不回滚,重放可能重复。 |
失败消息是否进入死信队列取决于实际 RabbitMQ 配置,拒绝不等于模块自动配置了重试。采集 enabled=false 不会替代 consumer 自身的启停配置。
SystemLogFileJsonService
源码:SystemLogFileJsonService;实现:SystemLogFileJsonServiceImpl。
按原始 SystemLog 写 JSON Lines,不转换为数据库查询 VO。一次写一行完整 JSON,以请求开始日期归档;不提供查询 Provider。
| 方法 / 重载 | 用途、参数与返回值 | 注意事项 |
|---|---|---|
| save(SystemLog log) | 包装成单元素列表,再执行批量路径。 | log=null 立即抛异常。 |
| save(Collection<SystemLog> logs) | 转为 Iterable 路径。 | 实现对整个 null 集合无操作,但 null 元素会失败。 |
| save(Iterable<SystemLog> logs) | 小批迭代、按日期分文件追加。 | 后续批次失败不回滚前面的文件写入。 |
SystemLogFileJsonServiceImpl
源码:SystemLogFileJsonServiceImpl。
正式写入实现;Lombok 构造接收 SystemLogFileJsonProperty。空 Iterable 不创建文件,非空时要求有效 writeBatchSize、savePath 和 filePrefix。
| 方法 / 重载 | 用途、参数与返回值 | 注意事项 |
|---|---|---|
| save(Iterable<SystemLog> logs) | 每批按 TimeUtil.DEFAULT_ZONE_ID 的请求日期分组,写 prefix_日期.jsonl,使用进程锁、文件锁并 force(false)。 | 旧文件末尾不是换行则拒绝追加;不会去重或自动修复残缺尾行。文件锁不能替代跨后端事务。 |
私有 directory 校验目录与前缀;validateLog 要求原始 ID/身份/起止时间;append 检查尾部并逐行写;writeFully 循环处理部分写入。实现不做迁移调度,重复 save 会重复追加。完整配置与文件样例见日志存储。
SystemLogBackupHook
迁移适配器契约。输入输出是 SystemLogStandardEntity,源读取和目标保存与实时 SystemLogPersistence 是不同入口。
| 方法 / 重载 | 用途、参数与返回值 | 注意事项 |
|---|---|---|
| list(LocalDateTime startTime, LocalDateTime endTime, String sort, int limit) | 读取下一批标准记录;sort 为源实现的游标,首批空串。 | 游标与时间过滤需要稳定推进;不是普通分页页码。各后端时间边界见迁移页。 |
| save(Collection<SystemLogStandardEntity> list) | 保存一批标准记录到目标。 | 是否去重/覆盖由目标决定,没有所有目标的原子性。 |
| name() | 返回迁移后端枚举,用于 origin/target 选择。 | 同名多实现被配置 Map 覆盖,不是全部执行。 |
| before() | 目标迁移前准备,默认无操作。 | 核心在进入循环前对目标调用,不自动调用源的 before。 |
| after() | 目标迁移完成后收尾,默认无操作。 | 核心未放 finally;中途异常不保证执行。 |
| ignoreTime() | 默认 false;false 时下一批 begin 更新为末条请求时间。 | true 时只推进 searchAfter,不更新时间。 |
| getIdFromStandardEntity(SystemLogStandardEntity source) | 36 字符 ID 按 UUID 转 Long;其他尝试 parseLong,失败返回 null。 | 36 字符但不是合法 UUID 会抛异常;不是无损可逆的跨后端 ID 协议。 |
SystemLogBackupHookConfig
根据开关、源、目标注册迁移 Hook。构造器接收配置与全部 Hook 列表,检查源与目标不能相同;未启用或配置不足时可只记录日志而不建立选择结果。
| 方法 / 重载 | 用途、参数与返回值 | 注意事项 |
|---|---|---|
| SystemLogBackupHookConfig(SystemLogBackupProperty systemLogBackupProperty, List<SystemLogBackupHook> systemLogBackupHookList) | 按 name() 构建静态映射,再选择 origin 和 targets。 | 重复 name 覆盖;部分目标找不到时列表可能含 null,不能只看列表非空。 |
| getGainBackupHook() | 返回所选源 Hook。 | 未选中抛“没有指定备份的数据源”。 |
| getSaveBackupHookList() | 返回目标 Hook 列表。 | 列表未建立抛业务异常;调用前确保每个目标实际有实现。 |
SystemLogBackupHookCore
显式、同步执行迁移,不是定时器。应用通过受控后台调用,需先配置源和所有目标并验证目标写入能力。
| 方法 / 重载 | 用途、参数与返回值 | 注意事项 |
|---|---|---|
| run(LocalDateTime startTime, LocalDateTime endTime) | 使用配置 pageSize 委托三参数运行。 | 时间不可 null;不会因方法被注册成 Bean 就自动启动。 |
| run(LocalDateTime startTime, LocalDateTime endTime, int pageSize) | 目标 before→循环源 list→各目标 save→推进末条时间/游标→可选间隔→目标 after。 | pageSize 要自行保证正数;任一目标失败中止,已成功写入不回滚,after 不保证执行;不持久化断点。 |
AdminSystemLogController
HTTP 前缀 /api/admin/system/log,ResultModel 包装。构造器接收 SystemLogQueryService。
| 方法 / 重载 | 用途、参数与返回值 | 注意事项 |
|---|---|---|
| page(SystemLogQuery query) | POST /page,返回公共分页 VO。 | 不强制用户范围。 |
| getById(String id) | GET /{id},返回单条 VO。 | String ID;空结果按 Provider 返回,可能 data=null。 |
| getByTraceId(String traceId) | GET /trace/{traceId},返回单条 VO。 | 管理端此方法标 @LoginIgnore 且不限定用户,应用需控制公开范围。 |
AppSystemLogController
HTTP 前缀 /api/app/system/log,ResultModel 包装。构造器接收 SystemLogQueryService。
| 方法 / 重载 | 用途、参数与返回值 | 注意事项 |
|---|---|---|
| page(SystemLogQuery query) | POST /page,返回公共分页 VO。 | 覆盖当前用户 ID,不采用客户端指定的归属。 |
| getById(String id) | GET /{id},返回单条 VO。 | String ID;空结果按 Provider 返回,可能 data=null。 |
| getByTraceId(String traceId) | GET /trace/{traceId},返回单条 VO。 | 使用当前非 null 用户 ID 限定,TraceId 不能绕过归属。 |
AdminSystemLogStatsController
源码:AdminSystemLogStatsController。
HTTP 前缀 /api/admin/system/log/stats。构造器接收查询服务,当前统计依赖 Elasticsearch Provider;方法无独立 PermissionOperation 注解,需核实应用管理端访问策略。
| 方法 / 重载 | 用途、参数与返回值 | 注意事项 |
|---|---|---|
| statsForTimeRange(SystemLogStatsTimeRangeQuery query) | POST /time/range;返回时间分组统计。 | 不同层级 Item 的含义见日志查询页。 |
| statsForUserTimeRange(SystemLogStatsTimeRangeQuery query) | POST /user/time/range;返回用户时间分组。 | 管理范围,不自动当前用户。 |
| statsForUserCountTimeRange(SystemLogStatsTimeRangeQuery query) | POST /user/count/time/range;返回用户数量统计。 | 不是下载分页。 |
| statsForUserCountTimeRangeOnlyApp(SystemLogStatsTimeRangeQuery query) | POST /only/app/user/count/time/range;强制 query.onlyApp=1 后统计。 | 会修改 Query,其他过滤规则仍由后端决定。 |
| statsForDeviceCountTimeRange(SystemLogStatsTimeRangeQuery query) | POST /device/count/time/range;返回设备统计分组。 | 记录未采集到所需字段时不能凭空补全统计。 |
验证与使用场景
查询请求和模型见日志查询,生产/消费配置与消息确认见RabbitMQ 集中保存,有副作用的历史迁移流程见历史迁移。真实投递、写库与迁移需在已准备的应用环境中按对应场景验证。