OpenTelemetryコレクターで実現する、賢いトレース情報管理とコスト削減

本記事では、OpenTelemetryコレクターを活用してMackerel APMのコストを賢く最適化する方法を解説します。フィルタリングやテイルサンプリングなどの実践的な設定例を交え、必要な情報を逃さずデータ量を劇的に削減する「賢いトレース管理」の具体策を紹介します。

こんにちは。Mackerelチームでサブディレクターとして主にプロダクトマネジメントを担当している id:RyuGoo です。

トレース情報は、アプリケーションの動作を可視化する上で非常に重要です。

しかし、すべてのデータを収集して送信すると、Mackerel APMの利用料金にも直結します。そこで本記事では、OpenTelemetryコレクターを活用して「必要なデータだけを賢く集める」方法を紹介します。特に、Mackerel APMと組み合わせてコストを最適化する実践的な設定例を取り上げます。

OpenTelemetryコレクターの基本を押さえよう

Mackerel APMを導入する際、最もシンプルな方法は、アプリケーションに組み込んだOpenTelemetry SDKからMackerel APMに直接データを送信することです。小規模な構成や検証段階ではこの方法でも十分に機能します。

しかし、システムの規模が拡大したり、マイクロサービス化が進むにつれて、SDKからの直接送信にはいくつかの課題が浮かび上がってきます。

  • アプリケーションへの負荷が増える
    データの送信処理がアプリケーションのパフォーマンスに予期せぬ影響を与える可能性があります
  • 管理が複雑になる
    データの送信先の設定や認証情報の個別管理が求められます
  • データの制御が難しくなる
    「エラーが起きたときだけ送る」「特定の通信は除外する」といった柔軟な調整が難しくなります

これらの課題を解決し、トレース情報をより「賢く」管理するために不可欠なのが、データの中継地点となるOpenTelemetryコレクター(以下、コレクター)です。

コレクターの役割と3つのコンポーネント

コレクターは、テレメトリーデータ(メトリック、トレース、ログ)を収集、加工し、任意の場所へ送信するプロキシとして機能します。大きく分けて次の3つのコンポーネントで構成されています。

  • Receiver(収集)
    アプリケーションやSDKからテレメトリーを受け取ります
  • Processor(加工)
    データのフィルタリング、属性の追加、バッチ処理など送信前の加工処理を担います
  • Exporter(送信)
    加工したデータをMackerelなどのバックエンドに送信します

SDKからの直接送信ではなく、コレクターを間に挟むことで、アプリケーション側に手を加えることなく、一元的に「どのデータを送り、どのデータを捨てるか」を制御できるようになります。

すべてのデータを送ってコストが膨らむ状態から、コレクターでデータを賢く選んで、本当に必要な情報だけをMackerelに送る状態にすることで、オブザーバビリティを高めながらのコスト削減も実現します。

基礎を押さえたところで、次はコレクターの「Processor」を使って具体的にどのように必要なデータを選んでいくのか、その方法を紹介します。

TIPS:MackerelのためのOpenTelemetryコレクター

OpenTelemetryコレクターは非常に強力ですが、多くのコンポーネントが存在するため、初めから自分で構成を組んだり、設定を書いたりするのは手間がかかります。

そこで活用したいのが、Mackerel Distro of OpenTelemetry(MDOT)Collectorです。

github.com

MDOTが提供するMackerel OpenTelemetryコレクターは、MackerelでのOpenTelemetry活用に最適化された公式配布パッケージ(ディストリビューション)です。本記事執筆時点でDockerイメージ、debパッケージ、rpmパッケージの3種類のインストーラーを提供しています。

Mackerel OpenTelemetryコレクターには次のような特徴があります。

  • セットアップを簡単にできる
    Mackerelへの送信に便利なmackerel_otlp Exporterがあらかじめ組み込まれており、最小限の設定ですぐに利用を開始できます
  • 公式サポートの安心感がある
    Mackerelの開発チームによってメンテナンスされており、Mackerelとの相性や信頼性が高く、アップデートも容易です
  • 軽量な運用ができる
    コレクターコンポーネントの中から特に有用性の高いものを厳選してパッケージングしているため、バイナリサイズが小さく、セキュリティリスクの低減にもつながります

コレクターを導入する際には、Mackerel OpenTelemetryコレクターの採用をご検討ください。

コストコントロールに効く! 必要なデータだけを送る方法

トレース情報はアプリケーション内部の非常に詳細な情報を得られる反面、膨大なデータ量とそれに伴うコストに悩まされることになります。

理想的には、システムで発生するすべてのリクエストを記録したいところです。しかし、現実には以下のような課題が立ちはだかります。

  1. 直接的なコストが増大する
    Mackerel APMは「スパン量(送信されたスパンの総量)」に基づく課金体系です。トレース情報の送信量に比例して費用が増えていくため、理由なくすべてのデータを送り続けると、インフラ予算を圧迫する大きな要因となり得ます
  2. インフラへの負荷が増える
    大量のデータを送信し続けることはシステムのCPUリソースやネットワーク帯域を圧迫し、パフォーマンスへの悪影響を及ぼすことがあります
  3. 分析のノイズになる
    大量の情報があっても、トラブル解決に役立つのはその中の数件の情報だったりします。不要な情報が多すぎると、本当に見るべき情報を見つけ出すのが難しくなります

したがって「価値のあるデータを選び、それ以外は捨てる」ことが、コストとオブザーバビリティのバランスを取るために有効な手段となります。コレクターのProcessorを活用して、データ選びを自動化していきましょう。

捨てることから始めるフィルタリング

コスト削減の第一歩は、分析の価値が低いスパンを除外することです。代表的なものとしては、システムの死活監視によるヘルスチェックの通信が挙げられます。これらは短時間に大量に発生しますが、トラブルシューティングで必要になることはまれです。

コレクターではFilter Processorを使うことで、特定の条件に合致するデータを送信前にドロップできます。

設定例:特定のパス(/health)を除外する

processors:
  filter:
    error_mode: ignore
      traces:
        span:
          - 'attributes["url.path"] == "/health"'

このように特定のURLパスや特定のHTTPメソッド(GET以外など)をフィルタリングするだけで、転送量を削減することが可能です。

属性の整理でトレース情報のサイズを削減する

データ量はスパン数だけではなく、1スパンあたりの「サイズ」にも依存します。データ量を減らすことでネットワーク帯域を節約でき、インフラコストを抑えられるかもしれません。

Webアプリケーションフレームワークが自動付与する属性の中には、監視に不要な情報が含まれていることがあります。Attributes Processorを使えば不要な属性を削除し、データ構造をスリムに保てます。

設定例:ヘッダーに付いている不要なCookie情報を削除する

processors:
  attributes:
    actions:
      - action: delete
        key: http.request.header.cookie
      - action: delete
        key: http.request.header.authorization
      - action: delete
        key: http.response.header.set-cookie

コスト削減しながら必要な情報をしっかりと集めよう

前節では不要なデータを捨てる方法を紹介しました。しかし、コストをさらに最適化するには、必要なデータの中でも「送信する頻度」を調整する戦略が必要になります。

そこで登場するのがサンプリングという考え方です。

確率で間引く「ヘッドサンプリング」

最も一般的な手法は、リクエストの開始時点でサンプリングを行うルールを決める方法です。これをヘッドサンプリングと呼びます。一般的に「10%だけ記録する」といった確率ベースのサンプリングが用いられます。

コレクターでProbabilistic Sampling Processorを設定することで、確率によるサンプリングを行えます。この場合のメリット・デメリットは次のとおりです。

  • メリット
    トレースの開始時点でサンプリングが決定されるため、不要なデータがネットワークに流れず、ネットワーク帯域やコレクターの負荷を最も低く抑えられます
  • デメリット
    確率で決まるため、発生頻度の低い「重要なエラー」や「特定の遅延リクエスト」が捨てられてしまうおそれがあります

設定例:10%だけ記録する

processors:
  probabilistic_sampler:
    sampling_percentage: 10

なお、Mackerel OpenTelemetryコレクターを利用している場合は、環境変数を設定するだけでトレースにヘッドサンプリングを適用できます。

github.com

エラーを見逃さない「テイルサンプリング」

“コストを大幅に削りたいけれども、「エラーが起きたときのトレース」だけは絶対に逃したくない”という願いをかなえるのが、テイルサンプリングです。

ヘッドサンプリングではサンプリングの決定はトレースの開始時点で決まりますが、テイルサンプリングは「トレースの終わり」で決定します。つまり、一連の処理が完了した後に、その内容を見て送信するかどうかを判断します。

コレクターでTail Sampling Processorを設定することで、次のような制御が可能になります。

  • エラー発生時
    HTTP通信においてステータスコードが500番台のときは、100%送信する
  • 遅延発生時
    レスポンスに3秒以上かかった場合は、詳細分析のために100%送信する
  • 正常時
    通信に問題がない場合は、統計的な傾向が見られれば十分と判断して1%だけ送信する

設定例:エラー発生時・遅延発生時・正常時についてそれぞれ設定する

processors:
  tail_sampling:
    decision_wait: 30s
    num_traces: 50000
    policies:
      # 1.エラーコードが500番台のときは、100%送信
      - name: errors-policy
        type: status_code
        status_code: {status_codes: [ERROR]}
      # 2.レスポンスに3秒以上かかった場合は、100%送信
      - name: latency-policy
        type: latency
        latency: {threshold_ms: 3000}
      # 3.正常時は1%だけ送信する
      - name: common-policy
        type: probabilistic
        probabilistic: {sampling_percentage: 1}

設定の解説

  • decision_waitオプション
    トレースの最初のスパンを受信してからサンプリング判定を行うまでの待機時間です。デフォルトでは30秒となっています
  • status_codeポリシー
    HTTPステータスコードが500番台など、スパンがエラー判定になっているものを抽出します
  • latencyポリシー ユーザー体験に直結する「遅延」を条件にします。設定例では3秒以上のものをすべて捕捉していますが、upper_threshold_msと併用することで上限値を決められます
  • probabilisticポリシー
    これまでの条件に当てはまらなかった通信に対して、確率によるサンプリング(設定例では1%)を適用します。これによりコストを削減しながら定常的な傾向を把握できるようになります

テイルサンプリングの注意点が1つあります。Tail Sampling Processorは「一連のトレースが揃うまでメモリに貯めておく」という動きをします。そのため、コレクターが動作するサーバーやコンテナ環境には一定のメモリリソースを割り当てておく必要があります(decision_waitnum_tracesなどのオプションを変更してチューニングすることも可能です)。

ここで紹介したオプションやポリシー以外にも、複数の項目が用意されています。最新の情報はGitHubのopentelemetry-collector-contribリポジトリのTail Sampling Processorのドキュメントをご覧ください。

github.com

どれくらいコストは削減できるの?

コレクターによる管理が実際にどれくらいコストに影響を与えるのかを、Mackerel APMの具体的な料金体系に基づいて試算してみましょう。今回は「1リクエストあたり10スパン」が発生する構成を例にします。

Mackerel APMの料金体系

  • 従量課金
    100万スパンごとに300円(税抜)
  • 無料枠
    スタンダードプランの場合、500万スパンまで無料

ケーススタディ:秒間10リクエストのWebアプリケーション

  • リクエスト数
    10リクエスト/秒(月間2,600万リクエスト)
  • 1リクエストあたりの平均スパン数 = 10スパン
    Webアプリケーションフレームワークを使っており、内部でさまざまな処理が動いている想定

パターンA:素直に「全件送信」した場合

すべてのトレース情報をそのまま送信すると、スパン数は多量になり、コストに直結します。

  • 月間総スパン数
    2,600万リクエスト × 10スパン = 2億6,000万スパン
  • 月額費用
    (260(100万スパン単位) - 5(無料枠)) × 300円 = 76,500円

パターンB:コレクターで賢く管理した場合

「フィルタリング」と「サンプリング」を適用し、送信量を全体の10%に最適化したとします。

  • フィルタリング
    ヘルスチェックなどを除外
  • サンプリング
    正常な通信を間引き、異常や遅延のみを100%抽出する

このような設定を行うと、スパン数や費用は以下のような形になります。

  • 月間総スパン数
    2,600万スパン(元の10%にまで圧縮)
  • 月額費用
    (26(100万スパン単位) - 5(無料枠)) × 300円 = 6,300円
項目 パターンA パターンB
月間総スパン数 2億6,000万 2,600万
月額費用 76,500円/月 6,300円/月
削減額 - -70,200円/月

1リクエストあたりのスパン数が多い環境では、全件送信を続けると月額76,500円という金額になります。しかし、OpenTelemetryコレクターを導入して適切なフィルタリングとサンプリングを行うと6,300円となり、10分の1以下の金額にまで抑えることができました。

理想的には、前述のとおり、予算が許すならば「システムで発生するすべてのリクエストを記録したい」ところですが、現実的には予算や目的に応じたコストコントロールが必要となるでしょう。とは言え、コストコントロールを意識しすぎるあまり、必要な情報の取得ができないとなっては本末転倒です。

フィルタリングやサンプリングを賢く使って、必要な情報を逃さないようにしながらコスト削減を実現しましょう。

まとめ

本記事では、OpenTelemetryコレクターを活用したトレース情報の管理とコスト削減について解説しました。OpenTelemetry SDKを使った直接のトレース送信からコレクター経由への構成を変えることで、Mackerel APMのスパン量課金と賢く付き合い、オブザーバビリティの恩恵を長期間にわたって享受できます。

まずはコレクターの導入によってMackerelでオブザーバビリティを実現するための管理基盤を作り、そこからFilterやAttributesを使って情報を削りつつ、Samplingによって質を維持したまま必要な量に絞り込んでいく賢いトレース情報管理を目指しましょう。

もう「なんか遅い」で悩まない!開発者のためのAPM入門

アプリケーションを開発・運用していると、特定の処理が遅い、リクエストごとに応答時間がばらつくなど、「なんか遅い」と感じる場面があります。本資料では、こうした「なんか遅い」と感じる状況に対して、どこから調べればよいのか、何を手がかりにすればよいのかという観点から、APM(アプリケーションパフォーマンスモニタリング)が調査の進め方をどう変えるのかを解説します。

ダウンロードはこちら