Diary of a Perpetual Student

Perpetual Student: A person who remains at university far beyond the normal period

Mackerelのメトリックと集約

arthur-1 Mackerel Advent Calendar 2023ラソン22日目の記事です。

メトリックの時間方向の集約

Mackerelのグラフは表示範囲を広くしていくとメトリックの粒度がどんどん荒くなっていきます。これは、Mackerel内製の時系列データベースが、周囲の点の平均を取ることで点の数を間引いていることによって起こります。以後、このように時間方向に点を間引く操作を集約(aggregation)と呼びます。

集約はどうして行われるのでしょうか。

ひとつは大域的な変化に着目しやすくするためです。表示範囲を広くしてグラフを見ているとき、1分単位の細かな変動よりも大域的な変動に着目したいはずです。1分単位でグラフを描画するとグラフがギザギザしてしまい、本来着目したい変化がわかりづらくなってしまうことがあります。

二つ目の理由に、通信量の最適化が挙げられます。点を間引きたいだけならクライアントであるWebコンソール側で行えば良いのですが、時系列データベース上ですでに間引いたものをユーザーに返しています。必要のない点をレスポンスに載せないことで、通信にかかる時間や大量のデータをクライアントで処理する時間が減り、結果として高速にグラフを描画することができます。

また、Mackerelの時系列データベースでは集約した結果をメモ化しておくことにより、表示範囲が広くなっても高速にグラフを描画できるようにしています。例えば1か月(30日)間のグラフを表示するには1系列あたり最大で43,200個の点が必要です。これをリクエストの度に集計して100個ほどに間引くのは計算コストが大きいため、あらかじめ特定の粒度に間引いたものをストレージに保管しています。ある程度古いメトリックがもう更新され得ないことを利用したテクニックです。

そもそも投稿時からすでに集約されている

この集約はDiamond上だけで行っているように見えるものの、実際にはユーザーがメトリックを投稿する際に似た操作を自然と行っています。この文脈においてはサンプリングという言葉を用いた方がわかりやすいかもしれません。

mackerel-agentは1分間に一度システムメトリックを取得してMackerelに投稿しています。これらのメトリック(の源泉となる値)は実際には連続した時系列データと捉えることができ、その濃度(cardinality)は連続体濃度になります。平たく言えば数えられないほど無限に点が存在するということですね。しかし、無限回数システムメトリックを取得することはいろんな意味で不可能だしする理由もないでしょう。そこで、一定の間隔で計測することで間引いているというわけです。本来であればここでサンプリング定理などに触れるべきだし、数学的にはもっと厳密な表現をしたいところですが、主題ではないのでこの程度にしておきましょう。

Mackerelの仕様上メトリックの最小粒度は1分であることから、1分よりも細かいメトリックを1分単位のメトリックに集約してから投稿するのはユーザーの責務になります。この話題としては、cloudwatch-logs-aggregatorを用いた手法を過去にご紹介しました。

blog.arthur1.dev

Mackerel上での集約は平均だけであることに注意

ユーザーがMackerelに投稿するためにどのような集約方法を用いたとしても、Mackerelのグラフを描画するために行われる集約方法は平均のみです。これを意識せずにグラフを閲覧すると、思わぬ誤解を生んでしまう可能性があります。

一番分かりやすいのは何らかの(分単位の)実行数をグラフで閲覧しているケースです。

これはmackerel-plugin-mysqlを用いて計測したクエリの実行数のグラフです。これは2日間粒度のグラフになっています。

このグラフを見てSelectクエリが2日間で70回ほど実行されていると思った方は要注意!これは分単位で数えられたものの平均値なので、「この時刻のあたりでは1分あたり70回ほどのSelectクエリが実行されている」と読み解くのが正しいです。もし2日間でどれほどのクエリが実行されているかが知りたければ、毎分メトリックを投稿しているなら掛け算をすると良いでしょう。2日間/1分=2880なので、2880倍してあげると2日間で実行されたSelectクエリの数が20万ほどと概算でわかります。

システムメトリックは平均で構わないが

mackerel-agentがシステムメトリックだけをMackerelに投稿するような時代には時系列データベース上の集約が平均だけで良かったのですが、先ほどの例のように平均ではなく合計を集約に用いたいケースが現代にはたくさん存在します。他にもレイテンシの集約のためなどに最大・最小あたりは欲しいです。

前述の通り、Mackerelは1分単位より細かいメトリックを受け付けられないので、ユーザーの責務で1分単位に集約する必要があります。この集約の方法に合わせてMackerel上の集約方法も選択できるようになる未来にしたいなと思っています。最初に紹介した時系列データベースのメモ化の仕様上、この夢を実現するためにはやることがたくさんあって大変なのですが……