otelcol-contrib を printf デバッグする方法。または、パッチをあてた receiver を含むバイナリをビルドする方法
opentelemetry-collector はプラグイン機構を備えていることが魅力の一つです。様々な送信先・受信元に対応するためにビルド時点で、何からの受信・送信ができるバイナリを作るかを YAML で設定出来るようになっています。
主なプラグインは opentelemetry-collector-contrib というレポジトリにありますが、この中で管理されているモジュールたちは、たくさんのコントリビューターが寄贈したものであって、クオリティやできる事もまちまちで、玉石混淆という感じです。
otelcol-contrib にあるモジュールを printf debug したくなったときや、パッチを当てたカスタムバージョンを使いたくなったときにどうすればいいかを本稿では解説します。
どのようにビルドするか
普通のプロジェクトであれば、 open-telemetry/opentelemetry-collector-contrib を git clone してきてビルドすれば良いのですが、このレポジトリをサッとみても、どうやってビルドしたら良いのかを理解するのは難しいです。
実は公式ドキュメントに Building a custom collector
というドキュメントがあるのでこれを参考にすれば良いです。
カスタムバイナリを作るための方法を紹介するためのドキュメントとしてよく紹介されている本ドキュメントですが、デバッグをするときにもこのドキュメントを参考にします。
otelcol のビルドは mac 環境などでも手元で行えますが、ちょっといじるぐらいなら、docker container としてビルドしてしまったほうが楽なので、僕はそうしてしまいます。
以下のように Dockerfile を置きます。
ここで、ocb というツールを利用するのですが、このバージョンは builder-config.yaml に書くバージョンと合わせないといけない事に注意。
FROM alpine:3.19 AS certs
RUN apk --update add ca-certificates
FROM golang:1.25.0 AS build-stage
WORKDIR /build
COPY ./builder-config.yaml builder-config.yaml
RUN --mount=type=cache,target=/root/.cache/go-build GO111MODULE=on go install go.opentelemetry.io/collector/cmd/builder@v0.140.0
RUN --mount=type=cache,target=/root/.cache/go-build builder --config builder-config.yaml
FROM gcr.io/distroless/base:latest
ARG USER_UID=10001
USER ${USER_UID}
COPY ./collector-config.yaml /otelcol/collector-config.yaml
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --chmod=755 --from=build-stage /build/otelcol-dev /otelcol
ENTRYPOINT ["/otelcol/otelcol-dev"]
CMD ["--config", "/otelcol/collector-config.yaml"]
EXPOSE 4317 4318 12001
builder-config.yaml は以下のように書く。
dist:
name: otelcol-dev
description: Basic OTel Collector distribution for Developers
output_path: ./otelcol-dev
exporters:
- gomod: go.opentelemetry.io/collector/exporter/debugexporter v0.140.0
processors:
- gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.140.0
receivers:
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver v0.131.0
providers:
- gomod: go.opentelemetry.io/collector/confmap/provider/envprovider v1.18.0
- gomod: go.opentelemetry.io/collector/confmap/provider/fileprovider v1.18.0
- gomod: go.opentelemetry.io/collector/confmap/provider/httpprovider v1.18.0
- gomod: go.opentelemetry.io/collector/confmap/provider/httpsprovider v1.18.0
- gomod: go.opentelemetry.io/collector/confmap/provider/yamlprovider v1.18.0
ここで、go.opentelemetry.io/collector/ が書いてある行に書いてあるバージョンは ocb のバージョンと合わせないとビルド出来ない、ということです。
最後に collector-config.yaml をおいたらビルド出来ます。
receivers:
hostmetrics:
scrapers:
cpu:
exporters:
debug:
verbosity: detailed
service:
pipelines:
metrics:
receivers: [hostmetrics]
exporters: [debug]
docker build -f Dockerfile -t myotelcol . とかするとビルド出来ます。
docker run --rm myotelcol とかで起動できる感じ。
どのように既存コードを置換するか
ここでは hostmetrics のコードを置換することを考えます。
opentelemetry-collector-contrib のレポジトリをクローンしてきて、v0.140.0 をチェックアウトします。ここでも ocb のバージョンと合わせる必要があることに注意してください。
./receiver/hostmetrics にコピーを入れます。
つぎに builder-config.yaml に replaces: セクションを入れます。
dist:
name: otelcol-dev
description: Basic OTel Collector distribution for Developers
output_path: ./otelcol-dev
exporters:
- gomod: go.opentelemetry.io/collector/exporter/debugexporter v0.140.0
processors:
- gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.140.0
receivers:
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver v0.131.0
providers:
- gomod: go.opentelemetry.io/collector/confmap/provider/envprovider v1.18.0
- gomod: go.opentelemetry.io/collector/confmap/provider/fileprovider v1.18.0
- gomod: go.opentelemetry.io/collector/confmap/provider/httpprovider v1.18.0
- gomod: go.opentelemetry.io/collector/confmap/provider/httpsprovider v1.18.0
- gomod: go.opentelemetry.io/collector/confmap/provider/yamlprovider v1.18.0
replaces: # ここ
- github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver => ../receiver/hostmetricsreceiver
これにより、hostmetricsreceiver がローカルのものに差し替えられます。
Dockerfile の中で receiver をコピーするようにします。
FROM alpine:3.19 AS certs
RUN apk --update add ca-certificates
FROM golang:1.25.0 AS build-stage
WORKDIR /build
COPY ./builder-config.yaml builder-config.yaml
# ここ
COPY ./receiver/ ./receiver/
RUN GO111MODULE=on go install go.opentelemetry.io/collector/cmd/builder@v0.140.0
RUN builder --config builder-config.yaml
FROM gcr.io/distroless/base:latest
ARG USER_UID=10001
USER ${USER_UID}
COPY ./collector-config.yaml /otelcol/collector-config.yaml
COPY /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY /build/otelcol-dev /otelcol
ENTRYPOINT ["/otelcol/otelcol-dev"]
CMD ["--config", "/otelcol/collector-config.yaml"]
EXPOSE 4317 4318 12001
最後に以下のようにデバッグメッセージをいれて docker build します。
diff --git receiver/hostmetricsreceiver/factory.go receiver/hostmetricsreceiver/factory.go
index 6df9c0d..300ff94 100644
--- receiver/hostmetricsreceiver/factory.go
+++ receiver/hostmetricsreceiver/factory.go
@@ -64,6 +64,7 @@ func mustMakeFactories(factories ...scraper.Factory) map[component.Type]scraper.
// NewFactory creates a new factory for host metrics receiver.
func NewFactory() receiver.Factory {
+ fmt.Printf("NewFactory!!!!!!!!!!!!!!!\n\n")
return receiver.NewFactory(
metadata.Type,
createDefaultConfig,
そうすると、以下のようなメッセージが出ます。

まとめ
ocb を使ってカスタムビルドするときに replaces を使うことでソースコードを差し替えられるので、コレを使ってどんどん開発していきましょう!
Discussion