mcpField
O
oodle-dashboards

oodle-dashboards

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

关于 oodle-dashboards

oodle-dashboards 是指导 Agent 通过 Oodle CLI 管理仪表板与文件夹的 skill,适用于需要维护仪表板结构的团队。它强调先读取完整定义、保留面板配置,并将仪表板放入明确的文件夹。

主要功能

  1. 01列出、读取、创建和删除仪表板
  2. 02创建文件夹并将仪表板归类
  3. 03更新前读取完整定义以保留面板
  4. 04安全删除共享仪表板的分阶段流程
  5. 05提供 PromQL 窗口与统计面板建议

适用场景

  1. 01按文件夹查找并整理团队仪表板
  2. 02修改仪表板标题而不丢失面板
  3. 03创建仪表板并放入指定文件夹
  4. 04优化查询窗口以减少不必要的数据读取

安装

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

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

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

详细介绍

Oodle 仪表板 — CRUD 和组织管理

本技能将教会 Agent 如何管理 Oodle 仪表板和文件夹,避免丢失面板状态,也避免仪表板孤立在根文件夹中。

前提条件

brew install oodle-ai/oodle/oodle
oodle configure
# or
export OODLE_API_KEY=<key>
export OODLE_INSTANCE=<instance>
export OODLE_DEPLOYMENT=<url>

验证仪表板端点是否正常:

oodle dashboards list -o json | jq 'length'
oodle folders list -o json | jq 'length'

命令执行顺序

运行任何 oodle 命令前:

  1. 检查所需的资源 ID 或名称是否已在上下文中。
  2. 如果没有,运行发现命令(例如,oodle dashboards list -o json)。
  3. 如果结果不明确,请先让用户确认,再继续操作。
  4. 使用已解析的 ID 运行目标命令。
  5. 不要运行试探性命令(例如,未先 get 资源就不要 delete)。

快速参考

任务命令
列出仪表板oodle dashboards list -o json
获取仪表板oodle dashboards get <uid> -o json
创建仪表板oodle dashboards create -f save.json
更新仪表板使用 "overwrite": true 运行 oodle dashboards create -f save.json(没有 dashboards update)
删除仪表板oodle dashboards delete <uid> --force
列出文件夹oodle folders list -o json
创建文件夹oodle folders create --title "Platform" -o json
删除文件夹没有 CLI 命令;请使用 Oodle UI

常见操作

列出仪表板
# ✅ CORRECT
oodle dashboards list -o json

# ✅ CORRECT — filter by folder (the list also has folders, with `type` "dash-folder")
oodle dashboards list -o json | jq '.[] | select(.type=="dash-db" and .folderUid=="platform")'

# ❌ WRONG — parsing table output to find an ID
oodle dashboards list | grep "API Overview" | awk '{print $1}'
更改仪表板前先读取
# ✅ CORRECT — fetch the full definition first; preserves all panels and queries
oodle dashboards get dash_123 -o json > current.json
jq '{dashboard: .dashboard, folderUid: .meta.folderUid, overwrite: true}' current.json > save.json
$EDITOR save.json
oodle dashboards create -f save.json

# ❌ WRONG — sending an incomplete payload removes panels
oodle dashboards create -f <(echo '{"dashboard":{"uid":"dash_123","title":"new title"},"overwrite":true}')
创建仪表板

oodle dashboards create -f 接受一个保存请求:dashboard 中是 Grafana 仪表板 JSON,另有 folderUid 和 overwrite。面板会在 targets[].expr 中保留其 PromQL。完整的保存请求会将仪表板放入指定文件夹:

{
  "dashboard": {
    "title": "API Overview",
    "description": "Latency, error rate, and throughput for the API service.",
    "tags": ["service:api", "team:platform"],
    "panels": [
      {
        "title": "Request rate",
        "type": "timeseries",
        "targets": [{"refId": "A", "expr": "sum(rate(http_requests_total{service=\"api\"}[$__rate_interval]))"}]
      },
      {
        "title": "Error rate",
        "type": "timeseries",
        "targets": [{"refId": "A", "expr": "sum(rate(http_requests_total{service=\"api\",status=~\"5..\"}[$__rate_interval]))"}]
      },
      {
        "title": "P99 latency",
        "type": "timeseries",
        "targets": [{"refId": "A", "expr": "histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket{service=\"api\"}[$__rate_interval])))"}]
      }
    ]
  },
  "folderUid": "platform",
  "overwrite": false
}
# ✅ CORRECT
oodle dashboards create -f save.json

# ❌ WRONG — no folderUid, dashboard ends up in root and is hard to find
oodle dashboards create -f <(echo '{"dashboard":{"title":"API Overview","panels":[...]}}')
文件夹管理
# ✅ CORRECT — create folder first, capture id, then create dashboards in it
FOLDER_UID=$(oodle folders create --title "Platform" -o json | jq -r '.uid')
jq --arg f "$FOLDER_UID" '.folderUid=$f' save.json > save.with-folder.json
oodle dashboards create -f save.with-folder.json

# ❌ WRONG — creating dashboards before folders, then trying to move them later
oodle dashboards create -f save.json
oodle folders create --title "Platform"
安全删除 — 分两阶段

运行手册、Slack 消息和书签中都可能包含仪表板链接。请分两阶段删除。

# ✅ CORRECT — phase 1: rename so users see it's about to be removed
oodle dashboards get dash_123 -o json > dash.json
jq '{dashboard: (.dashboard | .title = "[MARKED FOR DELETION] " + .title), folderUid: .meta.folderUid, overwrite: true}' dash.json > dash.deletion.json
oodle dashboards create -f dash.deletion.json
# wait at least 7 days, then:
oodle dashboards delete dash_123 --force

# ❌ WRONG — immediate hard delete, breaks every existing link
oodle dashboards delete dash_123 --force

最佳实践

切勿将 $__range 用作面板回看窗口

$__range 会扩展为整个仪表板时间范围,因此窗口在每个步长都保持同样的宽度,并且每个步长重新读取的数据几乎与前一个步长相同。一个 6h 的仪表板若使用 [$__range] 窗口,读取的样本量约为同一面板使用 [$__dd_interval] 时的 180 倍;用户缩小视图时,这个倍数还会增加——而这正是仪表板超时发生的时刻。Oodle 会用警告三角形标记此类面板。

请改用随时间范围变化的窗口:

变量含义用途
$__rate_intervalGrafana 内置的速率窗口,等于 max(step + scrape interval, 4 x scrape interval),确保速率计算始终有足够的样本。在图表上使用 rate() 和 increase()
$__dd_intervalOodle 根据时间范围选择的汇总窗口,与 Datadog 默认值一致。上限为 4h。默认汇总,以及统计面板总计
$__large_interval同一时间范围下比 $__dd_interval 更粗略的汇总窗口。上限为 12h。柱状图和较长的回看窗口

两个 Oodle 汇总窗口的解析结果如下:

仪表板范围$__dd_interval$__large_interval
1 小时20s1m
6 小时2m5m
24 小时5m20m
7 天1h4h
30 天4h12h

这三个窗口都会随仪表板时间范围增减,因此无论用户将视图缩小到多大范围,每个步长读取的样本数都大致相同。

# ✅ CORRECT — the window shrinks and grows with the dashboard range
"expr": "sum(rate(http_requests_total[$__rate_interval]))"

# ✅ CORRECT — coarser rollup for a bar chart
"expr": "topk(10, sum by (route) (rate(http_request_duration_seconds_sum[$__large_interval])))"

# ❌ WRONG — one flat line at the range average, read 180 times over
"expr": "sum(rate(http_requests_total[$__range]))"

# ❌ WRONG — `$__range_s` is there to undo an `increase`; use `rate` instead
"expr": "sum(increase(http_requests_total[$__range])) / $__range_s"
对窗口求和作为统计面板结果,而不是对 $__range 求和

显示整个时间范围内一个数值的统计面板确实需要每个样本,但不需要一次性读取。将时间范围拆分为多个窗口,再把各个窗口的结果加起来。

# ✅ CORRECT — window == min step, range query, reduced back to one number
"expr": "sum(increase(http_requests_total[$__dd_interval]))"
"interval": "$__dd_interval"
"instant": false
"transformations": [{"id": "reduce", "options": {"reducers": ["sum"]}}]

# ❌ WRONG — instant query that reads the whole range on every refresh
"expr": "sum(increase(http_requests_total[$__range]))"
"instant": true

将最小步长设为与窗口相同,这样各个窗口才能恰好覆盖整个时间范围:步长更小会重复计算样本,步长更大则会漏掉样本。根据函数选择对应的归约器——increase 使用 sum,sum_over_time 和 count_over_time 使用 sum,max_over_time 使用 max,min_over_time 使用 min,avg_over_time 使用 mean。不要用这种方式拆分 quantile_over_time、changes 或 resets;归约后的值并不等于整个时间范围内的值。

始终先执行 get 再执行 update,以保留面板配置

使用 "overwrite": true 保存会替换整个文档。载荷中缺少的面板会被删除。

# ✅ CORRECT
oodle dashboards get dash_123 -o json > dash.json
jq '{dashboard: (.dashboard | .panels[0].title = "Request rate (per second)"), folderUid: .meta.folderUid, overwrite: true}' dash.json > dash.new.json
oodle dashboards create -f dash.new.json

# ❌ WRONG — sends a single-field payload; all panels disappear
oodle dashboards create -f <(echo '{"dashboard":{"uid":"dash_123","description":"updated"},"overwrite":true}')
创建仪表板时始终设置 folderUid

根文件夹中的仪表板很难被团队发现。

# ✅ CORRECT
"folderUid": "platform"

# ❌ WRONG — omitting folderUid means root
"folderUid": null
对共享仪表板使用“两阶段重命名 → 等待 → 删除”模式

直接硬删除仪表板会破坏所有外部链接(操作手册、Slack 表情反应、书签)。

# ✅ CORRECT — phase 1: rename
oodle dashboards create -f dash.deletion.json
# wait, confirm no traffic, then phase 2: delete
oodle dashboards delete dash_123 --force

# ❌ WRONG — same-day delete on a shared dashboard
oodle dashboards delete dash_123 --force
使用 service 和 team 标签为仪表板添加标签

标签可让仪表板更容易搜索,也方便其他工具(例如服务目录)链接到它们。

# ✅ CORRECT
"tags": ["service:api", "team:platform", "env:prod"]

# ❌ WRONG
"tags": []

故障处理

错误原因修复方法
401 UnauthorizedAPI 密钥无效或缺失运行 oodle configure 或设置 OODLE_API_KEY
404 Not Found仪表板或文件夹 ID 不存在使用 oodle dashboards list -o json 验证
connection refusedOODLE_DEPLOYMENT URL 错误检查 OODLE_DEPLOYMENT 环境变量
folder not foundfolderUid 指向已删除的文件夹使用 oodle folders list -o json 列出文件夹;选择现有 ID 或创建一个
更新后面板消失保存时 "overwrite": true 使用了不完整的载荷根据最近一次 get 快照重新创建;今后始终遵循 get → 编辑 → 保存
无法删除文件夹文件夹中仍有仪表板,且 CLI 没有 folders delete先移动或删除仪表板(`oodle dashboards list -o json
429 Too Many Requests批量同步仪表板添加 --retries 3,将创建频率限制在每秒少于 10 个

参考资料

评论

支持 Markdown