OpenTelemetry Go implementation providing APIs for distributed tracing, metrics, and logging to instrument applications and send telemetry data to observability platforms
The OpenTelemetry Go SDK log implementation provides concrete implementations of the log API interfaces, including LoggerProvider, processors, and exporters. Note: The logging signal is currently in beta status.
import sdklog "go.opentelemetry.io/otel/sdk/log"The SDK log package provides:
The LoggerProvider is the SDK implementation of the log.LoggerProvider interface.
type LoggerProvider struct {
// Has unexported fields
}func NewLoggerProvider(opts ...LoggerProviderOption) *LoggerProviderDefault Configuration:
Example:
package main
import (
"context"
"log"
"go.opentelemetry.io/otel/log/global"
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
"go.opentelemetry.io/otel/sdk/log"
"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 exporter
exporter, err := otlploghttp.New(ctx)
if err != nil {
log.Fatal(err)
}
// Create processor
processor := log.NewBatchProcessor(exporter)
// Create logger provider
lp := log.NewLoggerProvider(
log.WithResource(res),
log.WithProcessor(processor),
)
// Set as global logger provider
global.SetLoggerProvider(lp)
// Cleanup
defer func() {
if err := lp.Shutdown(ctx); err != nil {
log.Printf("Error shutting down logger provider: %v", err)
}
}()
// Use logger
logger := global.GetLoggerProvider().Logger("my-component")
// Emit log records...
}// Logger returns a Logger with the given name and options
func (p *LoggerProvider) Logger(name string, opts ...log.LoggerOption) log.Logger
// Shutdown shuts down the LoggerProvider and all processors
func (p *LoggerProvider) Shutdown(ctx context.Context) error
// ForceFlush flushes all processors
func (p *LoggerProvider) ForceFlush(ctx context.Context) errorOptions for configuring a LoggerProvider.
type LoggerProviderOption interface {
// Has unexported methods
}Available Options:
// WithResource configures the Resource for the LoggerProvider
func WithResource(res *resource.Resource) LoggerProviderOption
// WithProcessor registers a Processor with the LoggerProvider
func WithProcessor(processor Processor) LoggerProviderOption
// WithAttributeCountLimit sets the maximum allowed log record attribute count
// Any attribute added to a log record once this limit is reached will be dropped
// Setting this to zero means no attributes will be recorded
// Setting this to a negative value means no limit is applied
// Default: 128 (or value from OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT env var)
func WithAttributeCountLimit(limit int) LoggerProviderOption
// WithAttributeValueLengthLimit sets the maximum allowed attribute value length
// This limit only applies to string and string slice attribute values
// Any string longer than this value will be truncated
// Setting this to a negative value means no limit is applied
// Default: -1 unlimited (or value from OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT env var)
func WithAttributeValueLengthLimit(limit int) LoggerProviderOption
// WithAllowKeyDuplication sets whether deduplication is skipped for log attributes
// By default, key-value collections are deduplicated (only last value kept for duplicate keys)
// Disabling deduplication can improve performance but requires ensuring no duplicate keys
func WithAllowKeyDuplication() LoggerProviderOptionExample:
lp := sdklog.NewLoggerProvider(
sdklog.WithResource(res),
sdklog.WithProcessor(processor),
sdklog.WithAttributeCountLimit(200),
sdklog.WithAttributeValueLengthLimit(4096),
sdklog.WithAllowKeyDuplication(),
)Processors process log records before they are exported.
type Processor interface {
// OnEmit is called when a log record is emitted
OnEmit(ctx context.Context, record *Record) error
// Enabled returns whether the processor is enabled for the given context and record
Enabled(ctx context.Context, record Record) bool
// Shutdown shuts down the processor
Shutdown(ctx context.Context) error
// ForceFlush flushes all log records
ForceFlush(ctx context.Context) error
}BatchProcessor batches log records and exports them in batches.
func NewBatchProcessor(exporter Exporter, opts ...BatchProcessorOption) *BatchProcessorDefault Configuration:
Example:
import (
"time"
"go.opentelemetry.io/otel/exporters/stdout/stdoutlog"
sdklog "go.opentelemetry.io/otel/sdk/log"
)
func setupBatchProcessor() *sdklog.BatchProcessor {
exporter, err := stdoutlog.New()
if err != nil {
log.Fatal(err)
}
processor := sdklog.NewBatchProcessor(
exporter,
sdklog.WithMaxQueueSize(4096),
sdklog.WithExportInterval(5*time.Second),
sdklog.WithExportTimeout(30*time.Second),
sdklog.WithExportMaxBatchSize(1024),
)
return processor
}Options for configuring a BatchProcessor.
type BatchProcessorOption func(*BatchProcessor)Available Options:
// WithMaxQueueSize sets the maximum queue size
func WithMaxQueueSize(size int) BatchProcessorOption
// WithExportInterval sets the interval between exports
func WithExportInterval(d time.Duration) BatchProcessorOption
// WithExportTimeout sets the maximum duration for exporting
func WithExportTimeout(d time.Duration) BatchProcessorOption
// WithExportMaxBatchSize sets the maximum batch size
func WithExportMaxBatchSize(size int) BatchProcessorOption
// WithExportBufferSize sets the batch buffer size
// Batches will be temporarily kept in memory buffer until exported
// Default: 1
func WithExportBufferSize(size int) BatchProcessorOptionSimpleProcessor exports log records synchronously when they are emitted. Not recommended for production use.
func NewSimpleProcessor(exporter Exporter, opts ...SimpleProcessorOption) *SimpleProcessorExample:
import (
"go.opentelemetry.io/otel/exporters/stdout/stdoutlog"
sdklog "go.opentelemetry.io/otel/sdk/log"
)
func setupSimpleProcessor() *sdklog.SimpleProcessor {
exporter, err := stdoutlog.New()
if err != nil {
log.Fatal(err)
}
// Only use for testing/debugging
processor := sdklog.NewSimpleProcessor(exporter)
return processor
}Options for configuring a SimpleProcessor.
type SimpleProcessorOption interface {
// Has unexported methods
}FilterProcessor extends the Processor interface to allow processors to report whether they will process a given log record. This enables Logger.Enabled to return false when all processors would drop the record.
type FilterProcessor interface {
// Enabled reports whether the Processor will process for the given context and param
// Returns true when the Processor will process the log record
// Returns false if the Processor will drop the log record
Enabled(ctx context.Context, param EnabledParameters) bool
}Use Case: Filtering log records by severity level before expensive operations.
Example:
// See go.opentelemetry.io/contrib/processors/minsev for a reference implementation
// that filters out records below a minimum severity thresholdEnabledParameters provides information for FilterProcessor.Enabled method.
type EnabledParameters struct {
InstrumentationScope instrumentation.Scope
Severity log.Severity
EventName string
}Note: EnabledParameters may contain partial record information. Processors should handle cases where not all fields are populated.
Exporters send log records to external systems.
type Exporter interface {
// Export serializes and transmits log records
Export(ctx context.Context, records []Record) error
// Shutdown flushes all log records and releases resources
Shutdown(ctx context.Context) error
// ForceFlush flushes any log records held by the exporter
ForceFlush(ctx context.Context) error
}Record represents a log record.
type Record struct {
// Timestamp is the time when the log record was created
Timestamp time.Time
// ObservedTimestamp is the time when the log record was observed
ObservedTimestamp time.Time
// Severity is the severity of the log record
Severity log.Severity
// SeverityText is the severity text
SeverityText string
// Body is the body of the log record
Body log.Value
// Attributes are the attributes associated with the log record
Attributes []log.KeyValue
// TraceID is the trace ID associated with the log record
TraceID trace.TraceID
// SpanID is the span ID associated with the log record
SpanID trace.SpanID
// TraceFlags are the trace flags
TraceFlags trace.TraceFlags
// Resource is the resource associated with the log record
Resource *resource.Resource
// InstrumentationScope is the instrumentation scope
InstrumentationScope instrumentation.Scope
// DroppedAttributes is the number of dropped attributes
DroppedAttributes int
}package main
import (
"context"
"log"
"time"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
"go.opentelemetry.io/otel/log"
"go.opentelemetry.io/otel/log/global"
sdklog "go.opentelemetry.io/otel/sdk/log"
"go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
"go.opentelemetry.io/otel/trace"
)
func main() {
ctx := context.Background()
// Step 1: Create resource
res, err := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceName("my-service"),
semconv.ServiceVersion("1.0.0"),
),
)
if err != nil {
log.Fatalf("Failed to create resource: %v", err)
}
// Step 2: Create exporter
exporter, err := otlploghttp.New(ctx,
otlploghttp.WithEndpoint("localhost:4318"),
otlploghttp.WithInsecure(),
)
if err != nil {
log.Fatalf("Failed to create exporter: %v", err)
}
// Step 3: Create processor
processor := sdklog.NewBatchProcessor(
exporter,
sdklog.WithMaxQueueSize(4096),
sdklog.WithExportInterval(5*time.Second),
sdklog.WithExportTimeout(30*time.Second),
sdklog.WithExportMaxBatchSize(512),
)
// Step 4: Create logger provider
lp := sdklog.NewLoggerProvider(
sdklog.WithResource(res),
sdklog.WithProcessor(processor),
)
// Step 5: Set as global provider
global.SetLoggerProvider(lp)
// Step 6: Setup cleanup
defer func() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := lp.ForceFlush(ctx); err != nil {
log.Printf("Failed to flush logs: %v", err)
}
if err := lp.Shutdown(ctx); err != nil {
log.Printf("Failed to shutdown logger provider: %v", err)
}
}()
// Step 7: Use logger
logger := global.GetLoggerProvider().Logger("my-component")
// Emit log records
var record log.Record
record.SetTimestamp(time.Now())
record.SetObservedTimestamp(time.Now())
record.SetSeverity(log.SeverityInfo)
record.SetSeverityText("INFO")
record.SetBody(log.StringValue("Application started"))
record.AddAttributes(
log.String("environment", "production"),
log.Int("port", 8080),
)
// Add trace context if available
span := trace.SpanFromContext(ctx)
if span.SpanContext().IsValid() {
record.SetTraceID(span.SpanContext().TraceID())
record.SetSpanID(span.SpanContext().SpanID())
record.SetTraceFlags(span.SpanContext().TraceFlags())
}
logger.Emit(ctx, record)
}The SDK respects the following environment variables:
# Maximum number of attributes per log record
OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT=128
# Maximum attribute value length (-1 for unlimited)
OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT=-1
# Batch processor maximum queue size
OTEL_BLRP_MAX_QUEUE_SIZE=2048
# Batch processor export interval in milliseconds
OTEL_BLRP_SCHEDULE_DELAY=1000
# Batch processor export timeout in milliseconds
OTEL_BLRP_EXPORT_TIMEOUT=30000
# Batch processor maximum export batch size
OTEL_BLRP_MAX_EXPORT_BATCH_SIZE=512// Good: Use batch processor
processor := sdklog.NewBatchProcessor(exporter)
// Bad: Don't use simple processor in production
processor := sdklog.NewSimpleProcessor(exporter) // Synchronous, slowlp := sdklog.NewLoggerProvider(/*...*/)
defer func() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := lp.Shutdown(ctx); err != nil {
log.Printf("Error shutting down: %v", err)
}
}()// Add trace context to correlate logs with traces
span := trace.SpanFromContext(ctx)
if span.SpanContext().IsValid() {
record.SetTraceID(span.SpanContext().TraceID())
record.SetSpanID(span.SpanContext().SpanID())
record.SetTraceFlags(span.SpanContext().TraceFlags())
}lp := sdklog.NewLoggerProvider(
sdklog.WithResource(res),
sdklog.WithProcessor(processor),
// Limits are configured via environment variables or code
)Install with Tessl CLI
npx tessl i tessl/golang-go-opentelemetry-io--otel