Orchestrion(オーケストリオン)は、DatadogがGitHubのDataDog/orchestrionで公開しているGo向けのコンパイル時自動計装ツールです。go buildの途中でソースコードを書き換え、分散トレーシングの計装コードをビルド成果物に織り込みます。アプリケーションのコードにトレーサーの呼び出しを書かなくても、net/httpやデータベースドライバーの呼び出しがスパンとして記録されます。ライセンスはApache-2.0で、2026年10月6日時点の最新版はv1.13.1(2026年9月17日公開)です。
楽器のオーケストリオンやPat Methenyのアルバム「Orchestrion」とは別物です。本記事の旧版では「YAMLでテストを組み立てるテストオーケストレーションツール」と説明していましたが、これは誤りでした。2026年10月に全面改訂し、手元のGo 1.26.5環境でv1.13.1を動かした実測値を加えています。
まとめ:Orchestrionの要点(v1.13.1時点)
- Go標準の
-toolexecフラグでコンパイラとリンカーの呼び出しを横取りし、ビルド時に計装を差し込みます。実行時のエージェント注入やeBPFは使いません。 - 導入は
go install、orchestrion pin、orchestrion go buildの3ステップです。pinがorchestrion.tool.goを作り、go.modに依存を登録します。 - 対応するGoは最新の2リリース(2026年10月時点では1.27系と1.26系)で、Go modulesが必須です。Bazelの
rules_goには対応していません。 - 既定の設定では46のライブラリ連携がまとめて有効になり、ビルドが重くなります。手元の実測では、コード変更後の再ビルドが素の
go buildの約2秒から約45秒に延びました。連携をnet/httpだけに絞ると約18秒に縮みます。 - 関数単位のスパンは
//dd:span、計装の除外は//orchestrion:ignoreというコメントディレクティブで指定します。 - OpenTelemetryにも同じ方式の
otelcがあり、Orchestrionはその寄贈元の一つです。送信先がDatadogならOrchestrion、ベンダー中立を優先するならotelcを選びます。
以下、仕組み、導入手順、連携の選び方、ビルドコストの実測、採用を見送るべき条件の順に説明します。
dd-trace-goの手動計装とOrchestrionの違い
手動計装でライブラリごとに必要になる書き換え
DatadogのGoトレーサー(dd-trace-go v2)を手動で組み込む場合、トレーサーを起動し、計装したいライブラリの呼び出しをcontribパッケージのラッパーに置き換えます。net/httpのサーバーなら次のようになります(dd-trace-go v2.10.1でビルドとgo vetを通したサンプルからの抜粋です。package main、標準ライブラリのimport、handlerの定義は省略しています)。
import (
httptrace "github.com/DataDog/dd-trace-go/contrib/net/http/v2"
"github.com/DataDog/dd-trace-go/v2/ddtrace/tracer"
)
func main() {
if err := tracer.Start(); err != nil {
log.Fatal(err)
}
defer tracer.Stop()
mux := http.NewServeMux()
mux.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8080", httptrace.WrapHandler(mux, "demo", "")))
}
HTTPクライアント、SQLドライバー、Redis、Kafkaと、ライブラリが増えるたびに同じ書き換えが要ります。どこか1か所でラップを忘れると、そこでトレースが途切れます。Datadogの公式ドキュメントは、コンパイル時計装の利点として「手動計装の見落としによるカバレッジの穴を防ぐ」ことを挙げています。
コンパイル時計装が標準ライブラリと依存パッケージまで届く理由
Orchestrionは自分のコードだけでなく、依存パッケージとGo標準ライブラリのソースもビルド時に書き換えます。上のコードからラッパーを外し、素のhttp.ListenAndServe(":8080", nil)のままOrchestrion経由でビルドしても、トレーサーの起動ログにはHTTP連携が計装済み(instrumented: true)として出ました。
もう一つの違いがセキュリティ機能です。DatadogのApp and API ProtectionのExploit Prevention(RASP。SQLインジェクションやローカルファイルインクルードを実行時に止める機能)は、Orchestrionでビルドしたアプリケーションだけが使えます。RASPを使う予定があるなら、手動計装ではなくOrchestrionが前提になります。
go build -toolexecで計装を差し込む仕組み
compileとlinkの呼び出しを横取りする流れ
Goの-toolexecは、go buildが内部で呼ぶgo tool compileやgo tool linkの前に任意のプログラムを挟むためのフラグです。Orchestrionはここに入り、パッケージごとに次の処理をします(公式のArchitectureドキュメントより)。
go/parserでソースを解析し、型チェックする- 有効な連携の規則に合う箇所へコードを挿入し、書き換えたファイルを作業ディレクトリに書き出す(
//lineプラグマで元の行番号を保つ) - 挿入で増えた依存(トレーサー本体など)を
-importcfgに追加して、本物のコンパイラを呼ぶ - リンク時に、増えた依存を
-importcfgへ反映してリンカーを呼ぶ
パッケージごとに短命のプロセスが大量に立つため、OrchestrionはビルドのあいだだけNATSプロトコルのジョブサーバーを起動します。同じパッケージを二重にビルドしないことと、重いpackages.Loadを1回で済ませることが目的です。
実際に挿入されるコードはorchestrion diffで確認できます。手元のサンプルでは、//dd:spanを付けた関数の先頭にtracer.StartSpanFromContextとdefer span.Finish(tracer.WithError(...))が入り、main関数にはトレーサーとプロファイラーの停止処理がdeferで追加されていました。
orchestrion.ymlのアスペクト(join pointとadvice)
どこに何を挿入するかは、各連携パッケージに同梱されたorchestrion.ymlが決めます。書式はアスペクト指向プログラミングに倣っており、挿入位置を表すjoin pointと、加える変更を表すadviceの組で1つのアスペクトになります。dd-trace-goは100を超えるアスペクトを持つため、ビルド中のパッケージがnet/httpをimportしていなければHTTPのアスペクトは評価しない、といった絞り込みをしています。orchestrion.ymlを書けば、Datadog以外のトレーサー向けの連携も作れます。
ビルドキャッシュが無効化される条件
Goのビルドキャッシュは、各ツールが-V=fullで返すバージョン文字列をキーに含めます。Orchestrionはこの応答に、自身のバージョンと、有効な連携・注入されうるパッケージから計算したハッシュを付け足します。Orchestrionの版やorchestrion.tool.goを変えると、キャッシュ済みのパッケージも再ビルドされます。必要以上に無効化される設計であることは公式ドキュメントも認めています。
Orchestrionの導入手順とビルドへの組み込み
go installとorchestrion pinで変わるファイル
まずCLIを入れ、プロジェクトのルート(go.modがある場所)でpinを実行します。
go install github.com/DataDog/orchestrion@latest
export PATH="$PATH:$(go env GOPATH)/bin" # GOBINを設定しているならそのディレクトリを追加
orchestrion pin
git add go.mod go.sum orchestrion.tool.go
git commit -m "chore: enable orchestrion"
@latestで入る版は時期によって変わります。本記事の確認はv1.13.1で行ったので、同じ結果を再現したい場合は@v1.13.1を指定してください。どちらの場合も、使う版はpinがgo.modに固定します。
pinが生成したorchestrion.tool.goは次の内容でした(v1.13.1、コメントは一部省略)。
//go:build tools
//go:generate go run github.com/DataDog/orchestrion pin -generate
package tools
import (
_ "github.com/DataDog/orchestrion" // integration
_ "github.com/DataDog/dd-trace-go/orchestrion/all/v2" // integration
)
toolsビルドタグが付いているので、このファイルは通常のビルドには含まれません。役割は2つで、go.modにOrchestrionとdd-trace-goの版を固定することと、どの連携を有効にするかの宣言です。手元のサンプル(標準ライブラリだけのHTTPサーバー)では、pinの後にgo.modの// indirect行が0行から299行に増えました。Google Cloud Pub/SubやgqlgenなどのSDKが、使っていなくても依存グラフに入ります。
orchestrion go・-toolexec・GOFLAGSの3方式
計装付きでビルドする方法は3つあり、違いは既存のビルドスクリプトをどこまで変えるかだけです。
| 方式 | コマンド例 | 向いている場面 |
|---|---|---|
| orchestrion go(推奨) | orchestrion go build . |
手元の開発・Makefile |
| -toolexec を渡す | go build -toolexec 'orchestrion toolexec' . |
go コマンドを直接呼ぶCI |
| GOFLAGS に入れる | export GOFLAGS="${GOFLAGS} '-toolexec=orchestrion toolexec'" |
スクリプトを変えられないCI・Dockerfile |
GOFLAGS方式では、値の外側の一重引用符を省けません。空白を含むフラグ値は引用符で囲む、というgoツールチェーンの規則によるものです。go testやgo runも同じ方法で計装できます。
計装されたパッケージの確認(-work と orchestrion diff)
どのパッケージが書き換えられたかは、作業ディレクトリを残してビルドし、orchestrion diffに渡すと分かります。-aで全パッケージを再ビルドさせるため時間がかかります。
$ orchestrion go build -work -a .
WORK=/var/folders/.../go-build2535246427
$ orchestrion diff --package /var/folders/.../go-build2535246427
main
net/http
os
runtime
既定設定で手元のサンプルを確かめると、自分のmainのほかnet/http・os・runtimeの4パッケージが書き換えられていました。--packageを外すと、パッケージ名でなく差分そのものが出力されます。
実行時の設定(DD_SERVICE・DD_ENV・DD_VERSION)
Orchestrionでビルドしたバイナリは、生成されたinit関数でDatadogトレーサーを自動起動し、main関数の先頭には終了時のtracer.Stop()を呼ぶdeferを挿入します。サービス名などはコードでなく環境変数で渡します。
DD_SERVICE・DD_ENV・DD_VERSION:統合サービスタグ(service・env・version)DD_PROFILING_ENABLED=true:継続的プロファイラーを有効化(CPU・ヒープ・goroutine・mutex)DD_APPSEC_ENABLED=true:App and API Protectionを有効化(LinuxとmacOSのAMD64・ARM64)。CGOを無効にする場合はappsecビルドタグが必要で、Linuxでは実行環境の共有ライブラリ要件も確認します
Datadog Agentが無い環境ではDIAGNOSTICS Unable to reach agent intakeという警告が出ますが、アプリケーションは通常どおり応答しました。起動ログのDATADOG TRACER CONFIGURATION行には、計装済みの連携と送信先Agentが出ます。mainに//orchestrion:ignoreを付けると自動起動は止まり、tracer.Startを自分で呼ぶことになります。
orchestrion.tool.goによる連携ライブラリの選択
既定のorchestrion/all/v2が有効にする46連携
既定でimportされるgithub.com/DataDog/dd-trace-go/orchestrion/all/v2(v2.10.1)は、トレーサー本体とプロファイラーに加えて46の連携パッケージを読み込みます。
| 分類 | 主な連携(dd-trace-go v2.10.1) |
|---|---|
| 標準ライブラリ | net/http、database/sql、log/slog、os |
| Webフレームワーク | Gin、Echo v4・v5、chi、Fiber v2、Gorilla Mux、httprouter、fasthttp |
| RPC・GraphQL | gRPC、Twirp、gqlgen、graphql-go(2系統) |
| データベース | pgx v5、GORM、MongoDB、gocql、Aerospike、Elasticsearch v6 |
| キャッシュ | go-redis(v6〜v9)、redigo、rueidis、valkey-go |
| メッセージング | Sarama、confluent-kafka-go、kafka-go、franz-go、Pub/Sub |
| クラウド・その他 | AWS SDK(v1・v2)、Kubernetes client-go、Vault |
| ロガー | logrus、zerolog |
一覧はdd-trace-goの版で変わります。正確な対象は、使う版のorchestrion/all/orchestrion.tool.goのimport文で確かめるのが確実です。
必要な連携だけに絞るときの書き方とpinの落とし穴
使っていないSDKまで依存に入るのを避けたいときは、all/v2のimportを個別の連携に置き換えます。net/httpと//dd:spanだけを使うなら、次の3行で足ります。
//go:build tools
package tools
import (
_ "github.com/DataDog/orchestrion"
_ "github.com/DataDog/dd-trace-go/contrib/net/http/v2"
_ "github.com/DataDog/dd-trace-go/v2/ddtrace/tracer"
)
ここに落とし穴があります。この状態でorchestrion pinを実行し直すと、all/v2のimportが追加し直されます。v1.13.1のソース(internal/pin/pin.goのupdateToolFile)を見ると、pinはall/v2を無条件に追加しています。既定のファイルにある//go:generate行もpinを呼ぶので、go generate orchestrion.tool.goのようにファイルを直接指定した場合にも同じことが起きます。ただし、このファイルにはtoolsビルドタグがあるため、通常のgo generate ./...では対象になりません。連携を絞ったら//go:generate行を消し、依存の整理はpinではなくgo mod tidyで行ってください。
Datadogのドキュメントにも注意書きがあるとおり、個別importにした場合は、新しいライブラリを使い始めるたびに自分で連携を追記する必要があります。
//dd:spanと//orchestrion:ignoreによるトレースの調整
//dd:spanによる関数単位のスパン生成
関数宣言または関数リテラルの直前に//dd:spanを書くと、その関数の実行がスパンになります。引数のkey:valueはスパンのタグになります。
//dd:span span.name:compute.total customer:demo
func computeTotal(ctx context.Context, n int) (int, error) {
if n < 0 {
return 0, fmt.Errorf("negative: %d", n)
}
return n * 2, nil
}
スパン名は、span.nameタグ、関数名、最初のタグの値の順で決まります。名前のない関数リテラルでspan.nameも無ければ、最初のタグの値が名前になります。戻り値にerrorがある関数は、nil以外が返るとエラー情報がスパンに付きます。引数にcontext.Context(なければ*http.Request)があればそこからトレースを引き継ぎます。どちらも無い関数はgoroutineローカルの情報に頼るため、goroutineをまたぐとトレースが分かれることがあります。
//orchestrion:ignoreで計装を止める範囲
出力が多すぎる箇所や、手動計装とスパンが重複する箇所は//orchestrion:ignoreで除外します。関数に付ければ関数全体、文に付ければその構文木だけが対象外になります。
//orchestrion:ignore 監視不要なバッチ処理
func noInstrumentationThere() {
// この関数の中はOrchestrionが一切書き換えない
}
ただし、ライブラリの内部に計装を入れる方式(callee側)の連携は、このディレクティブで止められません。公式ドキュメントが挙げる対象はnet/httpのクライアントとサーバー、Gorilla Mux、httprouter、confluent-kafka-go、segmentio/kafka-go、Google Cloud Pub/Subです。これらを止めたいときは、orchestrion.tool.goから該当連携のimportを外します。
手動計装と併用したときのスパン重複
Orchestrionでビルドしたアプリケーションでも、dd-trace-goのAPI(tracer.StartSpanFromContextなど)は普通に使えます。関数に切り出さずに一部区間だけ測りたい場合や、//dd:spanより細かくタグを付けたい場合に向いています。
注意が要るのはcontribのラッパーとの併用です。Orchestrionが同じライブラリを自動計装すると、スパンが二重になります。未対応のライブラリを手で計装している場合、Orchestrionを更新したら必ずリリースノートを読み、自動計装が追加されたライブラリの手動ラッパーを外してください。
Orchestrionのビルド時間とバイナリサイズの実測
計装の代償はビルドです。2026年10月6日、Intel Mac(darwin/amd64)・Go 1.26.5・Orchestrion v1.13.1・dd-trace-go v2.10.1の環境で、標準ライブラリだけを使う約30行のHTTPサーバーを3通りにビルドしました。クリーンビルドはGOCACHEを空にした状態からの計測です。
| 構成 | クリーンビルド | コード変更後 | 変更なし | バイナリ | indirect依存 |
|---|---|---|---|---|---|
| 素の go build | 27.8秒 | 2.0〜3.0秒 | 0.7秒 | 8.5MB | 0行 |
| Orchestrion 既定(all/v2) | 182.1秒 | 43.4〜47.9秒 | 12.4秒 | 25.4MB | 299行 |
| Orchestrion net/httpのみ | 99.5秒 | 17.1〜20.3秒 | 2.6秒 | 23.8MB | 106行 |
差が大きいのは再ビルドです。「コード変更後」はmain.goの文字列を書き換えて3回ずつ測った範囲で、素のビルドが2〜3秒のところ、既定設定のOrchestrionでは43〜48秒かかりました。ソースを変えずに再ビルドしても12.4秒かかります。開発中に何度もgo buildやgo testを回すチームにとっては、クリーンビルドの時間よりこちらの方が負担になります。連携を絞ると、コード変更後は17〜20秒、変更なしなら2.6秒まで下がりました。一方、バイナリサイズは連携を絞っても23.8MBで、素のビルドの8.5MBより大きいままでした。この測定では、パッケージ別のサイズ内訳までは確認していません。
この結果から勧める運用は次のとおりです。
- 使うライブラリが決まっているサービスは、最初から連携を個別importにする。
- CIでは
GOCACHEをジョブ間で保存し、計装ありと計装なしでキャッシュを分ける。Orchestrionの版を上げた直後のビルドはクリーンビルド相当になると見込んでおく。 - 手元の開発では素の
goコマンドを使い、計装付きビルドはCIとリリースに限る。
この測定は小さなサンプル1本・1台のマシンでの値です。依存の多い実サービスでは絶対値が変わるため、導入前に自分のリポジトリで同じ3通りを測ってください。
Orchestrionを採用しない方がよい条件
次のどれかに当てはまる場合、Orchestrionは選びません。
- Bazelの
rules_goでビルドしている:Datadogの公式トラブルシューティングが非互換と明記しており、代替として手動計装を案内しています。 - Goの更新が遅れがち:サポート対象は最新2リリースだけです。2026年10月時点で1.25系以前のツールチェーンに留まるなら、動いても保証外になります。
- Go modulesを使っていない:GOPATHモードのプロジェクトは対象外です(vendoringは可)。
- 送信先をDatadogに固定したくない:既定の連携はdd-trace-goです。OpenTelemetry Collectorへ送る構成なら、次章の
otelcの方が素直です。
逆に、送信先がDatadogで、複数チームのGoサービスに計装を漏れなく入れたい場合や、Exploit Prevention(RASP)を使いたい場合は、Orchestrionを第一候補にしてよい条件です。
OpenTelemetryのコンパイル時計装(otelc)との関係
OpenTelemetryは2025年1月24日、Go Compile-Time Instrumentation SIGの発足を公式ブログで発表しました。Alibabaのopentelemetry-go-auto-instrumentationとDatadogのOrchestrionという2件の寄贈提案を受け、両社が共同でベンダー中立の方式を作るという内容です。
その成果がopen-telemetry/opentelemetry-go-compile-instrumentationで、CLIはotelcです。使い方はOrchestrionとよく似ており、otelc go buildのようにgoコマンドの前に付けます。v1.0.0は2026年7月14日、最新のv1.1.0は2026年8月24日に公開され、リポジトリのステータスはStableです。
| 観点 | Orchestrion | otelc |
|---|---|---|
| 開発元 | Datadog | OpenTelemetry(Datadog・Alibabaほか) |
| 最新版(2026-10-06) | v1.13.1 | v1.1.0 |
| 既定の計装 | dd-trace-go v2 | OpenTelemetry |
| Datadog固有機能 | RASP・プロファイラー連動 | なし |
送信先がDatadogで、Exploit Preventionやプロファイラーまで使うならOrchestrionです。複数のバックエンドに送る、あるいは将来移る可能性があるならotelcを選び、Datadog側はOTLPで受けます。DatadogでOpenTelemetryのデータを受ける方式はDatadog OpenTelemetry連携の4方式で整理しています。
ビルドの不具合を調べる手順とOrchestrionのアンインストール
ログレベルと作業ディレクトリの残し方
ビルドが失敗したり、期待した計装が入らなかったりした場合は、まずorchestrion versionとgo versionの出力を控えます。不具合報告で最初に求められる情報です。そのうえで次の2つを使います。
-work付きでビルドすると作業ディレクトリが残り、各パッケージのorchestrion/srcに書き換え後のソースが入っています。ORCHESTRION_LOG_LEVEL(ERROR・WARN・INFO・DEBUGなど)でログを出します。ORCHESTRION_LOG_FILEにファイルを指定すると既定レベルがWARNになり、パスに$PIDと書けばプロセスごとに分かれます。
DEBUG以上はビルド速度を大きく落とすため、常用しないでください。作業ディレクトリにはソースコードがそのまま含まれるので、公開のGitHub Issuesに添付する前に中身を確認し、出せない場合はDatadogサポート経由で共有します。
Orchestrionを外す手順
orchestrion.tool.goと、自分で作ったorchestrion.ymlを削除するgo mod tidyでgo.modからOrchestrion関連の依存を消す- ソース中の
//dd:spanと//orchestrion:ignoreを消す - ビルドスクリプト・CI・Dockerfileから
orchestrion goや-toolexec、GOFLAGSの設定を消す
外せたかどうかは、アプリケーションのログにDATADOG TRACER CONFIGURATIONで始まる起動ログが出なくなったことだけでは判断できません。手動計装を残す場合は同じログが出るため、Orchestrion用ファイル・ビルド設定・依存の除去と、通常のgo buildによる再ビルドを確認します。
よくある質問
OrchestrionのGitHubリポジトリはどこですか?
github.com/DataDog/orchestrion です(Apache-2.0)。利用者向けの手順はDatadog公式ドキュメントのGoトレーシング設定ページ(Compile-time instrumentationタブ)に、設定やアスペクトの書き方はプロジェクトサイトのdatadoghq.dev/orchestrion にあります。リリースはGitHubのReleasesで公開され、2026年10月6日時点の最新はv1.13.1です。
「Orchestion」と書かれているツールは同じものですか?
同じものです。正式な綴りはOrchestrion(r が2つ)で、「Orchestion」は綴りの誤りです。検索やgo installのパスでは正しい綴りを使ってください。なお、楽器のオーケストリオン(自動演奏楽器)や、Pat Methenyのアルバム「Orchestrion」もあるため、検索結果ではそちらが上位に出ることがあります。
Orchestrionは無料で使えますか?
ツール自体はApache-2.0のオープンソースなので無料です。ただし、既定の連携が送るトレースやプロファイルを見るには、Datadog側でAPMなどの契約が必要です。料金は送るホスト数やデータ量で決まるため、全サービスへ一度に入れる前に、対象サービスとサンプリング設定を決めておくと費用を見積もりやすくなります。Datadog以外へ送る連携を自作することも、仕組み上は可能です。
コードを変更せずにOrchestrionを導入できますか?
できます。変わるのはgo.mod・go.sum・orchestrion.tool.goの3ファイルとビルドコマンドだけで、トレーサーの起動処理も、生成されたinit関数へ自動で挿入されます。サービス名などはDD_SERVICE等の環境変数で渡します。コードに手を入れるのは、関数単位のスパンを足す//dd:spanや除外用の//orchestrion:ignoreを使いたいときだけです。
OrchestrionをOpenTelemetryと一緒に使えますか?
仕組みとしては可能です。公式READMEは、OpenTelemetryなど他のベンダーが別の連携を提供できると書いています。ただしorchestrion pinが有効にするのはDatadogのdd-trace-goで、OpenTelemetry向けの連携は同梱されていません。OpenTelemetryの計装をコンパイル時に入れるなら、OpenTelemetry公式のotelcを使う方が手間がかかりません。