はじめに
こんにちは、Datadog Japan で Sales Engineer をしている AoTo です。
オブザーバビリティで主要なシグナルとされるメトリクス・ログ・トレースはそれぞれ異なる特徴を持ったテレメトリーシグナル(監視データ)です。それぞれの目的・データ形式・運用上の課題・データ特性を考慮して、オブザーバビリティを拡大することが重要です。
今回はその中でも「メトリクスと次元(ディメンション)」に焦点を当てて解説します。
解説ではオブザーバビリティの共通認識としてまとめられている CNCF Tag Observability の『Observability Whitepaper』、標準化の例として OpenTelemetry/Prometheus・製品ベンダーの例として Datadog の公式ドキュメントを参考に解説を行います。
考慮事項
本投稿では以下の用途で表現を使い分けます。
- 監視情報: 後述のテレメトリーシグナルとそれから得られた分析情報などを含む、監視に関わる全てのデータ
- テレメトリーシグナル: 文脈上はシステム監視データと同義、人間や機械が知識を推測できるシステムの出力
- メトリクス: 時系列の数値データ
- メトリック: メトリクスの単一のデータ
メトリクスの特徴
メトリクスは最も一般的に収集・参照されるテレメトリーシグナルの一つです。
これらは単数系でメトリックとも呼称され、単数の場合は単一の種類または単一のデータであることを表します。ここでは、後者の単一のデータを指してメトリックと表現します。
メトリクスの各データは、必ずどの時点のデータであるかのデータポイントと、その時点での何かしらを表現する数値が対のメトリックとして表現されます。もちろん、どのようなメトリクスであるかを示す名称と値のデータ型(整数、浮動小数点など)、そして測定単位をメタデータ・ラベルとして付与します。
こうしたメタデータ・ラベルの組み合わせを、次元(demension) と呼びます。
さらに、メトリクスは不連続にデータポイント毎に数値を記録・集計するため、完全なデータではありません。このデータポイントの間隔を粒度や解決時間(resolution) と呼びます。
気温を例にすると、1分毎に気温計の温度を測れば1分間隔の気温の推移が分かりますが、その間にどのように気温が変化したかの詳細情報は欠落しています。
OpenTelemetry Docs『Metrics Data Model』より Gauge メトリクスの説明から引用
メトリクスは、大きく数値データと集約データの2つに分類できます。
さらに、メトリクスのタイプ(種類)は5つに分けられます。1
異なるメトリクスタイプであっても、メトリクスの基本的な特性は同じです。
こうした特性によりメトリクスは効率的なシグナルであり、モニタリングにおいても重要なテレメトリーシグナルとして広く活用されています。
- 事前に記録・収集間隔(resolution)が決まっているため、トラフィック量に応じてボリュームが増加しない
- メタデータ(次元)毎のグルーピング・フィルタリング・集計ができ、統計的な推測・分析ができる(長期計画の策定、インシデントの事後分析)
- 少量のデータから状況の概要を素早く把握したり、最も迅速に障害検知を行える
このようにメトリクスはシステム全体の動作と健全性を迅速に把握するために役立ちます。
一方で、そのメトリクスの変化要因を直接的に把握したり、障害の根本原因分析を行うためには情報が不足しています。こうした、どうして・何が起きたなどの情報は、ログ・トレースなどの他のテレメトリーシグナルに遷移し調査することが有効です。
メトリクスの次元とカーディナリティ
ここまでの解説を踏まえると、メトリクスは軽量で収集が容易なテレメトリーシグナルであり、様々な種類のメトリクスを様々な箇所から取得すると良いように見えるかもしれません。
しかし、ここで注意しなければならないのでメトリクスのカーディナリティです。メトリクスにおいてカーディナリティとは、一定期間に収集された一意のメトリクス名を持つ一連のメトリクスの数です。カーディナリティはメトリクスのメタデータである次元(demension)の種類×数で乗算されます。
再度、気温を例に考えてみましょう。気温は日本では少なくとも北海道・東北・関東・中部・関西・中国・四国・九州・沖縄のように複数地点でデータを収集します。これが都道府県毎になればカーディなリティは9つから47になりますし、市区町村毎になればあっという間に1000を超えます。さらにこれに、観測機器の種類やメーカー温度計の種別など細かな情報を含めると一気にそのカーディナリティは増加します。
このように、特にシステム上のメトリクスは急激に増加するリスクが高いものです。例えばメタデータとしてプロセス ID やユーザー ID などの上限のない一意な識別しを条件を付与すると、実質的に無制限にカーディナリティが増加する要因となります。
カーディナリティが増加すると、それらを保持するコストが比例して増加し、セルフマネージドなプラットフォームの場合は大量なデータによる分析パフォーマンスへの悪い影響が懸念されます。
こうした高カーディナリティの問題は、メトリクスの特性を理解しないまま利用することで頻繁に発生します。持続的に観測対象とする必要がない次元(demension)や、存続期間が短く頻繁に入れ替わる次元(demension)の付与の代わりに、集約した値を利用するかログ・トレースなど別のテレメトリーシグナルを利用することを検討しましょう。
プラクティス
メトリクスのカーディナリティが増加しすぎないためにも、いくつかの対処を行うことが推奨されます。メトリクスの生成時・取得時・保管時にそれぞれメトリクスのカーディナリティへの影響を考慮した対処が行えます。
生成時のラベル付け
メトリクスのカーディナリティが無制限に増加してしまう場合、メタデータ・ラベルとして付与された測定単位が細かすぎるか、分析に向いていないものであることがほとんどです。
さらにこうしたメタデータ・ラベルは、「トラフィック量に応じてボリュームが増加しない特性」を損ないます。トラフィック量に応じてメタデータ・ラベルが増加することで、カーディナリティが大幅に増加し場合によってはその組み合わせから天文学的な数字へと爆発してしまいます。
そのため、そもそもこうした単位で測定・記録を行わないことが最も重要で簡単なプラクティスとなります。メタデータをどういった次元(demension)・どのくらいの頻度(resolution)で取得するかで、そのカーディナリティは大幅に変化することを念頭に取得するメトリクスを考慮しましょう。
取得時のフィルタリング
既にこうした測定単位でメトリクスを生成している場合や、詳細な測定単位から集計値を算出したい場合は、メトリクスの取得時にメタデータ・ラベルのフィルタリングを行い、分析時に少ないカーディナリティでメトリクスを扱えます。
Promethus は pull 型のアーキテクチャで問い合わせたメトリクスのみを取得することができます。relabel_config
を活用すると、メトリクスの取得前にメタデータ・ラベルを集約し、カーディナリティを減らせます。
他にも、push 型で収集されたメトリクスから分析に不要なメタデータ・ラベルを破棄することでカーディナリティを下げ、コストを削減できます。Datadog の Metrics without Limits™︎ は収集したメトリクスを保持する際に、選択的にラベルを指定しカーディナリティを減らした状態のメトリクスを保持できます。
保管時のロールアップ
それでも大量のカーディナリティのメトリクスを保管してしまった場合、保存プラットフォーム側で利用状況や保管日数でのメトリクスのロールアップを行い、コストを削減する必要があります。
ロールアップの仕組みは主にプラットフォーム側で自動的に制御されます。Datadog の場合はこうしたロールアップを行わないのが特徴ですが、プラットフォームによっては数日間の保持の後データをロールアップします。
ロールアップの手法としては時系列ロールアップが一般的です。1分粒度のメトリクスであれば5分・1時間とメトリックを集約しその平均値などにデータを集約して保持コストを最適化します。
おわりに
メトリクスの特性である次元・カーディナリティを理解することで、メトリクスの特性から恩恵を受けて効率的・迅速にシステムの状態を把握することができます。
今回解説できなかった、時間性によるメトリクスの捉え方や思想の違いと相互互換性なども、メトリクスの特性を深く理解するには大切です。是非、参考文献を直接確認し、メトリクスを使いこなしていきましょう🐶
参考文献
- CNCF Tag Observability 『Observability Whitepaper』
- OpenTelemetry『Metrics Data Model』
- Prometheus『DATA MODEL』
- Datadog『Metrics』『Metrics Types』『Distribution』
-
カウント(count)は合計(sum)とも表現され、ヒストグラムと分布は区別されない場合がありますが、以下は最も区別が多い Datadog の説明に合わせています。 ↩