ログベースの指標の使用

このページでは、可用性 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 つ以上を作成する必要があります。

  1. 合計イベントをカウントする指標。この指標は、比率の totalServiceFilter で使用します。

    「stack-doctor」の例では、メッセージ文字列「request made」が入っているログエントリをカウントするログベースの指標を作成します。

  2. 「悪い」イベントをカウントする指標。この指標は、比率の badServiceFilter で使用します。

    「stack-doctor」の例では、メッセージ文字列「failure!」が入っているログエントリをカウントするログベースの指標を作成します。

  3. 「良い」イベントをカウントする指標。この指標は、比率の goodServiceFilter で使用します。

    「stack-doctor」の例では、メッセージ文字列「success!」が入っているログエントリをカウントするログベースの指標を作成します。

この例で説明する SLI は、log_based_total_requests という合計リクエストの指標と、log_based_errors というエラーの指標に基づいています。

ログベースの指標は、Google Cloud コンソール、Cloud Logging API、または Google Cloud CLI を使用して作成できます。Google Cloud コンソールを使用してログベースのカウンタ指標を作成する手順は次のとおりです。

  1. Google Cloud コンソールで、[ログベースの指標] ページに移動します。

    [ログベースの指標] に移動

    検索バーを使用してこのページを検索する場合は、小見出しが「Logging」の結果を選択します。

    ログベースの指標ページには、「ユーザー定義の指標」の表と「システム定義の指標」の表が表示されます。

  2. 「ユーザー定義の指標」の表の上にある [指標を作成] をクリックします。

  3. [指標タイプ] ペインで、[Counter] を選択します。

  4. [詳細] ペインで、新しい指標に名前を付けます。「stack-doctor」の例では、「log_based_total_requests」または「log_based_errors」と入力します。

    この例では、他のフィールドは無視してかまいません。

  5. [フィルタの選択] パネルで、指標でカウントするログエントリのみを取得するクエリを作成します。

    「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!"
    
  6. [ログをプレビュー] をクリックしてフィルタを確認し、必要に応じて調整します。

  7. この例では、[ラベル] ペインは無視します。

  8. [指標を作成] をクリックして手順を終了します。

ログベースのカウンタ指標の作成について詳しくは、カウンタ指標を作成するをご覧ください。

レイテンシ SLI の指標

Cloud Monitoring API でリクエストベースのレイテンシ SLI を表現するには、DistributionCut 構造体を使用します。これは、RequestBasedSli 構造体の distributionCutフィールドで使用されます。レイテンシ SLI を作成するには、ログベースの分布指標を作成する必要があります。この例では、log_based_latency. というログベースの分布指標を作成します。

ログベースの指標は、Google Cloud コンソール、Cloud Logging API、または Google Cloud CLI を使用して作成できます。Google Cloud コンソールを使用してログベースの分布指標を作成する手順は次のとおりです。

  1. Google Cloud コンソールで、[ログベースの指標] ページに移動します。

    [ログベースの指標] に移動

    検索バーを使用してこのページを検索する場合は、小見出しが「Logging」の結果を選択します。

    ログベースの指標ページには、「ユーザー定義の指標」の表と「システム定義の指標」の表が表示されます。

  2. 「ユーザー定義の指標」の表の上にある [指標を作成] をクリックします。

  3. [指標タイプ] ペインで [Distribution] を選択します。

  4. [詳細] ペインで、新しい指標に名前を付けます。「stack-doctor」の例では、「log_based_latency」と入力します。

    この例では、他のフィールドは無視してかまいません。

  5. [フィルタの選択] パネルで、指標でカウントするログエントリのみを取得するクエリを作成します。

    「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 が抽出されます。

  6. この例では、[ラベル] ペインは無視します。

  7. [指標を作成] をクリックして手順を終了します。

ログベースの分布指標の作成について詳しくは、分布指標の作成をご覧ください。

可用性 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"
}

参考情報