跳转到内容
Telemetry
浏览文档
API 参考更新于 2026年7月27日由 Telemetry 编辑团队和产品团队审核阅读约需 20 分钟

让编程智能体使用这篇文档

打开 Claude Code、Codex、Cursor 或其他编码代理的集中提示包,然后将其适应此处介绍的工作流程。

本页内容
  1. 列出回应
  2. 创建身体
  3. 创建响应
  4. 编辑正文
  5. 编辑回复
  6. 删除正文
  7. 删除回复
  8. 常见错误
  9. 小部件字段
  10. 了解布局
  11. 查询小部件配置
  12. 示例:带有分类条形图 x 轴的查询小部件
  13. 标题小部件配置
  14. 自由文本小部件配置
  15. 资源管理器小部件配置
  16. 示例:创建一个空仪表板
  17. 示例:列出仪表板
  18. 示例:创建一个空仪表板
  19. 示例:重命名仪表板并更新其描述
  20. 示例:替换现有仪表板上的所有小部件
  21. 示例:删除仪表板
  22. 常见小部件示例
  23. 示例:创建一个包含两个常见 Explore 小部件的仪表板
  24. 示例:创建队列保留微笑曲线的查询小部件
  25. 回应

仪表板

仪表板 API 允许您使用已用于摄取和查询操作的相同 API 密钥以编程方式列出、创建、编辑和删除仪表板。

支持的操作:

  • 列表. GET https://api.telemetry.sh/dashboard
  • 创建. POST https://api.telemetry.sh/dashboard
  • 编辑. PATCH https://api.telemetry.sh/dashboard
  • 删除. DELETE https://api.telemetry.sh/dashboard

标题

名称 类型 描述
Content-Type 字符串 必须是 application/json
Authorization 字符串 您的 API 密钥,作为原始密钥或 Bearer <key>

范围规则:

  • GET /dashboard 接受 readwriteread-and-write
  • POST /dashboardPATCH /dashboardDELETE /dashboard 需要 writeread-and-write

列出回应

GET /dashboard 返回 API 密钥团队的每个仪表板,由 updated_at DESC 订购。

支持的查询参数:

领域 类型 必填 精确合约 默认
page 整数 正整数页码。小于 1 的值将被拒绝。 1
pageSize 整数 正整数页面大小。大于 100 的值将被限制为 100。 API 还接受旧别名 page_size 50

每个项目都包含仪表板元数据、urlwidget_count 以及 API 形状的完整小部件列表。

高层回应:

领域 类型 精确合约
status 字符串 总是 "success" 就成功。
pagination 对象 当前页面的分页元数据。参见下表。
dashboards 数组 API 密钥团队的仪表板对象数组。当团队没有仪表板时,数组为空。

pagination 包括:

领域 类型 精确合约 示例
page 整数 当前从 1 开始的页码。 2
pageSize 整数 默认和最大尺寸限制后的有效页面尺寸。 25
total 整数 分页之前团队的仪表板总数。 63
totalPages 整数 当前总页数为pageSize0,当 total0 时。 3
hasNextPage 布尔值 当当前页面之后存在另一个页面时,true true
hasPreviousPage 布尔值 true 当当前页面之前存在另一个页面时。 true

dashboards中的每一项包括:

领域 类型 精确合约 示例
id 字符串 仪表板 ID。 "550e8400-e29b-41d4-a716-446655440000"
team_id 字符串 拥有团队 ID。 "a7d4..."
name 字符串 仪表板名称。 "Operations Overview"
slug 字符串 仪表板蛞蝓。 "operations-overview"
description 字符串或 null 保存的仪表板描述。 "Core service health and latency"
created_by 字符串或 null UI 创建的仪表板的用户 ID。 null 用于 API 创建的仪表板。 null
created_by_api_key_id 字符串或 null API 创建的仪表板的团队 API 密钥 ID。 null 用于 UI 创建的仪表板。 "key_123"
created_at 字符串 仪表板表中的时间戳字符串。 "2026-03-27T00:09:03.797Z"
updated_at 字符串 仪表板表中的时间戳字符串。 "2026-03-27T00:09:03.797Z"
url 字符串 Telemetry UI 中的相对仪表板 URL。 "/team/acme/dashboard/operations-overview"
widget_count 整数 附加到仪表板的小部件数量。 2
widgets 数组 创建和编辑响应返回的形状相同的小部件数组。 []

创建身体

领域 类型 必填 精确合约 示例
name 字符串 是的 修剪后的仪表板名称。修剪后必须非空。 "HTTP Monitoring"
slug 字符串 可选的定制块。 Telemetry 通过修剪、小写、删除除 a-z0-9、空格和 - 之外的所有字符、将空白运行转换为 -、折叠重复的 - 以及修剪前导/尾随来对其进行规范化-。如果省略,则 Telemetry 源自 name。标准化结果仍必须至少包含一个字母数字字符。 "HTTP Monitoring!!!" 变为 "http-monitoring"
description 字符串或 null 可选描述。空字符串标准化为 null "Core service health and latency"
widgets 数组 要立即创建的可选小部件数组。如果省略,仪表板将创建为空。如果任何小部件无效,则整个请求将被拒绝,并显示 400 []

创建响应

POST /dashboard 返回 201 Created 以及保存的仪表板和规范化的小部件列表。

{
  "status": "success",
  "dashboard": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "team_id": "a7d4...",
    "name": "HTTP Monitoring",
    "slug": "http-monitoring",
    "description": "Core service health and latency",
    "created_by": null,
    "created_by_api_key_id": "key_123",
    "created_at": "2026-03-27T00:09:03.797Z",
    "updated_at": "2026-03-27T00:09:03.797Z",
    "url": "/team/acme/dashboard/http-monitoring"
  },
  "widgets": [
    {
      "id": "0b3cb3f5-1147-4f2f-bf64-5044147c3e9a",
      "title": "Errors Per Hour",
      "widget_type": "query",
      "config": {
        "querySql": "SELECT hour, errors FROM error_rollups",
        "chartType": "Line Chart",
        "xAxis": "hour",
        "yAxis": "errors",
        "groupBy": null,
        "queryId": null,
        "sourceUrl": null
      },
      "layout": {
        "x": 0,
        "y": 0,
        "w": 12,
        "h": 4
      },
      "sort_order": 1
    }
  ]
}

编辑正文

PATCH /dashboard 是部分更新端点。省略的字段保持不变。

您必须使用 dashboardIddashboardSlug 标识目标仪表板。

领域 类型 必填 精确合约 示例
dashboardId 字符串 dashboardIddashboardSlug 之一 要编辑的现有仪表板 ID。如果发送两个标识符,它们必须引用同一个仪表板。 "550e8400-e29b-41d4-a716-446655440000"
dashboardSlug 字符串 dashboardIddashboardSlug 之一 要编辑的现有仪表板 slug。这是当前的 slug,而不是新的 slug。 "http-monitoring"
name 字符串 新修剪的仪表板名称。提供时必须非空。更新 name 不会自动更改 slug。 "HTTP Monitoring v2"
slug 字符串 新的段头值。 Telemetry 使用与 create 相同的规则对其进行规范化。如果省略,现有的 slug 保持不变。 "http-monitoring-v2"
description 字符串或 null 新的仪表板描述。 null"" 清除描述。如果省略,则现有描述保持不变。 "Updated on-call dashboard"
widgets 数组 完整的替换小部件列表。如果省略,现有小部件将保持不变。如果提供,Telemetry 将删除当前小部件集并将其替换为该数组中的小部件。 [] 清除所有小部件。 []

注意事项:

  • PATCH 尚不支持附加或编辑单个小部件。
  • 当提供 widgets 时,会重新生成小部件 ID,因为 API 会替换完整的小部件集。

编辑回复

PATCH /dashboard 返回 200 OK ,其响应形状与创建相同:

  • dashboard 包含保存的仪表板元数据和 url
  • widgets 包含 API 形状的完整持久小部件列表
  • 如果 widgets 被替换,则返回的小部件 id 反映新插入的行

删除正文

DELETE /dashboard 删除单个仪表板及其所有小部件。

您必须使用 dashboardIddashboardSlug 标识目标仪表板。

领域 类型 必填 精确合约 示例
dashboardId 字符串 dashboardIddashboardSlug 之一 要删除的现有仪表板 ID。如果发送两个标识符,它们必须引用同一个仪表板。 "550e8400-e29b-41d4-a716-446655440000"
dashboardSlug 字符串 dashboardIddashboardSlug 之一 要删除的现有仪表板 slug。 "http-monitoring"

注意事项:

  • 删除是永久性的。
  • 删除仪表板也会删除当前附加到其的所有小部件。

删除回复

DELETE /dashboard 返回 200 OK

{
  "status": "success",
  "deleted_dashboard": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "HTTP Monitoring",
    "slug": "http-monitoring",
    "description": "Core service health and latency",
    "widget_count": 2,
    "url": "/team/acme/dashboard/http-monitoring"
  }
}

常见错误

  • 400 Bad Request 如果 JSON 主体无效或请求主体不是 JSON 对象
  • 400 Bad Request 如果 pagepageSize 不是 GET /dashboard 上的正整数
  • 400 Bad Request(如果 PATCHDELETE 缺少 dashboardIddashboardSlug
  • 400 Bad Request(如果 PATCH 省略所有可编辑字段)
  • 400 Bad Request(如果 nameslugdescriptionwidgets 验证失败)
  • 400 Bad Request 如果查询小部件包含非只读 SQL
  • 403 Forbidden 如果 API 密钥没有请求操作的权限
  • 401 Unauthorized(如果 API 密钥丢失或无效)
  • 404 Not Found(如果 API 密钥的团队不存在仪表板)
  • 409 Conflict 如果同一团队中的另一个仪表板已使用请求的 slug

小部件字段

widgets中的每个项目都支持:

领域 类型 必填 精确合约 示例
title 字符串 是的 修剪后的小部件标题。修剪后必须非空。 "Errors Per Hour"
widget_type 字符串 是的 精确枚举:queryexplorerheaderfree_text "query"
config 对象 是的 小部件配置对象。其必填字段取决于widget_type { "querySql": "...", "chartType": "Line Chart" }
layout 对象 可选的网格放置。如果省略,Telemetry 使用小部件类型默认值垂直堆叠小部件。 { "x": 0, "y": 0, "w": 12, "h": 4 }

了解布局

Telemetry 仪表板使用 12 列网格。

layout 对象使用网格单位,而不是像素:

领域 类型 默认 精确合约 示例
x 整数 0 非负整数。 0 是最左边的。无效值回退到 0 0
y 整数 下一个空行 非负整数。 0是仪表板的顶部。如果省略,Telemetry 会将小部件放置在前一个小部件的 y + h 之后。无效值会回退到该计算行。 0
w 整数 12 网格列中的正整数宽度。 12 表示全角,6 表示半角。无效值回退到 12 12
h 整数 小部件类型默认值 网格行中的正整数高度。无效值会回退到下面列出的小部件类型默认值。 4

所以这个:

"layout": { "x": 0, "y": 0, "w": 12, "h": 4 }

意思是:

  • 将小部件放置在仪表板的左上角
  • 使其跨越所有 12 列
  • 使其高为 4 行仪表板网格

这个:

"layout": { "x": 6, "y": 0, "w": 6, "h": 4 }

意思是:

  • 将小部件放在顶行
  • 从仪表板的一半开始
  • 让它占据行的右半部分

例如,这两个小部件并排呈现:

[
  { "layout": { "x": 0, "y": 0, "w": 6, "h": 4 } },
  { "layout": { "x": 6, "y": 0, "w": 6, "h": 4 } }
]

如果省略 layout,Telemetry 将使用以下默认值垂直堆叠小部件:

  • x = 0
  • w = 12
  • h = 4 适用于 queryexplorer
  • h = 2header
  • h = 3free_text
  • y 放置在下一个空行上

Telemetry 不会将 xw 钳位到 12 列网格,并且不会为您解决重叠位置。如果您想要可预测的渲染,请保留 x + w <= 12 并避免重叠 x/y 范围。

查询小部件配置

领域 类型 必填 精确值或格式 示例
querySql 字符串 是的 已修剪只读 SQL 字符串。修剪后必须非空。仪表板查询小部件拒绝写入语句,例如 INSERTUPDATEDELETEDROPALTERTRUNCATECREATEGRANTREVOKE "SELECT endpoint, COUNT(*) AS errors FROM http_logs GROUP BY endpoint"
chartType 字符串 是的 由 API 验证的精确枚举:tableScatter PlotBar ChartLine ChartStacked Area Chart "Line Chart"
xAxis 字符串 table 图表需要 用于 x 轴的修剪结果列名称。对于 Bar Chart,这可以是文本/分类、数字或类似时间的列。对于 Scatter PlotLine ChartStacked Area Chart,请使用数字或类似时间的列。仅当 chartTypetable 时才可以为空字符串。 "hour"
yAxis 字符串 table 图表需要 修剪后的数字结果列名称用于 y 轴。仅当 chartTypetable 时才可以为空字符串。 "errors"
groupBy 字符串或 null 可选的修剪结果列名称,用于将图表拆分为多个系列。使用 null 或省略它以不进行分组。 "service"
queryId 字符串或 null 可选的修剪保存查询 ID。 API 将其存储为字符串,并且不验证其形状。 "550e8400-e29b-41d4-a716-446655440000"
sourceUrl 字符串或 null 单击小部件标题时打开的可选修剪 UI URL。建议使用相关应用程序 URL,例如 /team/acme/ops/draft/0?... "/team/acme/ops/draft/0?tab=chart&chartType=Line+Chart&xAxis=hour&yAxis=errors"

注意事项:

  • 如果您想要简单的结果表而不是图表,请使用 chartType: "table"
  • 仪表板查询小部件会在仪表板加载时自动运行,因此仅接受只读 SQL。
  • 对于所有非 table 图表,xAxisyAxis 必须与 querySql 返回的实际列匹配。
  • 对于 Bar ChartxAxis 可以是文本/分类、数字或类时间。
  • 对于 Scatter PlotLine ChartStacked Area ChartxAxis 必须是数字或类时间。
  • 对于所有非 table 图表,yAxis 必须是数字。
  • 对于分类 Bar Chart x 轴,小部件保留查询结果顺序。使用 querySql 中的 ORDER BY 来控制条顺序。
  • 如果省略 sourceUrl,则仪表板 UI 会在可能的情况下派生后备草稿查询 URL。派生链接保留 defaultQuerytabchartTypexAxisyAxisgroupBy

示例:带有分类条形图 x 轴的查询小部件

{
  "title": "Requests by Endpoint",
  "widget_type": "query",
  "config": {
    "querySql": "SELECT endpoint, COUNT(*) AS requests FROM http_logs GROUP BY endpoint ORDER BY requests DESC",
    "chartType": "Bar Chart",
    "xAxis": "endpoint",
    "yAxis": "requests",
    "groupBy": null
  }
}

在那个例子中:

  • endpoint 是文本 x 轴列
  • requests 是 y 轴数字列
  • ORDER BY requests DESC 控制从左到右的条形顺序

标题小部件配置

使用 widget_type: "header" 作为对相关小部件进行分组的部分标题。

领域 类型 必填 精确值或格式 示例
description 字符串或 null 可选的降价描述显示在标题标题下。空字符串标准化为 null "Watch these charts during deploys and incident triage."

注意事项:

  • 小部件 title 是可见部分标题。
  • description支持降价。原始 HTML 在 UI 中呈现之前会被转义。

示例:

{
  "title": "Deploy Health",
  "widget_type": "header",
  "config": {
    "description": "Use this section during rollout checks and incident response."
  }
}

自由文本小部件配置

使用 widget_type: "free_text" 获取独立的 Markdown 注释、链接或运行手册说明。

领域 类型 必填 精确值或格式 示例
content 字符串 是的 修剪后的非空 Markdown 内容。 "Check [the latency recipe](/sql/api-latency-percentiles) before paging infra."

注意事项:

  • content支持降价。原始 HTML 在 UI 中呈现之前会被转义。
  • 即使 UI 仅呈现此组件类型的 Markdown 主体,API 仍然需要小部件 title

示例:

{
  "title": "API Runbook Note",
  "widget_type": "free_text",
  "config": {
    "content": "Check the on-call runbook first, then compare request volume with deploy timestamps."
  }
}

资源管理器小部件配置

领域 类型 必填 精确值或格式 示例
tableName 字符串 是的 修剪后的源表名称。修剪后必须非空。 "queue_metrics"
explorerState 对象 是的 用于呈现小部件的完整探索配置。请参阅下面的详细字段表。 { "graphType": "line", "aggregation": "p95", ... }
sourceUrl 字符串或 null 单击小部件标题时打开的可选修剪 UI URL。如果省略,Telemetry 将从 tableNameexplorerState 派生回退探索 URL。 "/team/acme/table/queue_metrics?tab=explore&graphType=line"

explorerState 字段

领域 类型 必填 精确值或格式 默认 示例
graphType 字符串 是的 由 API 验证的精确枚举:samplestablelinebarstacked-area "samples" "line"
aggregation 字符串 是的 由 API 验证的精确枚举:countsumavgminmaxp50p90p95p99 "count" "p95"
metric 字符串或 null 修剪后的列或字段路径进行聚合。将 null 用于 count。对于非 count 聚合,这是主要度量,并且优先于自动检测到的数字 selectedColumns(如果提供)。 null "latency_ms"
timeZone 字符串或 null 使用 UTC 或 IANA 时区标识符,例如 America/Los_AngelesEurope/Berlin。 API 当前会修剪并存储任何非空字符串,但无效的时区名称稍后在小部件查询运行时可能会失败。如果省略,保存的配置将保留 null,并且 UI 根据上下文回退到客户端时区或 UTC null "America/Los_Angeles"
timePreset 字符串 是的 支持的值为 1h6h24h7d30d90dcustom。 API 当前接受任何非空字符串,但 UI 和 SQL 生成器仅支持这些值。 "7d" "7d"
customStart 字符串 timePresetcustom 时使用。推荐格式:YYYY-MM-DDTHH:mmYYYY-MM-DD HH:mmYYYY-MM-DDTHH:mm:ssYYYY-MM-DDTHH:mm:ss.sss,可选地后跟 Z 或数字偏移量(如 -07:00)。如果不存在时区后缀,则以 timeZone 解释该值。 未设置 "2026-03-20T00:00:00Z"
customEnd 字符串 customStart 格式相同。如果自定义范围被省略,则查询没有时间上限。 未设置 "2026-03-26T00:00:00-07:00"
granularity 字符串 是的 由 API 验证的精确枚举:autominutehourdayweekmonth "auto" "hour"
splitBy 字符串数组 是的 非空修剪字段名称数组。嵌套 JSON 字段允许使用点路径,例如 attributes.queue_name [] ["queue_name"]
seriesLimit 整数或 null 正整数或 nullnull 表示无明确系列上限。对于分割图最有用。 100 10
filters 数组 是的 过滤器组数组。每个组在内部进行“与”运算;多个组通过 OR 组合在一起。在规范化过程中,空的或无效的组将被删除。 [] []
selectedColumns 字符串数组 是的 要在 samplestable 视图中显示的非空修剪字段名称数组。允许使用点状 JSON 路径。使用 [] 让 Telemetry 选择默认值。 [] ["timestamp_utc", "queue_name", "latency_ms"]
orderBy 字符串或 null 用于对表格结果进行排序的可选字段名称。允许使用点状 JSON 路径。 null "timestamp_utc"
limit 整数 是的 正整数行或组限制。无效值将恢复为默认值。 200 200
orderDirection 字符串 是的 由 API 验证的精确枚举:ASCDESC "DESC" "DESC"

timePreset

价值 含义
1h 最后 1 小时
6h 最后 6 小时
24h 过去 24 小时
7d 过去 7 天
30d 过去 30 天
90d 过去 90 天
custom 使用 customStartcustomEnd 代替相对范围

如果您发送未记录的 timePreset,则当前的 SQL 生成器将回退到 7 天行为。将上述值视为受支持的合约。

granularity: "auto" 行为

granularityauto 时,Telemetry 解析如下:

timePreset 有效粒度
1h6h24h minute
7d hour
30d90dcustom day

过滤组和条件

filters 的形状应如下所示:

[
  {
    "logic": "AND",
    "conditions": [
      { "field": "queue_name", "operator": "=", "value": "email" },
      { "field": "latency_ms", "operator": ">", "value": "1000" }
    ]
  }
]

filters中的每一项都是一个过滤器组:

领域 类型 必填 精确值或格式 示例
logic 字符串 是的 必须是 AND。仪表板创建 API 将每个组标准化为 AND;没有每组 OR。要表达 OR,请使用多个组,因为组是通过 OR 组合在一起的。 "AND"
conditions 数组 是的 组中的过滤条件数组。有效条件为零的组将被删除。 [{ "field": "queue_name", "operator": "=", "value": "email" }]

conditions中的每个项目都支持:

领域 类型 必填 精确值或格式 示例
field 字符串 是的 非空修剪字段路径。支持点嵌套 JSON 路径,例如 attributes.queue_name。不允许有空路径段。 "latency_ms"
operator 字符串 是的 由 API 验证的精确枚举:=!=>>=<<=LIKENOT LIKEIS NULLIS NOT NULL ">"
value 字符串、数字、布尔值或 null 通常 在标准化期间存储为字符串。对于 IS NULLIS NOT NULL,使用 "" 或省略语义值。 null 变为 "" "1000"

生成的SQL运行时:

  • 组内条件与 AND 相连接
  • 组加入 OR
  • 点状字段路径(例如 attributes.queue_name)被转换为嵌套字段访问

示例:创建一个空仪表板

示例:列出仪表板

curl "https://api.telemetry.sh/dashboard?page=1&pageSize=25" \
  -H "Authorization: $API_KEY"

响应示例:

{
  "status": "success",
  "pagination": {
    "page": 1,
    "pageSize": 25,
    "total": 1,
    "totalPages": 1,
    "hasNextPage": false,
    "hasPreviousPage": false
  },
  "dashboards": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "team_id": "team_123",
      "name": "Operations Overview",
      "slug": "operations-overview",
      "description": "Core service health and latency",
      "created_by": null,
      "created_by_api_key_id": "key_123",
      "created_at": "2026-03-27T00:09:03.797Z",
      "updated_at": "2026-03-27T00:09:03.797Z",
      "url": "/team/acme/dashboard/operations-overview",
      "widget_count": 1,
      "widgets": [
        {
          "id": "widget_123",
          "title": "Requests Per Hour",
          "widget_type": "query",
          "config": {
            "querySql": "SELECT DATE_TRUNC('hour', timestamp_utc) AS hour, COUNT(*) AS requests FROM http_logs GROUP BY 1 ORDER BY 1",
            "chartType": "Line Chart",
            "xAxis": "hour",
            "yAxis": "requests",
            "groupBy": null,
            "sourceUrl": "/team/acme/ops/draft/0?tab=chart&chartType=Line+Chart&xAxis=hour&yAxis=requests"
          },
          "layout": { "x": 0, "y": 0, "w": 12, "h": 4 },
          "sort_order": 0
        }
      ]
    }
  ]
}

示例:创建一个空仪表板

curl -X POST https://api.telemetry.sh/dashboard \
  -H "Content-Type: application/json" \
  -H "Authorization: $API_KEY" \
  -d '{
    "name": "Operations Overview",
    "description": "Core service health and latency"
  }'

示例:重命名仪表板并更新其描述

curl -X PATCH https://api.telemetry.sh/dashboard \
  -H "Content-Type: application/json" \
  -H "Authorization: $API_KEY" \
  -d '{
    "dashboardSlug": "operations-overview",
    "name": "Operations Overview v2",
    "description": "Updated to focus on API latency and error rates"
  }'

示例:替换现有仪表板上的所有小部件

此请求保留相同的仪表板,但用新的 widgets 阵列替换完整的小部件集。

curl -X PATCH https://api.telemetry.sh/dashboard \
  -H "Content-Type: application/json" \
  -H "Authorization: $API_KEY" \
  -d '{
    "dashboardSlug": "operations-overview",
    "widgets": [
      {
        "title": "Revenue by City",
        "widget_type": "explorer",
        "config": {
          "tableName": "uber_rides",
          "explorerState": {
            "graphType": "table",
            "aggregation": "sum",
            "metric": "price",
            "timePreset": "30d",
            "granularity": "auto",
            "splitBy": ["city"],
            "filters": [],
            "selectedColumns": [],
            "orderBy": "price",
            "limit": 10,
            "orderDirection": "DESC"
          }
        },
        "layout": { "x": 0, "y": 0, "w": 12, "h": 4 }
      }
    ]
  }'

示例:删除仪表板

curl -X DELETE https://api.telemetry.sh/dashboard \
  -H "Content-Type: application/json" \
  -H "Authorization: $API_KEY" \
  -d '{
    "dashboardSlug": "operations-overview"
  }'

常见小部件示例

下一个示例仅显示您发送到 POST /dashboard 的 JSON 请求正文。

这些示例假设 uber_rides 表包含以下字段:

  • city
  • price
  • wait_time_minutes
  • status
  • user_id
  • timestamp_utc

示例:创建一个包含两个常见 Explore 小部件的仪表板

该示例包括:

  • 一个表格小部件,按城市汇总乘车收入并按收入降序排序
  • 一个时间序列小部件,将按城市的平均等待时间绘制为分组线
{
  "name": "Uber Marketplace Overview",
  "widgets": [
    {
      "title": "Revenue by City",
      "widget_type": "explorer",
      "config": {
        "tableName": "uber_rides",
        "explorerState": {
          "graphType": "table",
          "aggregation": "sum",
          "metric": "price",
          "timePreset": "30d",
          "granularity": "auto",
          "splitBy": ["city"],
          "filters": [
            {
              "logic": "AND",
              "conditions": [
                { "field": "status", "operator": "=", "value": "completed" }
              ]
            }
          ],
          "selectedColumns": ["city", "price"],
          "orderBy": "price",
          "limit": 20,
          "orderDirection": "DESC"
        }
      },
      "layout": { "x": 0, "y": 0, "w": 6, "h": 4 }
    },
    {
      "title": "Average Wait Time by City",
      "widget_type": "explorer",
      "config": {
        "tableName": "uber_rides",
        "explorerState": {
          "graphType": "line",
          "aggregation": "avg",
          "metric": "wait_time_minutes",
          "timePreset": "7d",
          "granularity": "hour",
          "splitBy": ["city"],
          "seriesLimit": null,
          "filters": [
            {
              "logic": "AND",
              "conditions": [
                { "field": "status", "operator": "=", "value": "completed" }
              ]
            }
          ],
          "selectedColumns": ["city", "wait_time_minutes"],
          "limit": 200,
          "orderDirection": "ASC"
        }
      },
      "layout": { "x": 6, "y": 0, "w": 6, "h": 4 }
    }
  ]
}

在那个例子中:

  • Revenue by City 是一个探索表格小部件
  • selectedColumns: ["city", "price"] 加上 aggregation: "sum" 为每个 city 生成一个聚合 price 色谱柱
  • orderBy: "price" 按汇总收入列排序
  • Average Wait Time by City 是一个探索行小部件
  • splitBy: ["city"] 每个城市创建一条线路
  • orderDirection: "ASC" 保持时间轴按时间顺序排列

示例:创建队列保留微笑曲线的查询小部件

此示例使用查询小部件,因为群组保留在探索中更难表达。它使用:

  • 首次乘坐群体定义
  • 独特的每周活动表
  • 队列规模和保留乘客之间的联系

可读querySql

WITH first_rides AS (
  SELECT
    user_id,
    date_trunc('week', MIN(timestamp_utc)) AS cohort_week
  FROM
    uber_rides
  WHERE
    status = 'completed'
  GROUP BY
    user_id
),
weekly_activity AS (
  SELECT DISTINCT
    user_id,
    date_trunc('week', timestamp_utc) AS activity_week
  FROM
    uber_rides
  WHERE
    status = 'completed'
),
cohort_activity AS (
  SELECT
    f.cohort_week,
    a.activity_week,
    date_part('day', a.activity_week - f.cohort_week) / 7 AS weeks_since_first_ride,
    COUNT(DISTINCT a.user_id) AS retained_riders
  FROM
    first_rides f
    JOIN weekly_activity a ON a.user_id = f.user_id
  WHERE
    a.activity_week >= f.cohort_week
  GROUP BY
    f.cohort_week,
    a.activity_week,
    date_part('day', a.activity_week - f.cohort_week) / 7
),
cohort_sizes AS (
  SELECT
    cohort_week,
    COUNT(*) AS cohort_size
  FROM
    first_rides
  GROUP BY
    cohort_week
)
SELECT
  weeks_since_first_ride,
  100.0 * retained_riders / cohort_size AS retention_pct,
  CAST(ca.cohort_week AS VARCHAR) AS cohort_week
FROM
  cohort_activity ca
  JOIN cohort_sizes cs ON ca.cohort_week = cs.cohort_week
WHERE
  weeks_since_first_ride BETWEEN 0 AND 12
ORDER BY
  weeks_since_first_ride ASC,
  cohort_week ASC
{
  "name": "Uber Rider Retention",
  "widgets": [
    {
      "title": "Weekly Rider Retention Smile Curves",
      "widget_type": "query",
      "config": {
        "querySql": "WITH first_rides AS ( SELECT user_id, date_trunc('week', MIN(timestamp_utc)) AS cohort_week FROM uber_rides WHERE status = 'completed' GROUP BY user_id ), weekly_activity AS ( SELECT DISTINCT user_id, date_trunc('week', timestamp_utc) AS activity_week FROM uber_rides WHERE status = 'completed' ), cohort_activity AS ( SELECT f.cohort_week, a.activity_week, date_part('day', a.activity_week - f.cohort_week) / 7 AS weeks_since_first_ride, COUNT(DISTINCT a.user_id) AS retained_riders FROM first_rides f JOIN weekly_activity a ON a.user_id = f.user_id WHERE a.activity_week >= f.cohort_week GROUP BY f.cohort_week, a.activity_week, date_part('day', a.activity_week - f.cohort_week) / 7 ), cohort_sizes AS ( SELECT cohort_week, COUNT(*) AS cohort_size FROM first_rides GROUP BY cohort_week ) SELECT weeks_since_first_ride, 100.0 * retained_riders / cohort_size AS retention_pct, CAST(ca.cohort_week AS VARCHAR) AS cohort_week FROM cohort_activity ca JOIN cohort_sizes cs ON ca.cohort_week = cs.cohort_week WHERE weeks_since_first_ride BETWEEN 0 AND 12 ORDER BY weeks_since_first_ride ASC, cohort_week ASC",
        "chartType": "Line Chart",
        "xAxis": "weeks_since_first_ride",
        "yAxis": "retention_pct",
        "groupBy": "cohort_week"
      },
      "layout": { "x": 0, "y": 0, "w": 12, "h": 5 }
    }
  ]
}

在那个例子中:

  • weeks_since_first_ride 是 x 轴
  • retention_pct 是 y 轴
  • groupBy: "cohort_week" 为每个注册队列创建一条线,从而生成微笑曲线风格比较
  • 这是一个查询小部件而不是探索小部件,因为队列逻辑依赖于多个 CTE 和连接

回应

成功的 POST 请求返回 201 Created

成功的 PATCH 请求返回 200 OK

两者都返回这个形状:

{
  "status": "success",
  "dashboard": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "team_id": "team_123",
    "name": "HTTP Monitoring",
    "slug": "http-monitoring",
    "description": null,
    "created_by": null,
    "created_by_api_key_id": "8dff0c1a-8b36-49c3-9e6b-dc0d3ff51d74",
    "created_at": "2026-03-26T00:00:00.000Z",
    "updated_at": "2026-03-26T00:00:00.000Z",
    "url": "/team/acme/dashboard/http-monitoring"
  },
  "widgets": [
    {
      "id": "9a6e4f27-d3bf-4a70-bf3a-38fe63211f93",
      "title": "Errors Per Hour",
      "widget_type": "query",
      "config": {
        "queryId": null,
        "querySql": "SELECT ...",
        "chartType": "Line Chart",
        "xAxis": "hour",
        "yAxis": "errors",
        "groupBy": null,
        "sourceUrl": null
      },
      "layout": {
        "x": 0,
        "y": 0,
        "w": 12,
        "h": 4
      },
      "sort_order": 1
    }
  ]
}

成功的 DELETE 请求返回 200 OK 以及删除摘要:

{
  "status": "success",
  "deleted_dashboard": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "HTTP Monitoring",
    "slug": "http-monitoring",
    "description": null,
    "widget_count": 6,
    "url": "/team/acme/dashboard/http-monitoring"
  }
}

通过此 API 创建的仪表板是团队范围的,并归因于创建它们的 API 密钥:

  • 对于 API 创建的仪表板,created_bynull,因为 API 密钥不是用户
  • created_by_api_key_id 是创建密钥的内部 team_api_keys.id
  • 通过 UI 创建的仪表板仍然使用 created_by 和用户 ID,并且通常将 created_by_api_key_id 保留为 null

如果您的团队已存在标准化的段,则 API 将返回 409 Conflict

其他常见错误:

  • 400 Bad Request(如果必填字段缺失或无效)
  • 400 Bad Request 如果查询小部件包含非只读 SQL
  • 404 Not Found(如果您的团队不存在目标仪表板)
  • 401 Unauthorized(如果 API 密钥丢失或无效)
  • 400 Bad Request 如果 API 密钥仅具有 read 范围

相关功能

将经过验证的查询转变为重点突出、可审查的操作视图。

页面作者和参考资料

Telemetry 编辑团队负责维护本文;产品团队审核功能行为、示例和适用范围。

我们如何审核文档