添加qiming-rcoder模块
This commit is contained in:
297
qiming-rcoder/.qoder/repowiki/zh/content/可观测性/日志系统.md
Normal file
297
qiming-rcoder/.qoder/repowiki/zh/content/可观测性/日志系统.md
Normal file
@@ -0,0 +1,297 @@
|
||||
# 日志系统
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [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)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
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<br/>init_telemetry()"]
|
||||
RMid["crates/rcoder/src/middleware/tracing_middleware.rs<br/>HTTP 追踪中间件"]
|
||||
end
|
||||
subgraph "agent_runner 服务"
|
||||
AMain["crates/agent_runner/src/main.rs<br/>init_telemetry()"]
|
||||
AMid["crates/agent_runner/src/middleware/tracing_middleware.rs<br/>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 无缝注入到每条日志中,既满足日常运维需求,又为分布式追踪提供了坚实基础。建议在生产环境中保持异步写入与合理的滚动策略,并根据需要调整日志级别与输出格式,以平衡可观测性与性能。
|
||||
Reference in New Issue
Block a user