OpenAPI 跨站点数据查询¶
本文说明如何通过 query_data 查询当前工作空间已获授权的其它站点数据,以及如何正确处理异步接口返回的 async_id。
适用接口¶
| 场景 | 接口 | 说明 |
|---|---|---|
| 同步查询(推荐) | POST /api/v1/df/query_data_v1 |
新接入优先使用 |
| 异步查询 | POST /api/v1/df/asynchronous/query_data |
仅在任务仍运行时回传 async_id |
| 旧版兼容 | GET/POST /api/v1/df/query_data |
GET 使用 body=<URL 编码后的 JSON>;新接入不推荐 |
| 查询授权目标 | GET /api/v1/wksp_share/granted_ws_list |
获取目标 workspaceUUID 和 targetRegion |
| 查询站点配置 | GET /api/v1/workspace/website/list |
仅用于查看站点注册信息,不代表已有数据授权 |
External API 的 POST /api/v1/df/{workspace_uuid}/query_data 是同步入口,不接受 async_id。它底层使用同一组 DQL 查询字段,但鉴权方式为 External API 的 AK/SK 签名。
请求模型与限制¶
跨站点查询仍然调用当前站点的 OpenAPI Endpoint,并使用当前工作空间的 DF-API-KEY。不需要直接请求目标站点,也不应使用目标站点的 Endpoint 替换当前 Endpoint。
每个 queries[i] 的结构为:
{
"qtype": "dql",
"query": {
"q": "L::re(`.*`):(`message`)",
"workspaceUUIDs": ["wksp_target"],
"targetRegion": "region_code"
}
}
需要遵守以下规则:
- 非空
workspaceUUIDs优先于workspaceUUID;当workspaceUUIDs为空数组或null时会回退使用workspaceUUID。建议不要同时传两个字段。两者都不传时查询当前工作空间。 - 跨站点查询应在每个 query 的
query对象内显式传入同一个targetRegion,不要只在请求顶层传入。 - 一个请求中的所有
queries[*]只能指向一个站点。多个站点必须拆成多次请求,再由客户端合并结果。 workspaceUUIDs: ["*"]或workspaceUUID: "*"表示查询指定targetRegion内当前工作空间可查看的全部授权空间;此时targetRegion必传。targetRegion是授权方工作空间所属站点的regionCode,不是toRegionCode。- 同一个请求内的多个目标工作空间必须属于同一
targetRegion。建议按站点对目标工作空间分组后再构造请求。
获取目标工作空间与 targetRegion¶
调用:
curl '<Endpoint>/api/v1/wksp_share/granted_ws_list?namespace=logging&pageIndex=1&pageSize=100' \
-H 'DF-API-KEY: <DF-API-KEY>' \
--compressed
namespace 可按数据类型过滤授权,例如:
- 日志:
logging - 链路:
tracing - 指标:
metric - 用户访问监测:
rum - 可用性监测:
dialtest
响应按授权方站点分组:
{
"code": 200,
"content": [
{
"regionCode": "region_a",
"regionName": "站点 A",
"data": [
{
"workspaceUUID": "wksp_target_a",
"workspaceName": "目标工作空间 A",
"regionCode": "region_a",
"toWorkspaceUUID": "wksp_current",
"toRegionCode": "region_current",
"type": ["logging"],
"indexes": ["*"]
}
],
"pageInfo": {
"pageIndex": 1,
"pageSize": 100,
"totalCount": 1
}
}
],
"success": true
}
组织参数时:
- 用
data[*].workspaceUUID作为query.workspaceUUID或query.workspaceUUIDs的值。 - 用该工作空间所在分组的
content[*].regionCode(或同一数据项的regionCode)作为query.targetRegion。 - 不要使用
toWorkspaceUUID作为查询目标;它通常是当前 API Key 所属的被授权方工作空间。 - 不要使用
toRegionCode作为targetRegion;它通常是当前站点。 granted_ws_list对每个站点分组独立分页,pageInfo.count只是当前页数量,不能直接用它和totalCount比较后无限递增页码。- 首次可不传
regionCode,用pageIndex=1&pageSize=100发现授权方站点;随后为每个需要查询的站点显式传入该regionCode,并分别从第 1 页开始翻页。 - 某站点累计取得的唯一授权数达到该组
pageInfo.totalCount,或pageIndex * pageSize >= totalCount时停止。合并页数据时按授权记录uuid去重,并用(regionCode, workspaceUUID)校验目标映射;同一映射出现冲突授权时不要自行扩大权限范围。
例如只翻取 region_a 的第 2 页:
curl '<Endpoint>/api/v1/wksp_share/granted_ws_list?namespace=logging®ionCode=region_a&pageIndex=2&pageSize=100' \
-H 'DF-API-KEY: <DF-API-KEY>' \
--compressed
GET /api/v1/workspace/website/list 返回的 content[*].regionCode 只能作为站点编码候选。某站点出现在站点列表中,不表示当前工作空间已经获得该站点的数据授权;最终必须以 granted_ws_list 的结果为准。
同步跨站点查询¶
以下示例查询 region_a 站点的 wksp_target_a:
curl '<Endpoint>/api/v1/df/query_data_v1' \
-H 'Content-Type: application/json' \
-H 'DF-API-KEY: <DF-API-KEY>' \
--data-raw '{
"queries": [
{
"qtype": "dql",
"query": {
"q": "L::re(`.*`):(`message`)",
"timeRange": [1772516130000, 1772519730000],
"limit": 100,
"workspaceUUIDs": ["wksp_target_a"],
"targetRegion": "region_a"
}
}
]
}' \
--compressed
查询某个站点内全部已授权工作空间:
{
"queries": [
{
"qtype": "dql",
"query": {
"q": "L::re(`.*`):(`message`)",
"timeRange": [1772516130000, 1772519730000],
"limit": 100,
"workspaceUUIDs": ["*"],
"targetRegion": "region_a"
}
}
]
}
如果需要同时查询 region_a 和 region_b,应分别发起两次请求:
不要在同一个 queries 数组中混用不同 targetRegion,否则接口会返回 ft.UnsupportMultiSiteQuery。
异步查询与 async_id 生命周期¶
async_id 是单次查询任务的句柄,不是会话 ID、固定客户端 ID 或分页游标。新查询绝不能携带历史 async_id。
1. 首次提交:省略 async_id¶
curl '<Endpoint>/api/v1/df/asynchronous/query_data' \
-H 'Content-Type: application/json' \
-H 'DF-API-KEY: <DF-API-KEY>' \
--data-raw '{
"queries": [
{
"qtype": "dql",
"query": {
"q": "L::re(`.*`):(`message`)",
"timeRange": [1772516130000, 1772519730000],
"limit": 100,
"workspaceUUIDs": ["wksp_target_a"],
"targetRegion": "region_a"
}
}
]
}' \
--compressed
若任务仍在运行,响应示例:
{
"code": 200,
"content": {
"data": [
{
"async_id": "async_task_001",
"is_running": true
}
]
},
"success": true,
"traceId": "TRACE-XXXX"
}
2. 轮询:只回传仍在运行的任务 ID¶
仅当同一结果项同时满足以下条件时才轮询:
把 ID 放回同一数组下标的 queries[i].async_id,并保持 qtype、query.q、时间范围、目标工作空间和 targetRegion 不变:
{
"queries": [
{
"async_id": "async_task_001",
"qtype": "dql",
"query": {
"q": "L::re(`.*`):(`message`)",
"timeRange": [1772516130000, 1772519730000],
"limit": 100,
"workspaceUUIDs": ["wksp_target_a"],
"targetRegion": "region_a"
}
}
]
}
建议使用递增退避并设置总超时,例如先等待 1 秒,再逐步增加到 2 秒、4 秒;不要无间隔连续请求。
3. 结束:停止携带 async_id¶
当 content.data[i].is_running 为 false 时,该任务已经结束。调用方应读取最终数据并立即停止轮询;无论响应对象里是否仍出现 async_id 字段,下一次新查询都必须省略旧 ID。
以下行为是错误的:
- 将上一次任务的
async_id固定写入所有后续请求。 - 修改 DQL、时间范围、工作空间或
targetRegion后继续复用旧 ID。 - 将
content.data[0].async_id填入queries[1]。 - 用
async_id代替search_after、cursor_time或cursor_token翻页。
若出现 is_running=true 但 async_id 为空,不要回填本地保存的历史 ID。应记录响应 traceId,按有限重试策略重新发起该逻辑查询;持续出现时联系技术支持。
批量异步查询中,content.data[i] 与 queries[i] 按数组下标对应。为了降低 ID 与查询项错配的风险,建议异步调用每次只提交一个 query。
分页与异步任务的区别¶
异步任务完成后,分页仍使用最终查询结果返回的分页字段:
| 场景 | 下一次请求参数 |
|---|---|
| 日志深度分页 | 将响应 search_after 传入下一次查询的 query.search_after |
| 分段时间查询 | 首次将 query.cursor_time 设为结束时间,后续传响应 next_cursor_time |
| 同时间戳安全翻页 | 将响应 next_cursor_token 传入下一次查询的 query.cursor_token |
翻页属于新的查询请求,不应继续携带已完成任务的 async_id。如果翻页请求再次转为异步任务,仍从“省略 async_id”开始新的生命周期。
客户端合并建议¶
服务端不支持在一次 query_data 请求中跨多个站点查询。客户端合并时建议:
- 先按
targetRegion分组目标工作空间。 - 每个站点独立请求、独立分页、独立处理异步任务。
- 为每批结果补充客户端元数据,例如
sourceRegion和queriedWorkspaceUUIDs。多工作空间查询不会保证每条记录都带可靠的来源工作空间,因此不能把整批结果标成某一个sourceWorkspaceUUID;只有每次只查询一个工作空间时才可这样标记。需要记录级来源时,应逐工作空间查询,或让 DQL 返回经业务确认可靠的来源维度。 - 日志类结果按
time、date_ns及稳定唯一标识排序并去重;指标结果应先确认时间粒度、聚合函数和标签集合一致再合并。 - 任一站点失败时保留其它站点成功结果,并返回分站点错误明细,不要把部分成功包装成全部成功。
常见错误¶
| 错误码 / 现象 | 原因 | 处理方式 |
|---|---|---|
ft.UnsupportMultiSiteQuery |
一个请求混入多个目标站点 | 按 targetRegion 拆分请求 |
ft.workspaceUnauthorized |
目标工作空间未授权给当前工作空间 | 重新查询 granted_ws_list,确认授权状态和 UUID |
ft.NotFoundWorkspaceAuthorizationCfg |
目标站点没有可用授权配置,常见于使用 * 但站点无授权 |
检查 targetRegion,并确认目标站点存在有效授权 |
ft.NoInitOtherNodeCfg |
跨外部组织站点授权存在,但目标站点 Front Endpoint / 节点配置缺失 | 不要盲目重试;联系站点管理员检查并补齐目标节点配置 |
ft.InvalidWorkspace |
当前站点目标工作空间无效或已停用 | 刷新工作空间列表并确认状态 |
| 一直轮询旧结果 | 客户端长期复用已完成任务的 async_id |
is_running=false 后删除本地 ID;新查询不传 async_id |
| 站点存在但查不到数据 | 只检查了 workspace/website/list,未确认授权 |
以 wksp_share/granted_ws_list 为准 |
DQLDataAccessScopeRestricted warning |
数据访问规则只允许部分索引或不允许相关索引 | 检查 warnings[].details[].metadata.restriction 和数据访问规则 |
上线前检查清单¶
- 使用当前工作空间的
DF-API-KEY请求当前站点 OpenAPI Endpoint。 - 从
granted_ws_list获取目标workspaceUUID与同组regionCode。 - 每个跨站点 query 都显式传入同一个
targetRegion。 - 多站点目标已按
targetRegion拆分为多次请求。 - 新异步查询不传
async_id。 - 仅在
is_running=true且 ID 非空时轮询,并按数组下标绑定任务。 -
is_running=false后删除任务 ID;分页从新的异步生命周期开始。 - 设置轮询退避、总超时、分页上限和分站点错误处理。
- 合并结果时保留来源站点/工作空间并按业务主键去重。