日志系统
cr4sync server 把日志输出按 target 分流,配合 tracing-subscriber 的多 layer 架构,让运维和调试都能拿到自己需要的信息。
输出位置
| Layer | 文件 / 输出 | 收集范围 |
|---|---|---|
| stderr | 终端 | 所有 target(按 [log] 配置过滤) |
sync_core.log | 文件 | 同 stderr |
server.log | 文件 | 仅 target = cr4sync 命名空间 |
server.log 用 Targets filter 收集所有 cr4sync 命名空间的日志,排除 sync-core 流水。
按天切割
server.log 与 sync_core.log 均按天切割(tracing-appender rolling daily),当天文件名带日期后缀:
server.log.YYYY-MM-DD、sync_core.log.YYYY-MM-DD。排查时按日期 grep 当天文件即可,避免单文件无限增长。
分层约定
cr4sync server 新写日志点遵守以下约定。该约定也写在 src/logging.rs 模块顶 doc 内:
| 级别 | 应包含 |
|---|---|
INFO | 一行结果性事件。只带最关键字段(如 authenticated user_id=... group_name=... is_admin=...,migrate.job.created job_id=...,migrate.job.completed completed=... failed=...) |
DEBUG | 参数、URL、中间步骤、缓存命中 / 未命中、JSON / text 响应体 |
TRACE | 结构化内部状态、循环细节、JSON 响应原文 |
TRACE 不打 raw 数据传输 body(chunk bytes / range download bytes)——这类位置只在 DEBUG 打 url + offset + size,避免日志撑爆磁盘。
看 cloudreve 远端响应
排查鉴权 / admin 识别问题最常用的姿势是开 trace:
./cr4sync serve --log-level trace
随后任何调到 cloudreve /user/info 的请求都会在 server.log 和 stderr 留下完整的链条:
debug cr4sync::server cloudreve /user/info request url=... sub=...
trace cr4sync::server cloudreve /user/info response status=200 body={"code":0,"data":{...}}
info cr4sync::server authenticated user_id=... group_name=... is_admin=...
body 字符串会被截到约 4 KiB 防爆。
字段不重复的设计
多 fmt layer 共享 FormattedFields 缓冲;如果对同一 span 字段调用 Span::current().record(...),每个 layer 都会 append 一次 → 字段在日志里重复 N 次(N = layer 数)。
cr4sync 目前是:
- 请求 span 在
request_idmiddleware(src/server/middleware/request_id.rs)创建时只带request_id,禁止后续record()回填。 - 用户身份通过
authmiddleware(src/server/middleware/auth.rs)塞进响应 extensions(LogIdentity { user_id, is_admin }),由外层access_logmiddleware(src/server/middleware/access_log.rs)在出口读取并作为事件字段输出。
净效果:access 行每个字段恰好出现一次。