# otelc: compile-time OpenTelemetry instrumentation for Go > [!summary] TL;DR > otelc is the OpenTelemetry Go compile-time instrumentation tool. The whole usage change is one word in front of your build: `otelc go build -o myapp .` gives you a binary with OTel spans for the libraries otelc knows, `net/http` and gRPC among them, with nobody opening a handler file. It needs a Go 1.25 or newer toolchain and a rebuild. v1.0.1 is the first usable stable release; v1.0.0 was retracted because `otelc pin` wrote incorrect module paths. ## Key points - The whole change fits in one build command, same flags, same package, one extra word in front: `go build -o myapp .` becomes `otelc go build -o myapp .`. - otelc is the OpenTelemetry Go compile-time instrumentation tool, CLI binary `otelc`. Orchestrion is Datadog's tool, CLI binary `orchestrion`, release v1.12.0 (2026-07-30) pinned for the talk. Two tools, same trick underneath, different codebases and default tracers. - The [SIG announcement](https://opentelemetry.io/blog/2025/go-compile-time-instrumentation/) (January 2025) came after Alibaba and Datadog had each proposed donating a tool, Alibaba's `opentelemetry-go-auto-instrumentation` and Datadog's Orchestrion; the two organizations "decided to join forces" and set up a new SIG, with further contributions from Quesma. The SIG built otelc from scratch; Orchestrion was never donated and stays at `github.com/DataDog/orchestrion` as Datadog's own product. - [v1.0.0 and v1.0.1](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/releases/tag/v1.0.1) both went out on 2026-07-14. The v1.0.0 release notes retract it because `otelc pin` wrote incorrect module paths, so v1.0.1 is the first usable stable release and the one pinned for the talk. [v1.1.0](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/releases/tag/v1.1.0) followed on 2026-08-24. - Mechanism: Go's `-toolexec` flag. Normally `go build` invokes the compiler directly; with `-toolexec` the go command runs each toolchain program (`compile`, `asm`, `link`, `vet`) through a wrapper binary first. `otelc go build` adds the flag and registers `otelc` as the wrapper. - When the wrapper intercepts a compile for a package one of its rules matches, it parses that package's `.go` files into an AST, applies the rules (which functions to wrap, which spans to inject, how to propagate context), and hands the rewritten source to the real compiler. Everything else passes through untouched. - The rewrite injects a small trampoline (a generated stub in the target function) that calls a hook function, linked in with `//go:linkname`. The hooks are ordinary Go in otelc's instrumentation packages and call the OTel API and SDK, so at runtime the spans look like ones you would have written by hand. - Constraint: otelc needs a Go 1.25 or newer toolchain (its [go.mod](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/blob/v1.0.1/go.mod) says `go 1.25.0`). The toolchain is what counts: a service whose `go.mod` says `go 1.24` still builds with a newer toolchain, and otelc raises the directive with a warning. Builds pinned to a Go 1.23 or 1.24 toolchain can't use otelc, nor [Orchestrion v1.12.0](https://github.com/DataDog/orchestrion/blob/v1.12.0/go.mod). Go 1.26 was current when the talk was prepared; Go 1.27 arrived on 2026-08-19, which ends upstream support for 1.25. - At v1.0.1 the default rules cover `net/http` (client and server), gRPC, `database/sql`, gin, go-redis v9, mongo-driver, Kubernetes client-go, the OpenAI Go SDK (v1 to v3) and segmentio/kafka-go. v1.1.0 added Anthropic, AWS SDK v2, linodego and mongo-driver v2. A custom rule is a YAML entry naming a target package, a selector and an action such as `inject_hooks`. - Orchestrion with dd-trace-go has its own list: HTTP frameworks (net/http, gin, gorilla/mux, chi, echo, fiber), gRPC, `database/sql` and the layers above it (pgx, gorm, mongo-driver), Redis (go-redis v6 to v9, redigo, rueidis), Kafka, AWS SDK v1 and v2, and Kubernetes client-go. - vs OBI: OBI attaches from outside the process at runtime, needs no rebuild, works on deployed services and covers other languages, but is bounded to RED metrics and library-level spans (13 Go libraries in the [v0.10.0 support matrix](https://github.com/open-telemetry/opentelemetry-ebpf-instrumentation/blob/v0.10.0/SUPPORT_MATRIX.md)); it cannot generate custom spans or instrument business logic. otelc requires a rebuild and Go 1.25+, but reaches stdlib internals, your own functions, dependencies and business logic, with the fidelity of hand-written OTel calls. - Decision rule: deployed and can't rebuild, need baseline visibility across services: OBI. Building or rebuilding, want granular spans, on Go 1.25+: otelc. Running Datadog APM with the widest framework coverage: Orchestrion. - To see traces, run the binary with `OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318` and `OTEL_SERVICE_NAME=my-go-service`. otelc exports OTLP over HTTP by default, so use 4318, not the gRPC port 4317. - Fine print: otelc touches `go.mod` during the build. It adds its hook modules as `replace` directives, runs `go mod tidy`, may raise the `go` directive (printing `Bumped go version` when it does), then restores `go.mod` and `go.sum` when the build finishes. A `.otelc-build/` directory stays behind. If a build is interrupted, the troubleshooting guide says to run `otelc cleanup` and `git restore go.mod go.sum`. - Tested with `otelhttp.NewHandler` plus one manual span (otelc v1.1.0, Go 1.27.1, macOS arm64): three requests to Jaeger, each one trace, with otelc's server span at the root, the `otelhttp` server span under it, and the manual span under that. Nothing orphaned, but two server spans per request. dd-trace-go was not tested. - Disclosure: the author works at Datadog, which maintains Orchestrion and dd-trace-go, and is one of otelc's maintainers; read the comparisons with that in mind. - Versions, links and commands checked on 2 October 2026. ## Why two tools: otelc vs Orchestrion `otelc` has a lookalike: Orchestrion is Datadog's tool, CLI binary `orchestrion`, released as [v1.12.0](https://github.com/DataDog/orchestrion/releases/tag/v1.12.0) (2026-07-30). Its [README](https://github.com/DataDog/orchestrion/blob/v1.12.0/README.md) says other vendors, OpenTelemetry among them, may provide alternate integrations, but the ones it defaults to (dd-trace-go/v2) are Datadog's. otelc is the OpenTelemetry Go compile-time instrumentation tool, CLI binary `otelc`. The [SIG announcement](https://opentelemetry.io/blog/2025/go-compile-time-instrumentation/) (January 2025) says Alibaba and Datadog had each proposed donating a tool, Alibaba's `opentelemetry-go-auto-instrumentation` and Datadog's Orchestrion. Then the two organizations "decided to join forces" and set up a new SIG, with further contributions from Quesma. The goal was a unified, vendor-neutral approach that "picks the best aspects of each solution", and it "won't be Alibaba's or Datadog's solution that 'wins'". The SIG built otelc from scratch; Orchestrion was never donated. [v1.0.0 and v1.0.1](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/releases/tag/v1.0.1) both went out on 2026-07-14, four weeks before the talk. The [v1.0.0 release notes](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/releases/tag/v1.0.0) retract it because `otelc pin` wrote incorrect module paths, so v1.0.1 is the first usable stable release and the one pinned for the talk. [v1.1.0](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/releases/tag/v1.1.0) followed on 2026-08-24. The OpenTelemetry blog's [v1 announcement](https://opentelemetry.io/blog/2026/go-compile-time-instrumentation-v1/) tells the milestone story. The two tools share a mechanism and differ in codebase and default tracer, so choosing is mostly about which tracer SDK you're committing to. ## How the -toolexec mechanism works Go's build system has a `-toolexec` flag. Normally `go build` invokes the compiler directly. With `-toolexec`, the go command runs each toolchain program (`compile`, `asm`, `link`, `vet`) through a wrapper binary first. `go help build` calls it "a program to use to invoke toolchain programs like vet and asm." That generic hook is exactly the right one for compile-time AOP: Orchestrion's maintainers describe their tool as, in some ways, a "compile-time-woven Aspect-oriented Programming (AoP) framework" ([golang/go#69887](https://github.com/golang/go/issues/69887)). The before and after: ```bash go build -o myapp . otelc go build -o myapp . ``` `otelc go build` adds the flag for us and registers `otelc` as the wrapper. When the wrapper intercepts a compile for a package one of its rules matches, it parses that package's `.go` files into an AST, applies the rules (which functions to wrap, which spans to inject, how to propagate context), and hands the rewritten source to the real compiler. Everything else passes through untouched. The compiler never sees the original, so as far as it knows you wrote the instrumentation yourself, and it's too polite to ask. The [OpenTelemetry blog](https://opentelemetry.io/blog/2026/go-compile-time-instrumentation-v1/) says otelc "hooks into the standard Go toolchain during the build (through its `-toolexec` mechanism) and injects OpenTelemetry instrumentation into your code, its dependencies, and the standard library as they are compiled." If `net/http` needs instrumentation, otelc can inject it as `net/http` gets compiled into your binary. The result has OTel spans baked in: no runtime agent, no sidecar, no dynamic injection. The rewrite injects a small trampoline that calls a hook function, linked in with `//go:linkname`; the hooks are ordinary Go in otelc's instrumentation packages, and they call the OTel API and SDK, so at runtime the spans look like ones you'd have written by hand. ## The Go 1.25 toolchain requirement otelc needs a Go 1.25 or newer toolchain; its [go.mod](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/blob/v1.0.1/go.mod) says `go 1.25.0`. The toolchain is what counts: a service whose `go.mod` says `go 1.24` still builds with a newer toolchain, and otelc raises the directive with a warning. Builds pinned to a Go 1.23 or 1.24 toolchain can't use otelc, nor Orchestrion v1.12.0 ([go.mod](https://github.com/DataDog/orchestrion/blob/v1.12.0/go.mod)). For those, OBI needs no rebuild. When the talk was prepared, Go 1.26 (February 2026) was current, and Go 1.27 arrived on 2026-08-19, which ends upstream support for 1.25. Toolchain pinning is a fine habit until a tool wants a newer one. In slow-upgrade environments that's the first question to answer. ## What the rules cover, and how to choose against OBI The default rules cover a list of libraries; for your own functions you write a custom rule. A rule is a YAML entry naming a target package, a selector and an action such as `inject_hooks` ([schema](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/blob/v1.1.0/docs/rules.md)); its hooks are Go in a package of their own. At v1.0.1 the [getting-started guide](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/blob/v1.0.1/docs/getting-started.md) listed `net/http` (client and server), gRPC, `database/sql`, gin, go-redis v9, mongo-driver, Kubernetes client-go, the OpenAI Go SDK (v1 to v3) and segmentio/kafka-go. v1.1.0 added Anthropic, AWS SDK v2, linodego and mongo-driver v2; the [supported-libraries page](https://opentelemetry.io/docs/zero-code/go/compile-time/supported-libraries/) has the current list. Orchestrion with dd-trace-go has its own list. Its [supported-integrations table](https://github.com/DataDog/dd-trace-go/blob/v2.9.1/contrib/supported_integrations.md) in dd-trace-go v2.9.1 (the version Orchestrion v1.12.0 pins) marks which integrations work with Orchestrion: HTTP frameworks (net/http, gin, gorilla/mux, chi, echo, fiber), gRPC, `database/sql` and the layers above it (pgx, gorm, mongo-driver), Redis (go-redis v6 to v9, redigo, rueidis), Kafka, AWS SDK v1 and v2, and Kubernetes client-go. Compare both lists against your own dependencies before choosing. OBI and otelc attack the same problem, zero source code changes, from opposite ends. OBI attaches from outside the process at runtime: no rebuild, deployed services, other languages too, but bounded by what eBPF can observe at library boundaries, RED metrics and library-level spans for the 13 Go libraries in its [v0.10.0 support matrix](https://github.com/open-telemetry/opentelemetry-ebpf-instrumentation/blob/v0.10.0/SUPPORT_MATRIX.md). It cannot generate custom spans or instrument business logic. otelc works at build time: a rebuild and Go 1.25 or newer, in exchange for stdlib internals, your own functions, dependencies and business logic, with a custom rule for anything the default set doesn't cover. Decision rule: deployed and can't rebuild, need baseline visibility across services: OBI. Building or rebuilding, want granular spans, on Go 1.25 or newer: otelc. Running Datadog APM with the widest framework coverage: Orchestrion. ## Try it: install, build, run Install otelc, pinned to a version. I ran v1.1.0; its runtime rules match v1.0.1, the version pinned for the talk: ```bash go install go.opentelemetry.io/otelc/tool/cmd/[email protected] ``` Then build the service with otelc wrapping the build command, exactly as in the opening: ```bash otelc go build -o myapp . ``` That's the complete usage change. To see traces, run the binary with `OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318` and `OTEL_SERVICE_NAME=my-go-service`. otelc exports OTLP over HTTP by default, so use 4318, not the gRPC port 4317. In CI, put `otelc` in `$PATH` and prefix your existing build command. If you can't prefix it, the getting-started guide describes a second route: run `otelc setup` once, then set `GOFLAGS="'-toolexec=otelc toolexec'"` and use plain `go build`. "Without a single line" sounds absolute, so here's the fine print. You don't edit `go.mod` yourself, but otelc does touch it. During the build it adds its hook modules as `replace` directives, runs `go mod tidy`, and may raise the `go` directive (it prints `Bumped go version` when it does), then restores `go.mod` and `go.sum` when the build finishes. A `.otelc-build/` directory stays behind. If a build is interrupted, the [troubleshooting guide](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/blob/v1.0.1/docs/troubleshooting.md) says to run `otelc cleanup` and `git restore go.mod go.sum`. Already using `otelhttp` and your own spans? I built a small server with `otelhttp.NewHandler` and one manual span using `otelc go build` (v1.1.0, Go 1.27.1, macOS arm64) and sent three requests to Jaeger. Each request was one trace: otelc's server span at the root, the `otelhttp` server span under it, and my manual span under that. Nothing is orphaned, but you get two server spans per request. I didn't test dd-trace-go. "Without a single line" really means one build command substitution and Go 1.25 on your toolchain. ## FAQ ### What is otelc? otelc is the OpenTelemetry Go compile-time instrumentation tool, CLI binary `otelc`. The OpenTelemetry SIG built it from scratch after Alibaba and Datadog proposed donating their tools and "decided to join forces", with contributions from Quesma. v1.0.1 (2026-07-14) is the first usable stable release. ### How do I use otelc with go build? Prefix your build command with `otelc`: `otelc go build -o myapp .`. Same flags, same package, one extra word. In CI, put `otelc` in `$PATH`; if you can't prefix the command, run `otelc setup` once, set `GOFLAGS="'-toolexec=otelc toolexec'"`, and use plain `go build`. ### What Go version does otelc need? A Go 1.25 or newer toolchain; its go.mod says `go 1.25.0`. The toolchain is what counts: a `go 1.24` directive still builds with a newer toolchain, and otelc raises the directive with a warning. Builds pinned to Go 1.23 or 1.24 can't use otelc, nor Orchestrion v1.12.0. ### Which libraries does otelc instrument by default? At v1.0.1: `net/http` (client and server), gRPC, `database/sql`, gin, go-redis v9, mongo-driver, Kubernetes client-go, the OpenAI Go SDK (v1 to v3) and segmentio/kafka-go. v1.1.0 added Anthropic, AWS SDK v2, linodego and mongo-driver v2. For anything else, write a custom YAML rule. ### How is otelc different from Orchestrion? Both wrap `go build` with `-toolexec`. Orchestrion is Datadog's tool and defaults to dd-trace-go/v2 integrations; otelc is the vendor-neutral OpenTelemetry SIG tool built from scratch, released under the OpenTelemetry project. Choosing between them is mostly about which tracer SDK you're committing to. ### otelc or OBI: which should I use? Deployed and can't rebuild, need baseline visibility across services: OBI. Building or rebuilding, want granular spans, on Go 1.25 or newer: otelc. Running Datadog APM with the widest framework coverage: Orchestrion. OBI covers 13 Go libraries from outside the process; otelc reaches stdlib internals, your own functions and business logic. ### What does otelc do to go.mod? During the build it adds hook modules as `replace` directives, runs `go mod tidy`, and may raise the `go` directive (it prints `Bumped go version`), then restores `go.mod` and `go.sum` when the build finishes. A `.otelc-build/` directory stays behind. If a build is interrupted, run `otelc cleanup` and `git restore go.mod go.sum`. ### Does otelc work together with otelhttp and manual spans? Yes, tested with `otelhttp.NewHandler` plus one manual span (v1.1.0, Go 1.27.1, macOS arm64): each request was one trace, nothing orphaned, but you get two server spans per request, otelc's at the root and the `otelhttp` one under it. dd-trace-go was not tested. ## Related - [[resources/documentation/Go/Instrumentation/Go Instrumentation|Go Instrumentation]] (series hub) - [[resources/documentation/Go/Instrumentation/Go Instrumentation - Why Go Cannot Be Monkey Patched|Why Go Cannot Be Monkey Patched]] (part 1: why Go has no agent slot) - [[resources/documentation/Go/Instrumentation/Go Instrumentation - OBI eBPF Auto-Instrumentation|OBI eBPF Auto-Instrumentation]] (part 2: the kernel route, no rebuild) - [[resources/documentation/Go/Instrumentation/Go Instrumentation - Agent-Actionable Observability|Agent-Actionable Observability]] (part 6: the runbook and what otelc covers) - [[resources/documentation/Go/Go - uretprobes]] - [[resources/documentation/Go/Go - Internals]] ## Field notes from agent sessions (2026-11-10) These notes come from agent sessions that built, tested, and reviewed the tool and its rule set. They cover build-cache mechanics and the exact semantics of the rule schema. - A `toolexec` build poisons the Go build cache by design. The wrapper's `-V=full` answer carries an otelc marker, so instrumented builds never share cache entries with plain builds. - Link-time imports are recorded as a side effect of compile actions. A cache hit skips those actions, so a restored `GOCACHE` fails at link with `cannot find package ... (using -importcfg)`. This failure reproduced across many test suites. - Instrumented packages reference hooks only through `//go:linkname`. The blank imports in the generated `otelc.runtime.go` file are the only mechanism that pulls hook archives into a test binary's importcfg. The runtime file must be generated for test packages that have no non-test Go files on the platform, or their binary links instrumented packages without the hook package. - In vendor mode, packages keep `Module.Version`. A fingerprint shortcut that hashes a package as `path@version` skips its source files, so editing a vendored injected dependency leaves the warm-build fingerprint unchanged. Hash vendored dependencies by content. - A version-pinned hook tool breaks when a library's declared version diverges from what the build graph resolves. The tool writes instrumented output to the stale module-cache path. Several integration test failures shared this one root cause. - A fresh checkout of the tool repository fails tool builds until the embedded bundle tarball is built. A data file loaded through `go:embed` does not exist in a clean worktree. Scope verification builds to the touched packages, or build the bundle first. - Rule filtering uses a three-phase `Point` interface: `PackageMayMatch`, `FileMayMatch`, `Matches`. The early phases exit cheaply before source parsing. This tiered approach is the key design difference from a flat filter list. - The `target` field of a rule is always an exact import path. The matcher pre-indexes rules into a `rulesByTarget` map for O(1) lookup, so glob or regex values in `target` never match. Put predicate logic in the `where` clause after the exact-match gate. - The normalize layer translates structured `where:` and `do:` YAML into flat rule structs at parse time. It discards the modifier key name and merges only the payload fields into the flat map. `do: - wrap_call: { replace: ... }` therefore puts `replace` in the flat struct, not `wrap_call`. - A `where: func:` rule with no `recv:` matches only package-level free functions. It cannot fire on method calls. - `where: func:` matches by function name across receiver types. Add `recv:` to a selector whenever the target symbol name repeats across receiver types. - Exact `signature` filters became silently unsatisfiable for any function with a slice, map, or chan parameter. A loud build abort turned into a silent no-match. Hooks are then omitted from user binaries with no signal, so missing production spans is the default failure mode. - Honoring `//otelc:ignore` comments embedded in dependency source is fail-open. Users cannot annotate dependency code, and a compromised dependency can silently opt out of instrumentation. - Orchestrion's configuration discovery reads tool files with `parser.ParseFile(..., parser.ImportsOnly)` and deliberately ignores the `//go:build tools` constraint. The build tag only keeps the file out of normal compilation. The tool then resolves import paths via `x/tools/go/packages` to find each package's `orchestrion.yml`, which makes the mechanism vendor-agnostic and recursively extensible. - The v1.1.0 tagged schema differs from the doc prose. There is no document-level `version` field. `version` belongs inside a rule and means a target-library version range. Matched-rule names are nested lowercase fields, and the HTTP hook stores a map rather than a `hookData` struct. Build material from the captured schema and the tagged code, not from doc prose. ### Observations - [go-build] Instrumented `toolexec` builds never share build-cache entries with plain builds, because the tool's `-V=full` answer carries an otelc marker. #build-cache (source: agent sessions, 2026-10) - [go-build] A restored `GOCACHE` fails at link with `cannot find package ... (using -importcfg)`, because a cache hit skips the compile actions that record link-time imports. #build-cache (source: agent sessions, 2026-10) - [otelc] The blank imports in the generated `otelc.runtime.go` are the only mechanism that pulls hook archives into a test binary, because instrumented packages reference hooks only via `//go:linkname`. #toolexec (source: agent sessions, 2026-10) - [go-tools] Vendored dependencies must be fingerprinted by content, because vendor-mode packages keep `Module.Version` and a `path@version` hash skips their source files. #build-cache (source: agent sessions, 2026-11) - [otelc] A version-pinned hook tool writes instrumented output to a stale module-cache path when a library's declared version diverges from the resolved version. #version-pinning (source: agent sessions, 2026-07) - [go-build] A clean checkout of the tool repository cannot build tool targets until the `go:embed` bundle tarball exists, so scope verification builds to the touched packages or build the bundle first. #build (source: agent sessions, 2026-07) - [otelc] Rule filtering uses the three-phase `Point` interface `PackageMayMatch`, `FileMayMatch`, `Matches` for cheap early exit before source parsing. #rules (source: agent sessions, 2026-03) - [otelc] The `target` field is always an exact import path, so glob or regex values never match, and predicate logic belongs in the `where` clause after the exact-match gate. #rules (source: agent sessions, 2026-03) - [otelc] The normalize layer discards the modifier key name and merges only its payload fields into the flat rule struct at parse time. #rules (source: agent sessions, 2026-05) - [otelc] A `where: func:` rule without `recv:` matches only package-level free functions and cannot fire on method calls. #rules (source: agent sessions, 2026-06) - [otelc] `where: func:` matches by name across receiver types, so `recv:` is required in a selector when the symbol name repeats across receivers. #rules (source: agent sessions, 2026-09) - [otelc] Exact `signature` filters turn silently unsatisfiable for functions with slice, map, or chan parameters, so missing production spans becomes the default failure mode. #rules (source: agent sessions, 2026-07) - [otelc] Honoring `//otelc:ignore` from dependency source is fail-open, because users cannot annotate dependency code and a compromised dependency can silently opt out. #supply-chain (source: agent sessions, 2026-07) - [otel] Orchestrion reads tool files with `parser.ImportsOnly`, ignores the `//go:build tools` tag by design, and resolves `orchestrion.yml` files through `x/tools/go/packages`. #orchestrion (source: agent sessions, 2026-06) - [otelc] The v1.1.0 tagged schema, not the doc prose, is the source of truth for the rule-level `version` field, matched-rule name fields, and the HTTP hook's map storage. #schema (source: agent sessions, 2026-09) ## Sources - [How to Instrument Go Without Changing a Single Line of Code (talk, GopherCon UK 2026, GoLab 2026)](https://kakkoyun.me/talks/instrument-go-without-changing-a-single-line/) - [How to Instrument Go Without Changing a Single Line of Code (series)](https://kakkoyun.me/series/how-to-instrument-go-without-changing-a-single-line-of-code/) - [OpenTelemetry SIG announcement: Go compile-time instrumentation (January 2025)](https://opentelemetry.io/blog/2025/go-compile-time-instrumentation/) - [OpenTelemetry blog: otelc v1 announcement](https://opentelemetry.io/blog/2026/go-compile-time-instrumentation-v1/) - [otelc v1.0.1 release notes](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/releases/tag/v1.0.1) - [otelc v1.0.0 release notes (retracted)](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/releases/tag/v1.0.0) - [otelc v1.1.0 release notes](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/releases/tag/v1.1.0) - [otelc go.mod (v1.0.1)](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/blob/v1.0.1/go.mod) - [otelc getting-started guide (v1.0.1)](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/blob/v1.0.1/docs/getting-started.md) - [otelc troubleshooting guide (v1.0.1)](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/blob/v1.0.1/docs/troubleshooting.md) - [otelc custom rules schema (v1.1.0)](https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/blob/v1.1.0/docs/rules.md) - [otelc supported-libraries page](https://opentelemetry.io/docs/zero-code/go/compile-time/supported-libraries/) - [Orchestrion v1.12.0 release](https://github.com/DataDog/orchestrion/releases/tag/v1.12.0) - [Orchestrion v1.12.0 README](https://github.com/DataDog/orchestrion/blob/v1.12.0/README.md) - [Orchestrion v1.12.0 go.mod](https://github.com/DataDog/orchestrion/blob/v1.12.0/go.mod) - [dd-trace-go v2.9.1 supported integrations](https://github.com/DataDog/dd-trace-go/blob/v2.9.1/contrib/supported_integrations.md) - [OBI v0.10.0 support matrix](https://github.com/open-telemetry/opentelemetry-ebpf-instrumentation/blob/v0.10.0/SUPPORT_MATRIX.md) - [golang/go#69887: AoP framework discussion](https://github.com/golang/go/issues/69887) - [Hooking into the Go toolchain (guest post)](https://internals-for-interns.com/posts/hooking-into-the-go-toolchain/)