观测云 OpenAPI 数据查询接口最佳实践

背景与价值

在云原生和微服务架构日益普及的今天,可观测性数据(日志、指标、链路追踪)呈爆炸式增长。观测云 OpenAPI 数据查询接口为开发者和运维团队提供了一种编程化、自动化获取这些高价值数据的能力,例如:

  • 自动化数据查询:将观测云数据集成到内部系统或第三方平台;
  • 构建自定义仪表盘:根据业务需求灵活展示监控数据;
  • 实现数据联动:打通观测云与企业内部的数据分析流程;
  • 批量数据处理:高效获取大规模监控数据进行离线分析。

OpenAPI 概览

观测云将 OpenAPI 作为开放能力的关键构成,支持工作空间配置和数据查询,通过请求头中附加的基于角色的 API Key 进行认证鉴权,默认请求频率限制为同一 API Key 每分钟最多请求 20 次、同一工作空间每分钟最多请求 200次。接入点和请求头等请参考官方文档 docs.guance.com/open-api/

前置条件

  • 创建 API Key:确保登录用户有所需的操作权限。登录观测云控制台,点击【管理】-【API Keys 管理】-【新建 Key】,填写名称与角色,本实践仅使用数据查询接口,因此使用内置角色 "Read-only"。
  • 调试 DQL:数据查询接口通过传入 DQL 查询语句进行查询,建议在调用接口之前确认查询语句,完整语法请参考 docs.guance.com/dql/ ,可以在观测云界面的查询工具中进行调试,点击快捷方式 -【查询工具】,选择 DQL 查询模式,支持语法校验和自动补全:

数据查询接口

基本信息

  • 方法:POST
  • 接口:/api/v1/df/query_data_v1

请求参数解析

queries,为 query 对象组成的列表,每个 query 对象中包含独立的 DQL 语句,依次实现单次请求返回多组查询结果,以下是单个 query 对象的关键参数:

序号 参数 类型 是否必填 描述
1 $.queries[*].qtype String 默认为 dql,可选:dql:DQL 类型查询promql:PromQL 类型查询
2 $.queries[*].query.q String 查询语句
3 $.queries[*].query.timeRange Array 执行查询的时间范围,默认值最近 30 分钟,毫秒时间戳列表:[start_time, end_time]
4 $.queries[*].query.interval Int 聚合时间分片间隔,单位秒
5 $.queries[*].query.offset Int 分页偏移量,DQL 语句中的子句优先级高于此参数
6 $.queries[*].query.limit Int 分页大小,DQL 语句中的子句优先级高于此参数
7 $.queries[*].query.orderby Array 排序列表,默认按照输出的 time 字段降序排列,DQL 语句中的子句优先级高于此参数
8 $.queries[*].query.cursor_time Int 分段查询阈值,第一次分段查询时设置为 timeRange 中的 end_time,此后的分段查询,将 cursor_time 设置为响应中的 next_cursor_time 字段的值,next_cursor_time 为 -1 时表示无新数据,注意,分段查询仅在存储引擎为 GuanceDB 3.0 时生效
9 $.queries[*].query.cursor_token String 在分段查询中,将 cursor_token 设置为响应中的 next_cursor_token 字段的值,以确保相同时间戳的数据不被分段跳过,注意,分段查询仅在存储引擎为 GuanceDB 3.0 时生效
10 $.queries[*].query.disable_sampling Bool 是否禁用采样,默认 false,仅对部分聚合类查询生效
11 $.queries[*].query.ignore_cache Bool 是否禁用缓存,默认 false
12 $.queries[*].query.disableMultipleField Bool 是否禁用单列模式,默认为 true,打开单列模式可有效减少返回数据的体积,为 false 时 $.queries[*].query.funcList 参数将失效

场景解析

数据查询场景和查询方法分类如下,需根据不同的查询类型合理配置查询参数:

示例一:查询指定 Span 的平均耗时(获取聚合后的数据)

请求体,参数说明见注释:

json 复制代码
{
    "queries": [
        {
            "qtype": "dql",
            "query": {
                "q": "R::resource:(AVG(`duration`) AS `avg(duration)`) { `service` = 'demo' AND `resource` = 'GET /health' }",
                "interval": 60, // 查询时间范围内每 60 秒聚合一个值
                "offset": 0,
                "limit": 500,
                "orderby": [
                    {
                        "time": "desc"
                    }
                ],
                "timeRange": [
                    1774144800000, // 2026-03-22 10:00:00
                    1774145100000  // 2026-03-22 10:05:00
                ],
                "disable_sampling": true // 禁止聚合采样
            }
        }
    ]
}

响应体,仅包含重要返回数据及其注释:

json 复制代码
{
    "code": 200, // 状态码,与 HTTP 响应码保持一致,无错误时固定为 200
    "content": { // 接口响应数据
        "data": [
            {
                // ...
                "next_cursor_time": -1,  // 下次请求的 cursor_time,因本次查询为聚合查询,返回为 -1
                "next_cursor_token": "", // 下次请求的 cursor_token,因本次查询为聚合查询,返回为空
                // ...
                "sample": 1,             // 采样率,为 1 表示采样率 100%,即未采样
                // ...
                "series": [              // 数据查询结果
                    {
                        "column_names": [
                            "time",
                            "avg(duration)"
                        ],
                        "columns": [
                            "time",
                            "avg(duration)"
                        ],
                        "units": [
                            null,
                            "time,ns"
                        ],
                        "values": [                 // 每间隔一个 interval 秒聚合一个数据点
                            [
                                1774145040000,      // 2026-03-22 10:04:00
                                1462101213.4054055
                            ],
                            [
                                1774144980000,      // 2026-03-22 10:03:00
                                520552891.31707317
                            ],
                            [
                                1774144920000,      // 2026-03-22 10:02:00
                                403010784
                            ],
                            [
                                1774144860000,      // 2026-03-22 10:01:00
                                496579998.11764705
                            ],
                            [
                                1774144800000,      // 2026-03-22 10:00:00
                                608395087.6444445
                            ]
                        ]
                    }
                ],
                "window": 60000
            }
        ],
        // ...
    },
    "errorCode": "",                              // 错误码,空表示无错误
    "message": "",                                // 错误信息
    "success": true,                              // 接口调用状态,为 true 时表示调用成功
    "traceId": "69bfdf42000000001ac3936f1436ac54" // 请求的跟踪 ID
}

示例二:获取指定类型的所有 Span(获取原始数据)

采用分段查询方式,请求体,参数说明见注释:

json 复制代码
{
    "queries": [
        {
            "qtype": "dql",
            "query": {
                "q": "R::resource:(`*`) { `service` = 'demo' AND `resource` = 'GET /health' }",
                "limit": 1,                   // 分段大小为 1
                "cursor_time": 1774145100000, // 初始请求取 timeRange 中的结束时间,后续请求取响应中的 next_cursor_time 的值
                "cursor_token": "",           // 初始请求取空值,后续请求取响应中的 next_cursor_token 的值
                "orderby": [
                    {
                        "time": "desc"
                    }
                ],
                "timeRange": [
                    1774144800000, // 2026-03-22 10:00:00
                    1774145100000  // 2026-03-22 10:05:00
                ]
            }
        }
    ]
}

响应体,仅包含重要返回数据及其注释:

json 复制代码
{
    "code": 200, // 状态码,与 HTTP 响应码保持一致,无错误时固定为 200
    "content": { // 接口响应数据
        "data": [
            {
                // ...
                "next_cursor_time": 1774145099284000, // 将值作为下次请求的 cursor_time
                "next_cursor_token": "1774145099284000000-R_1774145099284_d6vksl01so5nqftmhv20", // 将值作为下次请求的 cursor_token
                // ...
                "series": [ // 数据查询结果
                    {       // 将以单列的方式输出一条原始数据的所有字段,示例响应仅保留了 __block_id 字段,禁用单列模式时,列名、列值等分别作为一个单独的数组
                        "column_names": [
                            "time",
                            "__block_id"
                        ],
                        "columns": [
                            "time",
                            "__block_id"
                        ],
                        "units": [
                            null,
                            null
                        ],
                        "values": [
                            [
                                1774145099284,
                                2135893696351448600
                            ]
                        ]
                    },
                    // ...
                ],
                // ...
            }
        ],
        // ...
    },
    "errorCode": "",                              // 错误码,空表示无错误
    "message": "",                                // 错误信息
    "success": true,                              // 接口调用状态,为 true 时表示调用成功
    "traceId": "69bfec720000000042c950e749998eff" // 请求的跟踪 ID
}

最佳实践

  • 权限最小化:为不同的应用场景(如报表系统、告警机器人)创建独立的 API Key,并赋予最小必要权限;
  • 避免触发 API 限流:一次请求中包含多条查询语句,尽量在应用层增加历史数据缓存;
  • 错误处理:必须对 API 返回的错误进行处理,例如实现指数回退重试机制;
  • 监控请求 OpenAPI 的服务:确保相关业务健康运行;
  • 在接口参数中设置聚合间隔和排序字段,而非在 DQL 中设置:DQL 支持以时间子句设置聚合间隔,但是 API 返回的点数受到优先级规则限制,只有 interval 参数和时间子句中的间隔保持一致时才能获得符合预期的结果,因此,建议使用 API 参数设置聚合间隔和排序方式,在其他场景中,如果 API 参数与 DQL 子句功能重复,仍然建议优先使用 API 参数而非 DQL 子句,利于编码且语义统一;
  • 获取原始数据时关闭单列模式,以减小响应体的体积:请求时设置 disableMultipleField=false 即可关闭单列模式,注意,此时用于聚合查询的 funcList 参数将失效。

总结

本文档围绕观测云 OpenAPI 数据查询接口展开,介绍了其在云原生可观测场景下的应用价值,说明了接口认证、限流规则及创建 API Key、调试 DQL 语句等前置准备,详细解析了 /api/v1/df/query_data_v1 接口的请求参数,并通过聚合数据查询、原始数据分段查询两个典型示例展示使用方法,最后给出权限、限流、错误处理等方面的最佳实践,可帮助开发者快速接入并规范使用该接口实现监控数据的程序化获取与应用。

相关推荐
We་ct10 小时前
HTML5 原生拖拽 API 实战案例与拓展避坑
前端·html·api·html5·拖拽
智慧地球(AI·Earth)1 天前
用AI重构Python开发:从API调用到本地部署,代码全流程自动化实战
python·自动化·api
We་ct1 天前
HTML5 原生拖拽 API 基础原理与核心机制
前端·javascript·html·api·html5·浏览器·拖拽
牛奶2 天前
浏览器藏了这么多神器,你居然不知道?
前端·chrome·api
weixin_408099673 天前
【电商实战】如何用OCR批量提取商品SKU与参数?自动识别+批量处理完整方案(附代码)
ocr·api·图像识别·api接口·跨境电商·电商自动化·sku识别
心连欣3 天前
从静态页面到动态交互:DOM操作的核心API解析
前端·javascript·api
星速云3 天前
开源AI工具生态全景:20+工具如何对接统一API网关
人工智能·gpt·开源·api·claude
向量引擎4 天前
向量引擎中转站偷走我半条命后终于把API密钥这件事整明白了
人工智能·aigc·api·ai编程·ai写作·key·api调用
深念Y5 天前
Token 还没白菜价,我靠“AI 流水线”省token
ai·api·agent·开发·token·工程·词元