添加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,449 @@
# eBPF 诊断工具
本目录包含用于监控和诊断 `agent_runner` 及其子进程性能的 eBPF 工具。
## 📊 监控架构总览
```
┌─────────────────────────────────────────────────────────────────────────┐
│ 进程性能监控完整方案 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ CPU 性能监控(持续) │ │
│ │ │ │
│ │ Grafana Alloy (eBPF) → Pyroscope Server → Web UI (4040) │ │
│ │ - 97 Hz 采样率 │ │
│ │ - 每 15 秒发送数据 │ │
│ │ - 自动发现进程 │ │
│ │ - 支持历史查询 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 进程指标监控(持续) │ │
│ │ │ │
│ │ Alloy Process Exporter → Prometheus → Grafana Dashboard │ │
│ │ - CPU、内存、I/O、FD、线程数 │ │
│ │ - 15 秒采集间隔 │ │
│ │ - 时序数据存储 │ │
│ │ - Dashboard 可视化 (3000) │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Off-CPU 阻塞监控(定期) │ │
│ │ │ │
│ │ offcputime-bpfcc → SVG 火焰图文件 │ │
│ │ - 每 60 秒生成一次 │ │
│ │ - 显示阻塞堆栈 │ │
│ │ - 识别 I/O、锁、等待等阻塞 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 系统调用监控(持续) │ │
│ │ │ │
│ │ syscount-bpfcc → 统计文件 │ │
│ │ execsnoop-bpfcc → 进程创建日志 │ │
│ │ opensnoop-bpfcc → 文件访问日志 │ │
│ │ - 每 60 秒统计一次 │ │
│ │ - 持续追踪进程和文件访问 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 手动诊断工具(按需使用) │ │
│ │ │ │
│ │ diag-tool.sh - 综合诊断工具 │ │
│ │ auto-flamegraph.sh - 自动火焰图生成 │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
## 目录结构
```
ebpf-tools/
├── README.md # 本文档
├── alloy-config.alloy # Grafana Alloy 配置CPU 监控 + 进程指标导出)
├── diag-tool.sh # 手动诊断工具
├── auto-flamegraph.sh # 自动火焰图生成
├── offcpu-monitor.sh # Off-CPU 阻塞监控
└── syscall-monitor.sh # 系统调用监控
```
---
## 🔧 工具详解
### 1. alloy-config.alloy - Grafana Alloy 配置
**用途**: 持续 CPU 性能监控 + 进程指标导出
**工作原理**:
- 使用 eBPF 自动发现 `agent_runner` 及其子进程
- 以 97 Hz 频率采样 CPU 性能数据,发送到 Pyroscope
- 采集进程指标CPU、内存、I/O、FD、线程数发送到 Prometheus
- 在 Web UI 中实时查看Pyroscope (4040) + Grafana (3000)
**采集的指标**:
| 指标类别 | 指标名称 | 说明 |
|---------|---------|------|
| **CPU** | `process_cpu_seconds_total` | CPU 时间(累计) |
| **内存** | `process_resident_memory_bytes` | 常驻内存RSS |
| **内存** | `process_virtual_memory_bytes` | 虚拟内存VSZ |
| **FD** | `process_open_fds` | 打开的文件描述符 |
| **I/O** | `process_read_bytes_total` | 读取字节数 |
| **I/O** | `process_write_bytes_total` | 写入字节数 |
| **线程** | `process_num_threads` | 线程数量 |
| **上下文切换** | `process_context_switches_total` | 上下文切换次数 |
**进程标签**:
- `process_pid`: 进程 PID
- `process_name`: 进程名称
- `process_exe`: 完整执行路径
- `parent_pid`: 父进程 PID
- `project_id`: 项目 ID
- `container_id`: 容器 ID
**环境变量**:
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `ENABLE_ALLOY` | - | 是否启用(由 ebpf-debug feature 控制) |
| `PYROSCOPE_URL` | http://pyroscope:4040 | Pyroscope Server 地址 |
| `PROMETHEUS_URL` | http://prometheus:9090/api/v1/write | Prometheus 写入地址 |
**查看数据**:
```bash
# 1. Pyroscope Web UI (CPU 性能)
open http://localhost:4040
# 2. Grafana Dashboard (进程指标)
open http://localhost:3000
# 登录: admin / admin
# 查找: "Agent Runner 进程监控"
```
---
### 2. offcpu-monitor.sh - Off-CPU 阻塞监控
**用途**: 定期生成 Off-CPU 阻塞火焰图,分析进程阻塞原因
**工作原理**:
- 每 60 秒自动运行一次(可配置)
-`agent_runner` 及其所有子进程进行采样
- 使用 `offcputime-bpfcc` 捕获阻塞堆栈
- 生成 SVG 火焰图文件,自动清理旧文件(最多保留 50 个)
**环境变量**:
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `ENABLE_OFFCPUTIME` | - | 是否启用(由 ebpf-debug feature 控制) |
| `OFFCPU_DURATION` | 30 | 每次采样时长(秒) |
| `OFFCPU_INTERVAL` | 60 | 生成间隔(秒) |
| `MAX_OFFCPU_FILES` | 50 | 最多保留文件数量 |
**输出文件**:
```
/app/container-logs/diag/
├── offcpu-monitor.log # 监控日志
├── offcpu-agent_runner-1-20250111_143025.svg # 主进程阻塞火焰图
└── offcpu-claude-code-acp-123-*.svg # 子进程阻塞火焰图
```
---
### 3. syscall-monitor.sh - 系统调用监控
**用途**: 监控进程的系统调用活动,包括进程创建、文件访问和系统调用统计
**工作原理**:
- 每 60 秒统计一次系统调用(可配置)
- 后台持续追踪进程创建 (`execsnoop-bpfcc`)
- 后台持续追踪文件访问 (`opensnoop-bpfcc`)
- 定期生成系统调用统计报告
**采集的数据**:
| 工具 | 数据 | 说明 |
|------|------|------|
| `syscount-bpfcc` | 系统调用统计 | 每个系统调用的次数和耗时 |
| `execsnoop-bpfcc` | 进程创建日志 | 新进程的创建时间和命令行 |
| `opensnoop-bpfcc` | 文件访问日志 | 文件打开/关闭操作 |
**环境变量**:
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `ENABLE_SYSCALL_MONITOR` | - | 是否启用(由 ebpf-debug feature 控制) |
| `SAMPLE_DURATION` | 30 | 每次采样时长(秒) |
| `GENERATE_INTERVAL` | 60 | 生成间隔(秒) |
**输出文件**:
```
/app/container-logs/diag/
├── syscall-monitor.log # 监控日志
├── syscall-count-agent_runner-1-*.txt # 系统调用统计
├── execsnoop-*.log # 进程创建日志
└── opensnoop-*.log # 文件访问日志
```
**日志说明**:
- **控制台输出**: 每次采样只输出一行汇总日志
- **文件日志**: 详细日志写入 `syscall-monitor.log`
---
### 4. diag-tool.sh - 手动诊断工具
手动触发的 eBPF 诊断工具,用于在怀疑有性能问题时主动采集数据。
**用法**:
```bash
diag-tool.sh {offcpu|flame|profile|all} <pid> [duration]
```
**命令**:
| 命令 | 说明 |
|------|------|
| `offcpu <pid> [duration]` | 分析 off-cpu 堆栈,默认 30 秒 |
| `flame <pid> [duration]` | 生成火焰图,默认 30 秒 |
| `profile <pid> [duration]` | CPU 性能分析,默认 30 秒 |
| `all <pid>` | 综合诊断(包含所有分析) |
**快捷命令**:
- `e-offcpu` - 等同于 `diag-tool.sh offcpu`
- `e-flame` - 等同于 `diag-tool.sh flame`
- `e-profile` - 等同于 `diag-tool.sh profile`
- `e-all` - 等同于 `diag-tool.sh all`
---
### 5. auto-flamegraph.sh - 自动火焰图生成
持续在后台运行的火焰图生成工具,自动监控 `agent_runner` 及其所有子进程。
**工作原理**:
1. 自动检测 `agent_runner` 进程 PID
2. 递归获取所有子进程 PID
3. 使用 bpftrace 采样性能数据(默认 30 秒)
4. 生成火焰图 SVG 文件
5. 每 60 秒重复一次
---
## 🎯 使用场景
### 场景 1: 持续监控 CPU 性能
**目标**: 在 Web UI 中实时查看 agent_runner 性能数据
**步骤**:
1. 确保容器已启动Alloy 自动运行)
2. 打开 http://localhost:4040 (Pyroscope)
3. 选择应用 `agent_runner`
4. 按需过滤标签(如 `process_name="agent_runner"`
5. 查看火焰图、时序数据、Top 函数
**适用问题**:
- CPU 使用率异常
- 函数调用热点分析
- 性能回归检测
---
### 场景 2: 查看进程指标趋势
**目标**: 监控内存、I/O、FD 等进程指标的趋势
**步骤**:
1. 打开 http://localhost:3000 (Grafana)
2. 登录admin / admin
3. 查找 "Agent Runner 进程监控" Dashboard
4. 选择 `project_id``instance``process_name` 过滤
5. 查看各面板数据
**可用面板**:
- 概览: RSS/VSZ 内存、CPU 使用率、文件描述符
- 内存趋势: RSS 和 VSZ 的时间序列图
- I/O 监控: 读取/写入速率
- 上下文切换: 自愿/非自愿切换速率
- 线程详情: 线程数量、FD 使用率
- 缺页错误: 次要/主要缺页错误速率
---
### 场景 3: 分析进程阻塞问题
**目标**: 找出进程为什么被阻塞(等待 I/O、锁等
**步骤**:
1. 等待 offcpu-monitor 自动生成火焰图(或手动触发)
2. 导出 SVG 文件到本地
3. 在浏览器中打开火焰图
4. 查找宽的阻塞堆栈
```bash
# 导出最新的 Off-CPU 火焰图
docker cp <container>:/app/container-logs/diag/offcpu-*.svg ./
open offcpu-*.svg
```
**适用问题**:
- `new_session` 超时
- 进程响应缓慢
- I/O 阻塞
- 锁竞争
---
### 场景 4: 分析系统调用模式
**目标**: 了解进程的系统调用行为,找出系统调用热点
**步骤**:
1. 查看系统调用统计日志
2. 分析哪些系统调用最频繁
3. 查看 execsnoop/opensnoop 日志了解进程和文件访问
```bash
# 查看系统调用统计
docker exec <container> cat /app/container-logs/diag/syscall-count-*.txt | head -20
# 查看进程创建日志
docker exec <container> tail -f /app/container-logs/diag/execsnoop-*.log
```
---
### 场景 5: 手动诊断已知问题
```bash
# 进入容器
docker exec -it <container> bash
# 诊断 agent_runner
e-all $(pgrep agent_runner)
# 导出结果
docker cp <container>:/app/container-logs/diag ./diag-results
```
---
## 📈 火焰图分析
### CPU 火焰图Alloy + Pyroscope
**如何阅读**:
- **横轴**: CPU 时间占比(越宽表示占用越多)
- **纵轴**: 调用堆栈(从上到下是调用关系)
- **颜色**: 暖色调表示热点函数
**典型问题识别**:
| 现象 | 可能原因 |
|------|----------|
| 某个函数占据大部分宽度 | CPU 密集型计算 |
| 深层函数很宽 | 递归调用或深层嵌套 |
| 出现 `syscall` 大量时间 | 系统调用开销 |
| 出现 `sleep`/`usleep` | 主动休眠或等待 |
### Off-CPU 火焰图offcputime-bpfcc
**如何阅读**:
- **横轴**: 阻塞时间占比(越宽表示阻塞越久)
- **纵轴**: 阻塞时的调用堆栈
- **颜色**: 暖色调表示阻塞热点
**典型问题识别**:
| 现象 | 可能原因 |
|------|----------|
| `schedule()` 占据大量时间 | 进程被调度出去CPU 竞争) |
| `do_wait()`/`wait_event()` | 等待事件或信号 |
| `__sock_sendmsg()`/`__sock_recvmsg()` | 网络 I/O 阻塞 |
| `blk_mq_submit_bio()` | 磁盘 I/O 阻塞 |
| `futex_wait()` | 锁等待(互斥锁) |
---
## 🔍 故障排查
### Grafana Dashboard 显示 "No Data"
```bash
# 1. 检查 Prometheus 中是否有数据
curl -s 'http://localhost:9091/api/v1/query?query=process_resident_memory_bytes'
# 2. 检查标签值
curl -s 'http://localhost:9091/api/v1/label/project_id/values'
# 3. 确认 agent_runner 容器正在运行
docker ps | grep agent_runner
```
### 变量下拉框为空
```bash
# 检查标签值是否存在
curl -s 'http://localhost:9091/api/v1/label/project_id/values'
# 如果没有数据,说明没有 agent_runner 容器在运行
# 启动一个 agent_runner 容器后再检查
```
### Pyroscope Web UI 无数据
```bash
# 1. 检查 Pyroscope Server
docker ps | grep pyroscope
docker logs rcoder-pyroscope
# 2. 检查 Alloy 是否发送数据
docker exec <container> grep "collected profiles" /app/container-logs/diag/alloy.log
# 3. 检查网络连接
docker exec <container> curl http://pyroscope:4040
```
### Off-CPU 火焰图未生成
```bash
# 1. 检查 offcputime-bpfcc 是否可用
docker exec <container> which offcputime-bpfcc
# 2. 检查监控进程
docker exec <container> ps aux | grep offcpu-monitor
# 3. 查看监控日志
docker exec <container> tail -f /app/container-logs/diag/offcpu-monitor.log
```
### 系统调用监控无输出
```bash
# 1. 检查 syscount-bpfcc 是否可用
docker exec <container> which syscount-bpfcc
# 2. 检查监控脚本是否运行
docker exec <container> ps aux | grep syscall-monitor
# 3. 查看监控日志
docker exec <container> tail -f /app/container-logs/diag/syscall-monitor.log
```
---
## ⚠️ 安全注意事项
⚠️ **eBPF 工具需要容器特权模式运行**,仅在受信任的调试环境使用!
生产环境请使用 `make docker-build-agent-production` 构建无 eBPF 工具的镜像。
---
## 📚 相关文档
- [Grafana Alloy Documentation](https://grafana.com/docs/alloy/latest/)
- [Pyroscope Documentation](https://pyroscope.io/docs/)
- [Prometheus Documentation](https://prometheus.io/docs/)
- [Grafana Documentation](https://grafana.com/docs/)
- [Brendan Gregg's FlameGraph](https://github.com/brendangregg/FlameGraph)
- [bpftrace 参考指南](https://bpftrace.dev/)
- 主项目文档: `/docker/README.md`