mcpField
O
oodle-log-metrics

oodle-log-metrics

github.com/oodle-ai云与 DevOps0125 次安装3 周前更新
代码仓库

关于 oodle-log-metrics

oodle-log-metrics 是一项指导 Agent 将日志行转换为指标的技能,重点包括创建前验证过滤条件、控制标签基数,以及更新时保留现有规则。

主要功能

  1. 01创建规则前验证日志过滤条件
  2. 02估算标签基数
  3. 03定义计数器、仪表和直方图指标
  4. 04用正则提取标签和值
  5. 05更新前读取现有规则

适用场景

  1. 01将匹配的日志行计为指标
  2. 02根据日志事件创建告警
  3. 03测量纯文本日志中的工具延迟

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/oodle-ai/agent-skills --skill oodle-log-metrics

安装后在 Claude Code 中输入/oodle-log-metrics确认已加载。

详细介绍

Oodle 日志指标 — 规则与基数

本技能介绍如何安全地将日志流转换为指标:验证筛选条件、缩小 labels 范围,并避免创建高基数时间序列。日志指标规则也可用于统计日志行中的值或针对这些值触发告警:监控器会针对规则生成的指标触发告警。

前置条件

brew install oodle-ai/oodle/oodle
oodle configure

确认日志指标端点可用:

oodle log-metrics list -o json | jq 'length'

命令执行顺序

运行任何 oodle 命令之前:

  1. 检查规则的筛选条件和 labels 是否已在上下文中。
  2. 如果没有,运行示例日志查询(例如 oodle logs query,请参阅 oodle-logs 技能,或使用日志浏览器),验证筛选条件确实能匹配日志。
  3. 估算基数:将每个标签的不同值数量相乘。
  4. 仅在验证筛选条件后运行 oodle log-metrics create -f rule.json。
  5. 运行 update 前,务必先运行 get,以获取现有规则。

快速参考

任务命令
列出规则oodle log-metrics list -o json
获取规则oodle log-metrics get <id> -o json
创建规则oodle log-metrics create -f rule.json
更新规则oodle log-metrics update <id> -f rule.json
删除规则oodle log-metrics delete <id> --force

常见操作

规则架构
{
  "name": "http_errors_from_logs",
  "filter": {
    "all": [
      {"field": "level", "operator": "is", "value": "error"},
      {"field": "service", "operator": "is", "value": "api"}
    ]
  },
  "labels": [
    {"name": "service", "valueExtractor": {"field": "service"}},
    {"name": "env", "valueExtractor": {"field": "env"}}
  ],
  "metricDefinitions": [
    {"name": "http_errors", "type": "log_count"}
  ]
}

字段含义:

字段含义
name规则的人类可读标识符。必填。
filter规则读取哪些日志行。可以是条件 {"field", "operator", "value", "jsonPath"},也可以是 {"all": [...]}(AND)、{"any": [...]}(OR)或 {"not": <filter>}。可以嵌套。运算符:is、contains、matches regex、exists。没有 !=;请使用 not。
labels添加到生成指标中的标签。每个标签包含一个 name 和静态 value,或一个 valueExtractor {"field", "jsonPath", "regex"}。
metricDefinitions要生成的指标。至少需要一个。每个指标包含一个 name 和一个 type:log_count(匹配行数)、counter(数值总和)、gauge(最后一个值)或 histogram(数值分布)。counter、gauge 和 histogram 从 field 读取数值,可选使用 jsonPath 或 regex。
  • field 是顶层日志字段:只能包含字母、数字和下划线。使用 jsonPath 读取嵌套的 JSON 值,例如 {"field": "log", "jsonPath": "user.id"}。
  • regex 使用 Rust 语法。捕获组 1 是要提取的值,因此请在所需部分外加一个分组。在 JSON 中,每个反斜杠都要转义:\d 应写为 "\\d"。
  • 如果正则表达式与某行不匹配,标签值为空,数值为 0。因此,筛选条件应仅选取包含该值的行。
  • 生成的指标名称为 oodle_logs_<name>(oodle_logs_http_errors)。histogram 会生成 _bucket、_sum 和 _count 系列。使用 increase(...) 或 rate(...) 查询 log_count 和 counter,并使用 sum by (...) 聚合。
  • 规则仅适用于创建后到达的日志。对于过去的数据,请使用 oodle logs query。
  • 如示例所示,在 all 列表中放入单个条件。这种写法适用于所有 CLI 和服务版本。
创建规则
# ✅ CORRECT — validate filter first, then create
# (preview with the log explorer or `oodle logs query`)
oodle log-metrics create -f rule.json

# ❌ WRONG — creating with an untested filter; the resulting metric is silently empty
oodle log-metrics create -f <(echo '{"name":"x","filter":{"all":[{"field":"levl","operator":"is","value":"eror"}]},"metricDefinitions":[{"name":"x","type":"log_count"}]}')
更新规则
# ✅ CORRECT — get → edit → update
oodle log-metrics get lm_123 -o json > rule.json
jq '.labels = [{"name":"service","valueExtractor":{"field":"service"}},{"name":"env","valueExtractor":{"field":"env"}}]' rule.json > rule.new.json
oodle log-metrics update lm_123 -f rule.new.json

# ❌ WRONG — partial payload removes existing fields (and has no `id`, so it is rejected)
oodle log-metrics update lm_123 -f <(echo '{"labels":[{"name":"service","valueExtractor":{"field":"service"}}]}')
删除规则
# ✅ CORRECT — verify and delete
oodle log-metrics get lm_123 -o json > /dev/null
oodle log-metrics delete lm_123 --force

# ❌ WRONG — speculative delete by name match
oodle log-metrics delete "$(oodle log-metrics list | grep errors | awk '{print $1}')" --force
对日志行发出告警

监控器运行的是 PromQL,而不是日志查询。要针对日志行发出告警,请创建日志指标规则,然后创建一个监控器来监控该规则生成的指标(参见 oodle-monitors 技能)。规则使用正则表达式读取原始行文本,因此适用于纯文本行,无需进行日志转换。从行中提取的标签(user、tool、tenant)会用来标识告警中的时间序列。

示例:对于以下日志行,为每个信用额度耗尽的用户分别发出告警:

2026-10-07T10:12:03Z WARN credit exhausted for user=alice plan=pro

credit-exhausted.json:

{
  "name": "credit-exhausted",
  "filter": {"all": [{"field": "message", "operator": "contains", "value": "credit exhausted"}]},
  "labels": [
    {"name": "user", "valueExtractor": {"field": "message", "regex": "user=(\\S+)"}}
  ],
  "metricDefinitions": [{"name": "credit_exhausted", "type": "log_count"}]
}

credit-exhausted-monitor.json(op 2 表示 >):

{
  "name": "Credit exhausted",
  "promql_query": "sum by (user) (increase(oodle_logs_credit_exhausted[10m]))",
  "conditions": {"critical": {"op": 2, "value": 0}},
  "labels": {"team": "billing", "env": "prod"},
  "annotations": {"summary": "User {{ $labels.user }} ran out of credit"}
}
oodle log-metrics create -f credit-exhausted.json
oodle monitors create -f credit-exhausted-monitor.json
# Later: whose credit ran out in the last 24 hours
oodle metrics query --query 'sum by (user) (increase(oodle_logs_credit_exhausted[24h])) > 0' -o json

此处每个用户一个标签是可行的,因为此事件很少发生(参见“将 labels 保持在 2–3 个低基数标签”)。

示例:提取行中的值,例如 tool Bash ok in 12345 ms 中的持续时间。每个值使用一个正则表达式,每个表达式包含一个捕获组,并使用过滤条件确保该值存在:

{
  "name": "tool-latency",
  "filter": {"all": [{"field": "message", "operator": "matches regex", "value": "tool \\S+ (?:ok|failed) in \\d+ ms"}]},
  "labels": [
    {"name": "tool", "valueExtractor": {"field": "message", "regex": "tool (\\S+) "}},
    {"name": "status", "valueExtractor": {"field": "message", "regex": " (ok|failed) in "}}
  ],
  "metricDefinitions": [
    {"name": "tool_calls", "type": "log_count"},
    {"name": "tool_duration_ms", "type": "histogram", "field": "message", "regex": " in (\\d+) ms"}
  ]
}
# p95 tool latency in ms, per tool
histogram_quantile(0.95, sum by (le, tool) (rate(oodle_logs_tool_duration_ms_bucket[5m])))
# failed calls per tool
sum by (tool) (increase(oodle_logs_tool_calls{status="failed"}[10m]))

最佳实践

创建规则前,先根据实际日志量验证 filter

过滤条件中的拼写错误(levl=eror)会导致规则悄无声息地生成零个数据点。

# ✅ CORRECT — preview matching log volume in the log explorer first;
# only then run `oodle log-metrics create`
# (or run `oodle logs query` with the same condition and confirm count > 0)

# ❌ WRONG — create the rule, then notice the dashboard panel is empty next week
oodle log-metrics create -f rule.json
将 labels 保持在 2–3 个低基数标签

每个标签都会使时间序列数量倍增。避免使用 request_id、user_id、trace_id、path(包含 ID)。只有在信用拒绝这类罕见事件中,才适合使用 user 标签。

# ✅ CORRECT — bounded labels
"labels": [{"name": "service", "valueExtractor": {"field": "service"}}, {"name": "env", "valueExtractor": {"field": "env"}}]

# ❌ WRONG — `user_id` on every request blows up cardinality (one series per user)
"labels": [{"name": "service", "valueExtractor": {"field": "service"}}, {"name": "user_id", "valueExtractor": {"field": "user_id"}}]
更新前务必先 get,以保留字段

update 会替换整个文档。只发送一个字段会将其他所有字段置空。

# ✅ CORRECT
oodle log-metrics get lm_123 -o json > rule.json
jq '.filter.all += [{"field": "status", "operator": "matches regex", "value": "^5"}]' rule.json > rule.new.json
oodle log-metrics update lm_123 -f rule.new.json

# ❌ WRONG — clobbers labels and metricDefinitions
oodle log-metrics update lm_123 -f <(echo '{"filter":{"all":[{"field":"level","operator":"is","value":"error"}]}}')
使用稳定且描述性强的指标名称

生成的名称为 oodle_logs_<name>。采用 <domain>_<measurement> 格式,便于在仪表板和删除规则中查找该指标。仅使用字母、数字和下划线。

# ✅ CORRECT
"metricDefinitions": [{"name": "http_errors", "type": "log_count"}]

# ❌ WRONG — generic name collides with other rules
"metricDefinitions": [{"name": "errors", "type": "log_count"}]

故障处理

错误原因解决方法
401 UnauthorizedAPI 密钥无效或缺失运行 oodle configure,或设置 OODLE_API_KEY
404 Not Found日志指标规则 ID 不存在使用 oodle log-metrics list -o json 验证
connection refusedOODLE_DEPLOYMENT URL 错误检查 OODLE_DEPLOYMENT 环境变量
400 Match must have a valid Operator运算符不是 is、contains、matches regex 或 exists使用这四种运算符之一;如需表示“不等于”,请用 not 包裹条件
400 Field ... must contain only alphanumeric characters and underscoresfield 中包含带点的字段名使用顶层字段,并将路径放入 jsonPath
400 Regex ... is not a valid rust regex正则表达式语法错误,或缺少 JSON 转义在 JSON 中转义反斜杠(\\d);不支持环视
400 'logCount' metric definition has a Field, JSONPath, or Regexlog_count 包含 field、jsonPath 或 regex移除这些字段
400 Log Metrics ID in path and body don't match请求体中的 id 缺失,或与 <id> 不同运行 get 并编辑其输出
指标存在,但没有数据点过滤条件没有匹配任何日志,或规则创建后没有新日志行在日志浏览器或使用 oodle logs query 重新测试过滤条件;检查字段名称是否与日志架构一致。规则不会回填数据
标签为空 / 值全为 0正则表达式不匹配,或第 1 组不是数字在示例行上测试正则表达式;确保过滤条件要求该值存在
UI 中出现基数告警labels 包含高基数字段编辑规则以删除该标签;旧时间序列会在常规保留期结束后过期
429 Too Many Requests批量创建规则添加 --retries 3,并将创建速率限制在每秒 <10 次

参考资料

评论

支持 Markdown