
この記事は hacomono Advent Calendar 2025 の7日目の記事です
はじめに
こんにちは。SRE部のiwachan(@Diwamoto_)です。
気づけばhacomonoに入ってもう2年になります。
hacomonoに入社してすぐに生まれた娘ももう少しで2歳です。成長曲線を大きく上に逸脱している娘は12kgを突破し、心なしか自分の腕も太くなっているような気がします。
今回は、hacomonoのO11yに対する課題を解決するために OpenTelemetry を導入しようとした奮闘の記録を残します。
TL;DR
- OpenTelemetry Collector Contrib は多くの場合不要
- カスタム OpenTelemetry Collector を使うと場合によっては SideCar を減らせる
- Datadog Agent のトレースを OpenTelemetry Collector で受けることができ、APMをコスパよく使える
- ECSのテレメトリ収集目的のSideCarはOpenTelemetry Collector に全部任せろ
想定読者
- OpenTelemetry の導入を検討されている方
- カスタム OpenTelemetry Collector とはなんぞやとなってる方
- Datadog APM の料金に悩まされてる方
内容
課題
hacomonoのマルチテナント環境ではすでに Datadog APM が導入されていますが、アクセス量が膨大なため、コスト面を考慮してサンプリングを実施していました。その結果、調査に必要なトレースが取得できないケースが発生するという課題を抱えていました。
hacomonoのマルチテナントについてはこちらを参考にしてください。
この課題に対して調査を進めたところ、OpenTelemetry Collector のテールサンプリング機能を活用すれば、重要なトレースを確実に取得できることがわかりました。
Datadog Agent でも同様のテールサンプリング 「エラートレース」「レアトレース」がありますが、「最大 10 トレース/秒 (Agent 毎) 」「最大で毎秒 5 トレース (Agent 毎) 」等の制限があり、hacomonoのアクセス量だと耐えられない可能性があったため、OpenTelemetry Collector の選定に至りました。
具体的には、以下のような設定を検討しました。
# Tail-based Sampling: # エラーや遅いリクエストを優先的に保持し、正常なトレースは 10% サンプリング # コスト削減と重要なトレースの保持を両立 tail_sampling: decision_wait: 10s # トレース完了を待つ時間 num_traces: 100 # メモリ内で保持するトレース数 expected_new_traces_per_sec: 10 policies: # エラートレースは 100% 保持(5xx サーバーエラー、4xx クライアントエラー) - name: errors-policy type: status_code status_code: {status_codes: [ERROR]} # 遅いリクエストは 100% 保持(1500ms 以上) # パフォーマンス問題の調査に必須 - name: latency-policy type: latency latency: {threshold_ms: 1500} # 正常なトレースをランダムサンプリング # サンプリングレートは環境変数 SAMPLING_PERCENTAGE で制御(例: 10 = 10%) # コスト削減しつつトラフィックパターンを把握 - name: randomized-policy type: probabilistic probabilistic: sampling_percentage: ${STANDARD_TRACE_SAMPLING_PERCENTAGE}
リリース前の現在は STANDARD_TRACE_SAMPLING_PERCENTAGE を100に設定しています。これにより、開発フェーズではすべてのトレースを取得し、デバッグに活用しています。
カスタム OpenTelemetry Collectorをビルドしてみた
さっそくこの設定を使いたいと思い調査を進めたところ、OpenTelemetry Collector Contrib というものがあり、コミュニティが開発した多くのコンポーネントが含まれていることがわかりました。しかし、Contrib に含まれるコンポーネントの大半は今回のユースケースでは使用せず、本番環境で動作させるには無駄が多いと感じました。
そこで、 OpenTelemetry Collector Builder を使用して、必要なコンポーネントだけを組み込んだカスタム OpenTelemetry Collector をビルドすることにしました。実際に使用した設定は以下のとおりです。
# OpenTelemetry Collector Builder Configuration # カスタムコンポーネントを組み込んだ OpenTelemetry Collector をビルドするための設定 # hacomono-otel-collector という名前でビルドされます dist: name: hacomono-otel-collector description: Custom OpenTelemetry Collector for hacomono output_path: /tmp/dist version: 1.0.0 # Receivers: テレメトリーデータの受信元 receivers: # datadog: Datadog Agent 互換のレシーバー(Datadog SDK からのトレースを受信) - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/datadogreceiver v0.136.0 # filelog: ファイルからログを読み取り(nginx ログの収集) - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/filelogreceiver v0.136.0 # awsecscontainermetrics: ECS コンテナのメトリクスを収集(CPU、メモリ使用率など) - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/awsecscontainermetricsreceiver v0.136.0 # Processors: テレメトリーデータの加工・フィルタリング processors: # batch: データをバッチ処理して効率的に送信(ネットワーク負荷軽減) - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.136.0 # memorylimiter: メモリ使用量を制限して OOM を防止 - gomod: go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.136.0 # attributes: スパンやログに属性を追加・削除・変更 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor v0.136.0 # resource: リソース属性(サービス名、環境など)を設定 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor v0.136.0 # tailsampling: トレース全体を見てからサンプリング判定(エラーや遅延を優先的に保持) - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/tailsamplingprocessor v0.136.0 # transform: OTTL(OpenTelemetry Transformation Language)でデータを変換 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor v0.136.0 # probabilisticsampler: 確率的サンプリング(指定した割合のトレースを保持) - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/processor/probabilisticsamplerprocessor v0.136.0 # Exporters: テレメトリーデータの送信先 exporters: # debug: 標準出力にデータを出力(トラブルシューティング用) - gomod: go.opentelemetry.io/collector/exporter/debugexporter v0.136.0 # datadog: Datadog にトレース、メトリクス、ログを送信(メイン監視基盤) - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter v0.136.0 # awss3: S3 にログを保存(長期保存・コンプライアンス対応) - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awss3exporter v0.136.0 # awscloudwatchlogs: CloudWatch Logs にログを送信(AWS ネイティブ統合) - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awscloudwatchlogsexporter v0.136.0 # Connectors: パイプライン間でデータを受け渡し connectors: # forward: あるパイプラインから別のパイプラインにデータを転送 - gomod: go.opentelemetry.io/collector/connector/forwardconnector v0.136.0
これで、hacomonoのニーズに最適化されたカスタム OpenTelemetry Collector が完成しました。
これ、ログ収集も一緒にできる...?
上記の設定を見ていただくとお気づきかもしれませんが、filelogreceiverというコンポーネントを使用しています。これを活用すると、ファイルに出力されたログを収集することができます。
さらに、batchprocessorとawss3exporterを組み合わせることで、複数のログを圧縮してS3に効率よく保存できます。つまり、これまで fluent-bit や vector で行っていたログ収集を、OpenTelemetry Collector で一元化できるのです。
この構成により、ログ収集用のSideCarコンテナを削減することができました。
OpenTelemetry SDK ではなく Datadog SDK を使った理由
Lambda でも同様にトレースを取得したかったからです。hacomono では非同期処理に Lambda を使用するケースがあり、 ECS との連携には SQS を利用しています。
まずは OpenTelemetry SDK の利用を検討しましたが、その場合 hacomono → SQS の部分と、SQS → Lambdaの部分でトレースを繋ぎ込む必要があります。
ECS 側はDatadog SDK → OpenTelemetry Collector → Datadog というフローで、
Lambda 側はDatadog SDK → Datadog Lambda Extension → Datadog というフローです。
Datadog SDK を共通で使用することで、ECS → SQS → Lambdaというフロー全体でトレースコンテキストの伝播を容易に実現できます。
OpenTelemetry Collector はdatadogreceiverを利用するとなんと Datadog SDK をそのまま受け取ることができます。素晴らしいです。
Lambda 側では OpenTelemetry Collector を使わなかった
Lambda で Datadog SDK のトレースを受け取って Datadog に転送するためには、 Lambda Extension で OpenTelemetry Collector を動かす必要があります。
ですが、ECS と同じように OpenTelemetry Collector Builder を使うだけでは対応できず、内部的なコードを修正してビルドする必要があることがわかりました。自前で Lambda Extension をビルドした例もありましたが、長期的なメンテナンスの観点から今回は断念しました。
また、Lambda については、ECS と異なりリクエスト数と同数呼ばれるわけではないため、明示的なサンプリングを行わなくてもコスト面で大きな問題は発生しないと判断しました。
導入結果
まだ本番リリース前の段階ですが、すでに開発チームからトレースを活用したコミュニケーションが生まれています。API→Lambdaへと繋がったトレースを見ることで、パフォーマンスの分析や改善にも役立てることができています。導入して良かったと実感しています。

まとめ
今回は、hacomono の O11y の改善のためにカスタム OpenTelemetry Collector を導入した事例をご紹介しました。
テールサンプリングによるコスト最適化、SideCar コンテナの削減、トレースとログの一元管理など、多くのメリットを享受できており、今後のサービス開発においても活用できる知見が得られたと考えています。