Glossary · Z

Zero-Code Instrumentation

Collecting traces, metrics and logs from an application without modifying its source code, using agents or eBPF.

By Obseria Editorial TeamUpdated

Definition

Zero-code instrumentation is a way to collect telemetry from an application without changing its source code. An agent, runtime hook or eBPF program attaches to the process and instruments common libraries such as HTTP servers, database clients and messaging frameworks automatically. OpenTelemetry uses this term for what was previously called automatic instrumentation.

What is zero-code instrumentation?

Zero-code instrumentation gives you traces, metrics and often logs from an application without editing its code. Instead of calling the OpenTelemetry API inside your handlers, you attach an agent or enable a runtime hook at startup, and it instruments the libraries the application already uses. OpenTelemetry documentation adopted the term to replace "automatic instrumentation", because it describes more precisely what the user does: nothing in the code.

It complements, rather than replaces, code-based instrumentation. Zero-code gives broad coverage of frameworks and protocols on day one; manual spans and attributes add the business context only your code knows.

How it works

The mechanism depends on the runtime:

  • Bytecode manipulation (Java): a Java agent rewrites classes of supported libraries as they load and inserts span creation and context propagation.
  • Monkey patching (Python, Node.js, Ruby): library functions are wrapped at import time.
  • Profiler APIs (.NET): the CLR profiling interface lets an external component inject instrumentation.
  • eBPF (compiled languages such as Go, or any process): kernel programs observe function calls or network traffic from outside the process. OpenTelemetry has eBPF-based projects for this, such as OpenTelemetry Go automatic instrumentation and OpenTelemetry eBPF Instrumentation (OBI).

All approaches emit data following semantic conventions, so a Java service and a Python service report HTTP spans with the same attributes.

Examples per language

Java

export OTEL_SERVICE_NAME=checkout
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
java -javaagent:./opentelemetry-javaagent.jar -jar checkout.jar

Python

pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install
opentelemetry-instrument --service_name checkout python app.py

Node.js

npm install @opentelemetry/api @opentelemetry/auto-instrumentations-node
node --require @opentelemetry/auto-instrumentations-node/register app.js

.NET, PHP and other runtimes

For .NET, the OpenTelemetry .NET automatic instrumentation project ships install scripts and uses the CLR profiler interface, so ASP.NET Core, HttpClient and common database clients are traced without code changes. PHP uses a compiled extension together with instrumentation packages installed through Composer. Ruby offers an all-in-one instrumentation gem that only needs a few lines of configuration. Coverage differs between languages, so check the list of supported libraries for your stack before you rely on it in production.

Configuration happens through standard environment variables such as OTEL_SERVICE_NAME, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_RESOURCE_ATTRIBUTES and OTEL_TRACES_SAMPLER, which work the same across languages.

Zero-code on Kubernetes with the Operator

The OpenTelemetry Operator makes zero-code instrumentation a platform feature. You define an Instrumentation resource with exporter endpoint, propagators and sampler once, then opt workloads in with an annotation on the pod template:

metadata:
  annotations:
    instrumentation.opentelemetry.io/inject-java: "true"

The Operator injects the agent via an init container and sets the environment variables. Annotations exist for Java, Node.js, Python, .NET and Go, among others. Application teams get tracing without touching their images, and the platform team controls versions centrally.

Benefits and limits

BenefitsLimits
Fast time to value, no code changes or redeploys of new codeOnly instruments supported libraries and frameworks
Consistent coverage across many services and teamsNo business context, such as order value or tenant, without manual attributes
Works for third-party and legacy applicationsStartup time and memory overhead, depending on runtime and agent
Upgrades managed centrallyCan produce noisy spans, for example for health checks, that need filtering

Zero-code, eBPF or manual: how to choose

The three approaches answer different needs. Language agents give the richest detail for supported frameworks, including database statements and messaging metadata, and they propagate trace context inside the process. eBPF-based instrumentation needs no runtime support at all and covers services you cannot restart with an agent, but it sees less application context and depends on kernel features. Manual instrumentation offers full control and business attributes, at the cost of developer time. In practice, most teams combine them: agents for the languages they run widely, eBPF for gaps such as compiled or third-party binaries, and manual spans for the few code paths where business context really matters.

Best practices

  1. Start with zero-code, then add manual spans where business logic matters. Agents usually expose the OpenTelemetry API, so manual spans join the same trace.
  2. Set service.name and environment explicitly; defaults such as unknown_service make data hard to find.
  3. Disable instrumentations you do not need to cut overhead and noise; most agents support per-library switches.
  4. Pin agent versions and test upgrades in staging, because instrumentation changes can alter span names and attributes.
  5. Measure overhead under realistic load before rolling out widely.
  6. Filter noise in the Collector, for example health-check and readiness probe spans.

How Obseria helps

Obseria works with the standard OpenTelemetry zero-code agents and the Operator; point OTEL_EXPORTER_OTLP_ENDPOINT at Obseria and teams with existing OpenTelemetry setups typically see a first trace within 15 minutes. Alternatively, the Obseria Agent is installed once per host and collects metrics, logs, traces and profiles without per-service code changes. Language guides: Java, Python and Node.js.

Frequently asked questions

Yes. OpenTelemetry now uses the term zero-code instrumentation for what was previously called automatic instrumentation. Both describe collecting telemetry through agents or runtime hooks without changing application source code.

Go compiles to native binaries without a runtime hook for agents, so classic agents do not apply. eBPF-based approaches, such as OpenTelemetry Go automatic instrumentation and OpenTelemetry eBPF Instrumentation, can observe Go services from outside the process. Library-level instrumentation in code remains an option.

Yes, and it is the recommended approach. The agent creates spans for frameworks and clients, while your code adds custom spans and attributes through the OpenTelemetry API. Both end up in the same trace.

It depends on runtime, number of active instrumentations, sampling and traffic. Startup time and memory usually increase somewhat, and per-request overhead is typically small. Measure under realistic load and disable instrumentations you do not need.

Put these concepts into practice

Try Obseria free for 14 days, with OpenTelemetry and no proprietary agents.