すべての記事

正情報が嘘になった瞬間──異常なしのログが信用できない理由

正情報が嘘になった瞬間──異常なしのログが信用できない理由

正情報が嘘になった瞬間──異常なしのログが信用できない理由

エラーなし。ログ正常。プロセス完走。でも「結果が信用できない」──壊れていたのはデータでも実装でもなく、判断を返さないシステムそのものだった。


① 導入:異常はなかった

スクレイパーが動いた。
ログにエラーはない。
プロセスは最後まで完走した。

でも、「結果が信用できない」

違和感だけが残った。

システムは正常に動作している。
異常検知は発火していない。
ステータスコードは 200 OK

それなのに、運用者は確信する。
「これは嘘だ」と。


② 何が起きていたか(事実だけ)

観測された事実

• master_controller.log: SUCCESS

• 商品データ抽出件数: 0

• スナップショット更新: なし

• スクレイパー実行: 正常終了

• 差分検知システム: 起動せず

評価も解釈もしない。
時系列の事実だけ。

# ログの該当箇所
[INFO] [hoge_scraper] 実行開始
[INFO] [hoge_scraper] 成功 (12.3s) - 0件取得
[INFO] スナップショット: タイムスタンプのみ更新

success=True が返ってきた。
でも、count=0

システムは「成功した」と主張している。
でも、業務的には「何も起きていない」。


③ 当時の判断(ここが肝)

正直に書く。

当時の私の認識:

  • 「抽出できた = 成功」
  • 「0件 = 失敗」
  • success を返せば上位は判断できる」

この判断は、当時は合理的だった

データ抽出器 (StableDataExtractor) の実装を見ると:

def extract_stable(self, output: str, script_name: str) -> Dict[str, Any]:
    # ... 商品データ抽出処理 ...
    
    product_count = len(products)
    success = product_count > 0  # ← ここ
    
    return {
        'count': product_count,
        'success': success,  # ← 0件なら False
        'products': products
    }

コードは正しい。
ロジックも正しい。
抽出できなければ False を返す。

問題ない。


④ 嘘が始まった瞬間

核心。

「嘘」とは、間違った情報のことではない。
正しい情報が、誤った判断を導く状態を指す。

システムが何を返していたか

1. Extractorsuccess=True を返した

2. master_controller がそれを信じた

3. でも業務的な 「何も起きていない」 が表現できなかった

正しい情報が、
判断に使えない形で流れ始めた。

success=True という情報は正しい。
「実行は完了した」という意味では。

でも、上位システム(master_controller)が受け取る情報は:

{
  'count': 0,
  'success': True,  # ← これを信じる
  'products': []
}

count=0 という情報も正しい。
「取得件数はゼロだった」という意味では。

でも、それが「正常な結果」なのか「異常な状態」なのか
この情報だけでは判断できない。

「嘘をついた」という言葉を初めて使う。

正しい情報が、判断を誤らせる形で伝わる。
それは「嘘」と何が違うのか。


⑤ 本質:壊れていたのは何か

答えはこれ。

何が壊れていたのか

データ → 壊れてない

実装 → 壊れてない

処理 → 壊れてない

壊れていたのは、「成功の定義が1bitだったこと」

successTrueFalse しかない。

でも、実際の業務では:

  • 「実行は成功したが、結果は空」
  • 「データは取得できたが、品質不明」
  • 「処理は完了したが、判断はできない」

こういう状態が存在する。

1bit の情報では、この状態を表現できない。

# 1bit の世界
success = True   # ← これだけ
success = False  # ← これだけ

# 実際に必要だった情報
{
  'execution_status': 'completed',  # 実行は完了した
  'data_acquired': False,           # データは取れなかった
  'business_valid': False,          # 業務判断としては無効
  'requires_alert': True            # アラートが必要
}

正情報は、処理の最後で勝手に揃わない。


⑥ 一般化(製造業DXに接続)

ここで初めて外に広げる。

製造業でも同じ構造が繰り返される:

  • 在庫データは更新された。でも、品質は確認されていない。
  • 生産工程は完了した。でも、検査は未通過。
  • AIの推論は成功した。でも、業務判断としてはNG。

データは正しい。
でも、意味が揃っていない

これはシステムの問題ではない。
判断を返さない設計 の問題だ。

# ダメな例
status = execute_process()
if status == "success":
    log("処理成功")  # ← これだけ

# 正しい例
result = execute_process()
if result.execution_completed and result.data_valid and result.business_ready:
    log("処理成功: 業務判断可能")
elif result.execution_completed and not result.data_valid:
    alert("処理完了: データ異常検知")  # ← 判断を返す
else:
    alert("処理失敗")

⑦ 結論

正情報は、処理の最後で勝手に揃わない。

判断を返さないシステムは、
正しく動いていても、
信頼されなくなる。

壊れていたのは、実装でもデータでもなく、
「成功とは何か」を定義する構造 だった。


次回予告

「ロックを入れても壊れる理由──同時実行されているのは"データ"ではなく"判断"だった」

排他制御は完璧だった。
WALモード有効。トランザクション保証。
でも「同じ商品に2回通知」が起きた。

壊れていたのはデータの整合性ではなく、
判断のタイミングだった。