TL; DR
-
https/total_latencies
メトリクスはDISTRIBUTION
型で、集計元のデータが既にヒストグラム - ヒストグラムの
ALIGN_SUM
はヒストグラムのマージ(だと思われる) -
https/total_latencies
の集計はALIGN_SUM
+REDUCE_PERCENTILE_99
が良さそう
事の発端
Stackdriver MonitoringのDashboardsは標準でGoogle Cloud Load Balancersなどのダッシュボードを用意してくれて、 レスポンスタイム(Total Latency)やステータスコード(Response by Response Code Class)などが見える
用意されている_Total Latency_の設定はこんな感じになっており、
これを丸コピ参考にしてアラートポリシーを作っていた(最初にWebConsole上で作って terraform import
してゴニョゴニョして.tfにしていた。泥臭…)
が、どうも挙動がおかしい
閾値以上のlatencyが検知されてアラートが鳴るが、stackdriver以外のログをどう調べても遅いレスポンスがあったように見えない
で、調べてみたら
Aggregator と Aligner の設定が逆になってた
直せばチャートは正しそうっぽい感じの雰囲気が出てきたけど、何がどうなってたかよくわからなかったのでちゃんと調べてみた
特に Aligner
: sum
が激しく謎
レスポンスタイム足し合わせたらダメでは???
調査結果
結論:ダメじゃなさそうだった
https/total_latencies
の型
Google Cloud metrics | Stackdriver Monitoring
https/total_latencies
は_データの種類_がDELTA
で_データの型_が**DISTRIBUTION
型**
ナニソレ
Distribution
型とは
TimeSeries | Stackdriver Monitoring | Google Cloud
Distribution contains summary statistics for a population of values. It optionally contains a histogram representing the distribution of those values across a set of buckets.
こんなフォーマットらしい
JSON representation
{
"count": string,
"mean": number,
"sumOfSquaredDeviation": number,
"range": {
object (Range)
},
"bucketOptions": {
object (BucketOptions)
},
"bucketCounts": [
string
],
"exemplars": [
{
object (Exemplar)
}
]
}
ドユコト
DISTRIBUTION
型のhttps/total_latencies
のデータを直接見てみる
Method: projects.timeSeries.list | Stackdriver Monitoring
Google API Explorerで projects.timeSeries.list
を取得
name
: projectId
filter
: (実際は改行じゃなく空白区切り)
metric.type="loadbalancing.googleapis.com/https/total_latencies"
resource.type="https_lb_rule"
resource.label."url_map_name"="対象のurl_map_name"
resource.label."project_id"="対象プロジェクトID"
interval.startTime
/interval.endTime
: RFC3339 (ex. 2020-02-09T14:00:00+09:00
)
結果
{
"timeSeries": [
{
"metric": {
"labels": {
"client_country": "Japan",
"response_code_class": "200",
"protocol": "HTTP/1.1",
"response_code": "200",
"cache_result": "DISABLED",
"proxy_continent": "Asia"
},
"type": "loadbalancing.googleapis.com/https/total_latencies"
},
"resource": {
"type": "https_lb_rule",
"labels": {
"backend_target_type": "BACKEND_SERVICE",
"project_id": "プロジェクトID",
"backend_type": "INSTANCE_GROUP",
"forwarding_rule_name": "k8s-fw-default-my-ingress--dba157e117f099a8",
"backend_target_name": "",
"backend_name": "",
"backend_scope": "asia-northeast1-b",
"matched_url_path_rule": "/",
"region": "global",
"url_map_name": "k8s-um-default-my-ingress--dba157e117f099a8",
"backend_scope_type": "ZONE",
"target_proxy_name": "k8s-tp-default-my-ingress--dba157e117f099a8"
}
},
"metricKind": "DELTA",
"valueType": "DISTRIBUTION",
"points": [
{
"interval": {
"startTime": "2020-02-09T07:02:00Z",
"endTime": "2020-02-09T07:03:00Z"
},
"value": {
"distributionValue": {
"count": "2",
"mean": 64,
"bucketOptions": {
"exponentialBuckets": {
"numFiniteBuckets": 66,
"growthFactor": 1.4,
"scale": 1
}
},
"bucketCounts": [
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"0",
"2"
]
}
}
}
]
},
{
...
}
]
}
DISTRIBUTION
型のhttps/total_latencies
のデータ解読
-
bucketOptions
: exponentialBuckets- 各区間が指数関数的なヒストグラム
- ほかの形式としては
linearBuckets
,explicitBuckets
がある - ヒストグラムの各区間は
scale * (growthFactor ^ (i - 1))
-scale * (growthFactor ^ i)
-
scale
,growthFactor
は取得したデータすべて同じ値だった -
https/total_latencies
では固定なのかもしれないし、もしかしたらアクセス流量によって変動するのかもしれない
-
bucketCounts
-
bucketOptions
で定義されるヒストグラムでのデータの分布
-
-
metric
,resource
とpoints
-
metric
,resource
: リクエストの各種ラベルでまずデータが分けられ - それぞれさらに時刻(
points
)ごとに分割されている
-
つまり↑のデータは
scale: 1
、growthFactor: 1.4
、i=13
のデータ数が2
→ Latencyが 1.4^12
(=56.6939124
)ms 〜 1.4^13
(=79.3714773
)ms のレスポンスが2回
読める・・・読めるぞ・・・!
ALIGN_SUM
REST Resource: projects.alertPolicies | Stackdriver Monitoring
まずperSeriesAligner
が適用されて時間軸(alignmentPeriod
)に集約されて、
次にcrossSeriesReducer
が適用されてリソース分類の軸(groupByFields
)で集約される
で
perSeriesAligner : enum (
Aligner
)
ALIGN_SUM
: Align the time series by returning the sum of the values in each alignment period. This aligner is valid forGAUGE
andDELTA
metrics with numeric and distribution values. ThevalueType
of the aligned result is the same as thevalueType
of the input.
ALIGN_SUM
の出力の型は、入力の型そのまま
入力がDISTRIBUTION
型なら出力もDISTRIBUTION
型
つまり、sumとはレスポンスタイムの足し算ではなく、ヒストグラムの足し合わせ(マージ?)の意味だったのだよ
(注:ドキュメントにそう明言はされてないので予想)
REDUCE_PERCENTILE_99
最後に 「Aggregator : 99th percentile」の部分
ヒストグラムからどうパーセンタイルを算出するかがドキュメントに記載なかったので検算してみた
99th percentile
1.4^12*0.01 + 1.4^13*0.99 = 79.1447017
95th percentile
1.4^12*0.05 + 1.4^13*0.95 = 78.2375991
50th percentile
1.4^12*0.50 + 1.4^13*0.50 = 68.0326949
完全に一致
でもデータが複数のバケットに分布してるときはどう計算するのかわからん・・・
数学的に定義されるような気がする
ALIGN_PERCENTILE_99
して REDUCE_SUM
してしまうと?
間違って設定していたときになにが起こっていたか
ALIGN_PERCENTILE_99
Align the time series by using percentile aggregation. The resulting data point in each alignment period is the 99th percentile of all data points in the period. This aligner is valid for GAUGE and DELTA metrics with distribution values. The output is a GAUGE metric with valueType DOUBLE.
アウトプットはDOUBLE
型
この時点でもうヒストグラムではなくなる
つまり
- まず
ALIGN_PERCENTILE_99
- 各リソースについて、
alignmentPeriod
ごとに99th percentileの値=レスポンスタイム(ms)が計算される
- 各リソースについて、
- その後
REDUCE_SUM
-
groupByFields
に基づいて↑の結果を「合計」 - ここの合計は、本当にレスポンスタイムの値が足し算されてしまう
-
こっちの場合、「レスポンスタイム足し合わせたらダメでは???」とイメージしたことが本当に発動している
実際のところ、 resource.labels.backend_scope
が "asia-northeast1-a"
, "-b"
, "-c"
に散らばったときに足し算が発生し、Stackdriver上でだけ、まるで2倍遅いレスポンスタイムがあったかのように見えていた
雑記
- 設定ミスしたおかげでよくわかってないけど放置してしまっていたところを調べる気になって、いろいろと知らなかったことがわかった
- _Total Latency_より_Backend Latency_で監視したほうがよかったりする・・・?
- Latency系はデフォルトダッシュボードまるパクリで良さそうだけど、Request Count系は
ALIGN_RATE
よりALIGN_SUM
の方がよくないだろうか - WebConsole上のチャートで時間のスケール(1h ,6h ,1d, ...)を変えると、左パネルの設定を無視して自動的に
alignmentPeriod
が変わるから要注意 - こういうデータフォーマットしてるのってモニタリング界隈では標準的なのかstackdriver独自なのか?
- Datadogだと99th percentileはおろかmaxも取れずavgしかないのってみんなどうしてるんだろう