コンテンツにスキップ

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 対象の workspaceUUIDtargetRegion を取得します
サイト設定の照会 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"
  }
}

次のルールに従う必要があります。

  1. 空でない workspaceUUIDsworkspaceUUID より優先されます。workspaceUUIDs が空配列または null の場合は workspaceUUID にフォールバックします。両方のフィールドを同時に渡さないことを推奨します。どちらも渡さない場合は現在のワークスペースをクエリします。
  2. サイト間クエリでは、各 query の query オブジェクト内に同じ targetRegion を明示的に渡してください。リクエストの最上位でのみ渡すのは避けてください。
  3. 1つのリクエスト内のすべての queries[*] は1つのサイトのみを指すことができます。複数のサイトをクエリする場合はリクエストを分割し、クライアント側で結果をマージしてください。
  4. workspaceUUIDs: ["*"] または workspaceUUID: "*" は、指定した targetRegion 内で現在のワークスペースが参照できるすべての認可ワークスペースをクエリすることを意味します。この場合、targetRegion は必須です。
  5. targetRegion は、認可元ワークスペースが属するサイトの regionCode であり、toRegionCode ではありません。
  6. 同じリクエスト内の複数の対象ワークスペースは、同じ targetRegion に属している必要があります。対象ワークスペースをサイトごとにグループ化してからリクエストを構築することを推奨します。

時間範囲とページネーションカーソル

query.timeRange の開始時刻と終了時刻は、同じ単位(秒、ミリ秒、マイクロ秒、ナノ秒)を使用する必要があります。単位を混在させると HTTP 400 と ft.TimeRangeUnitMismatch が返され、サーバー側で自動修正は行われません。この記事のリクエスト例ではミリ秒を使用しています。実際のクエリ時間範囲に置き換えてください。

cursor_timecursor_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[*].workspaceUUIDquery.workspaceUUID または query.workspaceUUIDs の値として使用します。
  • そのワークスペースが属するグループの content[*].regionCode(または同じデータ項目の regionCode)を query.targetRegion として使用します。
  • toWorkspaceUUID をクエリ対象に使用しないでください。これは通常、現在の API Key が属する認可先ワークスペースです。
  • toRegionCodetargetRegion として使用しないでください。これは通常、現在のサイトです。
  • 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&regionCode=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_aregion_b を同時にクエリする必要がある場合は、それぞれ別々に2回リクエストを送信します:

対象リスト
  ├─ region_a: [wksp_a1, wksp_a2] -> リクエスト 1
  └─ region_b: [wksp_b1]          -> リクエスト 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 のみを返す

同じ結果項目が次の条件をすべて満たす場合にのみポーリングします:

content.data[i].is_running === true
かつ
content.data[i].async_id が空ではない

ID を同じ配列インデックスの queries[i].async_id に戻し、qtypequery.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_runningfalse の場合、そのタスクは終了しています。呼び出し側は最終データを読み取り、すぐにポーリングを停止してください。レスポンスオブジェクトに async_id フィールドがまだ含まれているかどうかに関わらず、次の新しいクエリでは古い ID を省略する必要があります。

次の動作は誤りです:

  • 前回のタスクの async_id を固定値として以降のすべてのリクエストに書き込む。
  • DQL、時間範囲、ワークスペース、または targetRegion を変更した後も古い ID を使い続ける。
  • content.data[0].async_idqueries[1] に入れる。
  • async_idsearch_aftercursor_timecursor_token の代わりにページングに使用する。

is_running=trueasync_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 リクエストでの複数サイトにわたるクエリをサポートしていません。クライアント側でマージする際は次の点を推奨します:

  1. 最初に targetRegion ごとに対象ワークスペースをグループ化します。
  2. サイトごとにリクエスト、ページング、非同期タスクの処理を独立させます。
  3. 各バッチの結果に、sourceRegionqueriedWorkspaceUUIDs などのクライアントメタデータを追加します。複数ワークスペースのクエリでは、各レコードに信頼できるソースワークスペースが必ず含まれるとは限らないため、バッチ全体を特定の sourceWorkspaceUUID としてタグ付けすることはできません。1回のクエリで1つのワークスペースだけを対象にする場合にのみ、そのようにタグ付けできます。レコードレベルのソースが必要な場合は、ワークスペースごとにクエリするか、DQL でビジネス上信頼できるソースディメンションを返すようにしてください。
  4. ログ系の結果は timedate_ns と安定した一意な識別子で並べ替えて重複排除します。メトリクス結果は、時間粒度、集計関数、タグセットが一致していることを確認してからマージしてください。
  5. いずれかのサイトが失敗した場合は、他のサイトの成功結果を保持し、サイトごとのエラー詳細を返してください。部分成功を全体の成功として扱わないでください。

よくあるエラー

エラーコード / 現象 原因 対応方法
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 を削除します。ページングは新しい非同期ライフサイクルから開始します。
  • ポーリングのバックオフ、全体タイムアウト、ページング上限、サイトごとのエラー処理を設定します。
  • 結果をマージする際はソースサイト/ワークスペースを保持し、業務主キーで重複排除します。

フィードバック

このページは役に立ちましたか?