はじめに

平素は大変お世話になっております。
クイックガードのパー子です。

皆様は Cloud MonitoringAggregation を活用されていますでしょうか?
(昔は Stackdriver Monitoring という名称だったと記憶しているのですが、今は Stackdriver というワードは外されて いますね)

弊社でも GCP を扱う案件は多く、システムの健康状態の把握のために Cloud Monitoring を多用しています。

状況分析や問題の特定のためには適切な Aggregation が欠かせないのですが、Aligner, Reducer, Alignment period など登場人物が多く、なかなか概念を理解しづらいところがあります。

そこで今回は、Aggregation とは何なのか、どんな要素で構成されていて、どんなことができるのかを整理してみました。

Aggregation の概念

まずは Aggregation の概念を見ていきます。

構成要素

Cloud Monitoring API いわく、Aggregation は以下 2段階のステップで構成されます。

Aggregation of time series is done in two steps. First, each time series in the set is aligned to the same time interval boundaries, then the set of time series is optionally reduced in number.

つまり、

  1. 各タイム・シリーズ (= 1本1本のグラフ) それぞれについて、一定のアライメント区間 (= 時間間隔) ごとに Align (= 1つのデータ・ポイントに集約) する。
  2. それらのタイム・シリーズ群を Reduce (= 1本のタイム・シリーズに集約) する。

という Aligner & Reducer で構成されるということです。

Webコンソールには Reducer という表記がないが…

GCP の Webコンソール上には Reducer という表記はありませんが、Aggregator = Reducer です。

どんなことができるのか

Aligner と Reducer の関係を理解したところで、次にどんな関数があるのかまとめてみました。

Aligner

https://cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.alertPolicies#aligner

関数 動作
ALIGN_NONE 何もしない (集約せず、そのままの値を返す)
ALIGN_DELTA 差分
ALIGN_RATE 単位時間あたりの変化量 (ALIGN_DELTA をアライメント区間長で割った値)
ALIGN_INTERPOLATE 補間 (詳細は後述)
ALIGN_NEXT_OLDER 各アライメント区間の最後のデータ・ポイントを当該区間の値として採用
ALIGN_MIN 最小値
ALIGN_MAX 最大値
ALIGN_MEAN 平均
ALIGN_COUNT データ・ポイントの個数
ALIGN_SUM 合計
ALIGN_STDDEV 標準偏差
ALIGN_COUNT_TRUE BOOL型TRUE のデータ・ポイントの個数 (データ型の説明は後述)
ALIGN_COUNT_FALSE BOOL型FALSE のデータ・ポイントの個数
ALIGN_FRACTION_TRUE 全データ・ポイントを分母とした場合の BOOL型TRUE の比率
ALIGN_PERCENTILE_99 99パーセンタイル
ALIGN_PERCENTILE_95 95パーセンタイル
ALIGN_PERCENTILE_50 50パーセンタイル
ALIGN_PERCENTILE_05 5パーセンタイル
ALIGN_PERCENT_CHANGE 前データ・ポイントからの変化率

わかりづらい関数

いくつかわかりづらい関数があるので実物を見ながら補足します。

ALIGN_INTERPOLATE

ALIGN_MEAN と重ね合わせてみました。
アライメント区間はどちらのタイム・シリーズも 1分です。

区間1つ飛ばしで間が補間されていることがわかります。

(メトリクスの計測間隔は 1分、つまり 1分間にデータ・ポイントは 1つなので、重ね合わせ対象となる ALIGN_MEAN は MEAN と言いながら実質的に無加工の生の値です)

ALIGN_NEXT_OLDER

今度はアライメント区間 1分の ALIGN_MEAN と 3分 の ALIGN_NEXT_OLDER を重ねました。

アライメント区間の最後のデータ・ポイントが当該区間の値として採用されていることがわかります。

Reducer

Aligner と似たようなものなので省略します。

https://cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.alertPolicies#reducer

MetricKind と ValueType

ところで、各メトリクスは ValueTypeMetricKind という 属性 を持っています。

その組み合わせによって適用可能な Aligner / Reducer が変わってくるので、ここでざっと解説します。

  • ValueType: データ型
  • MetricKind: 前データ・ポイントからの増減をどう計測したか

それぞれどんな種類があるのか見ていきましょう。

ValueType

Type 説明
BOOL 真偽値
INT64 64bit 整数
DOUBLE 倍精度浮動小数点数
STRING 文字列
DISTRIBUTION 複数の計測値のセットに対する統計値とヒストグラム

DISTRIBUTION の存在がとても斬新な気がしますが、それ以外は一般的なデータ型ですね。

(本題から外れるので DISTRIBUTION の説明は割愛しますが、詳細が気になる方は こちら)

MetricKind

Kind 説明
GAUGE 一定範囲の値域のうち、その瞬間に指し示している値 CPU使用率
DELTA 前回のデータ・ポイントからの差分 HTTPリクエスト数
CUMULATIVE 単調増加する値 ネットワーク送信Byte数

CUMULATIVE は他のモニタリング・ツールでは COUNTER と呼ばれていることが多いように思います。

CUMULATIVE とは別に DELTA があるのも特徴的な気がします。
(DELTA[n] = CUMULATIVE[n] - CUMULATIVE[n-1] で導出できそう)

可能な組み合わせ

ValueType と MetricKind はすべての組み合わせをとれるわけではなく、共存できない組み合わせもあります。

例えば DELTA と CUMULATIVE は BOOL をサポートしていません。

ここでは詳しく列挙しませんので、具体的な組み合わせは ドキュメント を参照してください。

確認方法

どのメトリクスがどんな ValueType / MetricKind なのか調べたい場合は この一覧 が便利です。

また、メトリクス選択時に確認することもできます。

Aligner / Reducer の入出力

ValueType / MetricKind の組み合わせによって適用可能な関数が異なります。
また、出力される値の ValueType / MetricKind も関数によって違ってきます。

関数ごとの入出力の詳細はドキュメント (Aligner, Reducer) に記載されていますが、わかりづらいので見やすくまとめ直してみました。

入出力表

(?) が付与されているものはドキュメントの誤りと思われます。(詳細は後述)

注意点

いくつか注意点があります。

ALIGN_PERCENT_CHANGE が Webコンソールに出てこない

Webコンソールでは選択肢に ALIGN_PERCENT_CHANGE が出てきません。

なぜか Webコンソールはこの関数をサポートしていないようで、API でならチャートを作ることができます。

まず ALIGN_PERCENT_CHANGE.yml を作って、

---
displayName: ALIGN_PERCENT_CHANGE
gridLayout:
  columns: '2'
  widgets:
  - title: GKE Container - CPU utilization for 1bb1eb3c-117b-11ea-aa67-42010a92023b
    xyChart:
      chartOptions:
        mode: COLOR
      dataSets:
      - minAlignmentPeriod: 60s
        plotType: LINE
        timeSeriesQuery:
          timeSeriesFilter:
            aggregation:
              perSeriesAligner: ALIGN_PERCENT_CHANGE
            filter: metric.type="container.googleapis.com/container/cpu/utilization"
              resource.type="gke_container" resource.label."pod_id"="1bb1eb3c-117b-11ea-aa67-42010a92023b"
            secondaryAggregation: {}
          unitOverride: '%'
      timeshiftDuration: 0s
      yAxis:
        label: y1Axis
        scale: LINEAR

gcloud でぶん投げると、

$ gcloud monitoring dashboards create --config-from-file=ALIGN_PERCENT_CHANGE.yml
Created [7a3076af-d4ef-4227-8a5e-cf48ccf083b0].

できました。

ちなみに API で作成したこのチャートを Webコンソールで Edit しようとすると勝手に mean に戻されてしまい、ALIGN_PERCENT_CHANGE はもう選ぶことができません。

ALIGN_COUNT_FALSE が Webコンソールに出てこない

ALIGN_PERCENT_CHANGE と同じく ALIGN_COUNT_FALSE も Webコンソールの選択肢に出てきませんが、これも API で作成可能です。

---
displayName: ALIGN_COUNT_FALSE
gridLayout:
  columns: '2'
  widgets:
  - title: Check passed for 1bb1eb3c-117b-11ea-aa67-42010a92023b
    xyChart:
      chartOptions:
        mode: COLOR
      dataSets:
      - minAlignmentPeriod: 60s
        plotType: LINE
        timeSeriesQuery:
          timeSeriesFilter:
            aggregation:
              perSeriesAligner: ALIGN_COUNT_FALSE
            filter: metric.type="monitoring.googleapis.com/uptime_check/check_passed"
              resource.type="gce_instance" resource.label."instance_id"="7131606653945400975"
            secondaryAggregation: {}
          unitOverride: '1'
      timeshiftDuration: 0s
      yAxis:
        label: y1Axis
        scale: LINEAR

入力値 DELTA に対して REDUCE_COUNT_TRUE などが Webコンソールに出てこない

MetricKind が DELTA のメトリクスに対して、以下 3つの関数は Webコンソールの選択肢に出てきません。

  • REDUCE_COUNT_TRUE
  • REDUCE_COUNT_FALSE
  • REDUCE_FRACTION_TRUE

ドキュメント には、

This reducer is valid for DELTA and GAUGE metrics of Boolean valueType.

と書いてあるので DELTA のメトリクスにも適用できるように読めたのですが、どうもドキュメントが誤っているようです。

チャート自体は以下のような定義で API を叩けば作成できるのですが、
(container/memory/page_fault_count に ALIGN_DELTA を適用すると DELTA / INT64 が得られます)

---
displayName: REDUCE_COUNT_TRUE
gridLayout:
  columns: '2'
  widgets:
  - title: GKE Container - Page faults
    xyChart:
      chartOptions:
        mode: COLOR
      dataSets:
      - minAlignmentPeriod: 60s
        plotType: LINE
        timeSeriesQuery:
          timeSeriesFilter:
            aggregation:
              crossSeriesReducer: REDUCE_COUNT_TRUE
              perSeriesAligner: ALIGN_DELTA
            filter: metric.type="container.googleapis.com/container/memory/page_fault_count"
              resource.type="gke_container"
            secondaryAggregation: {}
          unitOverride: '1'
      timeshiftDuration: 0s
      yAxis:
        label: y1Axis
        scale: LINEAR

チャートを閲覧しようとすると Chart definition invalid. という警告が出てデータが表示されません。

関数の意味的にもやはり BOOL型しか取り得ないように思えるので、DELTA は不適な気がします。
(DELTA には BOOL型が 存在しない)

STRING型のデータポイントが見当たらない

Webコンソールからは STRING型のメトリクスを選択できません。

https://cloud.google.com/monitoring/api/metrics_gcp

Note: Metric types with values of type STRING can’t be retrieved by using the Google Cloud Console or used in alerting policies. To retrieve string-valued data, you must use a method in the Monitoring API like timeSeries.list.

STRING型のメトリクスを扱いたい場合は API を叩く必要があります。

例えば MySQL の Slave I/O thread の稼働状態を示すメトリクス database/mysql/replication/slave_io_running (Yes, No, Connecting のいずれかが返る) を取得したい場合は、以下のようなコマンドを実行します。

$ PROJECT_ID='YOUR_PROJECT_ID'

$ ACCESS_TOKEN="$( gcloud auth print-access-token )"

$ FILTER="$( echo -n 'metric.type = "cloudsql.googleapis.com/database/mysql/replication/slave_io_running"' | ruby -n -r 'cgi' -e 'print(CGI.escape($_))' )"

$ START="$( echo -n '2020-05-15T05:50:00.000000Z' | ruby -n -r 'cgi' -e 'print(CGI.escape($_))' )"

$ END="$( echo -n '2020-05-15T05:55:00.000000Z' | ruby -n -r 'cgi' -e 'print(CGI.escape($_))' )"

$ curl -H "Authorization: Bearer ${ACCESS_TOKEN}" \
    "https://monitoring.googleapis.com/v3/projects/${PROJECT_ID}/timeSeries/?filter=${FILTER}&interval.startTime=${START}&interval.endTime=${END}"
{
  "timeSeries": [
    {
      "metric": {
        "type": "cloudsql.googleapis.com/database/mysql/replication/slave_io_running"
      },
      "resource": {
        "type": "cloudsql_database",
        "labels": {
          "project_id": "YOUR_PROJECT_ID",
          "database_id": "YOUR_PROJECT_ID:qg-hogehage123-replica1",
          "region": "asia-northeast1"
        }
      },
      "metricKind": "GAUGE",
      "valueType": "STRING",
      "points": [
        {
          "interval": {
            "startTime": "2020-05-15T05:54:24.820Z",
            "endTime": "2020-05-15T05:54:24.820Z"
          },
          "value": {
            "stringValue": "Yes"
          }
        },
        {
          "interval": {
            "startTime": "2020-05-15T05:53:24.820Z",
            "endTime": "2020-05-15T05:53:24.820Z"
          },
          "value": {
            "stringValue": "Yes"
          }
        }
      ]
    }
  ]
}

出力値の MetricKind が明記されていない関数

出力値の ValueType はすべての関数についてドキュメントで明記されているのですが、MetricKind が何になるのかは一部の関数にしか記載がありません。

Webコンソールではおおむね直感的な Aligner x Reducer の組み合わせを選べるので出力値の MetricKind を気にするケースは少ないと思いますが、気になる場合は timeSeries.list API で確認できます。

例: GKE Container » Page faults に ALIGN_COUNT を適用した場合

ALIGN_COUNT (ドキュメント に MetricKind が記載されていない) を例に、実際に API を叩いて出力を確認してみます。

MetricKind: DELTA, ValueType: INT64 のメトリクス container/memory/page_fault_count に ALIGN_COUNT を適用した結果は以下のクエリで確認できます。

$ curl -H "Authorization: Bearer ${ACCESS_TOKEN}" \
    "https://monitoring.googleapis.com/v3/projects/${PROJECT_ID}/timeSeries/?filter=metric.type+%3D+%22container.googleapis.com%2Fcontainer%2Fmemory%2Fpage_fault_count%22&interval.startTime=2020-05-15T05%3A50%3A00.000000Z&interval.endTime=2020-05-15T05%3A55%3A00.000000Z&aggregation.alignmentPeriod=60s&aggregation.perSeriesAligner=ALIGN_COUNT"
{
  ...
  {
    "metric": {
      "labels": {
        "fault_type": "minor"
      },
      "type": "container.googleapis.com/container/memory/page_fault_count"
    },
    "resource": {
      ...
    },
    "metricKind": "GAUGE",
    "valueType": "INT64",
    "points": [
      ...
    ]
  }
}

ALIGN_COUNT の出力は MetricKind: GAUGE, ValueType: INT64 になることがわかりました。

まとめ

以上、Cloud Monitoring の Aggregation について、その概念と各関数の機能をまとめてみました。
また、関数の入出力 (MetricKind / ValueType) を一覧化し、いくつかの注意点も列挙しました。

全体的に Webコンソールでできることは制限されており、機能をフルに活用したい場合は API を使いこなす必要がありそうです。

Cloud Monitoring は公式ドキュメントから正確に情報を読み取るのが難しいので、この記事が Cloud Monitoring の理解の一助になれば幸いです。
今後ともよろしくお願い申し上げます。