OpenAPI サイト間データクエリ¶
この記事では、query_data を使用して現在のワークスペースで認可されている他サイトのデータをクエリする方法と、非同期 API が返す async_id を正しく処理する方法について説明します。
対象API¶
| シナリオ | API | 説明 |
|---|---|---|
| 同期クエリ(推奨) | 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を明示的に渡してください。リクエストの最上位でのみ渡すのは避けてください。 - 1つのリクエスト内のすべての
queries[*]は1つのサイトのみを指すことができます。複数のサイトをクエリする場合はリクエストを分割し、クライアント側で結果をマージしてください。 workspaceUUIDs: ["*"]またはworkspaceUUID: "*"は、指定したtargetRegion内で現在のワークスペースが参照できるすべての認可ワークスペースをクエリすることを意味します。この場合、targetRegionは必須です。targetRegionは、認可元ワークスペースが属するサイトのregionCodeであり、toRegionCodeではありません。- 同じリクエスト内の複数の対象ワークスペースは、同じ
targetRegionに属している必要があります。対象ワークスペースをサイトごとにグループ化してからリクエストを構築することを推奨します。
時間範囲とページネーションカーソル¶
query.timeRange の開始時刻と終了時刻は、同じ単位(秒、ミリ秒、マイクロ秒、ナノ秒)を使用する必要があります。単位を混在させると HTTP 400 と ft.TimeRangeUnitMismatch が返され、サーバー側で自動修正は行われません。この記事のリクエスト例ではミリ秒を使用しています。実際のクエリ時間範囲に置き換えてください。
cursor_time、cursor_token などのページネーションパラメータはクエリの時間範囲とは独立しています。ページングの際は、API の仕様に従ってレスポンスのカーソルをそのまま渡し、元のクエリの timeRange は変更しないでください。桁を揃えるためにカーソルを換算しないでください。
対象ワークスペースと 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):
rum - Synthetic モニタリング:
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 を同時にクエリする必要がある場合は、それぞれ別々に2回リクエストを送信します:
同じ queries 配列内で異なる targetRegion を混在させないでください。混在させると API は 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 とクエリ項目の誤対応のリスクを減らすため、非同期呼び出しでは毎回1つの query だけを送信することを推奨します。
ページングと非同期タスクの違い¶
非同期タスクの完了後、ページングは最終クエリ結果で返されるページングフィールドを引き続き使用します:
| シナリオ | 次のリクエストパラメータ |
|---|---|
| ログのディープページング | レスポンスの search_after を次のクエリの query.search_after に渡す |
| 時間範囲分割クエリ | 初回は query.cursor_time に終了時刻を設定し、以降はレスポンスの next_cursor_time を渡す |
| 同一タイムスタンプでの安全なページング | レスポンスの next_cursor_token を次のクエリの query.cursor_token に渡す |
ページングは新しいクエリリクエストに該当するため、完了済みタスクの async_id を引き続き含めるべきではありません。ページングリクエストが再び非同期タスクになった場合は、async_id を省略するところから新しいライフサイクルを開始します。
クライアント側のマージ推奨事項¶
サーバー側は1回の query_data リクエストでの複数サイトにわたるクエリをサポートしていません。クライアント側でマージする際は次の点を推奨します:
- 最初に
targetRegionごとに対象ワークスペースをグループ化します。 - サイトごとにリクエスト、ページング、非同期タスクの処理を独立させます。
- 各バッチの結果に、
sourceRegionやqueriedWorkspaceUUIDsなどのクライアントメタデータを追加します。複数ワークスペースのクエリでは、各レコードに信頼できるソースワークスペースが必ず含まれるとは限らないため、バッチ全体を特定のsourceWorkspaceUUIDとしてタグ付けすることはできません。1回のクエリで1つのワークスペースだけを対象にする場合にのみ、そのようにタグ付けできます。レコードレベルのソースが必要な場合は、ワークスペースごとにクエリするか、DQL でビジネス上信頼できるソースディメンションを返すようにしてください。 - ログ系の結果は
time、date_nsと安定した一意な識別子で並べ替えて重複排除します。メトリクス結果は、時間粒度、集計関数、タグセットが一致していることを確認してからマージしてください。 - いずれかのサイトが失敗した場合は、他のサイトの成功結果を保持し、サイトごとのエラー詳細を返してください。部分成功を全体の成功として扱わないでください。
よくあるエラー¶
| エラーコード / 現象 | 原因 | 対応方法 |
|---|---|---|
ft.TimeRangeUnitMismatch |
timeRange の開始時刻と終了時刻で単位が混在している |
同じ単位で時間範囲を再構成します。ページネーションカーソルはレスポンスの値をそのまま返します |
ft.UnsupportMultiSiteQuery |
1つのリクエストに複数の対象サイトが混在している | 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 警告 |
データアクセスルールで一部のインデックスのみ許可されている、または関連インデックスが許可されていない | warnings[].details[].metadata.restriction とデータアクセスルールを確認します |
リリース前チェックリスト¶
- 現在のワークスペースの
DF-API-KEYを使用して現在のサイトの OpenAPI Endpoint にリクエストします。 -
granted_ws_listから対象のworkspaceUUIDと同じグループのregionCodeを取得します。 - すべてのサイト間クエリで同じ
targetRegionを明示的に渡します。 - 複数サイトの対象を
targetRegionごとに複数のリクエストへ分割しました。 - 新しい非同期クエリには
async_idを渡しません。 -
is_running=trueかつ ID が空でない場合のみポーリングし、配列インデックスでタスクを紐付けます。 -
is_running=falseになったらタスク ID を削除します。ページングは新しい非同期ライフサイクルから開始します。 - ポーリングのバックオフ、全体タイムアウト、ページング上限、サイトごとのエラー処理を設定します。
- 結果をマージする際はソースサイト/ワークスペースを保持し、業務主キーで重複排除します。