OpenTelemetry Go implementation providing APIs for distributed tracing, metrics, and logging to instrument applications and send telemetry data to observability platforms
OpenTelemetry Go provides several alternative exporters beyond OTLP for different use cases and backends.
Available exporters:
Console exporters for development, debugging, and examples.
Package: go.opentelemetry.io/otel/exporters/stdout/stdouttrace
go get go.opentelemetry.io/otel/exporters/stdout/stdouttrace@v1.38.0package main
import (
"context"
"log"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
func main() {
ctx := context.Background()
// Create stdout trace exporter
exporter, err := stdouttrace.New(
stdouttrace.WithPrettyPrint(),
)
if err != nil {
log.Fatal(err)
}
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
)
otel.SetTracerProvider(tp)
defer tp.Shutdown(ctx)
}type Option interface {
// Has unexported methods
}
// WithPrettyPrint enables formatted JSON output
func WithPrettyPrint() Option
// WithWriter sets the output writer
func WithWriter(w io.Writer) Option
// WithoutTimestamps disables timestamps in output
func WithoutTimestamps() OptionPackage: go.opentelemetry.io/otel/exporters/stdout/stdoutmetric
go get go.opentelemetry.io/otel/exporters/stdout/stdoutmetric@v1.38.0import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/stdout/stdoutmetric"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
)
exporter, err := stdoutmetric.New(
stdoutmetric.WithPrettyPrint(),
)
if err != nil {
log.Fatal(err)
}
mp := sdkmetric.NewMeterProvider(
sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exporter)),
)
otel.SetMeterProvider(mp)Package: go.opentelemetry.io/otel/exporters/stdout/stdoutlog
go get go.opentelemetry.io/otel/exporters/stdout/stdoutlog@v0.9.0import (
"go.opentelemetry.io/otel/exporters/stdout/stdoutlog"
"go.opentelemetry.io/otel/log/global"
sdklog "go.opentelemetry.io/otel/sdk/log"
)
exporter, err := stdoutlog.New(
stdoutlog.WithPrettyPrint(),
)
if err != nil {
log.Fatal(err)
}
lp := sdklog.NewLoggerProvider(
sdklog.WithProcessor(sdklog.NewBatchProcessor(exporter)),
)
global.SetLoggerProvider(lp)Pull-based metric exporter for Prometheus.
Package: go.opentelemetry.io/otel/exporters/prometheus
go get go.opentelemetry.io/otel/exporters/prometheus@v0.51.0package main
import (
"context"
"log"
"net/http"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/prometheus"
"go.opentelemetry.io/otel/sdk/metric"
)
func main() {
ctx := context.Background()
// Create Prometheus exporter
exporter, err := prometheus.New()
if err != nil {
log.Fatal(err)
}
// Create meter provider with Prometheus exporter
mp := metric.NewMeterProvider(
metric.WithReader(exporter),
)
otel.SetMeterProvider(mp)
// Serve Prometheus metrics
http.Handle("/metrics", promhttp.Handler())
log.Println("Serving metrics on :8080/metrics")
log.Fatal(http.ListenAndServe(":8080", nil))
}type Option interface {
// Has unexported methods
}
// WithNamespace sets the Prometheus namespace
func WithNamespace(namespace string) Option
// WithAggregationSelector sets the aggregation selector
func WithAggregationSelector(selector metric.AggregationSelector) Option
// WithoutTargetInfo disables target_info metric
func WithoutTargetInfo() Option
// WithoutScopeInfo disables otel_scope_info metric
func WithoutScopeInfo() Option
// WithoutUnits disables metric units in names
func WithoutUnits() Optionpackage main
import (
"context"
"log"
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus/promhttp"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/prometheus"
"go.opentelemetry.io/otel/metric"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
)
func main() {
ctx := context.Background()
// Create resource
res, err := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceName("my-service"),
semconv.ServiceVersion("1.0.0"),
),
)
if err != nil {
log.Fatal(err)
}
// Create Prometheus exporter
exporter, err := prometheus.New(
prometheus.WithNamespace("myapp"),
prometheus.WithoutUnits(),
)
if err != nil {
log.Fatal(err)
}
// Create meter provider
mp := sdkmetric.NewMeterProvider(
sdkmetric.WithResource(res),
sdkmetric.WithReader(exporter),
)
otel.SetMeterProvider(mp)
// Create instruments
meter := otel.Meter("my-service")
requestCounter, err := meter.Int64Counter(
"http_requests_total",
metric.WithDescription("Total number of HTTP requests"),
)
if err != nil {
log.Fatal(err)
}
// Record metrics
go func() {
for {
requestCounter.Add(ctx, 1, metric.WithAttributes(
attribute.String("method", "GET"),
attribute.Int("status", 200),
))
time.Sleep(1 * time.Second)
}
}()
// Serve Prometheus metrics
http.Handle("/metrics", promhttp.Handler())
log.Println("Serving Prometheus metrics on http://localhost:8080/metrics")
log.Fatal(http.ListenAndServe(":8080", nil))
}Export trace spans to Zipkin.
Package: go.opentelemetry.io/otel/exporters/zipkin
go get go.opentelemetry.io/otel/exporters/zipkin@v1.38.0package main
import (
"context"
"log"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/zipkin"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
func main() {
ctx := context.Background()
// Create Zipkin exporter
exporter, err := zipkin.New(
"http://localhost:9411/api/v2/spans",
)
if err != nil {
log.Fatal(err)
}
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
)
otel.SetTracerProvider(tp)
defer tp.Shutdown(ctx)
}type Option func(*config)
// WithLogger sets the logger
func WithLogger(logger *log.Logger) Option
// WithClient sets the HTTP client
func WithClient(client *http.Client) Optionpackage main
import (
"context"
"log"
"net/http"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/zipkin"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
)
func main() {
ctx := context.Background()
// Create resource
res, err := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceName("my-service"),
semconv.ServiceVersion("1.0.0"),
),
)
if err != nil {
log.Fatal(err)
}
// Create Zipkin exporter
exporter, err := zipkin.New(
"http://localhost:9411/api/v2/spans",
zipkin.WithClient(&http.Client{
Timeout: 10 * time.Second,
}),
)
if err != nil {
log.Fatal(err)
}
// Create tracer provider
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
sdktrace.WithResource(res),
)
otel.SetTracerProvider(tp)
defer tp.Shutdown(ctx)
// Use tracer
tracer := otel.Tracer("my-component")
ctx, span := tracer.Start(ctx, "example-operation")
defer span.End()
span.SetAttributes(
attribute.String("key", "value"),
)
}Using multiple exporters simultaneously.
package main
import (
"context"
"log"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
func main() {
ctx := context.Background()
// Create OTLP exporter for production
otlpExporter, err := otlptracehttp.New(ctx,
otlptracehttp.WithEndpoint("otlp.example.com:443"),
)
if err != nil {
log.Fatal(err)
}
// Create stdout exporter for debugging
stdoutExporter, err := stdouttrace.New(
stdouttrace.WithPrettyPrint(),
)
if err != nil {
log.Fatal(err)
}
// Create tracer provider with both exporters
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(otlpExporter),
sdktrace.WithBatcher(stdoutExporter),
)
otel.SetTracerProvider(tp)
defer tp.Shutdown(ctx)
}// Development: stdout for debugging
exporter, _ := stdouttrace.New(stdouttrace.WithPrettyPrint())
// Production: OTLP or other backend
// exporter, _ := otlptracehttp.New(ctx)// Pull-based metrics (Prometheus scrapes endpoint)
exporter, _ := prometheus.New()
mp := sdkmetric.NewMeterProvider(
sdkmetric.WithReader(exporter),
)// Prometheus: use namespace to avoid conflicts
exporter, _ := prometheus.New(
prometheus.WithNamespace("myapp"),
)Install with Tessl CLI
npx tessl i tessl/golang-go-opentelemetry-io--otel