注意: このブログは私のプラクティスを記述したもので、 OpenTelemetry 公式の方法を紹介したものではありません。
OpenTelemetry Collector をプロダクションにデプロイする時、自分がつかうコンポーネントのみを含めた Collector をカスタムビルドすることが推奨されています。 カスタムビルドは ocb (OpenTelemetry Collector Builder) を使っておこないます。このブログでは ocb のバージョンを固定する方法を紹介します。 ocb を使った Collector の作り方自体は他のブログに譲ります。
結論を先に言うと tools.go を用いた方法です。 Go に詳しい方ならすぐわかると思います。次のページが詳しいです。
簡単に言うと Go のモジュールマネージャに ocb のバージョンを固定させます。 Go のモジュールマネージャは次のチュートリアルが詳しいです。このブログでは実行するコマンドを書くだけに留め、詳しい説明は次のブログを参照してください。
また(このブログを書いたときの最新バージョンは Go 1.23)将来のバージョン Go 1.24 からは tools.go ではなく、もっと簡潔な方法できるようになりそうです。
前提
Git などのバージョン管理ツールを使って OpenTelemetry Collector builder の設定ファイルやバージョンを管理しようとしている。
以下の説明は Git で管理しているディレクトリ mycustomcollector/ の中で実行しているとする。 また mycustomcollector/ には OpenTelemetry Collector Builder の設定ファイルがあるとする。
$ pwd /path/to/mycustomcollector $ ls builder-config.yaml # OpenTelemetry Collector Builder の設定ファイル
go mod init
Go のモジュールを初期化しましょう。次のコマンドを実行します。
go mod init {このディレクトリをおくリポジトリのURL}{/ディレクトリ...}
{}
内は適宜値を入れてください。お試しで作る場合、つまりリポジトリにおかない場合、{}
内は何でもいいです。Go のモジュールを定義するファイル go.mod を生成します。 go.mod にはモジュールが依存するサードパーティモジュールも記述します。後々の説明で依存モジュールに ocb を含めます。これによって Go に ocb のバージョンを管理させるのです。
この説明では以下、
go mod init example.com/mycustomcollector
を実行したとします。
tools.go を書く
次のようなファイルを作ります。tools.go という名前にします。
//go:build tools package tools import _ "go.opentelemetry.io/collector/cmd/builder"
tools.go は普通の Go プログラムのファイルです。tools.go というファイルを Go が特別扱いすると言うわけではありません。名前も tools.go でなくても良いですが、習慣的に tools.go となっています。
先頭の行の //go:build
は Build Constraints と呼ばれるもので、コードをビルドするときにこのファイルを含めるかの条件を書くものです。例えば Unix-like な環境だけビルドに含めたいファイルは //go:build unix
と書きます。Go は今回の条件である tools
を (unix
や windows
などと違って) 知りません。この場合、常にビルドに含まれないファイルとなります。
"go.opentelemetry.io/collector/cmd/builder"
をインポートするだけのファイルです。go.opentelemetry.io/collector/cmd/builder は ocbのパスですね。通常の Go のコードではライブラリをインポートしますが、ここではコマンド (ocb) をインポートします。これによって go.mod に記述された依存モジュールに ocb を追加させるのです。
import
と "go.opentelemetry.io/..."
の間にある _
を忘れないようにしてください。ブランクインポートと言うものです。詳しい説明は省きます。
go mod tidy を実行する
go mod tidy
はgo.mod を整頓するコマンドです。モジュール以下にある Go のコードファイルを探し、go.mod に記述していない依存サードパーティパッケージを go.mod に追加したり、 go.mod にあるのに誰も依存していないサードパーティパッケージを消したりします。今回は tools.go が依存しているパッケージである ocb を go.mod に追加します。
go mod tidy
すると go.mod は次のようになります。
module example.com/mycustomcollector go 1.23.3 require go.opentelemetry.io/collector/cmd/builder v0.116.0 require ( github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect github.com/knadh/koanf/parsers/yaml v0.1.0 // indirect github.com/knadh/koanf/providers/env v1.0.0 // indirect github.com/knadh/koanf/providers/file v1.1.2 // indirect github.com/knadh/koanf/providers/fs v0.1.0 // indirect github.com/knadh/koanf/v2 v2.1.2 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/spf13/cobra v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/mod v0.22.0 // indirect golang.org/x/sys v0.21.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect )
またパッケージのハッシュが記録された go.sum も生成されます。
generate.go ファイルを作る
この準備が終わると、 go.mod があるディレクトリ以下で
go run go.opentelemetry.io/collector/cmd/builder
と実行すると、常にバージョンが固定された ocb が実行されます。上の go.mod ならば常に v0.116.0 の ocb が実行されることになります。
毎回 go run go.opentelemetry.io/collector/cmd/builder
を実行してもよいですが、長いし、めんどくさいので go generate
コマンドで実行できるようにしましょう。
次のような Go のプログラムのファイルを作ります。名前は何でもいいですが、generate.go にしました。たった2行です。
package mycustomcollector //go:generate go run go.opentelemetry.io/collector/cmd/builder --config {builder の設定ファイル} --skip-compilation
{builder の設定ファイル}
は今回の場合 builder-config.yaml になります。
go generate
はモジュール以下にある go のソースコードから //go:generate {cmd ...}
と書かれた行を探して cmd ...
を実行するコマンドです。Go ではソースコードを自動生成することが多々あり、その用途に使われることが多いです。 ocb はカスタムコレクターのソースコードを生成するもので、この用途にぴったりですね。
--skip-compilation
はカスタムコレクターのソースコードを生成するだけで、コレクターのバイナリを作らないように ocb に指定するものです。私の場合、バイナリ自体は Docker でビルドするのでバイナリのビルドが不要です。
コレクターを生成する
ここまで準備をしたらあとは go generate を実行するだけ ocb が実行され、カスタムのコレクターのコードが生成されます。
go generate
ここまで実行するとカレントディレクトリは次のようになっているはずです。
collector/
は ocb が自動生成したコレクターのソースコードが入っているディレクトリです。 ocb の設定ファイル builder-config.yaml で ./collector に出力するように指定しました。
$ ls -F -1 collector/ builder-config.yaml generate.go go.mod go.sum tools.go
今後 builder-config.yaml を変更したとき
ocb の設定ファイル builder-config.yamlを変更したら、毎回 go generate
をしましょう。バージョンが固定された ocb でコレクターをビルドしてくれます。
自動生成された collector/ 以下を git で管理するか?
Go では自動生成したファイルも git add
するのが習慣になっています。その延長で私は ocb が自動生成した collector/ 以下も git で管理しています。ただこれは私がそうしているだけで OpenTelemetry 公式がそのように書いた文章があったわけではないです。