添加qiming-rcoder模块
This commit is contained in:
426
qiming-rcoder/.qoder/repowiki/zh/content/可观测性/可观测性.md
Normal file
426
qiming-rcoder/.qoder/repowiki/zh/content/可观测性/可观测性.md
Normal 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 请求级链路追踪与日志注入
|
||||
- 清理任务:闲置资源回收与孤立容器清理
|
||||
- 代理 API:Pingora 代理的状态、统计与配置查询
|
||||
|
||||
```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_id(UUID 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)
|
||||
|
||||
### 错误处理与返回值
|
||||
- 统一错误类型
|
||||
- AppError:AnyhowError、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 配置
|
||||
- AppConfig:default_agent、projects_dir、port、proxy_config、docker_config
|
||||
- ProxyConfig:listen_port、default_backend_port、backend_host、port_param、health_check
|
||||
- HealthCheckConfig:enabled、interval_seconds、timeout_seconds、healthy_threshold、unhealthy_threshold
|
||||
- DockerConfig:multi_image_config、network_mode、work_dir、auto_cleanup、container_ttl_seconds
|
||||
- agent_runner 配置
|
||||
- AppConfig:default_agent、projects_dir、port、proxy_config
|
||||
- ProxyConfig:listen_port、default_backend_port、backend_host、port_param、health_check
|
||||
- HealthCheckConfig:enabled、interval_seconds、timeout_seconds、healthy_threshold、unhealthy_threshold
|
||||
- 环境变量覆盖
|
||||
- rcoder:RCODER_PORT、RCODER_PROJECTS_DIR、RCODER_NETWORK_MODE、RCODER_WORK_DIR、RCODER_AUTO_CLEANUP、RCODER_CONTAINER_TTL
|
||||
- agent_runner:RCODER_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)
|
||||
|
||||
### 与容器与镜像的关系
|
||||
- 服务镜像配置
|
||||
- ServiceImageConfig:image/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 一致性,又提供了可操作的健康检查与代理监控接口。建议在生产环境中结合日志滚动策略、代理指标与清理任务配置,持续优化性能与稳定性。
|
||||
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 无缝注入到每条日志中,既满足日常运维需求,又为分布式追踪提供了坚实基础。建议在生产环境中保持异步写入与合理的滚动策略,并根据需要调整日志级别与输出格式,以平衡可观测性与性能。
|
||||
188
qiming-rcoder/.qoder/repowiki/zh/content/可观测性/链路追踪.md
Normal file
188
qiming-rcoder/.qoder/repowiki/zh/content/可观测性/链路追踪.md
Normal 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`生命周期;对于专家,提供了丰富的性能优化选项。这种分层的设计既满足了基本的可观测性需求,又为高级用例留下了扩展空间。
|
||||
365
qiming-rcoder/.qoder/repowiki/zh/content/可观测性/错误处理.md
Normal file
365
qiming-rcoder/.qoder/repowiki/zh/content/可观测性/错误处理.md
Normal 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)
|
||||
Reference in New Issue
Block a user