このページでは、可用性 SLI とレイテンシ SLI を作成するためのログ出力の基本について説明します。また、ログベースの指標を使用して SLO を定義する方法の実装例も紹介します。
ログエントリでデータ要素を使用してサービスレベル指標を作成することは、既存のログペイロードを活用する 1 つの方法です。そうしない場合は、指標の計測を作成するよりも、既存のサービスにロギングを追加する方が簡単と思われます。
ログと指標
ログは、コンピュータ システムで発生する特定のイベントを記述するログエントリと呼ばれるレコードを収集します。ログは、コード、コードが実行されているプラットフォーム サービス(Dataflow など)、プラットフォームが依存するインフラストラクチャ(Compute Engine インスタンスなど)によって記述されます。
最近のシステムでは、ログはディスクに書き込まれたテキスト ファイルに由来する(場合によってはそのものである)ため、ログエントリはログファイル内の行に似ており、ロギングの基本単位とみなすことができます。
ログエントリは、少なくとも次の 2 つの要素から構成されます。
- イベントが発生した日時、またはロギング システムに取り込まれたときを示すタイムスタンプ。
- テキスト ペイロード。非構造化テキストデータまたは構造化データで、通常は JSON です。
ログ、特に Cloud Logging に取り込まれるログには、関連するメタデータを含めることができます。このようなメタデータには、ログを書き込むリソース、ログ名、各エントリの重大度が含まれる場合があります。
ログ
ログは、主に次の 2 つを目的として使用されます。
- イベントログは、システム内で発生する特定のイベントを記述します。イベントログは、正常な動作をユーザーに知らせるメッセージを出力する(「タスクが成功しました」など)ためか、何かが失敗したという情報を提供する(「サーバーから例外を受信しました」など)ために使用できます。
- トランザクション ログには、システムやコンポーネントによって処理されたすべてのトランザクションの詳細が記述されます。たとえば、ロードバランサは、リクエストが正常に行われたかどうかに関係なく受信したすべてのリクエストをログに記録し、リクエストされた URL、HTTP レスポンス コード、場合によってはリクエストの処理に使用されたバックエンドなどの追加情報を記録します。
指標
ログとは異なり、通常、指標では特定のイベントは記述されません。一般に、指標は、経時的なシステムの状態や健全性を表すために使用されます。指標は、システムに関するなんらかの値を測定する一連のデータポイントで構成され、各データポイントには、タイムスタンプと数値が含まれます。
指標にメタデータを関連付けることもできます。時系列という一連のデータポイントには、指標名や説明のほか、多くの場合、データを書き込むリソースを指定するラベルなどの情報が含まれます。Monitoring の指標モデルについては、指標、時系列、リソースをご覧ください。
ログベースの指標
ログベースの指標とは、ログエントリから情報を抽出して時系列データに変換することによって、ログエントリから作成される指標のことです。Cloud Logging には、ログエントリから次の 2 種類の指標を作成するための仕組みがあります。
カウンタ指標。特定のフィルタに一致するログエントリの数をカウントします。カウンタ指標を使用すると、ログに記録されたリクエストやエラーの数などを確認できます。
分布指標。正規表現を使用して各ログエントリのペイロードを解析し、数値を分布として抽出します。
Cloud Logging におけるログベースの指標の詳細については、ログベースの指標の使用をご覧ください。
ログベースの指標を SLI として使用する
ログベースの指標を使用すると、Monitoring で SLI の作成に使用できる形式でログからデータを抽出できます。
ログベースのカウンタ指標は、リクエスト ベースの可用性 SLI を表すために使用できます。
ログベースの分布指標は、リクエスト ベースのレイテンシ SLI を表すために使用できます。
サンプル ログエントリ
Stack Doctor アプリケーションは、サービスに対するすべてのリクエスト、エラー、レイテンシに関する情報を含むログメッセージを出力するようにインストルメント化されたサービスの一例です。サービスのコードは、GitHub リポジトリ stack-doctor
にあります。
このサービスは、projects/stack-doctor/logs/bunyan_log
ログに Cloud Logging ログエントリを生成します。イベントのタイプごとのログエントリには、異なる message
値が含まれます。タイプ別に、イベントのログエントリは次のようになります。
すべてのリクエスト
{ "insertId": "..........iTRVT5MOK2VOsVe31bzrTD", "jsonPayload": { "pid": 81846, "time": "Mon Aug 31 2020 20:30:49 GMT-0700 (Pacific Daylight Time)", "hostname": "<hostname>", "level": 30, "message": "request made", "v": 0, "name": "sli-log" }, "resource": { "type": "global", "labels": { "project_id": "stack-doctor" } }, "timestamp": "2020-09-01T03:30:49.263999938Z", "severity": "INFO", "logName": "projects/stack-doctor/logs/bunyan_log", "receiveTimestamp": "2020-09-01T03:30:50.003471183Z" }
成功したリクエスト
{ "insertId": "..........qTRVT5MOK2VOsVe31bzrTD", "jsonPayload": { "name": "sli-log", "v": 0, "pid": 81846, "level": 30, "hostname": "<hostname>", "time": "Mon Aug 31 2020 20:30:49 GMT-0700 (Pacific Daylight Time)", "message": "success!" }, "resource": { "type": "global", "labels": { "project_id": "stack-doctor" } }, "timestamp": "2020-09-01T03:30:49.874000072Z", "severity": "INFO", "logName": "projects/stack-doctor/logs/bunyan_log", "receiveTimestamp": "2020-09-01T03:30:50.201547371Z" }
完了したリクエスト
{ "insertId": "..........mTRVT5MOK2VOsVe31bzrTD", "jsonPayload": { "time": "Mon Aug 31 2020 20:30:49 GMT-0700 (Pacific Daylight Time)", "level": 30, "name": "sli-log", "message": "slept for 606 ms", "hostname": "<hostname>", "pid": 81846, "v": 0 }, "resource": { "type": "global", "labels": { "project_id": "stack-doctor" } }, "timestamp": "2020-09-01T03:30:49.874000072Z", "severity": "INFO", "logName": "projects/stack-doctor/logs/bunyan_log", "receiveTimestamp": "2020-09-01T03:30:50.201547371Z" }
エラー
{ "insertId": "..........DTRVT5MOK2VOsVe31bzrTD", "jsonPayload": { "hostname": "<hostname>", "level": 50, "pid": 81846, "message": "failure!", "name": "sli-log", "time": "Mon Aug 31 2020 20:30:44 GMT-0700 (Pacific Daylight Time)", "v": 0 }, "resource": { "type": "global", "labels": { "project_id": "stack-doctor" } }, "timestamp": "2020-09-01T03:30:44.414999961Z", "severity": "ERROR", "logName": "projects/stack-doctor/logs/bunyan_log", "receiveTimestamp": "2020-09-01T03:30:46.182157077Z" }
こうしたエントリに基づいて、すべてのリクエストのカウント、エラーのカウント、リクエストのレイテンシの追跡を行う、ログベースの指標を作成できます。その後、ログベースの指標を使用して、可用性 SLI とレイテンシ SLI を作成できます。
SLI 用のログベースの指標を作成する
ログベースの指標で SLI を作成する前に、ログベースの指標を作成する必要があります。
- リクエスト数とエラー数に関する可用性 SLI の場合、ログベースのカウンタ指標を使用します。
- レイテンシ SLI の場合、ログベースの分布指標を使用します。
作成したログベースの指標は、Monitoring で Metrics Explorer を使用して検索することで見つけられます。Monitoring では、ログベースの指標には logging.googleapis.com/user
という接頭辞が付いています。
可用性 SLI の指標
Cloud Monitoring API でリクエスト ベースの可用性 SLI を表現するには、TimeSeriesRatio
構造体を使用し、リクエスト全体に対する「良い」リクエストと「悪い」リクエストの比率を設定します。この比率は、RequestBasedSli
構造体の goodTotalRatio
フィールドで使用されます。
この比率を構成するために使用できるログベースのカウンタ指標を作成する必要があります。次に挙げる指標の 2 つ以上を作成する必要があります。
合計イベントをカウントする指標。この指標は、比率の
totalServiceFilter
で使用します。「stack-doctor」の例では、メッセージ文字列「request made」が入っているログエントリをカウントするログベースの指標を作成します。
「悪い」イベントをカウントする指標。この指標は、比率の
badServiceFilter
で使用します。「stack-doctor」の例では、メッセージ文字列「failure!」が入っているログエントリをカウントするログベースの指標を作成します。
「良い」イベントをカウントする指標。この指標は、比率の
goodServiceFilter
で使用します。「stack-doctor」の例では、メッセージ文字列「success!」が入っているログエントリをカウントするログベースの指標を作成します。
この例で説明する SLI は、log_based_total_requests
という合計リクエストの指標と、log_based_errors
というエラーの指標に基づいています。
ログベースの指標は、Google Cloud コンソール、Cloud Logging API、または Google Cloud CLI を使用して作成できます。Google Cloud コンソールを使用してログベースのカウンタ指標を作成する手順は次のとおりです。
-
Google Cloud コンソールで、[ログベースの指標] ページに移動します。
検索バーを使用してこのページを検索する場合は、小見出しが「Logging」の結果を選択します。
ログベースの指標ページには、「ユーザー定義の指標」の表と「システム定義の指標」の表が表示されます。
「ユーザー定義の指標」の表の上にある [指標を作成] をクリックします。
[指標タイプ] ペインで、[Counter] を選択します。
[詳細] ペインで、新しい指標に名前を付けます。「stack-doctor」の例では、「
log_based_total_requests
」または「log_based_errors
」と入力します。この例では、他のフィールドは無視してかまいません。
[フィルタの選択] パネルで、指標でカウントするログエントリのみを取得するクエリを作成します。
「stack-doctor」の例では、
log_based_total_requests
のクエリは次のようになります。resource.type="global" logName="projects/stack-doctor/logs/bunyan_log" jsonPayload.message="request made"
logs_based_errors
のクエリでは、メッセージ文字列を次のように変更します。resource.type="global" logName="projects/stack-doctor/logs/bunyan_log" jsonPayload.message="failure!"
[ログをプレビュー] をクリックしてフィルタを確認し、必要に応じて調整します。
この例では、[ラベル] ペインは無視します。
[指標を作成] をクリックして手順を終了します。
ログベースのカウンタ指標の作成について詳しくは、カウンタ指標を作成するをご覧ください。
レイテンシ SLI の指標
Cloud Monitoring API でリクエストベースのレイテンシ SLI を表現するには、DistributionCut
構造体を使用します。これは、RequestBasedSli
構造体の distributionCut
フィールドで使用されます。レイテンシ SLI を作成するには、ログベースの分布指標を作成する必要があります。この例では、log_based_latency.
というログベースの分布指標を作成します。
ログベースの指標は、Google Cloud コンソール、Cloud Logging API、または Google Cloud CLI を使用して作成できます。Google Cloud コンソールを使用してログベースの分布指標を作成する手順は次のとおりです。
-
Google Cloud コンソールで、[ログベースの指標] ページに移動します。
検索バーを使用してこのページを検索する場合は、小見出しが「Logging」の結果を選択します。
ログベースの指標ページには、「ユーザー定義の指標」の表と「システム定義の指標」の表が表示されます。
「ユーザー定義の指標」の表の上にある [指標を作成] をクリックします。
[指標タイプ] ペインで [Distribution] を選択します。
[詳細] ペインで、新しい指標に名前を付けます。「stack-doctor」の例では、「
log_based_latency
」と入力します。この例では、他のフィールドは無視してかまいません。
[フィルタの選択] パネルで、指標でカウントするログエントリのみを取得するクエリを作成します。
「stack-doctor」の例では、
log_based_latency
のクエリは次のようになります。resource.type="global" logName="projects/stack-doctor/logs/bunyan_log" jsonPayload.message="slept for"
フィルタクエリの次のフィールドを指定します。
- フィールド名:
json.message
正規表現:
\s(\d*)\s
完全なリクエストのメッセージ文字列の形式は、「slept for n ms」となります。正規表現によって、文字列からレイテンシの値 n が抽出されます。
- フィールド名:
この例では、[ラベル] ペインは無視します。
[指標を作成] をクリックして手順を終了します。
ログベースの分布指標の作成について詳しくは、分布指標の作成をご覧ください。
可用性 SLI
Cloud Monitoring では、TimeSeriesRatio
構造体を使用してリクエスト ベースの可用性 SLI を表現します。次の例は、比率で log_based_total_requests
指標と log_based_errors
指標を使用する SLO を示しています。この SLO では、24 時間のローリング期間で、リクエスト全体に対する「良い」リクエストの割合が 98% 以上となることを想定しています。
{
"serviceLevelIndicator": {
"requestBased": {
"goodTotalRatio": {
"totalServiceFilter":
"metric.type=\"logging.googleapis.com/user/log_based_total_requests\"
resource.type=\"global\"",
"badServiceFilter":
"metric.type=\"logging.googleapis.com/user/log_based_errors\"
resource.type=\"global\""
}
}
},
"goal": 0.98,
"rollingPeriod": "86400s",
"displayName": "Log-Based Availability"
}
レイテンシ SLI
Cloud Monitoring では、DistributionCut
構造体を使用してリクエスト ベースのレイテンシ SLI を表現します。次の例は、log_based_latency
指標を使用する SLO を示しており、24 時間のローリング期間でリクエストの 98% が 500 ms 未満となることを想定しています。
{
"serviceLevelIndicator": {
"requestBased": {
"distributionCut": {
"distributionFilter":
"metric.type=\"logging.googleapis.com/user/log_based_latency\"
resource.type=\"global\"",
"range": {
"min": 0,
"max": 500
}
}
}
},
"goal": 0.98,
"rollingPeriod": "86400s",
"displayName": "98% requests under 500 ms"
}
参考情報
- Stackdriver でログに関するアラートを使用できますか?| 投稿者: Yuri Grinshteyn | Google Cloud - Community
- ログベースの指標の通知を構成する | Cloud Logging
- ログベースの指標を使用したログからの値の抽出