🔕

ノイズゼロ監視: 「鳴らない監視」ではなく「意味のある監視」を設計する

に公開

はじめに

こんにちは。普段はNext.jsのフロントエンドアプリと、Go製のGatewayアプリ(各マイクロサービスへリクエストを転送する役)を運用しています。どちらも典型的なALB→アプリ構成です。

本記事のテーマは「鳴らない監視」ではなく「意味のある監視」。とくにGateway・フロントエンドで自サービスの責だけを正しく検知務し、上流(upstream)由来のノイズを遮断する設計にフォーカスします。

1. DatadogでALBの5xxを見るならelb_5xxを使う

なぜtarget_5xxが今回のケースでは向かなかったのか

aws.applicationelb.httpcode_target_5xx自体が悪いわけではありません。
ただ、私たちの環境ではアプリ側に別途モニターがあり、同じ障害で二重アラートになるという課題がありました。
もしアプリ側のモニターが存在しない場合は、target_5xxを使うのも有効な選択肢です。

一方で、aws.applicationelb.httpcode_elb_5xxはALB自身の異常(TLS/接続/容量/構成ミスなど)に限定して検知できるため、役割を分離してノイズを減らせます。

項目 httpcode_target_5xx httpcode_elb_5xx
検知対象 ターゲット(= アプリ)が返した 5xx ALB 自身が返した 5xx
代表的な原因 アプリケーションバグ、依存サービス障害 TLSエラー、接続上限、容量不足、ALB構成ミス
アプリ側モニターとの関係 アプリ側でも同じ失敗を検知するため二重アラートになる場合あり アプリとは独立して検知できる
向いているケース アプリのモニターがない場合、ALB経由でまとめて検知したい場合 アプリとインフラのアラートを明確に分離したい場合
ノイズの発生しやすさ アプリ側モニターと併用すると多め 少なめ

Datadogモニターのクエリー例(ALB自身の異常だけ)

sum:aws.applicationelb.httpcode_elb_5xx{...}.as_rate() > 1

つまり、アプリの責務である失敗はアプリで検知し、ALBはALB固有の異常だけを監視するという役割分担を徹底することで、ノイズを大幅に削減でき、障害発生時の原因特定や対応判断を格段に速く行えるようになります。

2. 「上流エラーで鳴らさない」を設計に落とす

Frontend(主にCSR時のエラー)とGatewayアプリは、とくに上流の失敗がノイズ源になります。

2-1. Frontend(CSR)のソフトフォールバックはユーザー体験が守られている限り、ページャーは鳴らさない

CSR構成では、上流APIの一部が失敗しても、フロントエンドが200を返す場合があります。
これはエラーを優雅に処理し、UIを部分非表示やプレースホルダーで代替している状態で、ユーザーは想定どおりの体験を得ています。

つまり、このケースは「アプリの正常動作の一部」であり、監視アラートにするとノイズになります。

2-2. Gatewayの転送完了は成功扱いにする

結論:上流の障害は上流のアラートだけが鳴る。Gatewayは自分の失敗でのみ鳴らせる

Gatewayの責務は正しく転送すること。
上流が遅延/障害で504(timeout)になるのは「Gatewayの責務外」なので、ページャー対象から除外します。
一方で、Gateway自身の不具合(例: ルーティング/ミドルウェア/リミット超過など)で発生する502/503/500は鳴らすべきです。

私はAPMのトレースメトリクスを使い、resource_nameでGateway自身の内部エンドポイントをフィルタしつつ、http.status_code:504を除外して自サービス起因の5xxだけでモニターを作りました。

Datadog モニタークエリの例

min(last_5m):default_zero(sum:trace.http.request.errors{...,!resource_name:/internal/*,!http.status_code:504}.as_rate()) >= ${local.threshold}
  • resource_name:/internal/*はGatewayの内部処理用パス(転送ではない)を除外して誤検知を防止
    • ※内部処理エラーは別モニターにて監視
  • !http.status_code:504 は上流タイムアウトを除外(Gatewayは転送まで成功しているため)
  • これにより上流障害は上流のモニターだけが鳴り、Gatewayは自分の失敗でのみ鳴るようになります

3. パス別モニターのノイズ低減(小さい分母問題対策)

APIの各パスごとにエラーレートを監視している場合、リクエスト数が少ないエンドポイントで過剰にアラートが鳴ることがあります。

例:

  • あるパスで5分間にたった1リクエスト → それがエラーになると、エラーレートは100%。
  • sum(last_5m)で集計していると、このようなたまたまなエラーを拾ってしまい、実際のユーザー影響がないのにページャーが鳴ってしまう。

そこで、時間集約をsum() → min()に切り替えました。min(last_5m)を使えば、短期的に跳ねたパスを下限値として扱うため、一時的なブレに強くなり、トラフィックが少ないパスの誤検知を減らせます。

https://docs.datadoghq.com/monitors/types/metric/?tab=threshold

  • 高トラフィックな主要APIは sum() のままでOK(影響度が高いため検知を優先)
  • 一方で、疎なパスは min() を使うことでノイズが激減し、より意味のある失敗だけを拾えるようになりました

まとめ(TL;DR)

  • ALBの5xxはelb_5xxを見る(target_5xxはアプリ側の失敗で二重アラート化しがち)
  • 上流(outbound)失敗ではページャー鳴らさない(Frontend CSRのフェイルソフト/Gatewayの転送完了は成功扱い)
  • リクエスト数が少ないAPIパスはsumではなくminにしてノイズを抑える

この記事の方針をベースに、タグ設計やモニタ粒度を調整してみてください。
内容について、ご意見やツッコミもお寄せいただけると嬉しいです🥰

GitHubで編集を提案

Discussion