株式会社インディバースの代表、エンジニアのDAIです。
監視において、「見逃しと誤検知の問題」にちょうど取り掛かっているのですが、
良い資料がネットに見当たらなかったので、社内共有用もかねてのメモです。
TL;DR
- 監視において、エラーの見逃しと誤検知を放っておくと, プロダクションのコードに対してのバグ混入率が増える
- その結果、サービスの信頼性が落ち、サービス自体の運営が厳しくなる
- 監視における見逃しと誤検知の問題に対して、どういう対処をすべきかについて解説します
見逃しと誤検知
- 見逃し = False Negative = 偽陰性
- 誤検知 = False Positive = 偽陽性
監視におけるFalse Negativeとは
- 仕様が間違っているものに対して、監視ではokを出してしまっている状態
- つまり、「エラーを見逃している状態」
緊急地震速報に例えると
- 大きめの地震が起こっていたのに-> 何か問題が起こった時に
- 緊急地震速報がならず、地震が来たことに気づかない -> 気付かないので
- 津波が来ているのに、逃げ遅れる -> 対応できない
False Negativeの例
- データのインポート処理のロジックをスケジューラーで動かしていた。データがインポートされていると思っていたが、静かにジョブが死んでいた。
- その結果エラーは通知されておらず、プロダクションのコードに影響が起こっていたことに気づかなかった
- 結果、顧客の環境で重大なエラーが起こっていた
監視におけるFalse Negativeが多い開発組織では何が起きるか
- クリティカルなエラーが起こっていても、誰も気づけない
- その結果プロダクションのコードに重大なエラーが入る
- その結果顧客が解約する
- サービスの存続ができなくなる
False Negativeに対する対応方針
- エラーの握りつぶしを極力止めるようにして、エラーが発生したらちゃんとraiseされるようにする
# NG
def Parent
end
def Child < Parent
def execute
# NG 雑に全てのエラーを握りつぶすと、予想外のエラーが通知されない
rescue StandardError => e
Rails.logger.debug(e)
end
end
# GOOD
def Parent
end
def Child < Parent
def execute
# OK 想定されるエラーのみrescueして対応する
# それ以外のエラーはちゃんとraiseされるようにする
rescue ArgumentError => e
# 引数間違っていた時の対応処理
end
end
- 親クラスで、キャッチできなかったエラーは全部拾って、監視システムに投げられる体制にする(raiseされたエラーが監視システムへ飛ばされる状態を作る
# NG
def Parent
end
def Child < Parent
def execute
# NG
# 想定されないエラーが起こった時に、エラーが監視システムに通知されない
rescue ArgumentError => e
# 引数間違っていた時の対応処理
end
end
# NG
def Parent
end
def Child < Parent
def execute
rescue ArgumentError => e
# 引数間違っていた時の対応処理
# NG
# 子クラスで実装すると、毎回エラーをraiseする処理作らないといけないので面倒くさい
rescue StandardError => e
Sentry.capture_exception(e) if Rails.env.production?
end
end
# OK
def Parent
# 親クラスで子クラスの拾いきれなかったエラーはまとめて監視システムへ通知する ※Sentryは監視ツール
rescue_from StandardError => notify_error_to_sentry(e)
def notify_error_to_sentry(e)
Sentry.capture_exception(e) if Rails.env.production?
end
end
def Child < Parent
def execute
rescue ArgumentError => e
# 引数間違っていた時の対応処理
end
end
False Positive(偽陽性)とは
- 仕様は合っているのに、監視ではNGを出している状態
- 間違っていない問題に対して、エラーだと認識して誤検知している状態
緊急地震速報に例えると
- 全く地震が起こってないのに、緊急地震速報が毎日流れているような状態で、いざ大きい地震が起こった時
- 誤検知だと判断して無視するので
- 津波が来ているのに逃げ遅れる
監視におけるFalse Positiveの例
- 外部サービスにスクレイピングしてCSVを取得するスクリプトで、csvが存在しない場合はcsvをダウンロードしないのだが、その仕様を想定せずSeleniumでdom指定した結果、エラーがraiseされた
- CSVが存在しないときにダウンロードできないというビジネス的な仕様としては正しいが、エラーがraiseされ続けている状態になる
監視におけるFalse Positiveを放っておくと
- エラーが毎日通知される
- その結果、他の重要なエラー通知を見逃す
- 重要なエラーが出ているのに、気づけないため、プロダクションコードにクリティカルなエラーが混入する
監視におけるFalse Positiveに対する対応方針
- 既にアラートが出ているエラーに対するエラーハンドリング、もしくは修正を行い、新規のエラーがない状態にする
- 即時での修正が難しい場合、最低限起票しておいて、対応方針を決めておく
最後に
Railsエンジニアを採用中です!
Wantedlyからカジュアル面談よろしくお願いします!