監視・オブザーバビリティ

Orchestrionとは?DatadogのGoコンパイル時自動計装の仕組みと導入手順【v1.13】

Orchestrionとは?DatadogのGoコンパイル時自動計装の仕組みと導入手順【v1.13】

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ドキュメントより)。

  1. go/parserでソースを解析し、型チェックする
  2. 有効な連携の規則に合う箇所へコードを挿入し、書き換えたファイルを作業ディレクトリに書き出す(//lineプラグマで元の行番号を保つ)
  3. 挿入で増えた依存(トレーサー本体など)を-importcfgに追加して、本物のコンパイラを呼ぶ
  4. リンク時に、増えた依存を-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を外す手順

  1. orchestrion.tool.goと、自分で作ったorchestrion.ymlを削除する
  2. go mod tidyでgo.modからOrchestrion関連の依存を消す
  3. ソース中の//dd:spanと//orchestrion:ignoreを消す
  4. ビルドスクリプト・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を使う方が手間がかかりません。

関連記事

お気に入りに入れた記事の一覧

一創の公式 SNS

X では毎朝の新着記事と IT ニュースの速報を、YouTube・TikTok・Instagram・LinkedIn・Facebook では記事の解説動画を配信しています。

この記事は以下の記事からリンクされています

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.29 テックブログ ソニー生命の情報漏洩38.5万件|ログインできない理由、再開状況と窓口の電話番号
  2. 2026.10.31 テックブログ 松屋の不正アクセス:237万件の対象確認と窓口、漏れたパスワードの守り方
  3. 2026.10.31 テックブログ osinaの情報漏洩:約23万人の対象確認とSNS連携の解除、分析ツールへ渡すデータの絞り方
  4. 2026.11.01 テックブログ RAGTAGの情報漏洩:延べ約120万件の対象項目と会員の備え、侵入から検知まで11日の意味
  5. 2026.10.31 テックブログ 無印良品の情報漏洩:MUJIアプリ最大2,726万件の対象確認となりすましメール対策

RELATED POSTS 関連記事

目次