devops infinity symbol

本ポストでは、New Relic のサービスレベル管理機能にて、サービスレベル (SLI/SLO) に関連するアラートについて記載いたします。
スタートガイド SLIとSLO の作成 などのドキュメントをご参考にサービスレベルを作成いただいたあとに、アラートを設定したが挙動が認識と異なるというような質問をいただくことがございます。デフォルトで設定される各アラート設定の内容につきまして、解釈を記載いたします。

また、本内容は後編となります。前編の New Relic サービスレベル管理のセカンドステップ (前編) では、サービスレベルの関連データ (表示ウィジェット) について記載しています。データやチャートの内容につきまして、前編をご参照ください。

サービスレベル関連アラート

本ブログ執筆時点 (2024/06) では、下記の 4つのアラートを作成することができます。

  • Fast-burn rate
  • Slow-burn rate
  • Error budget consumption
  • SLO compliance

デフォルトでは、設定された SLO の期間、目標値から閾値などが算出され、ワンクリックで作成できます。

とはいえ、それらのアラート設定の正確な内容や自動計算された閾値の算出方法も知りたいというご要望はあるかと思います。 作成されたアラート設定内容の視点で詳細を記載いたします。

また、各アラート設定は 対象サービスレベル > Summary または Alert conditions > 上部の Create an alert よりご確認いただけます。

サービスレベルの設定例について

New Relic サービスレベル管理のセカンドステップ (前編) で作成したサービスレベルを利用して、関連アラートを作成します。

前編にてサンプルとして作成したサービスレベルの概要は下記となります、詳細を確認されたい場合は ステップ1> SLI/SLO 設定例 をご確認ください。

  • SLO 期間: 7日間
  • SLO ターゲット: 98.5%
  • SLI 対象: Synthetic Ping モニター (周期1分)
  • SLI Valid: モニター試行
  • SLI Good: 成功したモニター かつ 応答時間が 2.4秒以下

後編の内容では、SLO 期間とターゲット値を閾値の算出に利用します、SLI に関する内容は特に利用しません。

サービスレベルのデータについて

New Relic サービスレベル管理のセカンドステップ (前編) でもを記載していますが、サービスレベルの関連チャートやアラート用の元データは サービスレベル作成後に生成されるようになる newrelic.sli.valid または newrelic.sli.good, bad という Metric データが利用されます。

設定例の場合、もととなるイベントは Synthetic モニターの SyntheticCheck にインジェストされたデータとなりますが サービスレベル対象が利用するデータは、上記をトリガーとして SLI 条件で評価された Metric の newrelic.sli.{valid, good, bad} データで、1分単位の集計されたデータとして保存されます。

SyntheticCheck では、いつ行われたか、成功失敗、応答時間や応答量などの個別の結果が記録されますが、newrelic.sli.* は 1分間ごとのデータで valid なイベントは N 回、good なレスポンスは M 回などの集計された回数データで記録されます。

そしてこれらの newrelic.sli.* は各アラートのソースデータとして利用します。

Fast-burn rate

エラーバジェットの消費量が急激に増加し、修正しなければエラーバジェット使い果たしてしまうような状況を検知することができます。 デフォルトでは、50時間で初期エラーバジェットが消費されてしまうようなペース、つまり、1時間で 初期エラーバジェットの 2% が消費されるような状況が発生した際に閾値違反と判定されます。

デフォルトのアラート設定は以下のようになります。閾値の値が サービスレベル設定値を参照して自動で計算されます。 (サービスレベル設定で Good を選択した場合と Bad を選択した場合で アラート用 NRQL が異なるため、両方記載しています。)

  • アラート用 NRQL (Good request の場合)
FROM Metric
SELECT 100 - clamp_max(sum(newrelic.sli.good) / sum(newrelic.sli.valid) * 100, 100) AS 'Error rate'
WHERE entity.guid = 'この SLI の GUID'
  • アラート用 NRQL (Bad request の場合)
FROM Metric
SELECT 100 - clamp_max((sum(newrelic.sli.valid) - sum(newrelic.sli.bad)) / sum(newrelic.sli.valid) * 100, 100) AS 'Error rate'
WHERE entity.guid = 'この SLI の GUID'
  • Window Duration: 60分
  • Sliding Window: 1分
  • Streaming Method: Event Flow (Delay: 2分)
  • No Gap Filling/No Evaluation delay
  • 閾値 (critical): result >= "自動計算された閾値" at least once in 1分

まずは Window Duration が 60分で Sliding Window が 1分という点ですが、これは平易にいうと、60分ごとのデータを 1分ごとに評価していることを意味します。

具体的には、下記のような 60分の時間幅で集計値が 1分おきに求められていきます。

  • 12:00 - 13:00 の 60分間に受信したデータ (newewrelic.sli.*) で集計値 (シグナル値) を算出
  • 12:01 - 13:01 の 60分間に受信したデータ (newewrelic.sli.*) で集計値 (シグナル値) を算出
  • 12:02 - 13:02 の 60分間に受信したデータ (newewrelic.sli.*) で集計値 (シグナル値) を算出
  • 12:03 - 13:03 の 60分間に受信したデータ (newewrelic.sli.*) で集計値 (シグナル値) を算出
  • ...

また、Streaming Method が Event Flow となっているので、後続データが定期的に存在しないとデータは集計されません。つまり不定期なデータや特定時間帯はイベントが発生しない (アクセスがない) ような場合は、集計が行われないため、適しませんのでご注意ください。

閾値の "at least once in 1分" というのは、最後に集計されたウィンドウデータのことを差しており、閾値設定全体の意味としては集計されたシグナル値のいずれかが閾値以上ならば違反判定されることになります。

1分と記載されるので紛らわしいですが、これは Sliding Window が 1分 なので、表記上の都合で 1分と表記されるものです。N分 という表記よりも ウィンドウ (Window Duration ) N 個分という表記の方がわかりやすいかもしれません。

次に アラート用 NRQL ですが、SELECT 内で clamp_max 関数を除いて記述するとシンプルで、要するに エラー率 と分かります。

100 - sum(newrelic.sli.good) / sum(newrelic.sli.valid) * 100 AS 'Error rate'

つまり Fast-burn rate アラートは、直近 1時間のエラー率を 1分おきに算出して、閾値を超えたらインシデントを作成するというものです。

Fast-burn rate 閾値の算出方法

サンプルの SLO 設定では、SLO 期間 が 7日間で、SLOターゲットが 98.5% なので、Fast-burn rate アラートの閾値は 5.04 と算出されます。

ドキュメントで算出式は、下記のように記載されています。

threshold = error budget * critical burn rate
          = (100 - SLOターゲット) * (2% * SLO期間)
          = (100 - 98.5) * (0.02 * 7*24) = 5.04

算出式に関し、個人的には下記のように解釈しています。

初期エラーバジェット (100-98.5 = 1.5) は、1.5% のエラー率が発生し続けた場合、SLO期間 (7*24時間) でちょうど使い切れるペースである。 では、そのバジェットを 50時間で使い切ってしまう (1時間あたり2% 消費する) ペースのエラー率はいくつか?

SLO期間 (168時間) で使い切るものを 50時間で使ってしまうペースなので、それは元のペースよりも 168/50 倍速いペースである。 元のペースは 1.5% でエラーが発生し続けるペースなので、その 168/50 倍速いペースのエラー率は、(1.5% * 168/50 = ) 5.04%、 です。

または、元のペース = 理想的なバーンレート (= 1)、50時間で使い切るペース = クリティカルバーンレート (SLO期間(h)/50(h))、 元のペースのエラー率 (100-SLOタージェット = 1.5%)、 クリティカルバーンレートの場合のエラー率を x% として、比を用いて求めます。

1.5% : x% = 1 : 7*24/50

SLO期間 や SLOターゲットが変わっても、上記の考え方で算出ができます。また、1時間で2%消費というペース以外を使用したい場合でも独自に基準を計算できるかと思います。

Slow-burn rate

エラーバジェットの消費量が増加し、修正しなければ SLO 期間が終了するまでにエラーバジェット使い果たしてしまうような状況が発生した際に検知することができます。 デフォルトでは、5日間で初期エラーバジェットが消費されてしまうようなペース、つまり、6時間で 初期エラーバジェットの 5% が消費されるような状況が発生した際に閾値違反と判定されます。

デフォルトのアラート設定は以下のようになります。閾値の値が サービスレベル設定から自動で算出されます。

  • アラート用 NRQL (Good request の場合)
FROM Metric
SELECT 100 - clamp_max(sum(newrelic.sli.good) / sum(newrelic.sli.valid) * 100, 100) AS 'Error rate'
WHERE entity.guid = 'この SLI の GUID'
  • アラート用 NRQL (Bad request の場合)
FROM Metric
SELECT 100 - clamp_max((sum(newrelic.sli.valid) - sum(newrelic.sli.bad)) / sum(newrelic.sli.valid) * 100, 100) AS 'Error rate'
WHERE entity.guid = 'この SLI の GUID'
  • Window Duration: 360分 (6時間)
  • Sliding Window: 15分
  • Streaming Method: Event Flow (Delay: 2分)
  • No Gap Filling/No Evaluation delay
  • 閾値 (critical): result >= "自動計算された閾値" at least once in 15分

アラート用 NRQL は Fast-burn rate アラートと同一ですが、Window Duration 期間、Sliding Window 幅および自動計算された閾値が異なります。

Fast-burn rate の例と同じですが、Window Duration が 6時間で、Sliding Window が 15分であるため、データは下記のような期間で 15分間隔で集計されます。

  • 12:00 - 18:00 の 6時間に受信したデータ (newewrelic.sli.*) で集計値 (シグナル値) を算出
  • 12:15 - 18:15 の 6時間に受信したデータ (newewrelic.sli.*) で集計値 (シグナル値) を算出
  • 12:30 - 18:30 の 6時間に受信したデータ (newewrelic.sli.*) で集計値 (シグナル値) を算出
  • 12:45 - 18:45 の 6時間に受信したデータ (newewrelic.sli.*) で集計値 (シグナル値) を算出
  • ...

閾値の期間が 15分ですが、これは 表示上の問題で Sliding Window の幅と同じなので、直近の集計データが閾値違反となるかで評価されます。 Fast-burn rate アラートでは 1時間で 2% の初期予算が消費されるペースのエラー率でしたが、Slow-burn rate アラートでは 6時間で 5% ペースと多少よ熊野かなペースを警告するものとなります。

Slow-burn rate 閾値の算出方法

サンプルの SLO 設定では、SLO 期間 が 7日間で、SLOターゲットが 98.5% なので、Slow-burn rate アラートの閾値は 2.1 と算出されます。

先の Fast-burn rate と同様で、数字を変えただけですが

初期エラーバジェット (100-98.5 = 1.5) は、1.5% のエラー率が発生し続けた場合、SLO期間 (7*24=168時間) でちょうど使い切れるペースである。 では、そのバジェットを 5日 (120時間)で使い切ってしまう (6時間あたり5% 消費する) ペースのエラー率はいくつか?

SLO期間 (168時間) で使い切るものを 120時間で使い切るペースなので、それは元の理想的なペースよりも 168/120 倍速いペース。 理想的なペースは 1.5% でエラーが発生し続けるペースなので、その 168/120 倍速いペースのエラー率は、(1.5% * 168/120 = ) 2.1%、同じように計算することができます。

Slow-burn rate の場合は、設定例の値を利用すると、直近 6時間のエラー率が 2.1% 以上になった場合、閾値違反となります。 この例の場合は エラー率が 1.5% の場合が、エラーバジェットをちょうど使い切るペースなので、それより多少多くエラーが発生する場合に通知が行われるとわかります。 SLO期間や目標値が変われば変わります。期間が長いほうがエラー率の閾値も高くなります。

SLO compliance

SLI が SLO の目標値を下回る状態が一定期間以上続いた場合を検出します。 具体的には、60分間に発生したイベントに対して、SLI 達成率を算出し、SLO 目標値以下だった場合、閾値違反となります。

  • アラート用 NRQL (Good request の場合)
FROM Metric
SELECT clamp_max(sum(newrelic.sli.good) / sum(newrelic.sli.valid) * 100, 100) AS 'SLO compliance'
WHERE entity.guid = 'この SLI の GUID'
  • アラート用 NRQL (Bad request の場合)
FROM Metric
SELECT clamp_max((sum(newrelic.sli.valid) - sum(newrelic.sli.bad)) / sum(newrelic.sli.valid) * 100, 100) AS 'SLO compliance'
WHERE entity.guid = 'この SLI の GUID'
  • Window Duration: 60分
  • Sliding Window: 5分
  • Streaming Method: Event Flow (Delay: 2分)
  • No Gap Filling/No Evaluation delay
  • 閾値 (critical): result >= "SLO 目標値" at least once in 5分

Fast/Slow-burn rate の例と類似ですが、Window Duration が 60分で、Sliding Window が 5分であるため、データは下記のような期間で 5分間隔で集計されます。

  • 12:00 - 13:00 の 60分間に受信したデータ (newewrelic.sli.*) で集計値 (シグナル値) を算出
  • 12:05 - 13:05 の 60分間に受信したデータ (newewrelic.sli.*) で集計値 (シグナル値) を算出
  • 12:10 - 13:10 の 60分間に受信したデータ (newewrelic.sli.*) で集計値 (シグナル値) を算出
  • 12:15 - 13:15 の 60分間に受信したデータ (newewrelic.sli.*) で集計値 (シグナル値) を算出

閾値は SLO 目標値 が設定されます。閾値の期間が 5分ですが、これは 表示上の問題で Sliding Window の幅と同じなので、直近の集計データが閾値違反となるかで評価されます。

繰り返しとなりますが、SLO compliance アラートは、直近の 60分データに関して SLI 達成率を算出し、SLO 目標値以下となった場合を検知します。

Error budget consumption

最後が、エラーバジェットに関するアラートですが、これは残りエラーバジェット率が特定の閾値を下回った際に通知するアラートとなります。 閾値は固定値で 20% 以下が Warning、10以下が Critical 閾値として設定されます。

  • アラート用 NRQL
FROM ServiceLevelSnapshot
SELECT latest(remainingErrorBudget) AS 'Remaining error budget (%)'
WHERE entity.guid = 'この SLI の GUID'
  • Window Duration: 10分
  • Sliding Window: 1分
  • Streaming Method: Event Flow (Delay: 2分)
  • No Gap Filling/No Evaluation delay
  • 閾値
    • Critical: result < 10 for at least 20分
    • Warning: result < 20 for at least 20分

他のアラートの NRQL と異なり、Metric ではなく、ServiceLevelSnapshot から算出された値を利用しています。 残りエラーバジェット率を利用するため、Window Duration 期間中のデータだけでは算出できないため、ServiceLevelSnapshot に記録された値を利用しています。

また、残りエラーバジェット率の算出式には、SLO 期間や目標値が含まれるため、SLO の変更をした場合にアラートコンディションまで変更しないでもよいというメリットもあります。

参考: 残りエラーバジェット率 (Good レスポンスの場合)

SELECT (sum(newrelic.sli.good) / sum(newrelic.sli.valid) * 100 - {{SLO目標値}}) / (100 - {{SLO目標値}}) * 100 as 'Remaining error budget (%)'
FROM Metric WHERE entity.guid = 'この SLI GUID' SINCE {{SLO期間}} AGO

ServiceLevelSnapshot は 5分間隔で記録され、その時点での SLO 値に基づいて、残りエラーバジェット率、SLI 達成率が保存されます。

まとめ

サービスレベル関連アラートについて、設定されるアラートの内容を深掘りしました。 意味が理解できればカスタマイズなどもしやすいかと思いますので、各環境に適した調整を行なっていただければと思います。

また、いずれのアラートでも Streaming Method は Event Flow ですので、イベント (アクセス) が発生し続けるような場合を対象としています。 アラート用の評価期間 (Window Duration) のエラー率や達成率から、閾値違反となるか否かの評価を行う関係で、特定の時間帯でアクセスが少なくなる場合などの不安定な場合は、アラートの精度か低くなってしまう可能性もあることにご留意ください。

SLO を変更した場合、作成済みアラートの閾値までは、追随して変化しませんので、変更に合わせて閾値を調整するか、新規でアラートコンディションを作成し直していただければと思います。