Choosing zero-code auto instrumentation for Go
You are viewing the English version of this page because it has not yet been fully translated. Interested in helping out? See Contributing.
For Go applications, OpenTelemetry provides two distinct “zero-code” approaches to instrument applications without modifying source code: runtime attachment and build-time weaving.
This guide compares
OpenTelemetry eBPF Instrumentation (OBI) and
OpenTelemetry Go Compile-Time Instrumentation
(otelc) to help you choose the right tool for your environment.
Note: For information on the Go auto-instrumentation SDK, see Auto Instrumentation. This guide specifically focuses on comparing the eBPF and compile-time zero-code approaches.
This is a decision guide, not a ranking. Both projects are official OpenTelemetry components. In many setups, they solve different problems or even work well together.
The two mental models
When evaluating zero-code instrumentation, it helps to understand the fundamental architectural difference between the two approaches:
Runtime (eBPF): The instrumentation runs alongside your application as a separate process (often on the host node). It observes the application from the outside—specifically at the application, kernel, and networking layers. While it may inject outgoing headers into the application’s memory space for trace context propagation, it does not require changes to the application’s build process.
Compile Time (otelc): The instrumentation is injected into the application’s source during the compilation process. The resulting binary contains the telemetry logic natively, meaning no external runtime agent is required.
OBI
OpenTelemetry eBPF Instrumentation (OBI) uses eBPF (What is eBPF?) to automatically inspect application executables and the OS networking layer.
- How it hooks in: Deploys eBPF probes in the Linux kernel and the application to capture trace spans and metrics as system calls and network packets occur.
- Language coverage: Broad and essentially polyglot. Supports Java, .NET, Go, Python, Ruby, Node.js, C, C++, and Rust, among others.
- Operational requirements: Requires a Linux environment (kernel 5.8+ or specific backports), BTF support, and elevated privileges (root or specific Linux capabilities).
- Telemetry produced: Excels at capturing traces (incoming and outgoing spans for HTTP/S, gRPC, database queries), RED (Rate, Errors, Duration) metrics, network flows, and log enrichment. It captures what enters and leaves the process, but internal spans specific to the application’s frameworks or libraries still need to be manually specified by the user, either by modifying the application code or by manually defining code sections in a configuration file.
otelc
OpenTelemetry Go Compile-Time Instrumentation
(otelc) uses the Go toolchain’s -toolexec mechanism to automatically inject
OpenTelemetry instrumentation directly into your application binary during the
compilation process.
- How it hooks in: Intercepts the compilation of packages, matches functions against instrumentation rules, and injects OpenTelemetry hooks directly into the compiled binary.
- Language coverage: Go only.
- Operational requirements: Requires access to the Go build pipeline. Because the instrumentation is baked into the binary, it runs anywhere the Go binary runs and requires no special OS privileges or kernel features at runtime.
- Telemetry produced: Provides deep in-process spans with high fidelity. It can trace internal function calls, capture application-specific context, and instrument third-party Go dependencies.
Trade-offs
| Feature | OBI (eBPF) | otelc (Compile-Time) |
|---|---|---|
| Deployment Model | Deployed separately (e.g., Kubernetes DaemonSet, sidecar, or host agent). Zero changes to application build pipeline. | Baked into the application binary during go build. Requires wrapping your build command. |
| Runtime Requirements | Requires specific Linux kernel versions, BTF, and elevated privileges (root/capabilities). | No special runtime privileges, kernel features or OS requirements needed. |
| Signal Fidelity & Depth | Excellent for network boundaries and protocol interactions. Cannot easily see internal function calls or custom business logic. | Deep in-process visibility. Can instrument internal functions, custom logic, and code paths. |
| Third-party Libraries | Sees the network calls and database queries made by dependencies. | Can instrument the internal code execution of Go module dependencies. |
| Lifecycle Management | Can be attached, detached, upgraded, or downgraded dynamically without application restarts. | Requires an application rebuild, redeploy, and restart to change versions or remove instrumentation. |
When to use which
Choose OBI if:
- You prioritize ease of deployment and immediate feedback: Deploying the OBI agent allows you to collect telemetry without modifying your software development lifecycle (SDLC) or build processes.
- You have a mixed-language fleet: You want a single, unified auto-instrumentation tool that works across Go, Java, Python, .NET, and more.
- You lack build pipeline access: You do not own the build process, use pre-compiled vendor binaries, or cannot access the source code.
- You care about boundary observability: Your primary goal is tracking service-to-service communications, RED metrics, and database calls across your infrastructure.
- You are running on Linux: You operate in a Linux environment (inside or outside of Kubernetes) and can deploy an agent with the necessary privileges to observe your processes. OBI provides selectors for instrumenting by executable name, open port(s), and process PID, as well as Container, Pod, Deployment, Namespace, and metadata labels in containerized scenarios (Docker/Kubernetes), making it flexible for various deployment scenarios.
Choose otelc if:
- You own the Go build pipeline: You have full control over how your Go services are compiled and deployed.
- You require instrumentation guarantees: You can write tests during the build phase to ensure the telemetry being collected is accurate before deployment.
- You need maximum span fidelity: You require deep, in-process tracing of business logic and internal application states.
- You want to trace third-party internals: You need visibility into the execution of the third-party Go modules that you import but don’t own.
- Your runtime is restricted: You operate in environments that restrict root privileges, eBPF capabilities, or specific kernel versions (e.g., certain serverless or highly locked-down container environments).
- You need a platform-agnostic solution: Your application must run on Windows, Linux, or macOS, or on specialized architectures that the Go runtime already supports.
Using them together
Because these tools operate at different layers of the stack, they are complementary and can be used together in the same environment:
- Use otelc to generate deep, high-fidelity traces for your Go business logic, internal library calls, and custom spans.
- Use OBI to provide infrastructure-level network observability, kernel-level TCP metrics, and coverage for any non-Go components or sidecars running in your environment.
Both Special Interest Groups (SIGs) plan to improve interoperability between these two tools in the future.
Opinia
Czy ta strona była pomocna?
Thank you. Your feedback is appreciated!
Please let us know how we can improve this page. Your feedback is appreciated!