# リアルタイム アイデンティティログテーブル

リアルタイムのIDステッチングは、受信したIDがどのプロファイルに属するかを判断します。アイデンティティログテーブルはその判断の1つ1つをクエリ可能な行として記録するため、プロファイルの状態がおかしいときには、どのキーがバリデーションに失敗したか、どのIDが統合を引き起こしたか、そしてプロファイルが関連付けの上限でどのIDを失ったかを、SQLで突き止められます。

この記録は2つのテーブルが担います。`id_changes` テーブルは、200件の関連付け上限での排出を含め、アイデンティティグラフへのすべての変更を記録します。`validation_failures` テーブルは、受信イベント上でバリデーションに失敗し、そのためステッチングから除外されたキー/値のペアを記録します。どちらも標準のインジェストパイプラインを経由して書き込まれるため、通常は行を生成したイベントから1分以内にクエリできるようになります。

このページは、各テーブルのカラムと、よくある疑問に答えるクエリのリファレンスとしてご利用ください。スループットやエラーを扱うDatadogダッシュボードについては、[リアルタイム オブザーバビリティとログ](/ja/products/customer-data-platform/real-time/real-time-observability-and-logs) を参照してください。`activations` テーブルについては、[リアルタイムでトリガーされたアクティベーションログの確認](/ja/products/customer-data-platform/real-time/reviewing-real-time-triggered-activation-logs) を参照してください。

## 何がいつ記録されるか

`id_changes` テーブルと `validation_failures` テーブルは、正常なトラフィックの逐次的なトレースではなく、アイデンティティの変更と例外を記録します。どのテーブルが行を受け取るのか、そしてどのような場合には何も書き込まれないのかを把握することが、これらを診断に使えるものにしています。

| 状況  | テーブル  | そこからわかること  |
|  --- | --- | --- |
| イベントがプロファイルを作成、統合、または削除した | `id_changes` | アイデンティティグラフの履歴：どのプロファイルがどのように変更されたか |
| イベントが200件の関連付けを保持するプロファイルにステッチングされた | `id_changes` | 空きを作るためにどのIDが排出されたか |
| 受信イベント上のキー/値のペアがバリデーションに失敗した | `validation_failures` | どのペアが拒否されたか、およびそれぞれの理由 |
| 設定が正しく、上限にも達していない | どちらにも記録されない | 何も書き込まれません。`validation_failures` テーブルが空であることは、キーが有効であることを意味します |


正常で安定した設定では、バリデーションの失敗も排出も発生しません。`validation_failures` に行が蓄積している場合は、トラッキングの実装、バルクアップロード、キー名といった上流のどこかに修正が必要なことを示しています。これらは通常の稼働状態ではありません。

イベント処理パスでのアイデンティティログはすべてのインスタンスで有効になっており、オプトインは不要です。パーソナライゼーションリクエストパスでのログは個別に扱われます。[パーソナライゼーションパスのログ](#%E3%83%91%E3%83%BC%E3%82%BD%E3%83%8A%E3%83%A9%E3%82%A4%E3%82%BC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%91%E3%82%B9%E3%81%AE%E3%83%AD%E3%82%B0) を参照してください。

## ライブトラフィックは決してブロックされない

リアルタイムのキーバリデーションは、ライブリクエストを拒否することはありません。無効なキーを含むイベントであっても処理されます。これは、リクエストを拒否すると訪問者が閲覧しているページの表示が遅れたり壊れたりするためです。無効なペアはステッチングから除外され、イベントの残りの部分は処理が進み、`validation_failures` に行が書き込まれます。

## id_changes テーブル

`id_changes` の各行は、アイデンティティグラフへの1件の変更を記録します。`profile_change_type` カラムはそれがどの種類の変更であったかを示し、他のどのカラムに値が入るかを決定します。

| カラム  | 型  | 説明  |
|  --- | --- | --- |
| `time` | int | 行が出力された時刻（Unixエポック秒）。`TD_INTERVAL` または `TD_TIME_RANGE` でフィルタリングします。 |
| `event_type` | string | このテーブルの行では常に `id` です。 |
| `reactor_instance_id` | string | 行を出力したリアルタイムインスタンス。 |
| `profile_change_type` | string | 変更の種類。[プロファイル変更タイプ](#%E3%83%97%E3%83%AD%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%A4%89%E6%9B%B4%E3%82%BF%E3%82%A4%E3%83%97) を参照してください。 |
| `current_rid` | string | 変更が発生したプロファイル（UUID）。 |
| `current_id_attributes` | `array<string>` | トリガーとなったイベントが持ち込んだIDのうち、そのプロファイルにまだ存在していなかったもの（`keyname:value` 形式の文字列）。 |
| `key_values` | string | 変更後のプロファイルの関連付けの全体像（カンマ区切り）。`profile_ids_evicted` の行では `NULL` です。 |
| `merged_rids` | `array<string>` | 統合によって `current_rid` に吸収されたプロファイル。`profile_updated_by_stitching` の行に値が入り、それ以外は `NULL` です。 |
| `evicted_ids` | string | 200件の関連付け上限内に収めるために削除されたIDのJSON配列。`profile_ids_evicted` の行に値が入り、それ以外のすべての行では `NULL` です。 |
| `td_rt_tracking_id` | string | 元のイベントがトラッキングIDを持っていた場合、その値。持っていない場合はnullです。 |


### プロファイル変更タイプ

| 値  | 意味  |
|  --- | --- |
| `profile_added` | イベントが既存のどのプロファイルにも一致しなかったため、新しいプロファイルが作成されました。 |
| `profile_updated_by_stitching` | イベントが既存のプロファイルに一致し、そのプロファイルが受信したIDを吸収しました。`merged_rids` に統合されたプロファイルが列挙されます。 |
| `profile_deleted_by_stitching` | 統合によって別のプロファイルに取り込まれたため、このプロファイルが削除されました。 |
| `profile_ids_evicted` | 受信したIDを追加すると200件の関連付けを超えるため、IDが排出されました。`evicted_ids` に排出されたIDが列挙されます。 |


プロファイルは同時に作成・更新・削除のいずれか1つしか行われないため、トリガーとなったイベント1件につき `profile_added`、`profile_updated_by_stitching`、`profile_deleted_by_stitching` のうち厳密に1つが書き込まれます。`profile_ids_evicted` の行は、同じイベントに対する `profile_updated_by_stitching` の行に*加えて*書き込まれ、両者は同じ `current_id_attributes` を持ちます。この共通の値が、2つの行を対応付ける手がかりになります。

統合の読み取り方
`current_id_attributes` には、トリガーとなったイベントが持ち込んだIDのうちそのプロファイルにとって新しかったものだけが入り、最終的にプロファイルに存在するすべてのIDが入るわけではありません。この違いがあることで、統合が起きた*こと*だけでなく、統合が起きた*理由*まで判断できます。統合後の全体像は `key_values` に入ります。

### 200件の関連付け上限

1つのプロファイルが保持できる関連付けは最大200件で、統合されたプロファイルとIDの両方が数に含まれます。受信イベントによってプロファイルがこの上限を超える場合、空きを作るために優先度の低い関連付けが排出され、`profile_ids_evicted` の行に削除された内容が記録されます。

排出の対象は、そのプロファイルが既に保持していたIDだけでなく、受信イベントが持ち込んだIDである場合もあります。受信したIDが必ず枠を確保できるとは限りません。どちらの種類も `evicted_ids` にまとめて現れます。

同じ `current_rid` で排出が繰り返されている場合、それは過剰ステッチング（オーバーステッチング）が起きていることを示す最も有力な手がかりです。過剰ステッチングとは、IDグラフのルールが複数のユーザーで共有される値でステッチングを行い、無関係な人物を1つのプロファイルにまとめてしまう状態です。上限付近で入れ替わりを繰り返しているプロファイルは一貫したアイデンティティを保持できていないため、これらの行はその原因となったルールを見直すべきシグナルとして扱ってください。

## validation_failures テーブル

`validation_failures` の各行は、受信イベント1件に対応します。そのイベントに無効なペアが複数含まれていた場合、ペアごとに行が分かれるのではなく、すべてが1つの行に現れます。

| カラム  | 型  | 説明  |
|  --- | --- | --- |
| `time` | int | 行が出力された時刻（Unixエポック秒）。`TD_INTERVAL` または `TD_TIME_RANGE` でフィルタリングします。 |
| `event_type` | string | このテーブルの行では常に `validation` です。 |
| `reactor_instance_id` | string | 行を出力したリアルタイムインスタンス。 |
| `invalid_keys` | `array<string>` | 拒否されたペアごとに1要素。各要素は `key`、`value`、`reason` を持つJSONオブジェクトで、たとえば `{"value":"12345","key":"customer_id","reason":"Value is not a string."}` のようになります。配列をアンネストしたうえで、`json_extract_scalar` で各フィールドを取り出します。 |
| `td_rt_tracking_id` | string | 元のイベントがトラッキングIDを持っていた場合、その値。持っていない場合はnullです。 |


### バリデーション失敗の理由

`invalid_keys` の各エントリの `reason` フィールドには、次のいずれかのメッセージが入ります。

| 理由  | 対処方法  |
|  --- | --- |
| `Key is not present in the config file.` | イベントが、リアルタイム設定に定義されていないキー名を送信しました。そのキーを設定に追加するか、送信を停止してください。 |
| `Key name case does not match a configured key.` | キー名が大文字・小文字の違いを除いて設定済みのキーと一致しています。たとえば、設定済みの `user_id` に対して `User_ID` が送信された場合です。トラッキングコード側で大文字・小文字を修正してください。 |
| `Value is not a string.` | 値が数値、真偽値、またはオブジェクトとして到着しました。アイデンティティの値は文字列として送信してください。数値のIDは引用符で囲む必要があります。 |
| `Value is empty.` | 値が空、null、または存在しませんでした。多くの場合、トラッキングスクリプトが値の入る前の属性を読み取っています。 |
| `Value does not meet the valid_regexp for this key.` | 値が、そのキーに定義された `valid_regexp` を満たしませんでした。データが不正か、パターンが厳しすぎるかのいずれかです。 |
| `Value is included in invalid_texts for this key.` | 値が、そのキーの `invalid_texts` のエントリに一致しました。多くの場合、`null` や `undefined` といったプレースホルダーが文字列リテラルとして送信されています。 |


## テーブルの保存場所

`id_changes` テーブルと `validation_failures` テーブルは、`activations` テーブルと同じく、親セグメントのリアルタイムデータベース `cdp_audience_<parent_segment_id>_rt` にあります。**Data Workbench** > **Queries** > **New Query** から、Trinoエンジンを使用してクエリします。

イベントが `td_rt_tracking_id` を持っている場合、その値はそのイベントが生成したすべての行に現れます。そのため1つの値で、アクティベーション・アイデンティティ・バリデーションにわたるイベントの処理結果を追跡できます。付与方法については、[リアルタイム オブザーバビリティ イベント トラッキング](/ja/products/customer-data-platform/real-time/real-time-observability-event-tracking) を参照してください。

これらのテーブルに対してすぐに使える診断クエリについては、[リアルタイムデバッグ用のAIスキル](/ja/products/customer-data-platform/real-time/real-time-ai-debugging-skills) を参照してください。

## ログ量と保持期間の管理

`id_changes` テーブルと `validation_failures` テーブルは、デフォルトでは無期限に保持されるインジェスト済みの行を保持します。`id_changes` はアイデンティティグラフのすべての変更を記録するため、大規模なバルクIDグラフのアップロードでは、対象となったプロファイル数に比例して行が書き込まれます。また、トラッキングの実装に誤りがある場合、イベントを送信するペースで `validation_failures` が埋まっていく可能性があります。

これを抑えるには、次の2つの方法があります。

- **根本原因を修正する。** バリデーションの失敗も排出も、どちらも望ましくない結果を表しています。設定の誤りを修正すれば、行の書き込みは止まります。
- **テーブルに有効期限を設定する。** テーブル単位の有効期限を設定し、調査対象の期間より古い行が自動的に削除されるようにします。[テーブルからのデータの期限切れ設定](/products/customer-data-platform/data-workbench/databases/expiring-data-from-a-table) を参照してください。


有効期限は自動設定されません
どちらのテーブルにも、デフォルトでは保持期間が設定されていません。設定する前に、調査でどこまで過去にさかのぼる必要があるかを判断してください。バリデーションの失敗には短い期間が適しますが、`id_changes` のアイデンティティグラフの履歴は、より長く保持する価値がある場合が多くあります。

## パーソナライゼーションパスのログ

パーソナライゼーションリクエストパスでのアイデンティティログは、イベント処理パスとは別に制御され、デフォルトでは無効です。パーソナライゼーションリクエストの処理中にこれらの行を出力すると、レイテンシに敏感なパスに処理が追加されるため、一律ではなくインスタンス単位で有効化されます。調査のために有効化が必要な場合は、カスタマーサポートにお問い合わせください。

## 次のステップ

- [リアルタイム IDステッチングの概要](/ja/products/customer-data-platform/real-time/real-time-id-stitching-overview) — ステッチングがどのIDをまとめるかを判断する仕組み。
- [リアルタイムデバッグ用のAIスキル](/ja/products/customer-data-platform/real-time/real-time-ai-debugging-skills) — これらのテーブルに対する診断クエリを生成してくれるスキル。
- [リアルタイム オブザーバビリティとログ](/ja/products/customer-data-platform/real-time/real-time-observability-and-logs) — スループット、レイテンシ、エラーを確認するDatadogダッシュボード。