「何が起きたか」ではなく「なぜそう動いたか」を残す
搬送ロボットが想定外の動きをして止まる。その後に説明を求められるのは、センサーが何を見ていたか、モデルが何を提案したか、誰が、あるいはどのコンポーネントがそれを許可したか、そして実際にはどう動いたか、の4点です。
ログやセンサ記録が大量に残っていても、この4つがつながっていなければ、一本の線としてはたどれません。監査ログの目的は、その線を残すことです。
デバッグログ、センサ記録、監査ログは用途が違う
ROS 2を例にすると、違いがはっきりします。
デバッグログ。 ROS 2のロギングは、DEBUGからFATALまでの重大度を持つメッセージを、コンソール、ディスク上のログファイル、ネットワーク上のトピックへ出力する仕組みで、出力先はノード単位で切り替えられます。中身は開発者の診断メッセージで、何を出すかは実装者の裁量です。
センサ記録。 rosbag2は、トピックやサービスに流れたデータを保存し、後から再生して再現・分析するためのツールです。
監査ログ。 違いは媒体ではなく、用途と記録内容にあります。診断メッセージやセンサー値だけでは、判断の理由や承認者は自動的には分かりません。ROS 2のロギングやrosbagを監査記録の運搬に使うこともできますが、その場合も、判断と承認を構造化したイベントとして出力する実装が要ります。監査ログとは、判断と因果を追跡するために、あらかじめ決めたイベントを、決めた項目で残す記録のことです。
記録項目は、追いたい問いで決まる
すべてを常に記録するのではなく、追跡したい問いに応じて行を選びます。
| 項目 | 目的 | 例 |
|---|---|---|
| task id / trace id | 1つの作業や指示に属するイベントをまとめる | 搬送ジョブ1件、ピッキング1回 |
| ref_event(参照イベントID) | どのイベントを受けて起きたかを明示し、因果をたどる | 許可イベントが参照する提案イベントのID |
| boot / session id | 再起動や再接続をまたぐ記録を区別する | 起動ごとに変わる識別子 |
| event id と seq | 発生源ごとの通し番号で欠損と順序を確認する | ノードごとの単調増加番号 |
| 発生時刻と時刻同期の状態 | 壁時計、単調時刻、同期のずれをそれぞれ持つ | UTC、起動からの経過時間、NTP/PTPのオフセット |
| 収集時刻 | 記録側が受け取った時刻を発生時刻と分けて持つ | 収集サーバーの受信時刻 |
| actor | 誰が、どのコンポーネントが、どのモデルが行為したか | 認識ノード、計画モデル、監督者のID |
| model / config / policy version | どの版の判断かを後から特定する | モデルのハッシュ、設定ファイルの版、許可ルールの版 |
| 入力の参照 | 判断の根拠になった入力を、実体ではなく参照で残す | フレームID、画像ハッシュ、bag内の位置 |
| 提案(action target とパラメータ) | モデルが何をしようとしたか | 目標位置、速度、把持力 |
| 判断(decision と reason) | 許可・拒否・修正と、その理由・適用ルール | 「速度上限超過のため修正」 |
| 実行結果(result) | 実際に送られた命令と、機体からのフィードバック | 送信した速度、到達位置、停止理由 |
構造の語彙は、OpenTelemetryのログデータモデルが参考になります。同モデルは、事象が発生した時刻と収集側が観測した時刻を別のフィールドとして持ち、トレースIDとスパンIDで関連するイベントを結び、正規化した重大度と属性を定義しています。ここで挙げた項目は、それを参考にした当社の設計例であり、公式の標準形式ではありません。
架空のイベント例
搬送ロボットが目標位置への移動を提案し、検証層が速度を修正して許可し、命令が送られ、しばらくしてから結果が届く。この流れを4つのイベントで書くと、次のようになります。時刻同期の状態のように各イベントで繰り返す項目は省いています。
[
{"trace_id":"job-4821","boot_id":"b-0f31","event_id":"plan-17","seq":17,"source":"planner",
"t_wall":"2026-09-21T03:12:08.412Z","t_mono_ns":8123456789012,
"actor":{"type":"model","name":"nav-planner","version":"sha256:9f3c…"},
"input_ref":{"frame_id":"cam0-77213","hash":"sha256:1a8e…"},
"proposal":{"action":"move_to","target":"dock-B","speed_mps":1.4}},
{"trace_id":"job-4821","boot_id":"b-0f31","event_id":"gate-9","seq":9,"source":"action-gate",
"t_wall":"2026-09-21T03:12:08.419Z","t_mono_ns":8123463901120,"ref_event":"plan-17",
"actor":{"type":"policy","name":"action-gate","policy_version":"v12"},
"decision":"modify","reason":"speed_limit_zone_C","result_params":{"speed_mps":0.6}},
{"trace_id":"job-4821","boot_id":"b-0f31","event_id":"exec-31","seq":31,"source":"base-controller",
"t_wall":"2026-09-21T03:12:08.430Z","t_mono_ns":8123474550301,"ref_event":"gate-9",
"command_sent":{"action":"move_to","target":"dock-B","speed_mps":0.6}},
{"trace_id":"job-4821","boot_id":"b-0f31","event_id":"exec-32","seq":32,"source":"base-controller",
"t_wall":"2026-09-21T03:12:41.902Z","t_mono_ns":8156946550301,"ref_event":"exec-31",
"result":{"status":"reached","position":"dock-B","motion":"stopped"}}
]
提案、許可(ここでは修正)、命令の送信、結果の取得が、それぞれ別のイベントとして追記されています。2件目以降は ref_event で直前のイベントを指し、許可されたことと、命令が送られたことと、その結果は、別々の事実として残ります。説明のための形式であり、特定の標準実装ではありません。
順序と因果は、時刻だけでは決まらない
複数の計算機とマイコンにまたがるシステムでは、壁時計はずれ、時刻と通し番号を組み合わせても因果までは確定できません。因果は、ref_event のような明示的な参照イベントIDでたどります。発生源ごとの通し番号と単調時刻は、その発生源の中での順序と欠損の候補を把握するために、壁時計と同期状態の記録は機器間の比較を補助するために使います。
再起動や再接続をまたぐ記録は boot / session id で区別し、順序が不明なイベントは不明のまま残して、推測で並べ替えません。OWASPのロギングに関する指針も、機器間の時刻同期を推奨しつつ、同期が難しい場合はオフセットや確度を記録する代替を挙げています。
保護と運用の設計
監査ログは、それ自体が攻撃と事故調査の対象です。設計の段階で次を決めます。
- 改ざん検知。 レコードごとの単純なハッシュは、ハッシュも書き換えられれば意味を持ちません。前のレコードのハッシュを含める連鎖も、丸ごと再計算されたり末尾を削除されたりし得るため、チェーンの検証値を別の管理先に定期的に固定します。署名を使う場合は鍵を機体の外で保護し、外部の保存先では変更・削除の権限を運用者と分離します。形式を整えるだけで真正性が保証されるわけではなく、これらは改ざんの検知であって防止の保証ではありません。
- アクセス分離。 ログの読み書きができる主体を、ロボットを操作する主体と分けます。ログへのアクセス自体も記録します。
- 保存と転送。 機体内の一時保存から外部への転送までの経路を暗号化し、転送後は追記のみの保存にします。
- 欠損検知。 通し番号の飛びと、定期的な生存信号で、記録の欠落を検出します。
- ログの停止と容量不足。 記録できない状態で運転を続けるか、停止するか、通知だけにするかを、用途ごとに事前に決めます。記録や転送の待ちで制御ループを無制限に止めない設計にし、記録処理の遅延・負荷と欠損時の動作を事前に検証します。記録できないことに気づけない状態が、最も避けたい状態です。
- 記録しないもの。 認証情報や鍵、必要のない個人情報は記録しません。人の顔を含む画像は、原画像ではなく参照とハッシュで残し、原画像の保持は定めた条件に限ったうえで、参照先にもアクセス権限と保持期間を設定します。保持期間は、調査・説明・再検証という目的と、自社に適用される要件から決めます。
最初の着手例
最初に決めるのは、追跡したい問いです。「なぜこの位置で止まったか」「なぜこの速度で動いたか」「誰が許可したか」のように具体的にして、3つほどに絞ります。問いが決まれば、必要なイベントと、上の表から選ぶ行も決まります。
次に、時刻とIDの方針を決めます。trace id の付け方、通し番号の発生源、同期状態の記録方法です。そのうえで、転送先、署名の鍵の置き場所、記録できないときの動作、保持期間を決めます。
これらを先に決める理由は単純で、そのとき記録していなかった判断や承認は、後から遡っては確認できないからです。運用が変われば項目の追加は起きますが、追加した項目が過去のイベントに現れることはありません。
この記録があると、異常時に入力・提案・判断・実行のどこで想定と違ったかを切り分けられ、モデルや設定の変更前後を同じ項目で比較でき、外部への説明と再検証の根拠が残ります。一方で、監査ログは事象の完全な再現や事故の防止を保証するものではありません。再現にはセンサ記録が、防止には設計と安全機構が、それぞれ別に必要です。
ご相談ください
異常が起きてから記録を足しても、そのとき残っていなかった判断や承認は復元できません。当社のAIシステム受託開発では、監査ログの設計を開発プロセスに組み込み、認識・判断・制御のどこで何が起きたかを追跡できるシステムをつくります。既存システムへの監査ログの追加や、記録項目の決め方についてのご相談は、お問い合わせフォームからお送りください。
参考資料
- Open Robotics, Logging and logger configuration, ROS 2 Documentation (Jazzy). 2026年9月21日確認。
- Open Robotics, Recording and playing back data, ROS 2 Documentation (Jazzy). 2026年9月21日確認。
- OpenTelemetry, Logs Data Model. 2026年9月21日確認。
- OWASP, Logging Cheat Sheet. 2026年9月21日確認。
記録項目、イベント例、保護と運用の方針は、上記資料を参考にした株式会社U-Recの設計例です。公式の標準形式や、特定の法定要件への適合を示すものではありません。