OpenTelemetry Go: Complete Guide to Distributed Tracing
1. What Is It and Why Do You Need It?
OpenTelemetry is a collection of APIs, SDKs, and tools designed to create and manage telemetry data such as traces, metrics, and logs. The opentelemetry-go library is the official implementation of the OpenTelemetry standard for the Go language. It provides developers with a unified, vendor-neutral way to instrument their applications for telemetry collection, which can then be sent to various backends like Jaeger, Zipkin, Prometheus, Grafana Tempo, Datadog, and many others.
Why do you need it? In modern microservices architectures, a user request often passes through dozens of different services. When a problem occurs — for example, a request takes too long or ends with an error — without distributed tracing it's extremely difficult to pinpoint which service is the bottleneck or the source of the failure. OpenTelemetry lets you trace the request's path across your entire system, see the execution time of each step, and link them into a single trace composed of spans. This gives developers and Site Reliability Engineers (SREs) a powerful tool for debugging, monitoring, and performance optimization.
The key advantage of OpenTelemetry over other solutions (such as the older OpenTracing or OpenCensus libraries) is its universality and standardization. You write your code once using a single API, and you can switch the backend for storing and visualizing data without changing your application code. This makes opentelemetry-go not just a library, but a foundation for building observable systems in Go.
2. Installation
To install the opentelemetry-go library and its core components, use the standard Go package manager. You'll need to install the main API package, the tracing SDK, and an exporter (for example, for the console or Jaeger).
# Install the core API
go get go.opentelemetry.io/otel
# Install the tracing SDK
go get go.opentelemetry.io/otel/sdk
# Install the console exporter (for debugging)
go get go.opentelemetry.io/otel/exporters/stdout/stdouttrace
# Install the HTTP context propagator (for HTTP integration)
go get go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
# Install the Jaeger exporter (for production)
go get go.opentelemetry.io/otel/exporters/jaeger
After running these commands, all necessary dependencies will be added to your go.mod file.
3. Quick Start — Minimal Working Example
This example shows how to create a simple trace with a single span and output it to the console. It's a great starting point for understanding the basic concepts.
package main
import (
"context"
"fmt"
"log"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
"go.opentelemetry.io/otel/trace"
)
func main() {
// 1. Create a console exporter
exporter, err := stdouttrace.New(
stdouttrace.WithPrettyPrint(),
)
if err != nil {
log.Fatal(err)
}
// 2. Create a TracerProvider with the exporter and resource
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
sdktrace.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceNameKey.String("my-service"),
)),
)
defer func() {
if err := tp.Shutdown(context.Background()); err != nil {
log.Fatal(err)
}
}()
// 3. Set the global TracerProvider
otel.SetTracerProvider(tp)
// 4. Get a Tracer
tracer := otel.Tracer("my-tracer")
// 5. Create a span
ctx, span :=