OpenTelemetry Protocol (OTLP) exporters send telemetry data using the OTLP protocol over gRPC or HTTP. OTLP is the native protocol for OpenTelemetry and is the recommended export format.
The SDK provides OTLP exporters for all three signals:
Export trace spans using the OTLP protocol.
Package: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp@v1.38.0func New(ctx context.Context, opts ...Option) (*Exporter, error)Example:
package main
import (
"context"
"log"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
func main() {
ctx := context.Background()
// Create OTLP HTTP trace exporter
exporter, err := otlptracehttp.New(ctx,
otlptracehttp.WithEndpoint("localhost:4318"),
otlptracehttp.WithInsecure(),
)
if err != nil {
log.Fatal(err)
}
// Create tracer provider with exporter
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
)
otel.SetTracerProvider(tp)
defer func() {
if err := tp.Shutdown(ctx); err != nil {
log.Printf("Error shutting down tracer provider: %v", err)
}
}()
}type Option interface {
// Has unexported methods
}Available Options:
// WithEndpoint sets the OTLP endpoint (default: "localhost:4318")
func WithEndpoint(endpoint string) Option
// WithInsecure disables TLS
func WithInsecure() Option
// WithURLPath sets the URL path (default: "/v1/traces")
func WithURLPath(urlPath string) Option
// WithHeaders sets HTTP headers
func WithHeaders(headers map[string]string) Option
// WithTLSClientConfig sets the TLS configuration
func WithTLSClientConfig(tlsCfg *tls.Config) Option
// WithCompression sets the compression method (gzip)
func WithCompression(compression Compression) Option
// WithTimeout sets the request timeout (default: 10s)
func WithTimeout(duration time.Duration) Option
// WithRetry configures retry behavior
func WithRetry(config RetryConfig) OptionExample with Options:
import (
"crypto/tls"
"time"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
)
exporter, err := otlptracehttp.New(ctx,
otlptracehttp.WithEndpoint("otlp.example.com:443"),
otlptracehttp.WithHeaders(map[string]string{
"Authorization": "Bearer " + token,
}),
otlptracehttp.WithCompression(otlptracehttp.GzipCompression),
otlptracehttp.WithTimeout(30*time.Second),
otlptracehttp.WithRetry(otlptracehttp.RetryConfig{
Enabled: true,
InitialInterval: 1 * time.Second,
MaxInterval: 30 * time.Second,
MaxElapsedTime: 5 * time.Minute,
}),
)Package: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc
import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc@v1.38.0func New(ctx context.Context, opts ...Option) (*Exporter, error)Example:
import (
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
exporter, err := otlptracegrpc.New(ctx,
otlptracegrpc.WithEndpoint("localhost:4317"),
otlptracegrpc.WithInsecure(),
)
if err != nil {
log.Fatal(err)
}
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter),
)// WithEndpoint sets the OTLP endpoint (default: "localhost:4317")
func WithEndpoint(endpoint string) Option
// WithInsecure disables TLS
func WithInsecure() Option
// WithHeaders sets gRPC metadata
func WithHeaders(headers map[string]string) Option
// WithTLSCredentials sets TLS credentials
func WithTLSCredentials(creds credentials.TransportCredentials) Option
// WithCompressor sets the gRPC compressor
func WithCompressor(compressor string) Option
// WithTimeout sets the request timeout
func WithTimeout(duration time.Duration) Option
// WithRetry configures retry behavior
func WithRetry(config RetryConfig) Option
// WithDialOption sets custom gRPC dial options
func WithDialOption(opts ...grpc.DialOption) OptionExport metrics using the OTLP protocol.
Package: go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp
import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"go get go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp@v1.38.0func New(ctx context.Context, opts ...Option) (*Exporter, error)Example:
import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
)
exporter, err := otlpmetrichttp.New(ctx,
otlpmetrichttp.WithEndpoint("localhost:4318"),
otlpmetrichttp.WithInsecure(),
)
if err != nil {
log.Fatal(err)
}
mp := sdkmetric.NewMeterProvider(
sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exporter)),
)
otel.SetMeterProvider(mp)Similar to trace exporter with different default URL path (/v1/metrics).
// WithEndpoint sets the OTLP endpoint
func WithEndpoint(endpoint string) Option
// WithInsecure disables TLS
func WithInsecure() Option
// WithURLPath sets the URL path (default: "/v1/metrics")
func WithURLPath(urlPath string) Option
// WithHeaders sets HTTP headers
func WithHeaders(headers map[string]string) Option
// WithCompression sets the compression method
func WithCompression(compression Compression) Option
// WithTimeout sets the request timeout
func WithTimeout(duration time.Duration) Option
// WithTemporalitySelector sets the temporality selector
func WithTemporalitySelector(selector TemporalitySelector) Option
// WithAggregationSelector sets the aggregation selector
func WithAggregationSelector(selector AggregationSelector) OptionPackage: go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc
import "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"go get go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc@v1.38.0func New(ctx context.Context, opts ...Option) (*Exporter, error)Example:
import (
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
)
exporter, err := otlpmetricgrpc.New(ctx,
otlpmetricgrpc.WithEndpoint("localhost:4317"),
otlpmetricgrpc.WithInsecure(),
)
if err != nil {
log.Fatal(err)
}
mp := sdkmetric.NewMeterProvider(
sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exporter)),
)Export log records using the OTLP protocol. Note: Logging is currently in beta.
Package: go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp
import "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"go get go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp@v0.9.0func New(ctx context.Context, opts ...Option) (*Exporter, error)Example:
import (
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
"go.opentelemetry.io/otel/log/global"
sdklog "go.opentelemetry.io/otel/sdk/log"
)
exporter, err := otlploghttp.New(ctx,
otlploghttp.WithEndpoint("localhost:4318"),
otlploghttp.WithInsecure(),
)
if err != nil {
log.Fatal(err)
}
lp := sdklog.NewLoggerProvider(
sdklog.WithProcessor(sdklog.NewBatchProcessor(exporter)),
)
global.SetLoggerProvider(lp)Package: go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc
import "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc"go get go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc@v0.9.0package main
import (
"context"
"log"
"time"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
"go.opentelemetry.io/otel/log/global"
"go.opentelemetry.io/otel/propagation"
sdklog "go.opentelemetry.io/otel/sdk/log"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
)
func setupOTLP(ctx context.Context) (shutdown func(context.Context) error, err error) {
var shutdownFuncs []func(context.Context) error
shutdown = func(ctx context.Context) error {
var err error
for _, fn := range shutdownFuncs {
err = errors.Join(err, fn(ctx))
}
shutdownFuncs = nil
return err
}
// Create resource
res, err := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceName("my-service"),
semconv.ServiceVersion("1.0.0"),
semconv.DeploymentEnvironment("production"),
),
resource.WithProcess(),
resource.WithHost(),
resource.WithOS(),
)
if err != nil {
return nil, err
}
// Setup trace provider
traceExporter, err := otlptracehttp.New(ctx,
otlptracehttp.WithEndpoint("localhost:4318"),
otlptracehttp.WithInsecure(),
otlptracehttp.WithCompression(otlptracehttp.GzipCompression),
)
if err != nil {
return nil, err
}
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(traceExporter,
sdktrace.WithMaxQueueSize(4096),
sdktrace.WithBatchTimeout(5*time.Second),
),
sdktrace.WithResource(res),
)
otel.SetTracerProvider(tp)
shutdownFuncs = append(shutdownFuncs, tp.Shutdown)
// Setup meter provider
metricExporter, err := otlpmetrichttp.New(ctx,
otlpmetrichttp.WithEndpoint("localhost:4318"),
otlpmetrichttp.WithInsecure(),
otlpmetrichttp.WithCompression(otlpmetrichttp.GzipCompression),
)
if err != nil {
return nil, err
}
mp := sdkmetric.NewMeterProvider(
sdkmetric.WithReader(sdkmetric.NewPeriodicReader(metricExporter,
sdkmetric.WithInterval(30*time.Second),
)),
sdkmetric.WithResource(res),
)
otel.SetMeterProvider(mp)
shutdownFuncs = append(shutdownFuncs, mp.Shutdown)
// Setup logger provider
logExporter, err := otlploghttp.New(ctx,
otlploghttp.WithEndpoint("localhost:4318"),
otlploghttp.WithInsecure(),
otlploghttp.WithCompression(otlploghttp.GzipCompression),
)
if err != nil {
return nil, err
}
lp := sdklog.NewLoggerProvider(
sdklog.WithProcessor(sdklog.NewBatchProcessor(logExporter)),
sdklog.WithResource(res),
)
global.SetLoggerProvider(lp)
shutdownFuncs = append(shutdownFuncs, lp.Shutdown)
// Setup propagators
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
propagation.TraceContext{},
propagation.Baggage{},
))
return shutdown, nil
}
func main() {
ctx := context.Background()
// Setup OTLP exporters
shutdown, err := setupOTLP(ctx)
if err != nil {
log.Fatal(err)
}
// Cleanup on exit
defer func() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := shutdown(ctx); err != nil {
log.Printf("Error shutting down: %v", err)
}
}()
// Your application code here
log.Println("Application running with OTLP exporters")
}The OTLP exporters respect standard OpenTelemetry environment variables:
# Endpoint configuration
OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.example.com:4318
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://otlp.example.com:4318/v1/traces
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://otlp.example.com:4318/v1/metrics
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://otlp.example.com:4318/v1/logs
# Headers (comma-separated key=value pairs)
OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer token,X-Custom=value
OTEL_EXPORTER_OTLP_TRACES_HEADERS=Authorization=Bearer token
OTEL_EXPORTER_OTLP_METRICS_HEADERS=Authorization=Bearer token
OTEL_EXPORTER_OTLP_LOGS_HEADERS=Authorization=Bearer token
# TLS configuration
OTEL_EXPORTER_OTLP_INSECURE=true
OTEL_EXPORTER_OTLP_CERTIFICATE=/path/to/cert.pem
# Compression
OTEL_EXPORTER_OTLP_COMPRESSION=gzip
# Timeout
OTEL_EXPORTER_OTLP_TIMEOUT=10000// HTTP is simpler and works in more environments
exporter, err := otlptracehttp.New(ctx)
// gRPC requires more dependencies
// exporter, err := otlptracegrpc.New(ctx)exporter, err := otlptracehttp.New(ctx,
otlptracehttp.WithCompression(otlptracehttp.GzipCompression),
)exporter, err := otlptracehttp.New(ctx,
otlptracehttp.WithTimeout(30*time.Second),
)// Good: Use TLS in production
exporter, err := otlptracehttp.New(ctx,
otlptracehttp.WithEndpoint("otlp.example.com:443"),
)
// Bad: Only use insecure for local development
exporter, err := otlptracehttp.New(ctx,
otlptracehttp.WithEndpoint("localhost:4318"),
otlptracehttp.WithInsecure(),
)exporter, err := otlptracehttp.New(ctx,
otlptracehttp.WithRetry(otlptracehttp.RetryConfig{
Enabled: true,
InitialInterval: 1 * time.Second,
MaxInterval: 30 * time.Second,
MaxElapsedTime: 5 * time.Minute,
}),
)