OpenTelemetry メトリクス属性とカーディナリティ管理 ​

OpenTelemetryのメトリクスは、単なる数値データだけでなく、そのデータがどのような文脈で発生したかを示す「属性(Attributes)」を持つことができます。この属性は、メトリクスデータを多角的に分析し、問題の根本原因を特定するために不可欠です。しかし、属性の設計を誤ると「高カーディナリティ問題」を引き起こし、監視システムのパフォーマンス低下やコスト増加につながる可能性があります。本記事では、メトリクス属性の重要性、設計のベストプラクティス、高カーディナリティ問題とその対策、およびコスト最適化戦略について解説します。

メトリクス属性の重要性 ​

メトリクス属性は、メトリクスデータに付加されるキーと値のペアで、そのメトリクスが計測されたコンテキストを詳細に記述します。これにより、単一のメトリクス値だけでは分からない、より深い洞察を得ることができます。

属性が提供する価値 ​

  • 多角的な分析: 例えば、http.server.request.duration というメトリクスに http.method や http.route、http.status_code といった属性を付与することで、「GETリクエストの平均処理時間」や「特定のエンドポイントでの5xxエラーの発生頻度」といった詳細な分析が可能になります。
  • 根本原因の特定: サービスが遅延している場合、属性を使って「どのバージョンのアプリケーションで」「どのリージョンで」「どの顧客からのリクエストが」遅延しているのかを絞り込むことができます。
  • フィルタリングとグルーピング: ダッシュボードやアラート設定において、特定の属性値に基づいてメトリクスをフィルタリングしたり、グルーピングして集計したりすることができます。

属性の例 ​

メトリクス名値属性 (Attributes)
http.server.request.duration150mshttp.method="GET", http.route="/users/{id}", http.status_code="200", service.name="user-service"
db.client.connections10db.system="mysql", db.name="user_db", host.name="db-instance-01"
system.cpu.usage75%host.name="web-server-01", os.type="linux", cpu.core="0"

カーディナリティとは? ​

カーディナリティ(Cardinality)とは、特定のメトリクスに付与される属性のユニークな組み合わせの数のことを指します。

低カーディナリティ vs 高カーディナリティ ​

  • 低カーディナリティ: 属性のユニークな値の組み合わせが少ない場合。例: http.method (GET, POST, PUT, DELETEなど数種類)。
  • 高カーディナリティ: 属性のユニークな値の組み合わせが非常に多い場合。例: user.id (数百万のユーザーID)、session.id (セッションごとに異なるID)。

高カーディナリティ問題 ​

高カーディナリティな属性を無制限にメトリクスに付与すると、以下のような問題が発生します。

  • ストレージコストの増加: ユニークな時系列データが増えるため、監視バックエンドのストレージ使用量が爆発的に増加します。
  • クエリパフォーマンスの低下: 大量の時系列データから特定の情報を検索・集計するのに時間がかかり、ダッシュボードの表示が遅くなったり、アラートの評価が遅延したりします。
  • 監視システムの負荷増大: 監視バックエンドやCollectorが処理しなければならないデータ量が増え、リソース消費が増加します。

高カーディナリティ問題の対策とベストプラクティス ​

高カーディナリティ問題は、メトリクス属性を設計する上で最も重要な考慮事項の一つです。以下の対策を講じることで、効果的かつコスト効率の良いメトリクス監視を実現できます。

1. 属性の厳選と標準化 ​

すべての情報を属性として付与するのではなく、本当に分析やアラートに必要な属性のみを厳選します。OpenTelemetryのセマンティック規約に従うことで、属性名の標準化と一貫性を保つことができます。

  • 避けるべき属性:
    • ユーザーID、セッションID、リクエストIDなど、ユニークな値が非常に多い属性。
    • タイムスタンプやランダムな文字列など、常に異なる値を持つ属性。
  • 推奨される属性:
    • サービス名、ホスト名、デプロイ環境、HTTPメソッド、HTTPステータスコード、データベースの種類など、ユニークな値の数が限定的な属性。

2. 属性値の正規化と制限 ​

属性値が自由形式の文字列である場合、意図しないバリエーションが発生し、カーディナリティが高くなることがあります。属性値を正規化したり、許容される値のリストを定義したりすることで、カーディナリティを管理します。

  • 例: http.route 属性で /users/123 や /users/456 のようにユーザーIDを含むパスをそのまま記録するのではなく、/users/{id} のように正規化します。

3. OpenTelemetry Collectorでの属性処理 ​

OpenTelemetry Collectorは、メトリクスデータがバックエンドに送信される前に、属性を処理するための強力な機能を提供します。

  • 属性のフィルタリング: 不要な属性を削除します。
  • 属性のリネーム/マッピング: 属性名を変更したり、複数の属性値を一つの属性にマッピングしたりします。
  • 属性の集約: 高カーディナリティな属性を低カーディナリティな属性に変換します(例: user.id を削除し、user.type に変換)。
  • 属性の追加: 共通の属性(例: region, cluster)を自動的に追加します。

Collector設定例 (YAML) ​

yaml
processors:
  # 高カーディナリティ属性の削除
  attributes/drop_high_cardinality:
    actions:
      - key: user.id
        action: delete
      - key: session.id
        action: delete
      - key: request.id
        action: delete
  
  # http.routeの正規化 (正規表現を使用)
  attributes/normalize_http_route:
    actions:
      - key: http.route
        action: update
        pattern: "/users/\\d+" # /users/123 を /users/{id} に変換
        replacement: "/users/{id}"
      - key: http.route
        action: update
        pattern: "/products/\\d+/items/\\d+" # /products/1/items/2 を /products/{id}/items/{item_id} に変換
        replacement: "/products/{id}/items/{item_id}"

service:
  pipelines:
    metrics: 
      receivers: [otlp]
      processors: [attributes/drop_high_cardinality, attributes/normalize_http_route] # 処理順序が重要
      exporters: [prometheus, googlecloud]

4. サンプリング戦略との組み合わせ ​

トレースデータと同様に、メトリクスデータでもサンプリングを適用することで、高カーディナリティ問題の影響を軽減できます。ただし、メトリクスは集計データであるため、トレースのような確率的サンプリングは慎重に行う必要があります。

  • 属性ベースのサンプリング: 特定の属性を持つメトリクスのみをサンプリング対象から除外したり、サンプリングレートを調整したりします。
  • レート制限: 特定のメトリクスや属性の組み合わせについて、報告される頻度を制限します。

5. バックエンドの選択と設定 ​

使用する監視バックエンド(Prometheus, Grafana Mimir, VictoriaMetrics, Datadogなど)が高カーディナリティデータをどの程度効率的に扱えるかを理解し、それに合わせて設定を最適化します。

  • Prometheus: 高カーディナリティに弱い傾向があるため、Collectorでの前処理が特に重要です。
  • 分散型TSDB: Grafana MimirやVictoriaMetricsのような分散型時系列データベースは、高カーディナリティデータに対する耐性が高いですが、それでも無制限な属性付与は避けるべきです。

まとめ ​

OpenTelemetryのメトリクス属性は、システムの深い洞察を得るための強力な手段ですが、その設計にはカーディナリティ管理という重要な課題が伴います。

課題対策
高カーディナリティ属性の厳選、値の正規化、Collectorでの処理
ストレージコスト不要な属性の削除、サンプリング、バックエンドの最適化
クエリパフォーマンス属性のインデックス設計、集計の事前処理

これらのベストプラクティスを適用することで、メトリクスデータを効果的かつコスト効率良く収集・分析し、システムの健全性を維持・向上させることができます。メトリクス属性の賢い利用は、Observability戦略の成功に直結します。


関連記事: OpenTelemetry メトリクス計測器の種類と活用関連記事: OpenTelemetry メトリクスエクスポーターとバックエンド連携関連記事: メトリクスと時系列データベース(TSDB)の連携設計関連記事: メトリクスのクエリと分析パターン関連記事: メトリクスに基づいたアラーティング設計