# 日志系统 **本文引用的文件** - [Cargo.toml](file://Cargo.toml) - [rcoder 主程序](file://crates/rcoder/src/main.rs) - [agent_runner 主程序](file://crates/agent_runner/src/main.rs) - [rcoder 追踪中间件](file://crates/rcoder/src/middleware/tracing_middleware.rs) - [agent_runner 追踪中间件](file://crates/agent_runner/src/middleware/tracing_middleware.rs) - [诊断脚本](file://docker/scripts/diagnose-blocking.sh) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖分析](#依赖分析) 7. [性能考量](#性能考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) ## 简介 本文件系统性阐述基于 tracing 和 tracing-appender 的日志实现,覆盖以下要点: - 控制台与文件双输出配置 - JSON 格式化输出 - 按天滚动策略与日志保留 - 日志级别与过滤 - 线程信息包含 - 与链路追踪的集成(trace_id 注入) - 常见问题(路径不存在、权限不足)及解决方案 - 性能优化建议(异步写入、滚动开销) 该说明面向初学者与资深开发者,既提供清晰的背景知识,也给出深入的技术细节与可视化图示。 ## 项目结构 日志系统在两个二进制服务中分别初始化: - rcoder 服务:负责主业务逻辑与容器管理 - agent_runner 服务:负责代理与子进程交互 两者均通过统一的遥测初始化流程,创建 logs 目录、配置文件 appender、控制台层,并注册 EnvFilter 作为日志级别来源。 ```mermaid graph TB subgraph "rcoder 服务" RMain["crates/rcoder/src/main.rs
init_telemetry()"] RMid["crates/rcoder/src/middleware/tracing_middleware.rs
HTTP 追踪中间件"] end subgraph "agent_runner 服务" AMain["crates/agent_runner/src/main.rs
init_telemetry()"] AMid["crates/agent_runner/src/middleware/tracing_middleware.rs
HTTP 追踪中间件"] end RMain --> |"注册 EnvFilter + 文件层 + 控制台层"| RMain AMain --> |"注册 EnvFilter + 文件层 + 控制台层"| AMain RMid --> |"生成/提取 trace_id 并注入 span"| RMain AMid --> |"生成/提取 trace_id 并注入 span"| AMain ``` 图表来源 - [rcoder 主程序](file://crates/rcoder/src/main.rs#L274-L320) - [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L181-L231) - [rcoder 追踪中间件](file://crates/rcoder/src/middleware/tracing_middleware.rs#L1-L179) - [agent_runner 追踪中间件](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L1-L179) 章节来源 - [Cargo.toml](file://Cargo.toml#L91-L105) - [rcoder 主程序](file://crates/rcoder/src/main.rs#L274-L320) - [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L181-L231) ## 核心组件 - 日志订阅者与层级 - EnvFilter:从环境变量读取日志级别,若未设置则回退到默认级别 - 文件层(JSON):按天滚动,保留最近 N 份日志文件 - 控制台层:简洁输出,便于本地调试 - 链路追踪集成 - 设置全局 TextMapPropagator,支持 trace context 传播 - HTTP 中间件为每个请求生成/提取 trace_id,并注入到日志 span - 目录与文件管理 - 启动时自动创建 logs 目录 - 文件名前缀区分不同服务(rcoder、agent-runner) 章节来源 - [rcoder 主程序](file://crates/rcoder/src/main.rs#L274-L320) - [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L181-L231) - [rcoder 追踪中间件](file://crates/rcoder/src/middleware/tracing_middleware.rs#L1-L179) - [agent_runner 追踪中间件](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L1-L179) ## 架构总览 日志系统由“订阅者注册 + 层级配置 + 过滤 + 追踪中间件”构成,形成“双输出 + 结构化 + 可追踪”的日志体系。 ```mermaid sequenceDiagram participant Svc as "服务进程" participant Sub as "tracing_subscriber : : registry" participant Env as "EnvFilter" participant F as "文件层(JSON)" participant C as "控制台层" participant Mid as "HTTP 追踪中间件" participant Log as "日志输出" Svc->>Sub : 初始化订阅者 Sub->>Env : 注册 EnvFilter Sub->>F : 注册文件层(JSON) Sub->>C : 注册控制台层 Svc->>Mid : 注入 HTTP 中间件 Mid->>Mid : 提取/生成 trace_id Mid->>Log : 写入带 trace_id 的结构化日志 F-->>Log : 写入 JSON 日志 C-->>Log : 写入控制台日志 ``` 图表来源 - [rcoder 主程序](file://crates/rcoder/src/main.rs#L274-L320) - [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L181-L231) - [rcoder 追踪中间件](file://crates/rcoder/src/middleware/tracing_middleware.rs#L1-L179) - [agent_runner 追踪中间件](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L1-L179) ## 详细组件分析 ### 1) 日志订阅者与层级配置 - EnvFilter - 从环境变量读取日志级别;若未设置,则 rcoder 回退到 info,agent_runner 回退到更细粒度的调试级别 - 文件层(JSON) - 使用 tracing-appender 的按天滚动策略 - 通过 filename_prefix 区分服务 - max_log_files 限制保留的旧日志数量 - 输出 JSON,便于后续结构化分析 - 控制台层 - 简洁输出,便于本地快速查看 - 关闭 ANSI,避免非终端环境污染 章节来源 - [rcoder 主程序](file://crates/rcoder/src/main.rs#L274-L320) - [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L181-L231) ### 2) 日志目录创建与文件滚动策略 - 目录创建 - 启动时检查 logs 目录是否存在,不存在则创建 - 滚动策略 - Rotation::DAILY:按自然日滚动 - filename_prefix:rcoder 或 agent-runner 前缀 - max_log_files:保留最近 N 个日志文件,超出自动清理 章节来源 - [rcoder 主程序](file://crates/rcoder/src/main.rs#L274-L320) - [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L181-L231) ### 3) 日志级别与输出格式 - 日志级别 - EnvFilter 优先级:环境变量 > 默认值 - rcoder 默认 info - agent_runner 默认更细粒度,便于调试 - 输出格式 - 文件层:JSON,包含目标、线程 ID、线程名等字段 - 控制台层:简洁,便于人类阅读 章节来源 - [rcoder 主程序](file://crates/rcoder/src/main.rs#L274-L320) - [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L181-L231) ### 4) 线程信息包含 - 文件层开启线程 ID 与线程名,便于定位并发场景下的日志来源 - 控制台层关闭线程信息,避免冗余 章节来源 - [rcoder 主程序](file://crates/rcoder/src/main.rs#L274-L320) - [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L181-L231) ### 5) 链路追踪与 trace_id 注入 - 全局传播器 - 设置 TraceContextPropagator,支持 trace context 传播 - HTTP 中间件 - 从请求头提取 trace_id;若无则生成新的 UUID - 为每次请求创建 info_span,携带 trace_id、方法、URI、UA、Content-Type 等 - 将 trace_id 注入请求扩展,便于后续处理器使用 - 在 span 中记录请求开始与结束,形成完整的调用链日志 ```mermaid sequenceDiagram participant Client as "客户端" participant Router as "Axum 路由" participant Mid as "Tracing 中间件" participant Handler as "业务处理器" participant Log as "日志系统(JSON/控制台)" Client->>Router : HTTP 请求 Router->>Mid : 进入中间件 Mid->>Mid : 提取/生成 trace_id Mid->>Log : 写入请求开始日志(含 trace_id) Mid->>Handler : 调用业务处理器 Handler-->>Mid : 返回响应 Mid->>Log : 写入请求结束日志(含 trace_id) Mid-->>Router : 返回响应 ``` 图表来源 - [rcoder 追踪中间件](file://crates/rcoder/src/middleware/tracing_middleware.rs#L1-L179) - [agent_runner 追踪中间件](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L1-L179) 章节来源 - [rcoder 主程序](file://crates/rcoder/src/main.rs#L274-L320) - [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L181-L231) - [rcoder 追踪中间件](file://crates/rcoder/src/middleware/tracing_middleware.rs#L1-L179) - [agent_runner 追踪中间件](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L1-L179) ### 6) 类图:日志与追踪相关组件 ```mermaid classDiagram class InitTelemetry { +init_telemetry() Result } class EnvFilter { +try_from_default_env() Filter } class FileLayer { +json() +with_writer(writer) +with_target(flag) +with_thread_ids(flag) +with_thread_names(flag) } class ConsoleLayer { +with_target(flag) +with_ansi(flag) } class TracingMiddleware { +tracing_middleware_handler(req,next) Response +add_tracing_layer(router) Router } InitTelemetry --> EnvFilter : "注册" InitTelemetry --> FileLayer : "注册" InitTelemetry --> ConsoleLayer : "注册" TracingMiddleware --> InitTelemetry : "配合使用" ``` 图表来源 - [rcoder 主程序](file://crates/rcoder/src/main.rs#L274-L320) - [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L181-L231) - [rcoder 追踪中间件](file://crates/rcoder/src/middleware/tracing_middleware.rs#L1-L179) - [agent_runner 追踪中间件](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L1-L179) ## 依赖分析 - 核心依赖 - tracing、tracing-subscriber:日志框架与订阅者 - tracing-appender:文件滚动与 writer - opentelemetry、opentelemetry_sdk、tracing-opentelemetry、axum-tracing-opentelemetry:链路追踪与传播 - uuid:生成 trace_id - 服务差异 - rcoder:EnvFilter 默认 info - agent_runner:EnvFilter 默认更细粒度,便于调试 章节来源 - [Cargo.toml](file://Cargo.toml#L91-L105) - [rcoder 主程序](file://crates/rcoder/src/main.rs#L274-L320) - [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L181-L231) ## 性能考量 - 异步日志写入 - tracing-appender 默认异步写入,减少阻塞 - 建议保持默认异步配置,避免同步 I/O 导致延迟放大 - 滚动开销 - 按天滚动在高吞吐下会产生少量文件系统操作 - max_log_files 控制保留数量,避免无限增长 - JSON 输出 - JSON 格式便于结构化分析,但序列化成本略高于文本 - 若对性能极度敏感,可在生产环境切换为文本格式或减少字段 - 级别过滤 - EnvFilter 仅在必要时进行解析,建议通过环境变量集中管理 - 并发与线程信息 - 启用线程 ID/名称会增加少量开销,建议仅在调试阶段开启 [本节为通用性能建议,无需特定文件来源] ## 故障排查指南 - 日志文件路径不存在 - 现象:启动时报错或无日志文件 - 处理:确认 logs 目录存在;若不存在,服务会自动创建 - 参考:日志初始化中包含目录创建逻辑 - 权限不足 - 现象:无法写入日志文件 - 处理:确保运行用户对 logs 目录具有写权限 - 日志过多占用磁盘 - 现象:磁盘空间被占满 - 处理:调整 max_log_files,或定期清理旧日志 - 无法看到 trace_id - 现象:日志中缺少 trace_id - 处理:确认中间件已注入;检查请求头是否携带 trace_id;或允许自动生成 - 诊断脚本辅助 - 使用诊断脚本检查今日日志中的 ERROR/WARN - 参考:诊断脚本中对日志文件的读取与错误定位 章节来源 - [rcoder 主程序](file://crates/rcoder/src/main.rs#L274-L320) - [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L181-L231) - [诊断脚本](file://docker/scripts/diagnose-blocking.sh#L49-L85) ## 结论 该日志系统以 tracing 为核心,结合 tracing-appender 实现了“双输出 + JSON + 按天滚动 + trace_id 注入”的完整方案。通过 EnvFilter 精准控制日志级别,借助 HTTP 中间件将 trace_id 无缝注入到每条日志中,既满足日常运维需求,又为分布式追踪提供了坚实基础。建议在生产环境中保持异步写入与合理的滚动策略,并根据需要调整日志级别与输出格式,以平衡可观测性与性能。