<!-- title: Claude Code可观测性：OpenTelemetry全链路监控 -->

## 概述

本教程面向已熟悉Claude Code基本用法的中高级开发者，手把手教你搭建一套完整的Claude Code可观测性监控体系。通过OpenTelemetry采集Token用量、成本、会话事件等核心指标，接入Grafana进行实时可视化与告警，实现从"盲飞"到"全链路透视"的质变。适合团队技术负责人、DevOps工程师和重度Claude Code用户。

## 前置条件

- 已安装 Claude Code CLI（v1.0.18+，内置OpenTelemetry支持）
- Docker & Docker Compose（用于部署监控栈）
- 基本熟悉 Prometheus/Grafana 概念
- 一个正在使用的 Anthropic API Key

## 为什么Claude Code需要可观测性

大多数开发者在用Claude Code时，关注点是"怎么写更好的Prompt"、"怎么选模型降成本"。但一个被忽视的问题是——你怎么知道你的优化真的生效了？

可观测性与优化是两个完全不同的问题域：

| 维度 | 优化（Optimization） | 可观测性（Observability） |
|------|---------------------|-------------------------|
| 核心问题 | 怎么让Claude Code做得更好 | 怎么知道它做得怎么样 |
| 典型动作 | 调整CLAUDE.md、选模型、裁剪上下文 | 采集指标、建Dashboard、设告警 |
| 数据来源 | 你的经验和直觉 | 结构化的遥测数据 |
| 反馈周期 | 天级甚至周级 | 秒级到分钟级 |

没有可观测性的优化，本质上是在黑暗中摸索。你可能觉得换了Haiku模型省钱了，但实际上因为重试率上升，总成本反而增加了——没有数据你永远不会知道。

Claude Code从v1.0.18开始内置了OpenTelemetry支持，这是Anthropic官方认可的可观测性方案。本文将基于此构建完整的监控体系。

## 架构总览

在动手之前，先理解整体架构：

```mermaid
flowchart TB
    subgraph ClaudeCode["Claude Code CLI"]
        CC_SESSION["会话Session"]
        CC_OTELENV["OTEL环境变量"]
    end

    subgraph OTEL Collector["OpenTelemetry Collector"]
        OTEL_RECV["OTLP Receiver<br/>:4317/gRPC :4318/HTTP"]
        OTEL_PROC["Processor<br/>batch/attributes"]
        OTEL_EXPORT["Exporter"]
    end

    subgraph Storage["时序存储"]
        PROM["Prometheus<br/>或 VictoriaMetrics"]
        LOKI["Loki<br/>日志存储"]
    end

    subgraph Viz["可视化层"]
        GRAFANA["Grafana Dashboard"]
        ALERT["AlertManager<br/>告警规则"]
    end

    CC_SESSION -->|"Traces + Metrics<br/>OTLP Protocol"| OTEL_RECV
    CC_OTELENV -->|"配置导出端点"| OTEL_RECV
    OTEL_RECV --> OTEL_PROC
    OTEL_PROC --> OTEL_EXPORT
    OTEL_EXPORT -->|"Metrics"| PROM
    OTEL_EXPORT -->|"Logs/Traces"| LOKI
    PROM --> GRAFANA
    LOKI --> GRAFANA
    PROM --> ALERT
    ALERT -->|"Slack/Email/Webhook"| NOTIFY["通知渠道"]
```

**数据流说明**：
1. Claude Code通过内置OTEL SDK生成遥测数据（Traces + Metrics）
2. 数据通过OTLP协议发送到OTEL Collector
3. Collector处理后分发到Prometheus（指标）和Loki（日志）
4. Grafana从存储层读取数据，渲染Dashboard
5. AlertManager基于Prometheus指标触发告警

## Step 1：环境变量配置

Claude Code的OpenTelemetry支持通过环境变量控制。在Shell配置文件中添加：

```bash
# ~/.bashrc 或 ~/.zshrc

# === Claude Code OpenTelemetry 配置 ===

# 启用OTEL导出
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317"

# 可选：设置服务名称，方便在Dashboard中区分
export OTEL_SERVICE_NAME="claude-code"

# 可选：添加资源属性（如用户名、机器名）
export OTEL_RESOURCE_ATTRIBUTES="service.name=claude-code,host.name=$(hostname),user.name=$(whoami)"

# 可选：设置采样率（1.0 = 100%采样，生产环境可降低）
export OTEL_TRACES_SAMPLER="parentbased_always_on"
```

**验证配置是否生效**：

```bash
# 重新加载Shell配置
source ~/.bashrc

# 确认环境变量已设置
env | grep OTEL
```

预期输出：
```
OTEL_EXPORTER_OTLP_PROTOCOL=grpc
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
OTEL_SERVICE_NAME=claude-code
OTEL_RESOURCE_ATTRIBUTES=service.name=claude-code,host.name=my-machine,user.name=dev
```

**常见问题**：

| 问题 | 原因 | 解决方案 |
|------|------|---------|
| Claude Code启动报OTEL连接错误 | Collector未启动 | 先启动监控栈再启动Claude Code |
| Dashboard无数据 | 端口不匹配 | 确认OTEL_EXPORTER_OTLP_ENDPOINT与Collector端口一致 |
| 数据延迟较高 | 批处理间隔太大 | 调整Collector的batch processor配置 |

## Step 2：一键部署监控栈

社区已经有现成的Docker Compose方案。这里推荐`rommelporras/claude-code-monitoring`项目，开箱即用：

```bash
# 克隆仓库
git clone https://github.com/rommelporras/claude-code-monitoring.git
cd claude-code-monitoring

# 一键启动
docker compose up -d
```

如果你想自己搭建，以下是完整的`docker-compose.yml`：

```yaml
# docker-compose.yml
version: "3.8"

services:
  # OpenTelemetry Collector
  otel-collector:
    image: otel/opentelemetry-collector-contrib:latest
    container_name: claude-otel-collector
    command: ["--config=/etc/otelcol/config.yaml"]
    volumes:
      - ./otel-collector-config.yaml:/etc/otelcol/config.yaml
    ports:
      - "4317:4317"   # gRPC
      - "4318:4318"   # HTTP
      - "8889:8889"   # Prometheus exporter
    networks:
      - monitoring

  # Prometheus
  prometheus:
    image: prom/prometheus:latest
    container_name: claude-prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus
    ports:
      - "9090:9090"
    networks:
      - monitoring
    depends_on:
      - otel-collector

  # Loki (日志存储)
  loki:
    image: grafana/loki:latest
    container_name: claude-loki
    ports:
      - "3100:3100"
    networks:
      - monitoring

  # Grafana
  grafana:
    image: grafana/grafana:latest
    container_name: claude-grafana
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=claude2026
      - GF_AUTH_ANONYMOUS_ENABLED=false
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana-dashboards:/etc/grafana/provisioning/dashboards
      - ./grafana-datasources:/etc/grafana/provisioning/datasources
    ports:
      - "3000:3000"
    networks:
      - monitoring
    depends_on:
      - prometheus
      - loki

volumes:
  prometheus-data:
  grafana-data:

networks:
  monitoring:
    driver: bridge
```

接下来是OTEL Collector的配置文件：

```yaml
# otel-collector-config.yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:
    timeout: 5s
    send_batch_size: 1024
  # 添加自定义属性，方便后续查询
  resource:
    attributes:
      - key: monitoring.source
        value: claude-code
        action: upsert

exporters:
  prometheus:
    endpoint: "0.0.0.0:8889"
    namespace: claude_code
  loki:
    endpoint: "http://loki:3100/loki/api/v1/push"
    default_labels_enabled:
      exporter: false
      job: true

service:
  pipelines:
    metrics:
      receivers: [otlp]
      processors: [batch, resource]
      exporters: [prometheus]
    logs:
      receivers: [otlp]
      processors: [batch, resource]
      exporters: [loki]
    traces:
      receivers: [otlp]
      processors: [batch, resource]
      exporters: [loki]
```

Prometheus配置：

```yaml
# prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: "otel-collector"
    scrape_interval: 10s
    static_configs:
      - targets: ["otel-collector:8889"]
```

Grafana数据源自动配置：

```yaml
# grafana-datasources/datasources.yml
apiVersion: 1
datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
    editable: true
  - name: Loki
    type: loki
    access: proxy
    url: http://loki:3100
    editable: true
```

启动并验证：

```bash
# 启动所有服务
docker compose up -d

# 检查所有容器状态
docker compose ps

# 预期输出：4个容器全部 running
# NAME                   STATUS
# claude-otel-collector  Up
# claude-prometheus      Up
# claude-loki            Up
# claude-grafana         Up
```

**验证各组件**：

```bash
# 验证OTEL Collector接收端口
curl -s http://localhost:4318/ | head -1

# 验证Prometheus
curl -s http://localhost:9090/-/healthy
# 预期：Prometheus is Healthy.

# 验证Grafana
curl -s http://localhost:3000/api/health
# 预期：{"commit":"...","database":"ok","version":"..."}
```

## Step 3：Claude Code采集的核心指标解读

Claude Code通过OpenTelemetry导出的核心指标包含以下几个维度。理解这些指标的含义是构建有效Dashboard的前提：

### 3.1 Token用量指标

| 指标名称 | 含义 | PromQL示例 |
|---------|------|-----------|
| `claude_code_tokens_input_total` | 输入Token累计用量 | `rate(claude_code_tokens_input_total[5m])` |
| `claude_code_tokens_output_total` | 输出Token累计用量 | `rate(claude_code_tokens_output_total[5m])` |
| `claude_code_tokens_cache_read_total` | 缓存命中Token数 | `rate(claude_code_tokens_cache_read_total[5m])` |
| `claude_code_tokens_cache_creation_total` | 缓存写入Token数 | `rate(claude_code_tokens_cache_creation_total[5m])` |

**缓存命中率**是成本优化的核心指标。计算公式：

```promql
# 缓存命中率 = cache_read / (cache_read + input)
sum(rate(claude_code_tokens_cache_read_total[5m]))
/
(sum(rate(claude_code_tokens_cache_read_total[5m])) + sum(rate(claude_code_tokens_input_total[5m])))
```

### 3.2 成本指标

| 指标名称 | 含义 |
|---------|------|
| `claude_code_cost_total` | 累计成本（美元） |
| `claude_code_cost_session` | 单次会话成本 |

成本计算涉及Anthropic的分层定价：
- 输入Token：$3/M（Opus）/ $3/M（Sonnet）/ $0.80/M（Haiku）
- 输出Token：$15/M（Opus）/ $15/M（Sonnet）/ $4/M（Haiku）
- 缓存读取：$0.30/M（享受90%折扣）

### 3.3 会话与事件指标

| 指标名称 | 含义 |
|---------|------|
| `claude_code_sessions_total` | 会话总数 |
| `claude_code_tool_calls_total` | 工具调用次数（按工具类型分） |
| `claude_code_errors_total` | 错误总数（按类型分） |
| `claude_code_session_duration_seconds` | 会话持续时间 |

### 3.4 工具调用分布

这是衡量Claude Code工作效率的关键维度。一个高效的工作流应该是Read/Glob/Grep > Edit/Write——说明Claude Code在充分理解代码后才动手修改。

```promql
# 各工具调用占比
sum by (tool_name) (rate(claude_code_tool_calls_total[1h]))
```

## Step 4：Grafana Dashboard搭建

### 4.1 创建核心Dashboard

登录Grafana（`http://localhost:3000`，默认账号admin/claude2026），按以下步骤创建Dashboard。

**Panel 1：Token用量趋势（时间序列图）**

```promql
# 输入Token速率
sum(rate(claude_code_tokens_input_total[5m])) * 60

# 输出Token速率
sum(rate(claude_code_tokens_output_total[5m])) * 60

# 缓存读取Token速率
sum(rate(claude_code_tokens_cache_read_total[5m])) * 60
```

**Panel 2：累计成本（Stat面板）**

```promql
# 今日总成本
sum(increase(claude_code_cost_total[24h]))

# 本周总成本
sum(increase(claude_code_cost_total[7d]))

# 本月总成本
sum(increase(claude_code_cost_total[30d]))
```

**Panel 3：缓存效率（Gauge面板）**

```promql
# 缓存命中率百分比
(sum(rate(claude_code_tokens_cache_read_total[5m]))
/
(sum(rate(claude_code_tokens_cache_read_total[5m])) + sum(rate(claude_code_tokens_input_total[5m])))) * 100
```

阈值设置：绿色 > 60%，黄色 30-60%，红色 < 30%

**Panel 4：工具调用分布（饼图）**

```promql
sum by (tool_name) (increase(claude_code_tool_calls_total[24h]))
```

**Panel 5：每小时成本热力图（Heatmap）**

```promql
sum by (le) (rate(claude_code_cost_session_bucket[1h]))
```

**Panel 6：错误率趋势**

```promql
# 错误率 = errors / (errors + tool_calls)
sum(rate(claude_code_errors_total[5m]))
/
(sum(rate(claude_code_errors_total[5m])) + sum(rate(claude_code_tool_calls_total[5m])))
```

### 4.2 Dashboard JSON模板

为了快速复现，这里提供一个完整的Dashboard JSON（可直接导入Grafana）：

```json
{
  "dashboard": {
    "title": "Claude Code Observability",
    "tags": ["claude-code", "ai", "observability"],
    "timezone": "browser",
    "panels": [
      {
        "id": 1,
        "title": "Token Throughput (per minute)",
        "type": "timeseries",
        "gridPos": {"h": 8, "w": 12, "x": 0, "y": 0},
        "targets": [
          {"expr": "sum(rate(claude_code_tokens_input_total[5m]))*60", "legendFormat": "Input"},
          {"expr": "sum(rate(claude_code_tokens_output_total[5m]))*60", "legendFormat": "Output"},
          {"expr": "sum(rate(claude_code_tokens_cache_read_total[5m]))*60", "legendFormat": "Cache Read"}
        ]
      },
      {
        "id": 2,
        "title": "Daily Cost ($)",
        "type": "stat",
        "gridPos": {"h": 4, "w": 6, "x": 12, "y": 0},
        "targets": [
          {"expr": "sum(increase(claude_code_cost_total[24h]))", "legendFormat": "24h"}
        ],
        "fieldConfig": {
          "defaults": {"unit": "currencyUSD", "thresholds": {"steps": [{"value": null, "color": "green"}, {"value": 10, "color": "yellow"}, {"value": 50, "color": "red"}]}}
        }
      },
      {
        "id": 3,
        "title": "Cache Hit Rate",
        "type": "gauge",
        "gridPos": {"h": 4, "w": 6, "x": 18, "y": 0},
        "targets": [
          {"expr": "(sum(rate(claude_code_tokens_cache_read_total[5m]))/(sum(rate(claude_code_tokens_cache_read_total[5m]))+sum(rate(claude_code_tokens_input_total[5m]))))*100"}
        ],
        "fieldConfig": {
          "defaults": {"unit": "percent", "max": 100, "thresholds": {"steps": [{"value": null, "color": "red"}, {"value": 30, "color": "yellow"}, {"value": 60, "color": "green"}]}}
        }
      },
      {
        "id": 4,
        "title": "Tool Calls Distribution",
        "type": "piechart",
        "gridPos": {"h": 8, "w": 6, "x": 12, "y": 4},
        "targets": [
          {"expr": "sum by (tool_name) (increase(claude_code_tool_calls_total[24h]))"}
        ]
      },
      {
        "id": 5,
        "title": "Error Rate",
        "type": "timeseries",
        "gridPos": {"h": 8, "w": 6, "x": 18, "y": 4},
        "targets": [
          {"expr": "sum(rate(claude_code_errors_total[5m]))/(sum(rate(claude_code_errors_total[5m]))+sum(rate(claude_code_tool_calls_total[5m])))", "legendFormat": "Error Rate"}
        ]
      }
    ],
    "refresh": "30s",
    "time": {"from": "now-6h", "to": "now"}
  },
  "overwrite": true
}
```

## Step 5：告警规则配置

光有Dashboard是不够的，你需要自动化告警来及时发现问题。

### 5.1 成本告警

```yaml
# alert-rules.yml - 放在Prometheus的rules目录下
groups:
  - name: claude_code_cost_alerts
    interval: 5m
    rules:
      # 单日成本超过阈值
      - alert: ClaudeCodeDailyCostHigh
        expr: sum(increase(claude_code_cost_total[24h])) > 30
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Claude Code daily cost exceeded $30"
          description: "Current 24h cost: {{ $value | printf \"%.2f\" }} USD"

      # 小时成本突增（可能是卡在循环中）
      - alert: ClaudeCodeHourlyCostSpike
        expr: sum(increase(claude_code_cost_total[1h])) > 10
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Claude Code hourly cost spike detected"
          description: "Hourly cost: {{ $value | printf \"%.2f\" }} USD. Possible infinite loop."

  - name: claude_code_performance_alerts
    interval: 2m
    rules:
      # 缓存命中率过低
      - alert: ClaudeCodeLowCacheHitRate
        expr: >
          (sum(rate(claude_code_tokens_cache_read_total[10m]))
          /
          (sum(rate(claude_code_tokens_cache_read_total[10m])) + sum(rate(claude_code_tokens_input_total[10m])))) < 0.2
        for: 15m
        labels:
          severity: info
        annotations:
          summary: "Claude Code cache hit rate below 20%"
          description: "Cache hit rate: {{ $value | printf \"%.2f\" }}. Consider optimizing CLAUDE.md."

      # 错误率过高
      - alert: ClaudeCodeHighErrorRate
        expr: >
          sum(rate(claude_code_errors_total[5m]))
          /
          (sum(rate(claude_code_errors_total[5m])) + sum(rate(claude_code_tool_calls_total[5m]))) > 0.1
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Claude Code error rate above 10%"
          description: "Error rate: {{ $value | printf \"%.2f\" }}"
```

### 5.2 Grafana告警通知渠道

在Grafana中配置通知渠道：

```bash
# 通过API添加Slack通知渠道
curl -X POST http://admin:claude2026@localhost:3000/api/alert-notifications \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Claude Code Alerts",
    "type": "slack",
    "settings": {
      "url": "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK",
      "channel": "#ai-cost-alerts"
    }
  }'
```

## 实战案例：团队级Claude Code监控平台

假设你是一个10人开发团队的技术负责人，需要监控全团队的Claude Code使用情况。以下是完整方案：

### 场景设定

- 10名开发者，每人每天使用Claude Code 4-8小时
- 月API预算：$2,000
- 需要追踪：个人用量、项目用量、成本分摊、效率指标

### 架构设计

```mermaid
flowchart TB
    subgraph Developers["10名开发者"]
        D1["Dev 1<br/>MacBook"]
        D2["Dev 2<br/>Linux"]
        D3["Dev 3<br/>Windows WSL"]
        DN["Dev N<br/>..."]
    end

    subgraph CentralCollector["中央OTEL Collector<br/>K8s/Docker"]
        GATEWAY["OTEL Gateway<br/>:4317"]
        ROUTER["标签路由<br/>按user.name分流"]
    end

    subgraph Storage["存储层"]
        PROM["VictoriaMetrics<br/>（兼容Prometheus）"]
        LOKI["Loki"]
    end

    subgraph Dashboards["Grafana Dashboards"]
        TEAM["团队总览"]
        PERSONAL["个人Dashboard"]
        PROJECT["项目Dashboard"]
        COST["成本分析"]
    end

    D1 -->|"OTEL<br/>user.name=alice"| GATEWAY
    D2 -->|"OTEL<br/>user.name=bob"| GATEWAY
    D3 -->|"OTEL<br/>user.name=carol"| GATEWAY
    DN -->|"OTEL<br/>user.name=..."| GATEWAY
    GATEWAY --> ROUTER
    ROUTER --> PROM
    ROUTER --> LOKI
    PROM --> TEAM
    PROM --> PERSONAL
    PROM --> PROJECT
    PROM --> COST
    LOKI --> TEAM
```

### 团队Dashboard核心PromQL

```promql
# 每人每日成本排行
topk(10, sum by (user_name) (increase(claude_code_cost_total[24h])))

# 每人Token用量分布
sum by (user_name) (increase(claude_code_tokens_input_total[24h]))

# 团队缓存效率排行
(sum by (user_name) (rate(claude_code_tokens_cache_read_total[1h])))
/
(sum by (user_name) (rate(claude_code_tokens_cache_read_total[1h])) + sum by (user_name) (rate(claude_code_tokens_input_total[1h])))

# 预算消耗速率（按当前趋势预测月末总成本）
sum(rate(claude_code_cost_total[7d])) * 30 * 24 * 3600
```

### 每位开发者的OTEL配置模板

```bash
# 每人在 ~/.bashrc 中添加（team-admin统一分发）
export OTEL_EXPORTER_OTLP_ENDPOINT="http://monitoring.internal:4317"
export OTEL_SERVICE_NAME="claude-code"
export OTEL_RESOURCE_ATTRIBUTES="service.name=claude-code,host.name=$(hostname),user.name=${USER},team=backend"
```

关键点：通过`user.name`和`team`标签实现多维度的用量分析。

## Step 6：进阶优化——基于数据的Claude Code调优

有了可观测性数据，就可以进行数据驱动的优化。以下是几个典型场景：

### 6.1 诊断缓存命中率低的问题

当Dashboard显示缓存命中率 < 30%时：

```bash
# 1. 检查CLAUDE.md文件大小
wc -c CLAUDE.md
# 如果 > 10KB，考虑拆分

# 2. 检查每次会话的系统提示长度
# 在Grafana中查询：
# sum(rate(claude_code_tokens_input_total[5m])) vs sum(rate(claude_code_tokens_cache_creation_total[5m]))
# 如果 input 远大于 cache_creation，说明上下文没有被有效缓存

# 3. 优化策略：将不变的指令放在CLAUDE.md头部
# Claude Code的缓存策略是前缀匹配，头部内容更容易被缓存
```

### 6.2 识别低效会话模式

```promql
# 找出Edit/Write调用占比最高的会话（可能是不充分理解就动手改）
sum by (session_id) (rate(claude_code_tool_calls_total{tool_name=~"Edit|Write"}[1h]))
/
sum by (session_id) (rate(claude_code_tool_calls_total{tool_name=~"Read|Glob|Grep"}[1h]))
```

当这个比值 > 1时，说明Claude Code的"改/读比"过高，可能需要在CLAUDE.md中添加类似这样的指令：

```markdown
# Coding Guidelines
- Always read at least 3 related files before making changes
- Use Glob to understand project structure first
- Use Grep to find all occurrences before modifying
```

### 6.3 模型成本效率对比

```promql
# 各模型的单位产出成本（$/有效Edit）
sum by (model) (increase(claude_code_cost_total[24h]))
/
sum by (model) (increase(claude_code_tool_calls_total{tool_name="Edit"}[24h]))
```

如果Haiku的$/Edit显著低于Opus，且Edit质量相当（通过CI通过率衡量），则应将更多任务路由到Haiku。

## 备选方案：轻量级单机监控

如果你觉得全套Docker栈太重，社区还有更轻量的方案：

### 方案A：VictoriaMetrics单进程

```bash
# 下载并启动VictoriaMetrics（单一二进制）
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.96.0/victoria-metrics-linux-amd64-v1.96.0.tar.gz
tar -xzf victoria-metrics-linux-amd64-v1.96.0.tar.gz
./victoria-metrics-prod -storageDataPath=./vm-data -retentionPeriod=30d

# 修改OTEL Collector的exporter直接指向VictoriaMetrics
# exporters.prometheus.endpoint -> 直接用Prometheus remote write
```

### 方案B：纯JSON日志 + 简单脚本

```bash
# 最简单的方案：将Claude Code事件输出到JSON文件
export OTEL_EXPORTER_OTLP_ENDPOINT=""
export OTEL_TRACES_EXPORTER=none
# 然后用Claude Code hooks记录事件

# 在 .claude/settings.json 中配置hooks
cat > .claude/settings.json << 'EOF'
{
  "hooks": {
    "PostToolUse": [{
      "matcher": "",
      "command": "echo '{\"tool\":\"$TOOL_NAME\",\"time\":\"$(date -Is)\",\"tokens\":\"$TOKENS\"}' >> ~/claude-usage.jsonl"
    }]
  }
}
EOF
```

### 方案选择决策矩阵

```mermaid
flowchart TD
    START["需要Claude Code监控"] --> Q1{"团队规模？"}
    Q1 -->|"1-3人"| Q2{"有Docker吗？"}
    Q1 -->|"4+人"| FULL["方案一：完整栈<br/>OTEL + Prometheus + Grafana"]
    Q2 -->|"有"| LIGHT["方案A：轻量栈<br/>VictoriaMetrics + Grafana"]
    Q2 -->|"没有"| MINIMAL["方案B：纯日志<br/>JSON Lines + 脚本"]

    FULL --> PROS1["优势：全功能<br/>告警、多维度分析、团队视图"]
    LIGHT --> PROS2["优势：低资源占用<br/>单进程、30天数据"]
    MINIMAL --> PROS3["优势：零依赖<br/>一行命令启动"]
```

## 关键注意事项

1. **数据安全**：OTEL传输的遥测数据可能包含文件路径、工具调用参数等信息。生产环境务必使用TLS加密传输，并确保监控栈在内网运行。

2. **采样策略**：对于高频使用场景（每分钟数十次工具调用），建议设置采样率避免存储膨胀：
   ```yaml
   # OTEL Collector配置
   processors:
     probabilistic_sampler:
       sampling_percentage: 50  # 50%采样
   ```

3. **数据保留期**：Prometheus默认保留15天数据。对于月度成本分析，需要修改为30天以上：
   ```bash
   # 在docker-compose.yml的prometheus中添加启动参数
   command: 
     - '--config.file=/etc/prometheus/prometheus.yml'
     - '--storage.tsdb.retention.time=90d'
   ```

4. **多实例隔离**：多个开发者共享Collector时，务必通过`user.name`标签区分，避免数据混淆。

5. **性能开销**：OTEL采集的开销极小（< 1% CPU，< 50MB 内存），不会影响Claude Code本身的使用体验。

## 延伸阅读

- Anthropic官方文档：Claude Code OpenTelemetry配置指南
- OpenTelemetry Collector官方配置参考
- Grafana Labs提供的AI Agent监控最佳实践

## 参考来源

1. [Claude Code Monitoring & Observability: Token Tracking, Error Tracing, and Cost Alerts (2026)](https://thepromptshelf.dev/blog/claude-code-monitoring-observability-2026/) — 完整的Claude Code可观测性概念与方案
2. [How I Set Up Observability for Claude Code with the Grafana Stack](https://prokopov.me/posts/claude-code-observability-grafana-stack/) — Grafana Stack实战搭建指南
3. [rommelporras/claude-code-monitoring](https://github.com/rommelporras/claude-code-monitoring) — 开箱即用的Docker Compose监控方案
4. [Monitoring Claude Code with OpenTelemetry and Grafana](https://claude-blog.setec.rs/blog/claude-code-grafana-monitoring) — OpenTelemetry详细配置教程
5. [Claude Code Metrics Dashboard: Grafana Setup (2026)](https://sealos.io/blog/claude-code-metrics/) — Sealos平台上的Dashboard搭建指南

## 训练营适用性评估

| 训练营类型 | 适用性 | 预计教学时长 | 备注 |
|-----------|--------|-------------|------|
| Claude Code高级用户训练营 | ★★★★★ | 3-4小时 | 核心课程，完整实操 |
| AI工程化训练营 | ★★★★☆ | 2-3小时 | 侧重架构设计与数据流 |
| DevOps/SRE训练营 | ★★★★☆ | 2小时 | OTEL和Grafana部分可快速带过 |
| Claude Code入门训练营 | ★★☆☆☆ | 不建议 | 需要先掌握Claude Code基础用法 |
| 企业AI工具治理训练营 | ★★★★★ | 4-5小时 | 结合成本管控和团队管理深入讲解 |

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
