OpenRouter 安全与可观测

OpenRouter 安全与可观测

ClickHouse

4 分钟阅读

ClickHouse

将追踪发送到 ClickHouse

ClickHouse 是面向实时分析的高性能开源列式数据库。OpenRouter 可以将追踪直接流式写入你的 ClickHouse 数据库,用于高性能分析和自定义仪表盘。

第 1 步:创建追踪表

在连接 OpenRouter 之前,先在 ClickHouse 数据库中创建 OPENROUTER_TRACES 表。配置该目标端时,可在 OpenRouter 控制台中找到确切的 SQL:

ClickHouse 设置说明

第 2 步:设置权限

确保你的 ClickHouse 用户具有 CREATE TABLE 权限:

GRANT CREATE TABLE ON your_database.* TO your_database_user;

第 3 步:在 OpenRouter 中启用广播

前往 设置 > 可观测性(Settings > Observability),打开 启用广播(Enable Broadcast) 开关。

启用广播

第 4 步:配置 ClickHouse

点击 ClickHouse 旁的编辑图标,并填写:

ClickHouse 配置
  • Host:你的 ClickHouse HTTP 端点(例如 https://clickhouse.example.com:8123
  • Database:目标数据库名称(默认:default
  • Table:表名(默认:OPENROUTER_TRACES
  • Username:用于身份验证的 ClickHouse 用户名(默认为 default
  • Password:用于身份验证的 ClickHouse 密码

对于 ClickHouse Cloud,主机 URL 通常为 https://{instance}.{region}.clickhouse.cloud:8443。可在 ClickHouse Cloud 控制台的 Connect 找到该地址。

第 5 步:测试并保存

点击 测试连接(Test Connection) 验证配置。仅当测试通过时才会保存配置。

第 6 步:发送测试追踪

通过 OpenRouter 发出一次 API 请求,然后查询 ClickHouse 表以确认已收到该追踪。

查询示例

按模型分析费用

SELECT
  toDate(TIMESTAMP) as day,
  MODEL,
  sum(TOTAL_COST) as total_cost,
  sum(TOTAL_TOKENS) as total_tokens,
  count() as request_count
FROM OPENROUTER_TRACES
WHERE TIMESTAMP >= now() - INTERVAL 30 DAY
  AND STATUS = 'ok'
  AND SPAN_TYPE = 'GENERATION'
GROUP BY day, MODEL
ORDER BY day DESC, total_cost DESC;

用户活动分析

SELECT
  USER_ID,
  uniqExact(TRACE_ID) as trace_count,
  uniqExact(SESSION_ID) as session_count,
  sum(TOTAL_TOKENS) as total_tokens,
  sum(TOTAL_COST) as total_cost,
  avg(DURATION_MS) as avg_duration_ms
FROM OPENROUTER_TRACES
WHERE TIMESTAMP >= now() - INTERVAL 7 DAY
  AND SPAN_TYPE = 'GENERATION'
GROUP BY USER_ID
ORDER BY total_cost DESC;

错误分析

SELECT
  TRACE_ID,
  TIMESTAMP,
  MODEL,
  LEVEL,
  FINISH_REASON,
  METADATA,
  INPUT,
  OUTPUT
FROM OPENROUTER_TRACES
WHERE STATUS = 'error'
  AND TIMESTAMP >= now() - INTERVAL 1 HOUR
ORDER BY TIMESTAMP DESC;

模型服务提供商性能对比

SELECT
  PROVIDER_NAME,
  MODEL,
  avg(DURATION_MS) as avg_duration_ms,
  quantile(0.5)(DURATION_MS) as p50_duration_ms,
  quantile(0.95)(DURATION_MS) as p95_duration_ms,
  count() as request_count
FROM OPENROUTER_TRACES
WHERE TIMESTAMP >= now() - INTERVAL 7 DAY
  AND STATUS = 'ok'
  AND SPAN_TYPE = 'GENERATION'
GROUP BY PROVIDER_NAME, MODEL
HAVING request_count >= 10
ORDER BY avg_duration_ms;

按 API 密钥统计用量

SELECT
  API_KEY_NAME,
  uniqExact(TRACE_ID) as trace_count,
  sum(TOTAL_COST) as total_cost,
  sum(PROMPT_TOKENS) as prompt_tokens,
  sum(COMPLETION_TOKENS) as completion_tokens
FROM OPENROUTER_TRACES
WHERE TIMESTAMP >= now() - INTERVAL 30 DAY
  AND SPAN_TYPE = 'GENERATION'
GROUP BY API_KEY_NAME
ORDER BY total_cost DESC;

访问 JSON 列

ClickHouse 将 JSON 数据存储为字符串。使用 JSONExtract 函数查询 嵌套字段:

SELECT
  TRACE_ID,
  JSONExtractString(METADATA, 'custom_field') as custom_value,
  JSONExtractString(ATTRIBUTES, 'gen_ai.request.model') as requested_model
FROM OPENROUTER_TRACES
WHERE JSONHas(METADATA, 'custom_field');

要解析输入消息:

SELECT
  TRACE_ID,
  JSONExtractString(
    JSONExtractRaw(INPUT, 'messages'),
    1, 'role'
  ) as first_message_role,
  JSONExtractString(
    JSONExtractRaw(INPUT, 'messages'),
    1, 'content'
  ) as first_message_content
FROM OPENROUTER_TRACES
WHERE SPAN_TYPE = 'GENERATION'
LIMIT 10;

表结构设计

类型化列

该表结构将常用查询字段提取为类型化列,以便高效筛选和聚合:

  • 标识符:TRACE_ID、USER_ID、SESSION_ID 等
  • 时间戳:用于毫秒精度时间序列分析的 DateTime64
  • 模型信息:用于费用和性能分析
  • 指标:用于计费的 Token 与费用

用于 JSON 的字符串列

访问频率较低、结构可变的数据以 JSON 字符串存储:

  • ATTRIBUTES:完整的 OTEL 属性集
  • INPUT/OUTPUT:可变的消息结构
  • METADATA:用户定义的键值
  • MODEL_PARAMETERS:模型特定配置

使用 ClickHouse 的 JSONExtract* 函数查询这些字段。

自定义元数据

trace 字段中的自定义元数据以 JSON 字符串形式存储在 METADATA 列中。你可以使用 ClickHouse 的 JSONExtract 函数进行查询。

支持的元数据键

ClickHouse 映射说明
trace_idTRACE_ID column / METADATA JSON用于归组的自定义追踪标识符
trace_nameMETADATA JSON追踪的自定义名称
span_nameMETADATA JSON中间 Span 的名称
generation_nameMETADATA JSONLLM 生成的名称

示例

{
  "model": "openai/gpt-4o",
  "messages": [{ "role": "user", "content": "Analyze these metrics..." }],
  "user": "user_12345",
  "session_id": "session_abc",
  "trace": {
    "trace_name": "Metrics Analysis Pipeline",
    "generation_name": "Analyze Trends",
    "team": "data-engineering",
    "pipeline_version": "2.0",
    "data_source": "clickhouse_metrics"
  }
}

查询自定义元数据

使用 ClickHouse 的 JSON 函数查询自定义元数据:

SELECT
  TRACE_ID,
  JSONExtractString(METADATA, 'team') as team,
  JSONExtractString(METADATA, 'pipeline_version') as pipeline_version,
  JSONExtractString(METADATA, 'data_source') as data_source,
  TOTAL_COST,
  TOTAL_TOKENS
FROM OPENROUTER_TRACES
WHERE JSONHas(METADATA, 'team')
  AND SPAN_TYPE = 'GENERATION'
ORDER BY TIMESTAMP DESC;

补充说明

  • user 字段会映射到类型化列 USER_ID
  • session_id 字段会映射到类型化列 SESSION_ID
  • trace 中的所有自定义元数据键都存储在 METADATA JSON 字符串列中
  • 若需对元数据字段进行高性能筛选,可考虑使用 ALTER TABLE ... ADD COLUMN 创建物化列

更多资源

隐私模式

当该目标端启用 隐私模式 时,追踪中会排除提示词和补全内容。其余追踪数据——Token 用量、费用、时间信息、模型信息以及自定义元数据——仍会正常发送。详情见 隐私模式