← Back to list

Auto-Instrumenting Go Applications Without Modifying Source Code

Issues with Auto-Instrumentation For Go Applications

Vitor Mouzinho · 2025-10-16 13:46 · 7 claps · 3.0 min read
#golang #observability #tracing #dash0 #devops
Open on Medium ↗
Wiki topics: ☁️ · DevOps & Cloud

Auto-Instrumenting Go Applications Without Modifying Source Code

Issues with Auto-Instrumentation For Go Applications

Go is statically compiled, which means all the code and libraries are “baked into” the binary at compile time. Because of this, traditional auto-instrumentation — which relies on dynamically hooking into functions at runtime — doesn’t work well in Go. Unlike languages such as Python or JavaScript, Go lacks runtime hooks to intercept library calls, so developers typically have to manually add tracing and propagate context making instrumentation more complex and error-prone.

Proposed Solution: Go Auto-Instrumentation with eBPF

The auto-instrumentation project for Go has been proposed and made to resolve this issue utilizing eBPF.

eBPF instrumentation solves this by tracing at the kernel level, outside the program itself. It can capture all network calls, syscalls, and I/O events, giving full observability without changing your Go code. Essentially, it sees everything Go’s “sewn-in” binary might hide.

Introduction:

This guide demonstrates how users can leverage eBPF to address the issue of having to modify your go source code for observability. Throughout the guide, I have created and deployed a ‘Hello World’ application on Kubernetes, written in Go, to serve as a reference.

Configuring OBI Permissions for Kubernetes Metadata Collection

Before we can start collecting telemetry with eBPF, we need to give our instrumentation tool, OBI, permission to see what’s running in the cluster.

Step 1: Create a ServiceAccount for OBI This gives OBI its own identity in the cluster, allowing it to access only the resources it needs. See here for Reference

Step 2: Grant OBI the necessary permissions We need to allow OBI to list and watch Pods and ReplicaSets so it can gather the information required. See here for reference.

Step 3: Bind the permissions to the ServiceAccount This connects the permissions to the OBI ServiceAccount. See here for reference.

Once these steps are complete, apply the configuration with: kubectl apply -f permissions.yaml

With these permissions, OBI can now decorate your traces with Kubernetes metadata, including:

  • k8s.namespace.name
  • k8s.deployment.name
  • k8s.statefulset.name
  • k8s.replicaset.name
  • k8s.daemonset.name
  • k8s.node.name
  • k8s.pod.name
  • k8s.container.name
  • k8s.pod.uid
  • k8s.pod.start_time
  • k8s.cluster.name

Deploy OBI as a sidecar container

There are a couple of ways to deploy OBI. For this guide, I chose to deploy it as a sidecar container, though a DaemonSet deployment is also available. See reference here.

The first step will be to Configure the Pod Spec for OBI Sidecar. When adding OBI as a sidecar container to your deployment, you need to adjust the Pod spec with the following fields: See Reference here

Explanation:

shareProcessNamespace: true

This allows all containers in the Pod (your main app and the OBI sidecar) to see each other’s processes.

OBI needs this to observe and instrument the main application process without modifying your code.

serviceAccountName: obi

Associate the Pod with the OBI ServiceAccount you created earlier.

This grants OBI the permissions necessary to access Kubernetes resources (Pods, ReplicaSets, Deployments, etc.) so it can decorate traces with metadata like k8s.pod.name, k8s.namespace.name, and more.

In short: these two settings allow OBI to observe your application processes and enrich telemetry with Kubernetes metadata.

Add the OBI Sidecar Container

Next, add OBI as a sidecar container alongside your main application in the Pod specification: See reference here. This allows OBI to run next to your Go application, automatically instrumenting it using eBPF without requiring any code changes.

Configuring OBI Environment Variables

Finally, define the environment variables for the OBI container See Reference Here

These environment variables tell OBI how to instrument and export telemetry data:

OTEL_GO_AUTO_TARGET_EXE — Points to the main Go executable for instrumentation.

OTEL_EXPORTER_OTLP_ENDPOINT — Specifies your Dash0 OTLP endpoint.

OTEL_EBPF_KUBE_METADATA_ENABLE — Enables Kubernetes metadata decoration.

OTEL_EXPORTER_OTLP_HEADERS — Adds your authentication key for secure export.

OTEL_SERVICE_NAME — Identifies your Go application in Dash0.

Once configured, OBI will automatically collect and send traces, metrics, and logs from your Go application to Dash0 — no code changes required.

Using Dash0 As Your Observability Platform

For this guide, I chose Dash0 because it’s one of the first observability platforms built natively around OpenTelemetry. Dash0 provides a full suite of observability tools — including metrics, traces, and logs — while offering a pay-as-you-go pricing model with no minimum contracts. Compared to traditional platforms, it can deliver the same major functionality with up to 65% cost reduction.

If you’re exploring OpenTelemetry-based observability, Dash0 is worth checking out for its simplicity, full-featured approach, and efficiency.

https://www.dash0.com/documentation/dash0/introduction


메타데이터
post_id
9bd61d229ea4
slug
auto-instrumenting-go-applications-without-modifying-source-code-9bd61d229ea4
url
https://medium.com/@vitor.mouzinho_24546/auto-instrumenting-go-applications-without-modifying-source-code-9bd61d229ea4
canonical_url
https://medium.com/@vitor.mouzinho_24546/auto-instrumenting-go-applications-without-modifying-source-code-9bd61d229ea4
author_url
https://medium.com/@vitor.mouzinho_24546
status
ok
fetched_at
2026-08-30 06:48:14