添加qiming-rcoder模块

This commit is contained in:
Codex
2026-06-01 13:54:52 +08:00
parent 8092c4b1f8
commit 4b1a580132
539 changed files with 151650 additions and 0 deletions

View File

@@ -0,0 +1,426 @@
# 可观测性
<cite>
**本文引用的文件**
- [rcoder 主程序](file://crates/rcoder/src/main.rs)
- [agent_runner 主程序](file://crates/agent_runner/src/main.rs)
- [rcoder 路由与状态](file://crates/rcoder/src/router.rs)
- [agent_runner 路由与状态](file://crates/agent_runner/src/router.rs)
- [rcoder 健康检查处理器](file://crates/rcoder/src/handler/health_handler.rs)
- [agent_runner 健康检查处理器](file://crates/agent_runner/src/handler/health_handler.rs)
- [rcoder 配置](file://crates/rcoder/src/config.rs)
- [agent_runner 配置](file://crates/agent_runner/src/config.rs)
- [rcoder 代理 API 处理器](file://crates/rcoder/src/handler/proxy_handler_api.rs)
- [agent_runner 代理 API 处理器](file://crates/agent_runner/src/handler/proxy_handler_api.rs)
- [rcoder 清理任务](file://crates/rcoder/src/proxy_agent/cleanup_task.rs)
- [agent_runner 清理任务](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs)
- [共享错误类型](file://crates/shared_types/src/model/app_error.rs)
- [服务镜像配置](file://crates/shared_types/src/service_config.rs)
- [rcoder 追踪中间件](file://crates/rcoder/src/middleware/tracing_middleware.rs)
- [agent_runner 追踪中间件](file://crates/agent_runner/src/middleware/tracing_middleware.rs)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
## 简介
本文件系统性阐述本仓库的可观测性实现,涵盖日志系统、链路追踪、性能监控与错误处理。内容基于实际代码库,提供面向初学者的易懂说明与面向资深工程师的技术深度,包括配置项、参数与返回值、组件关系、常见问题与解决方案。
## 项目结构
- 两个主要服务:
- rcoder主服务提供聊天、SSE 实时通知、代理与健康检查等能力
- agent_runner代理运行器负责代理会话、清理任务与健康检查
- 共享模块:
- shared_types共享模型与错误类型
- 配置模块:统一的配置加载与环境变量覆盖
- 追踪中间件HTTP 请求级链路追踪与日志注入
- 清理任务:闲置资源回收与孤立容器清理
- 代理 APIPingora 代理的状态、统计与配置查询
```mermaid
graph TB
subgraph "rcoder 服务"
RMain["rcoder 主程序<br/>初始化遥测/路由/代理"]
RRouter["路由与状态<br/>/health /chat /agent/* /proxy/*"]
RTracing["追踪中间件<br/>HTTP 请求追踪"]
RClean["清理任务<br/>闲置容器/会话清理"]
RProxyAPI["代理 API 处理器<br/>状态/统计/配置"]
end
subgraph "agent_runner 服务"
AMain["agent_runner 主程序<br/>初始化遥测/路由/代理"]
ARouter["路由与状态<br/>/health /chat /agent/* /proxy/*"]
ATracing["追踪中间件<br/>HTTP 请求追踪"]
AClean["清理任务<br/>闲置会话/SSE消息清理"]
AProxyAPI["代理 API 处理器<br/>状态/统计/配置"]
end
subgraph "共享"
SharedErr["共享错误类型<br/>AppError"]
SharedCfg["服务镜像配置<br/>ServiceImageConfig"]
end
RMain --> RRouter --> RTracing
RMain --> RClean
RMain --> RProxyAPI
AMain --> ARouter --> ATracing
AMain --> AClean
AMain --> AProxyAPI
RRouter --> SharedErr
ARouter --> SharedErr
RMain --> SharedCfg
AMain --> SharedCfg
```
图表来源
- [rcoder 主程序](file://crates/rcoder/src/main.rs#L1-L120)
- [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L1-L120)
- [rcoder 路由与状态](file://crates/rcoder/src/router.rs#L52-L84)
- [agent_runner 路由与状态](file://crates/agent_runner/src/router.rs#L41-L70)
- [rcoder 代理 API 处理器](file://crates/rcoder/src/handler/proxy_handler_api.rs#L1-L60)
- [agent_runner 代理 API 处理器](file://crates/agent_runner/src/handler/proxy_handler_api.rs#L1-L60)
- [rcoder 清理任务](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L1-L120)
- [agent_runner 清理任务](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L1-L120)
- [共享错误类型](file://crates/shared_types/src/model/app_error.rs#L1-L65)
- [服务镜像配置](file://crates/shared_types/src/service_config.rs#L1-L120)
章节来源
- [rcoder 主程序](file://crates/rcoder/src/main.rs#L1-L120)
- [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L1-L120)
- [rcoder 路由与状态](file://crates/rcoder/src/router.rs#L52-L84)
- [agent_runner 路由与状态](file://crates/agent_runner/src/router.rs#L41-L70)
## 核心组件
- 日志系统
- 使用 tracing 与 tracing-subscriber 输出到文件与控制台按天滚动JSON 格式便于后续分析
- rcoder 与 agent_runner 分别初始化各自的遥测系统,设置 TraceContextPropagator
- 链路追踪
- HTTP 请求中间件自动生成 trace_id注入 OpenTelemetry 上下文,记录请求/响应
- 中间件将 trace_id 放入请求扩展,便于后续处理器使用
- 性能监控
- Pingora 代理内置指标:总请求数、成功/失败响应数、平均响应时间等
- 代理 API 提供 /proxy/status、/proxy/stats、/proxy/config 查询
- 错误处理
- 统一的 AppError 类型,实现 IntoResponse返回标准化错误体
- 代理 API 对未启用代理场景返回明确的错误码与消息
章节来源
- [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#L71-L130)
- [agent_runner 追踪中间件](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L71-L130)
- [rcoder 代理 API 处理器](file://crates/rcoder/src/handler/proxy_handler_api.rs#L1-L120)
- [agent_runner 代理 API 处理器](file://crates/agent_runner/src/handler/proxy_handler_api.rs#L1-L120)
- [共享错误类型](file://crates/shared_types/src/model/app_error.rs#L1-L65)
## 架构总览
可观测性贯穿请求生命周期:从 HTTP 入口经中间件注入 trace_id进入路由与处理器期间产生日志与指标代理服务提供运行时状态与统计清理任务定期回收闲置资源错误统一收敛。
```mermaid
sequenceDiagram
participant Client as "客户端"
participant Router as "Axum 路由"
participant Tracing as "追踪中间件"
participant Handler as "业务处理器"
participant Proxy as "Pingora 代理"
participant Cleaner as "清理任务"
Client->>Router : "HTTP 请求"
Router->>Tracing : "进入中间件"
Tracing->>Tracing : "生成/提取 trace_id<br/>记录请求开始"
Tracing->>Handler : "继续处理"
Handler->>Proxy : "代理转发/查询"
Proxy-->>Handler : "代理响应"
Handler-->>Client : "业务响应"
Tracing->>Tracing : "记录响应状态"
Note over Cleaner : "定时扫描闲置资源并清理"
```
图表来源
- [rcoder 主程序](file://crates/rcoder/src/main.rs#L220-L271)
- [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L120-L178)
- [rcoder 路由与状态](file://crates/rcoder/src/router.rs#L52-L84)
- [agent_runner 路由与状态](file://crates/agent_runner/src/router.rs#L41-L70)
- [rcoder 追踪中间件](file://crates/rcoder/src/middleware/tracing_middleware.rs#L71-L130)
- [agent_runner 追踪中间件](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L71-L130)
- [rcoder 清理任务](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L278-L310)
- [agent_runner 清理任务](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L294-L310)
## 详细组件分析
### 日志系统
- 初始化
- 创建 logs 目录,按天滚动,最多保留 N 份日志文件
- 控制台输出简洁格式,文件输出 JSON 格式,包含目标、线程 ID/名称等
- 设置全局 TextMapPropagator支持 trace_id 传播
- 输出位置
- rcoder日志前缀 rcoder
- agent_runner日志前缀 agent-runner
- 使用方式
- 通过 tracing::info/warn/error/debug 等宏记录结构化日志
- 中间件在请求开始与结束处记录关键信息,便于关联 trace_id
章节来源
- [rcoder 主程序](file://crates/rcoder/src/main.rs#L274-L320)
- [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L181-L231)
### 链路追踪中间件
- 功能要点
- 自动生成 trace_idUUID v4 简短格式)
- 从常见 trace 请求头提取 trace_id如 x-trace-id、traceparent 等)
- 为每次请求创建 info_span记录 method、URI、trace_id、User-Agent、Content-Type
- 将 trace_id 插入请求扩展,供后续处理器使用
- 在 span 中执行请求处理,记录响应状态
- 适用范围
- rcoder 与 agent_runner 各自提供独立的中间件实现,均注册到各自路由
```mermaid
flowchart TD
Start(["进入中间件"]) --> Extract["尝试从请求头提取 trace_id"]
Extract --> HasHeader{"是否包含有效 trace 头?"}
HasHeader --> |是| UseHeader["使用请求头中的 trace_id"]
HasHeader --> |否| GenNew["生成新的 trace_id"]
UseHeader --> CreateSpan["创建请求 span含 trace_id 等字段"]
GenNew --> CreateSpan
CreateSpan --> LogStart["记录请求开始"]
LogStart --> Inject["将 trace_id 注入请求扩展"]
Inject --> RunHandler["继续处理下游处理器"]
RunHandler --> LogEnd["记录响应状态"]
LogEnd --> End(["返回响应"])
```
图表来源
- [rcoder 追踪中间件](file://crates/rcoder/src/middleware/tracing_middleware.rs#L44-L130)
- [agent_runner 追踪中间件](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L44-L130)
章节来源
- [rcoder 追踪中间件](file://crates/rcoder/src/middleware/tracing_middleware.rs#L44-L130)
- [agent_runner 追踪中间件](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L44-L130)
### 健康检查与代理监控
- 健康检查
- /health 返回标准结构,包含状态、时间戳与服务名
- rcoder 与 agent_runner 均提供独立实现
- 代理监控
- /proxy/status返回代理配置、后端列表与健康状态快照
- /proxy/stats返回总请求数、成功/失败响应数、平均响应时间等指标
- /proxy/config返回代理配置与健康检查配置
- 代理健康检查
- 配置包含启用开关、检查间隔、超时、健康阈值与不健康阈值
- 启动时可按配置启动健康检查循环
```mermaid
sequenceDiagram
participant Client as "客户端"
participant API as "代理 API 处理器"
participant ProxySvc as "Pingora 代理服务"
participant HC as "健康检查"
Client->>API : "GET /proxy/status"
API->>ProxySvc : "读取配置/后端/健康快照"
ProxySvc-->>API : "聚合状态信息"
API-->>Client : "返回状态/后端列表/健康状态"
Client->>API : "GET /proxy/stats"
API->>ProxySvc : "读取指标总请求数/成功/失败/平均响应时间"
ProxySvc-->>API : "返回指标"
API-->>Client : "返回统计信息"
Client->>API : "GET /proxy/config"
API->>ProxySvc : "读取代理配置"
API->>HC : "读取健康检查配置"
ProxySvc-->>API : "返回代理配置"
HC-->>API : "返回健康检查配置"
API-->>Client : "返回配置信息"
```
图表来源
- [rcoder 代理 API 处理器](file://crates/rcoder/src/handler/proxy_handler_api.rs#L1-L206)
- [agent_runner 代理 API 处理器](file://crates/agent_runner/src/handler/proxy_handler_api.rs#L1-L206)
- [rcoder 配置](file://crates/rcoder/src/config.rs#L52-L80)
- [agent_runner 配置](file://crates/agent_runner/src/config.rs#L51-L73)
章节来源
- [rcoder 健康检查处理器](file://crates/rcoder/src/handler/health_handler.rs#L1-L36)
- [agent_runner 健康检查处理器](file://crates/agent_runner/src/handler/health_handler.rs#L1-L36)
- [rcoder 代理 API 处理器](file://crates/rcoder/src/handler/proxy_handler_api.rs#L1-L206)
- [agent_runner 代理 API 处理器](file://crates/agent_runner/src/handler/proxy_handler_api.rs#L1-L206)
- [rcoder 配置](file://crates/rcoder/src/config.rs#L52-L80)
- [agent_runner 配置](file://crates/agent_runner/src/config.rs#L51-L73)
### 清理任务与资源回收
- rcoder 清理任务
- 基于 RAII 原则:从 project_and_agent_map 移除条目,触发 AgentLifecycleGuard 自动清理
- 保护期:新建容器在最小保护时间内不清理,避免误删
- 超时判断:考虑最后活动时间与创建时间,加入 1 秒缓冲避免时间误差
- 孤立容器清理:扫描 rcoder-agent-* 容器,批量并行清理,限制单次清理数量
- 超时保护:清理过程整体超时,防止阻塞
- agent_runner 清理任务
- 清理孤立的 SSE 会话与消息
- 仅清理 Idle 状态且超时的 agent避免中断 Active/Terminating 状态
```mermaid
flowchart TD
ScanStart["开始扫描"] --> Collect["收集所有项目ID"]
Collect --> Eval["逐个评估agent状态/最后活动/创建时间"]
Eval --> Protected{"是否在保护期内?"}
Protected --> |是| Skip["跳过清理"]
Protected --> |否| Timeout{"是否超时且Idle"}
Timeout --> |否| Skip
Timeout --> |是| Remove["从MAP移除触发RAII清理"]
Remove --> Orphan["清理孤立SSE会话/消息"]
Orphan --> Done["统计并记录清理结果"]
Skip --> Done
```
图表来源
- [rcoder 清理任务](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L248-L420)
- [agent_runner 清理任务](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L156-L245)
章节来源
- [rcoder 清理任务](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L1-L420)
- [agent_runner 清理任务](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L1-L245)
### 错误处理与返回值
- 统一错误类型
- AppErrorAnyhowError、IoError、Generic
- 实现 IntoResponse返回 JSON 结构,包含 success=false 与 error.code/message
- 代理 API 错误
- 未启用代理时返回 SERVICE_UNAVAILABLE携带错误码与消息
- 健康检查
- /health 返回标准结构,包含 status、timestamp、service
章节来源
- [共享错误类型](file://crates/shared_types/src/model/app_error.rs#L1-L65)
- [rcoder 代理 API 处理器](file://crates/rcoder/src/handler/proxy_handler_api.rs#L1-L120)
- [agent_runner 代理 API 处理器](file://crates/agent_runner/src/handler/proxy_handler_api.rs#L1-L120)
- [rcoder 健康检查处理器](file://crates/rcoder/src/handler/health_handler.rs#L1-L36)
- [agent_runner 健康检查处理器](file://crates/agent_runner/src/handler/health_handler.rs#L1-L36)
### 配置与参数
- rcoder 配置
- AppConfigdefault_agent、projects_dir、port、proxy_config、docker_config
- ProxyConfiglisten_port、default_backend_port、backend_host、port_param、health_check
- HealthCheckConfigenabled、interval_seconds、timeout_seconds、healthy_threshold、unhealthy_threshold
- DockerConfigmulti_image_config、network_mode、work_dir、auto_cleanup、container_ttl_seconds
- agent_runner 配置
- AppConfigdefault_agent、projects_dir、port、proxy_config
- ProxyConfiglisten_port、default_backend_port、backend_host、port_param、health_check
- HealthCheckConfigenabled、interval_seconds、timeout_seconds、healthy_threshold、unhealthy_threshold
- 环境变量覆盖
- rcoderRCODER_PORT、RCODER_PROJECTS_DIR、RCODER_NETWORK_MODE、RCODER_WORK_DIR、RCODER_AUTO_CLEANUP、RCODER_CONTAINER_TTL
- agent_runnerRCODER_PORT、RCODER_PROJECTS_DIR部分
章节来源
- [rcoder 配置](file://crates/rcoder/src/config.rs#L37-L110)
- [rcoder 配置](file://crates/rcoder/src/config.rs#L112-L210)
- [rcoder 配置](file://crates/rcoder/src/config.rs#L253-L332)
- [agent_runner 配置](file://crates/agent_runner/src/config.rs#L38-L110)
- [agent_runner 配置](file://crates/agent_runner/src/config.rs#L112-L180)
- [agent_runner 配置](file://crates/agent_runner/src/config.rs#L252-L315)
### 与容器与镜像的关系
- 服务镜像配置
- ServiceImageConfigimage/arm64_image/amd64_image/default_image、environment、mounts、resource_limits、work_dir、network_mode、container_path_template
- 支持镜像选择、环境变量合并、挂载点校验与路径模板解析
- Docker 配置
- rcoder DockerConfig 支持多镜像配置与环境变量覆盖,提供验证与摘要信息
- 启动时合并应用配置与多镜像配置,初始化全局 DockerManager
章节来源
- [服务镜像配置](file://crates/shared_types/src/service_config.rs#L1-L120)
- [服务镜像配置](file://crates/shared_types/src/service_config.rs#L120-L262)
- [服务镜像配置](file://crates/shared_types/src/service_config.rs#L314-L401)
- [rcoder 配置](file://crates/rcoder/src/config.rs#L148-L211)
## 依赖关系分析
- 日志与追踪
- rcoder/agent_runner 主程序分别初始化 tracing-subscriber 与 OpenTelemetry Propagator
- 追踪中间件依赖 tracing/tracing-opentelemetry生成/注入 trace_id
- 代理与监控
- 代理 API 依赖 Pingora 服务对象,读取配置、后端列表与健康快照
- 代理配置包含健康检查参数,启动时可开启健康检查循环
- 清理任务
- rcoder 清理任务依赖 DockerManager 全局实例,清理孤立容器与会话
- agent_runner 清理任务清理 SSE 会话与消息
- 错误处理
- AppError 实现 IntoResponse统一错误返回格式
```mermaid
graph LR
RCMain["rcoder 主程序"] --> RT["追踪中间件"]
RCMain --> RP["代理 API 处理器"]
RCMain --> RClean["rcoder 清理任务"]
AMain["agent_runner 主程序"] --> AT["追踪中间件"]
AMain --> AP["代理 API 处理器"]
AMain --> AClean["agent_runner 清理任务"]
RT --> TE["OpenTelemetry Propagator"]
AT --> TE
RP --> P["Pingora 代理服务"]
AP --> P
RClean --> DM["DockerManager 全局实例"]
AClean --> SSE["SSE 会话/消息"]
RP --> AE["AppError"]
AP --> AE
```
图表来源
- [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#L71-L130)
- [agent_runner 追踪中间件](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L71-L130)
- [rcoder 代理 API 处理器](file://crates/rcoder/src/handler/proxy_handler_api.rs#L1-L120)
- [agent_runner 代理 API 处理器](file://crates/agent_runner/src/handler/proxy_handler_api.rs#L1-L120)
- [rcoder 清理任务](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L431-L602)
- [agent_runner 清理任务](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L156-L245)
- [共享错误类型](file://crates/shared_types/src/model/app_error.rs#L1-L65)
章节来源
- [rcoder 主程序](file://crates/rcoder/src/main.rs#L274-L320)
- [agent_runner 主程序](file://crates/agent_runner/src/main.rs#L181-L231)
- [rcoder 代理 API 处理器](file://crates/rcoder/src/handler/proxy_handler_api.rs#L1-L120)
- [agent_runner 代理 API 处理器](file://crates/agent_runner/src/handler/proxy_handler_api.rs#L1-L120)
- [rcoder 清理任务](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L431-L602)
- [agent_runner 清理任务](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L156-L245)
- [共享错误类型](file://crates/shared_types/src/model/app_error.rs#L1-L65)
## 性能考量
- 日志滚动与保留
- 按天滚动,限制日志文件数量,降低磁盘占用与 IO 压力
- 代理指标
- 通过 /proxy/stats 获取平均响应时间等关键指标,辅助容量规划与性能调优
- 清理策略
- rcoder 清理任务对孤立容器清理加总超时与单次上限,避免阻塞
- agent_runner 清理任务仅清理 Idle 且超时的 agent避免中断活跃任务
- 超时与保护
- 清理过程整体超时、单容器清理超时、新建容器保护期,提升稳定性
章节来源
- [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/proxy_agent/cleanup_task.rs#L431-L602)
- [agent_runner 清理任务](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L156-L245)
## 故障排查指南
- Docker 相关
- 启动时自动检测宿主机挂载路径,失败时提供详细配置帮助与排错步骤
- 建议检查 DOCKER_SOCKET_PATH、Docker socket 权限与挂载路径
- 代理未启用
- 调用 /proxy/* 接口返回 SERVICE_UNAVAILABLE需确认代理配置与启动参数
- 日志定位
- 使用 trace_id 关联请求全链路日志,结合 /proxy/stats 观察异常时段的指标波动
- 清理异常
- rcoder 清理任务对单次清理与总清理过程设置超时,若出现长时间卡顿,检查 Docker API 可用性与容器状态
- 健康检查
- /health 返回 healthy 表示服务正常,若异常需结合日志与代理状态进一步排查
章节来源
- [rcoder 主程序](file://crates/rcoder/src/main.rs#L48-L118)
- [rcoder 主程序](file://crates/rcoder/src/main.rs#L322-L351)
- [rcoder 代理 API 处理器](file://crates/rcoder/src/handler/proxy_handler_api.rs#L1-L120)
- [agent_runner 代理 API 处理器](file://crates/agent_runner/src/handler/proxy_handler_api.rs#L1-L120)
- [rcoder 清理任务](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L431-L602)
## 结论
本项目通过统一的日志与链路追踪中间件、Pingora 代理指标、定时清理任务与统一错误类型构建了完善的可观测性体系。rcoder 与 agent_runner 在同一套可观测框架下运行,既保证了跨服务的 trace_id 一致性,又提供了可操作的健康检查与代理监控接口。建议在生产环境中结合日志滚动策略、代理指标与清理任务配置,持续优化性能与稳定性。

View 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 回退到 infoagent_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_prefixrcoder 或 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
- 服务差异
- rcoderEnvFilter 默认 info
- agent_runnerEnvFilter 默认更细粒度,便于调试
章节来源
- [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 无缝注入到每条日志中,既满足日常运维需求,又为分布式追踪提供了坚实基础。建议在生产环境中保持异步写入与合理的滚动策略,并根据需要调整日志级别与输出格式,以平衡可观测性与性能。

View File

@@ -0,0 +1,188 @@
# 链路追踪
<cite>
**本文档引用的文件**
- [tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs)
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs)
- [main.rs](file://crates/rcoder/src/main.rs)
- [main.rs](file://crates/agent_runner/src/main.rs)
- [router.rs](file://crates/rcoder/src/router.rs)
- [router.rs](file://crates/agent_runner/src/router.rs)
- [Cargo.toml](file://Cargo.toml)
- [Cargo.lock](file://Cargo.lock)
</cite>
## 目录
1. [引言](#引言)
2. [trace_id生成与传播机制](#trace_id生成与传播机制)
3. [追踪中间件实现](#追踪中间件实现)
4. [OpenTelemetry集成配置](#opentelemetry集成配置)
5. [日志系统协同工作](#日志系统协同工作)
6. [常见问题与解决方案](#常见问题与解决方案)
7. [性能优化建议](#性能优化建议)
8. [结论](#结论)
## 引言
链路追踪是分布式系统中至关重要的可观测性工具它能够帮助开发者理解请求在系统中的完整执行路径。本项目基于OpenTelemetry实现了完整的分布式追踪系统通过`tracing_middleware_handler`中间件为每个HTTP请求生成和传播`trace_id`,并将其与日志系统深度集成。该系统支持跨服务的请求追踪,确保在复杂的微服务架构中能够准确地定位问题和分析性能瓶颈。
**本文档引用的文件**
- [tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs)
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs)
## trace_id生成与传播机制
### trace_id生成策略
系统采用UUID v4作为`trace_id`的生成策略,确保了全局唯一性和高熵值。在`tracing_middleware.rs`文件中,`generate_trace_id()`函数通过`uuid::Uuid::new_v4().simple().to_string()`生成32位无连字符的UUID字符串。这种格式既保证了唯一性又便于日志记录和查询。
```mermaid
flowchart TD
Start([请求到达]) --> ExtractHeader["从请求头提取 trace_id"]
ExtractHeader --> HasTraceID{存在 trace_id?}
HasTraceID --> |是| UseExisting["使用现有 trace_id"]
HasTraceID --> |否| GenerateNew["生成新的 UUID v4"]
GenerateNew --> Format["转换为 simple 格式 (32位)"]
Format --> UseNew["使用新生成的 trace_id"]
UseExisting --> CreateSpan
UseNew --> CreateSpan
CreateSpan["创建包含 trace_id 的 span"]
```
**图示来源**
- [tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L44-L47)
### 请求头提取逻辑
系统支持从多种标准请求头中提取`trace_id`,包括`x-trace-id``x-request-id``traceparent``x-correlation-id``extract_trace_id_from_headers()`函数遍历这些头字段,优先使用最先找到的有效值。这种多头支持的设计提高了系统的兼容性,能够与不同的追踪系统和代理工具无缝集成。
**本文档引用的文件**
- [tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L49-L69)
## 追踪中间件实现
### tracing_middleware_handler完整流程
`tracing_middleware_handler`是链路追踪的核心处理函数,它在请求处理管道中扮演着关键角色。该函数首先从请求头中提取或生成`trace_id`然后创建一个包含丰富上下文信息的span。通过`info_span!`系统记录了HTTP方法、URI、用户代理、内容类型等关键信息。
```mermaid
sequenceDiagram
participant Client as "客户端"
participant Middleware as "追踪中间件"
participant Handler as "业务处理器"
Client->>Middleware : HTTP请求 (含trace_id头)
Middleware->>Middleware : 提取/生成trace_id
Middleware->>Middleware : 创建http_request span
Middleware->>Handler : 调用next.run()
Handler->>Handler : 业务逻辑处理
Handler->>Middleware : 返回响应
Middleware->>Middleware : 记录响应信息
Middleware->>Client : HTTP响应
```
**图示来源**
- [tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L72-L130)
### info_span!宏的使用
`info_span!`宏用于创建结构化的日志span它不仅记录了基本的请求信息还包含了`trace_id`作为核心标识。在中间件中span的创建包含了HTTP方法、URI、`trace_id`、用户代理和内容类型等字段,为后续的调试和分析提供了丰富的上下文信息。
```mermaid
classDiagram
class Span {
+method : String
+uri : String
+trace_id : String
+user_agent : Option<String>
+content_type : Option<String>
}
class TraceContext {
+trace_id : String
+span_id : String
+trace_flags : u8
}
Span --> TraceContext : "包含"
```
**图示来源**
- [tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L86-L93)
### .instrument(span)调用
`.instrument(span)`是tracing框架的关键特性它将异步代码块与创建的span关联起来。在中间件中整个请求处理过程被包裹在`.instrument(span)`中,确保了所有在该代码块内生成的日志都会自动关联到同一个`trace_id`下。这种设计实现了零侵入式的追踪集成,业务代码无需关心追踪细节。
**本文档引用的文件**
- [tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L126-L127)
## OpenTelemetry集成配置
### 上下文注入配置
系统通过`opentelemetry::global::set_text_map_propagator()`设置了全局的文本映射传播器,使用`TraceContextPropagator::new()`来处理W3C Trace Context标准。这确保了`traceparent`头能够在服务间正确传播,实现了跨服务的链路追踪。
**本文档引用的文件**
- [main.rs](file://crates/rcoder/src/main.rs#L302-L305)
### Jaeger后端集成
通过Cargo.toml中的依赖配置系统集成了Jaeger作为追踪后端。`cf-rustracing-jaeger`依赖在Cargo.lock中被明确列出表明系统支持将追踪数据发送到Jaeger服务器进行可视化和分析。这种集成使得开发者可以通过Jaeger UI直观地查看请求的完整调用链路。
**本文档引用的文件**
- [Cargo.toml](file://Cargo.toml)
- [Cargo.lock](file://Cargo.lock#L969-L983)
## 日志系统协同工作
### trace_id一致性保证
系统通过多种机制确保`trace_id`在所有日志条目中保持一致。首先,在请求开始时生成的`trace_id`被存储在请求扩展中(`req.extensions_mut().insert(trace_id.clone())`),可供后续处理器访问。其次,通过`.instrument(span)`确保了整个请求处理过程中的所有日志都自动关联到同一个span。
```mermaid
flowchart TD
A[请求到达] --> B[生成/提取trace_id]
B --> C[创建span并注入context]
C --> D[将trace_id存入请求扩展]
D --> E[处理请求]
E --> F[所有日志自动包含trace_id]
F --> G[响应返回]
```
**图示来源**
- [tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L106-L109)
### JSON日志格式
系统配置了JSON格式的日志输出便于后续的集中式日志分析。通过`fmt::layer().json()`设置所有日志以结构化JSON格式写入文件包含时间戳、级别、目标、消息和自定义字段`trace_id`。这种格式与ELK或Loki等日志系统完美兼容。
**本文档引用的文件**
- [main.rs](file://crates/rcoder/src/main.rs#L291-L297)
## 常见问题与解决方案
### trace_id丢失问题
`trace_id`丢失通常发生在异步任务或跨线程调用中。解决方案是确保在任务创建时正确传播OpenTelemetry上下文。对于`!Send`类型的值,可以使用`tokio::task::LocalSet`来确保它们在同一个线程中执行,避免上下文丢失。
### 跨服务传播失败
跨服务传播失败可能是由于代理或网关修改了请求头。确保`x-trace-id``traceparent`等头字段在服务间传递时未被过滤或修改。在Kubernetes环境中检查Ingress控制器的配置确保追踪头被正确转发。
**本文档引用的文件**
- [tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs)
## 性能优化建议
### 采样策略
在高流量场景下,建议配置合理的采样策略以减少追踪数据量。可以通过设置`EnvFilter`来控制追踪的详细程度,例如只对错误请求或特定路径进行全量追踪,对正常请求进行低频采样。
### span开销控制
避免在热点路径上创建过多细粒度的span这会增加性能开销。建议只在关键业务逻辑和外部调用处创建span。对于高频调用的简单操作可以考虑使用计时器而非完整的span。
**本文档引用的文件**
- [main.rs](file://crates/rcoder/src/main.rs#L309-L311)
## 结论
本项目的链路追踪实现基于OpenTelemetry标准通过精心设计的中间件和配置实现了高效、可靠的分布式追踪功能。`trace_id`的生成和传播机制确保了请求的完整可追溯性,与日志系统的深度集成提供了强大的调试能力。对于初学者,系统提供了清晰的`trace_id`生命周期;对于专家,提供了丰富的性能优化选项。这种分层的设计既满足了基本的可观测性需求,又为高级用例留下了扩展空间。

View File

@@ -0,0 +1,365 @@
# 错误处理
<cite>
**本文档中引用的文件**
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs)
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs)
- [tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs)
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs)
- [agent_cancel_handler.rs](file://crates/agent_runner/src/handler/agent_cancel_handler.rs)
- [lib.rs](file://crates/shared_types/src/lib.rs)
</cite>
## 目录
1. [简介](#简介)
2. [核心错误类型](#核心错误类型)
3. [HTTP中间件错误处理](#http中间件错误处理)
4. [应用级错误结构](#应用级错误结构)
5. [错误传播与日志记录](#错误传播与日志记录)
6. [错误分类与状态码映射](#错误分类与状态码映射)
7. [错误信息暴露策略](#错误信息暴露策略)
8. [可观测性集成](#可观测性集成)
9. [常见问题与解决方案](#常见问题与解决方案)
10. [错误处理流程图](#错误处理流程图)
11. [监控与告警最佳实践](#监控与告警最佳实践)
## 简介
本文档全面解释系统中的错误处理机制,重点描述在 `tracing_middleware_handler` 中如何捕获和处理HTTP中间件错误包括 `Result<Response, StatusCode>` 的返回模式。结合 `shared_types` 中的 `AppError` 模型,说明应用级错误的结构设计和序列化方式。文档包括来自实际代码库的具体示例,如中间件中错误的传播和日志记录,以及错误处理与可观测性的集成。
## 核心错误类型
系统采用分层错误处理架构,主要包含两种核心错误类型:`AppError``HttpResult``AppError` 作为应用级错误的统一抽象,封装了不同来源的错误,而 `HttpResult` 则是标准化的HTTP响应格式用于向客户端返回一致的错误信息。
```mermaid
classDiagram
class AppError {
+AnyhowError(anyhow : : Error)
+IoError(std : : io : : Error)
+Generic(String)
+generic(msg : impl Into<String>) AppError
+internal_server_error(msg : &str) AppError
+validation_error(msg : &str) AppError
}
class HttpResult~T~ {
+code : String
+message : String
+data : Option~T~
+tid : Option~String~
+success : bool
+success(data : T) HttpResult~T~
+error(code : &str, message : &str) HttpResult~T~
+internal_error(message : &str) HttpResult~T~
}
AppError --> "implements" axum : : response : : IntoResponse
HttpResult~T~ --> "implements" axum : : response : : IntoResponse
HttpResult~T~ --> "serializes to" JSON
```
**图源**
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L3-L30)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L24-L58)
**本节源**
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L64)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L1-L103)
## HTTP中间件错误处理
`tracing_middleware_handler` 是系统中的核心HTTP中间件负责请求追踪和错误处理。该中间件采用 `Result<Response, StatusCode>` 的返回模式确保所有HTTP请求都能被正确处理或以适当的HTTP状态码返回错误。
中间件的主要功能包括:
1. 为每个HTTP请求自动生成 `trace_id`
2. 创建请求span用于日志跟踪
3. 记录请求和响应信息
4. 自动将 `trace_id` 注入到OpenTelemetry上下文中
```mermaid
sequenceDiagram
participant Client as "客户端"
participant Middleware as "tracing_middleware_handler"
participant Next as "下一个处理器"
participant Response as "响应"
Client->>Middleware : HTTP请求
Middleware->>Middleware : 提取或生成trace_id
Middleware->>Middleware : 创建追踪span
Middleware->>Middleware : 记录请求开始日志
Middleware->>Next : 调用next.run()
Next-->>Middleware : 返回Response
Middleware->>Middleware : 记录响应完成日志
Middleware->>Response : 返回Result<Response, StatusCode>
Response-->>Client : HTTP响应
```
**图源**
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L72-L130)
- [tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L72-L130)
**本节源**
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L1-L179)
- [tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L1-L179)
## 应用级错误结构
`AppError` 枚举是系统中应用级错误的核心数据结构,定义了三种主要的错误类型:
1. **AnyhowError**: 包装 `anyhow::Error` 类型,用于处理任意错误
2. **IoError**: 包装标准库的 `std::io::Error`用于处理I/O操作错误
3. **Generic**: 通用错误类型,用于表示自定义错误消息
`AppError` 实现了 `axum::response::IntoResponse` trait使其可以直接作为HTTP响应返回。当错误发生时系统会根据错误类型映射到相应的HTTP状态码并生成结构化的JSON响应。
```mermaid
flowchart TD
Start([错误发生]) --> MatchError["匹配AppError类型"]
MatchError --> AnyhowError{"是AnyhowError?"}
AnyhowError --> |是| Set500["设置状态码500"]
MatchError --> IoError{"是IoError?"}
IoError --> |是| Set500
MatchError --> Generic{"是Generic?"}
Generic --> |是| Set500
Set500 --> CreateJSON["创建JSON响应体"]
CreateJSON --> ReturnResponse["返回Response"]
ReturnResponse --> End([错误响应完成])
```
**图源**
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L33-L56)
**本节源**
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L64)
## 错误传播与日志记录
系统中的错误传播遵循Rust的错误处理最佳实践使用 `?` 操作符进行错误传播,并在适当的位置使用 `map_err` 进行错误转换。这种模式确保了错误信息能够在调用栈中正确传递,同时保持代码的简洁性。
在日志记录方面,系统使用 `tracing` 库进行结构化日志记录。每个错误都会被记录为包含 `trace_id` 的结构化日志条目,便于后续的错误追踪和分析。
```rust
// 示例:错误传播和日志记录
let project_workspace = get_project_workspace(&project_id).await?;
```
```rust
// 示例:错误转换
.map_err(|e| anyhow::anyhow!(e))?;
```
```rust
// 示例:错误日志记录
error!(
"❌ 收到 agent 执行结果失败: {}",
e
);
```
**本节源**
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L261-L261)
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L283-L283)
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L312-L316)
## 错误分类与状态码映射
系统采用统一的错误分类和状态码映射策略,确保错误处理的一致性。错误分类主要基于错误的严重程度和来源:
1. **客户端错误** (4xx): 由客户端请求引起的错误,如参数验证失败
2. **服务器错误** (5xx): 由服务器内部问题引起的错误,如数据库连接失败
3. **业务逻辑错误**: 特定于业务场景的错误,使用自定义错误码
状态码映射遵循HTTP标准同时使用自定义错误码提供更详细的错误信息。例如`5000` 表示内部服务器错误,`9010` 表示Agent正在执行任务等。
```mermaid
erDiagram
ERROR_CATEGORY {
string code PK
string name
string description
int http_status
string severity
}
ERROR_CODE {
string code PK
string category FK
string message
string solution
datetime created_at
}
ERROR_CATEGORY ||--o{ ERROR_CODE : contains
ERROR_CATEGORY {
"CLIENT_ERROR" "客户端错误" "请求参数错误等" 400 "HIGH"
"SERVER_ERROR" "服务器错误" "内部服务错误" 500 "CRITICAL"
"BUSINESS_ERROR" "业务错误" "业务逻辑错误" 400 "MEDIUM"
}
ERROR_CODE {
"0001" "BUSINESS_ERROR" "停止智能体执行失败" "重试或联系管理员" "2024-01-01"
"5000" "SERVER_ERROR" "内部服务器错误" "检查服务日志" "2024-01-01"
"9010" "BUSINESS_ERROR" "Agent正在执行任务" "等待当前任务完成" "2024-01-01"
"PROMPT001" "SERVER_ERROR" "Agent处理失败" "检查Agent状态" "2024-01-01"
}
```
**图源**
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L56-L57)
- [agent_cancel_handler.rs](file://crates/agent_runner/src/handler/agent_cancel_handler.rs#L213-L213)
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L218-L218)
**本节源**
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L46-L58)
- [agent_cancel_handler.rs](file://crates/agent_runner/src/handler/agent_cancel_handler.rs#L134-L138)
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L181-L184)
## 错误信息暴露策略
系统采用谨慎的错误信息暴露策略,平衡了调试需求和安全考虑。错误信息暴露遵循以下原则:
1. **生产环境最小化暴露**: 在生产环境中,只暴露必要的错误信息,避免泄露敏感信息
2. **开发环境详细暴露**: 在开发环境中,提供详细的错误信息,便于调试
3. **结构化错误响应**: 所有错误都以统一的JSON格式返回包含错误码、消息和trace_id
`HttpResult` 结构的设计体现了这一策略,它包含 `code``message``data``tid``success` 字段,确保客户端能够获得足够的信息来处理错误,同时不会暴露过多的内部细节。
```mermaid
stateDiagram-v2
[*] --> Production
[*] --> Development
Production --> ErrorHandling : 发生错误
Development --> ErrorHandling : 发生错误
ErrorHandling --> CheckEnvironment : 检查环境
CheckEnvironment --> |生产环境| MinimizeInfo : 最小化错误信息
CheckEnvironment --> |开发环境| DetailedInfo : 详细错误信息
MinimizeInfo --> FormatResponse : 格式化为标准响应
DetailedInfo --> FormatResponse : 格式化为标准响应
FormatResponse --> LogError : 记录完整错误日志
LogError --> ReturnResponse : 返回响应
ReturnResponse --> [*]
```
**图源**
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L24-L33)
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L33-L56)
**本节源**
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L1-L103)
## 可观测性集成
错误处理与系统的可观测性深度集成,主要体现在以下几个方面:
1. **分布式追踪**: 每个请求都分配唯一的 `trace_id`,贯穿整个请求处理链路
2. **结构化日志**: 所有错误日志都包含 `trace_id`,便于跨服务追踪
3. **指标监控**: 错误发生时记录相应的指标,用于监控和告警
`trace_id` 的生成和传播机制确保了在复杂的微服务架构中,能够快速定位和诊断问题。系统优先从请求头中提取 `trace_id`如果不存在则生成新的UUID作为 `trace_id`
```mermaid
graph TD
A[客户端请求] --> B{包含trace_id?}
B --> |是| C[使用请求中的trace_id]
B --> |否| D[生成新的trace_id]
C --> E[注入到OpenTelemetry上下文]
D --> E
E --> F[记录带trace_id的日志]
F --> G[传播到下游服务]
G --> H[集中式日志系统]
H --> I[错误分析和根因定位]
```
**图源**
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L80-L83)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L9-L22)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L51-L51)
**本节源**
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L1-L179)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L1-L103)
## 常见问题与解决方案
在实际使用中,可能会遇到一些常见的错误处理问题,以下是这些问题及其解决方案:
### 错误信息泄露
**问题**: 生产环境中暴露了过多的内部错误细节,可能导致安全风险。
**解决方案**: 实现环境感知的错误响应策略,在生产环境中只返回通用的错误消息,详细的错误信息仅在开发环境中暴露。
### 错误码不一致
**问题**: 不同的处理器使用不同的错误码,导致客户端难以处理。
**解决方案**: 建立统一的错误码注册表,所有错误码都从中心化的位置获取,确保一致性。
### trace_id丢失
**问题**: 在某些异步操作中,`trace_id` 可能丢失,导致无法完整追踪请求链路。
**解决方案**: 在 `HttpResult``into_response` 实现中添加 `trace_id` 的补全逻辑,确保即使在中间件之外创建的响应也能包含 `trace_id`
```mermaid
flowchart TD
A[问题识别] --> B[错误信息泄露]
A --> C[错误码不一致]
A --> D[trace_id丢失]
B --> E[实施环境感知响应]
C --> F[建立错误码注册表]
D --> G[实现trace_id补全]
E --> H[解决方案]
F --> H
G --> H
H --> I[改进的错误处理]
```
**图源**
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L82-L84)
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L17-L29)
**本节源**
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L78-L85)
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L16-L30)
## 错误处理流程图
以下是系统错误处理的完整流程图,展示了从错误发生到最终响应的整个过程:
```mermaid
flowchart TD
A[HTTP请求] --> B[tracing_middleware]
B --> C[提取/生成trace_id]
C --> D[创建追踪span]
D --> E[调用业务处理器]
E --> F{发生错误?}
F --> |是| G[捕获错误]
F --> |否| H[返回成功响应]
G --> I[转换为AppError]
I --> J[记录错误日志]
J --> K[创建HttpResult错误响应]
K --> L[序列化为JSON]
L --> M[返回HTTP错误响应]
H --> N[创建HttpResult成功响应]
N --> O[序列化为JSON]
O --> P[返回HTTP成功响应]
M --> Q[客户端]
P --> Q
style F fill:#f9f,stroke:#333,stroke-width:2px
style G fill:#f96,stroke:#333,stroke-width:2px
style H fill:#6f9,stroke:#333,stroke-width:2px
```
**图源**
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L72-L130)
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L33-L56)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L77-L102)
**本节源**
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L72-L130)
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L33-L56)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L77-L102)
## 监控与告警最佳实践
为了有效监控和告警系统中的错误,建议采用以下最佳实践:
1. **基于trace_id的根因分析**: 利用 `trace_id` 作为关键字,在日志系统中搜索完整的请求链路,快速定位问题根源。
2. **错误率监控**: 监控不同错误码的发生频率,设置告警阈值。
3. **P99延迟监控**: 监控错误响应的P99延迟确保错误处理不会成为性能瓶颈。
4. **错误分类仪表板**: 创建按错误类型、服务、时间维度分类的仪表板,便于趋势分析。
通过这些实践,可以建立一个健壮的错误监控体系,及时发现和解决系统中的问题。
**本节源**
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L98-L103)
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L115-L122)