autolemetry

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 24, 2025 License: MIT Imports: 26 Imported by: 0

README

autolemetry-go

Go Reference Go Report Card

OpenTelemetry instrumentation for Go.

  • One-line initialization with Init() and Start() helpers
  • OTLP-first design with subscribers for PostHog, Mixpanel, Amplitude, Webhook, and custom destinations
  • Production features: adaptive sampling, rate limiting, circuit breakers, PII redaction
  • Automatic enrichment: trace context flows into spans, logs, and events

OpenTelemetry requires significant boilerplate. Autolemetry provides a simpler API while maintaining full control over your telemetry.

go get github.com/jagreehal/autolemetry-go

Quick Start

1. Initialize once at startup
import "github.com/jagreehal/autolemetry-go"

func main() {
    cleanup, err := autolemetry.Init(context.Background(),
        autolemetry.WithService("my-service"),
    )
    if err != nil {
        log.Fatal(err)
    }
    defer cleanup()
}

Configuration options:

  • Environment variables: OTEL_SERVICE_NAME, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_PROTOCOL, OTEL_EXPORTER_OTLP_HEADERS, AUTOLEMETRY_DEBUG, etc.
  • Explicit parameters override env vars
  • No OTLP exporters run unless you set WithEndpoint(...) or the OTEL env vars—making debug-only or subscriber-only setups zero-config.
  • Vendor presets (OTLP-first): WithBackend("datadog"|"honeycomb"|"grafana") sets endpoint + headers; use WithOTLPHeaders for API keys/datasets without extra SDKs.
  • Metrics on by default: OTLP metric exporter is wired alongside traces. Toggle with WithMetrics(false) or customize with WithMetricExporters/WithMetricInterval.
Environment variables (optional)

You can configure autolemetry-go entirely via standard OTEL env vars—the SDK only falls back to functional options if the env var is missing:

  • OTEL_SERVICE_NAME – overrides WithService.
  • OTEL_EXPORTER_OTLP_ENDPOINT – host:port or URL; when set we enable OTLP trace + metric exporters.
  • OTEL_EXPORTER_OTLP_PROTOCOLhttp (default) or grpc.
  • OTEL_EXPORTER_OTLP_HEADERS – comma-separated key=value pairs for API keys/datasets.
  • OTEL_RESOURCE_ATTRIBUTES – comma-separated key=value attributes (e.g., service.version=1.0.0,deployment.environment=prod).
  • AUTOLEMETRY_DEBUG1/true to mirror WithDebug(true) without code changes.

Environment values are sanitized (e.g., stripping http:// prefixes) so you can copy URLs from docs without worrying about exporter formatting.

2. Instrument code with Start()
import "github.com/jagreehal/autolemetry-go"

func CreateUser(ctx context.Context, data UserData) (*User, error) {
    ctx, span := autolemetry.Start(ctx, "CreateUser")
    defer span.End()

    span.SetAttribute("user.email", data.Email)

    user, err := db.Users.Create(ctx, data)
    if err != nil {
        span.RecordError(err)
        return nil, err
    }

    return user, nil
}
  • Errors are recorded automatically with Trace() helper
  • Works with any context-aware code
3. Track product events
import (
    "github.com/jagreehal/autolemetry-go"
    "github.com/jagreehal/autolemetry-go/subscribers"
)

cleanup, err := autolemetry.Init(context.Background(),
    autolemetry.WithService("my-service"),
    autolemetry.WithSubscribers(
        subscribers.NewPostHogSubscriber("phc_..."),
    ),
)
defer cleanup()

func ProcessOrder(ctx context.Context, order Order) error {
    ctx, span := autolemetry.Start(ctx, "ProcessOrder")
    defer span.End()

    // Events automatically include trace_id and span_id
    autolemetry.Track(ctx, "order.completed", map[string]any{
        "amount": order.Total,
    })

    return charge(order)
}

Every span, log, and event includes trace_id and span_id automatically.

4. Capture metrics with trace correlation
import "github.com/jagreehal/autolemetry-go"

m := autolemetry.Meter()
m.Counter(ctx, "checkout.requests", 1, map[string]any{"region": "iad"})
m.Histogram(ctx, "checkout.latency_ms", float64(duration.Milliseconds()), nil)
// trace_id/span_id are attached automatically when a span is present

Event delivery is hardened by default (buffer=1000, backoff 100ms→5s, circuit threshold=5, reset every 10s). Tune with WithEventQueue, WithEventBackoff, and WithEventRetry.

Features

  • One-line initialization - No boilerplate
  • Ergonomic API - Start() and Trace() helpers
  • Production-ready - Adaptive sampling, rate limiting, circuit breakers
  • PII redaction - Built-in PII detection and redaction
  • Event tracking - PostHog, Mixpanel, Amplitude, Webhook subscribers
  • Framework integrations - HTTP (net/http), gRPC, Gin middleware
  • Vendor lock-in free - Uses standard OpenTelemetry, works with any OTLP backend

Comparison

Feature Raw OpenTelemetry autolemetry-go
Initialization 20-30 lines 1 line (Init())
Span creation tracer.Start() + manual End() Start() with defer
Error recording Manual Automatic with Trace()
Adaptive sampling ❌ (collector only) ✅ Built-in
Rate limiting ✅ Built-in
PII redaction ✅ Built-in
Product events ✅ Built-in (subscribers)
HTTP middleware Manual HTTPMiddleware()
Convenience helpers Manual ✅ Built-in

Basic Usage

Simple function tracing
func GetUser(ctx context.Context, id string) (*User, error) {
    ctx, span := autolemetry.Start(ctx, "GetUser")
    defer span.End()

    span.SetAttribute("user.id", id)
    return db.Users.FindByID(ctx, id)
}
With Trace() helper
func CreateUser(ctx context.Context, data UserData) (*User, error) {
    return autolemetry.Trace(ctx, "CreateUser", func(ctx context.Context, span autolemetry.Span) (*User, error) {
        span.SetAttribute("user.email", data.Email)
        return db.Users.Create(ctx, data)
    })
}
HTTP middleware (net/http)
import (
    "net/http"
    "github.com/jagreehal/autolemetry-go/middleware"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/users", handleUsers)

    handler := middleware.HTTPMiddleware("my-service")(mux)
    http.ListenAndServe(":8080", handler)
}
Gin middleware
import (
    "github.com/gin-gonic/gin"
    "github.com/jagreehal/autolemetry-go/middleware"
)

func main() {
    r := gin.Default()
    r.Use(middleware.GinMiddleware("my-service"))
    r.GET("/users/:id", handleGetUser)
    r.Run(":8080")
}
gRPC instrumentation
import (
    "google.golang.org/grpc"
    "github.com/jagreehal/autolemetry-go/middleware"
)

// Server
server := grpc.NewServer(
    grpc.StatsHandler(middleware.GRPCServerHandler()),
)

// Client
conn, err := grpc.NewClient("localhost:50051",
    grpc.WithStatsHandler(middleware.GRPCClientHandler()),
)

Advanced Features

Structured Logging

Automatically inject trace context into logs using log/slog:

import (
    "log/slog"
    "github.com/jagreehal/autolemetry-go/logging"
)

// Option 1: Automatic enrichment with TraceHandler
logger := slog.New(logging.NewTraceHandler(
    slog.NewJSONHandler(os.Stdout, nil),
))

ctx, span := autolemetry.Start(ctx, "operation")
defer span.End()
logger.InfoContext(ctx, "Processing request") // trace_id and span_id automatically added

// Option 2: Manual enrichment
attrs := logging.WithTraceContext(ctx)
logger.InfoContext(ctx, "Processing request", slog.Group("trace", attrs...))
Event Tracking (Product Events)

Track product events with automatic trace context enrichment. Events are sent to subscribers (PostHog, Mixpanel, Amplitude, Webhook, etc.).

Recommended: Configure subscribers in Init(), use global Track() function:

import (
    "github.com/jagreehal/autolemetry-go"
    "github.com/jagreehal/autolemetry-go/subscribers"
)

cleanup, err := autolemetry.Init(ctx,
    autolemetry.WithService("my-service"),
    autolemetry.WithSubscribers(
        subscribers.NewPostHogSubscriber("phc_..."),
    ),
)
defer cleanup()

// Use the global Track function
ctx, span := autolemetry.Start(ctx, "userAction")
autolemetry.Track(ctx, "user_signed_up", map[string]any{
    "user_id": "123",
    "plan":    "premium",
})

Manual queue creation (for advanced use cases):

import "github.com/jagreehal/autolemetry-go/subscribers"

// Option 1: PostHog
queue := subscribers.NewQueue(
    subscribers.NewPostHogSubscriber("your-posthog-api-key"),
)
defer queue.Shutdown(context.Background())

// Option 2: Mixpanel
queue := subscribers.NewQueue(
    subscribers.NewMixpanelSubscriber("your-mixpanel-token"),
)

// Option 3: Amplitude
queue := subscribers.NewQueue(
    subscribers.NewAmplitudeSubscriber("your-amplitude-api-key"),
)

// Option 4: Webhook (for any service)
queue := subscribers.NewQueue(
    subscribers.NewWebhookSubscriber("https://api.example.com",
        subscribers.WithWebhookHeaders(map[string]string{
            "Authorization": "Bearer your-api-key",
        }),
    ),
)

// Track events (automatically enriched with trace_id and span_id)
ctx, span := autolemetry.Start(ctx, "userAction")
queue.Track(ctx, "user_signed_up", map[string]any{
    "user_id": "123",
    "plan":    "premium",
})

Every event automatically includes trace_id and span_id in the properties.

Production Hardening

Adaptive Sampling
cleanup, err := autolemetry.Init(ctx,
    autolemetry.WithService("my-service"),
    autolemetry.WithAdaptiveSampler(
        sampling.WithBaselineRate(0.1), // 10% baseline
        sampling.WithErrorRate(1.0),    // 100% errors
    ),
)
Rate Limiting
cleanup, err := autolemetry.Init(ctx,
    autolemetry.WithService("my-service"),
    autolemetry.WithRateLimit(100, 200), // 100 spans/sec, burst of 200
)
Circuit Breaker
cleanup, err := autolemetry.Init(ctx,
    autolemetry.WithService("my-service"),
    autolemetry.WithCircuitBreaker(5, 3, 30*time.Second), // 5 failures, 3 successes, 30s timeout
)
PII Redaction
cleanup, err := autolemetry.Init(ctx,
    autolemetry.WithService("my-service"),
    autolemetry.WithPIIRedaction(
        redaction.WithAllowlistKeys("user_id", "order_id"),
    ),
)

Complete Feature List

Core Features
  • ✅ One-line initialization with environment variable support
  • ✅ Ergonomic Start() and Trace() helpers
  • ✅ Convenience helpers (SetAttribute(), GetTraceID(), etc.)
  • ✅ Context-aware span operations
Events & Subscribers
  • subscribers.NewQueue() → sends to subscribers (PostHog, Mixpanel, Amplitude, Webhook, etc.)
  • ✅ Global Track() function
  • ✅ Auto-enrichment with trace context
  • ✅ Queue-based event system
Logging
  • ✅ Structured logging integration with log/slog
  • ✅ Automatic trace context injection
  • ✅ Zero configuration
Production Features
  • ✅ Adaptive sampling (10% baseline, 100% errors/slow)
  • ✅ Rate limiting (token bucket)
  • ✅ Circuit breaker (subscriber protection)
  • ✅ PII redaction (email, phone, SSN, credit card, API keys)
Framework Integrations
  • ✅ HTTP middleware (net/http)
  • ✅ Gin middleware
  • ✅ gRPC instrumentation
Testing
  • ✅ InMemorySpanExporter for unit tests
  • ✅ Test helpers in testing/ package

Examples

See the examples/ directory for complete working examples:

  • basic/ - Basic tracing usage
  • http-server/ - HTTP server with middleware
  • gin-server/ - Gin framework integration
  • logging/ - Structured logging integration
  • analytics/ - Event tracking (in-memory subscriber)
  • analytics-posthog/ - PostHog event integration
  • production-ready/ - Complete production setup with all hardening features

Run any example:

cd examples/basic
# Debug spans print to stderr and no backend is required
AUTOLEMETRY_DEBUG=true go run main.go

Debug Mode

Enable debug mode to see all span operations logged to stderr:

// Option 1: Via environment variable
// AUTOLEMETRY_DEBUG=true go run main.go

// Option 2: Programmatically
cleanup, err := autolemetry.Init(ctx,
    autolemetry.WithService("my-service"),
    autolemetry.WithDebug(true), // Enable debug mode
)

Debug output shows:

  • Span creation with trace_id and span_id
  • Attribute setting
  • Error recording
  • Span completion
  • PII redaction (when enabled)

Example debug output:

[autolemetry] Debug mode enabled
[autolemetry] Using AlwaysSample sampler for debug mode
[autolemetry] → Start span: ProcessOrder [trace_id=7130bb6d5bb4ef40..., span_id=6bf9a60ec0080bff]
[autolemetry]   Set attribute: order.id=12345 [trace_id=7130bb6d5bb4ef40...]
[autolemetry] ← End span [trace_id=7130bb6d5bb4ef40..., span_id=6bf9a60ec0080bff]

Convenience Helpers

Simple functions for common operations without needing to get the span first:

import "github.com/jagreehal/autolemetry-go"

// Set single attribute on current span
autolemetry.SetAttribute(ctx, "user.id", "123")

// Set multiple attributes at once
autolemetry.SetAttributes(ctx, map[string]any{
    "order.id":    orderID,
    "order.total": total,
    "customer.tier": "premium",
})

// Add a span event
autolemetry.AddEvent(ctx, "order.validated", map[string]any{
    "validator": "schema_v2",
})

// Record exception (sets span status to ERROR)
if err != nil {
    autolemetry.RecordError(ctx, err, map[string]any{
        "order.id": orderID,
    })
}

// Get IDs for logging
traceID := autolemetry.GetTraceID(ctx)
spanID := autolemetry.GetSpanID(ctx)
log.Printf("Processing in trace: %s, span: %s", traceID, spanID)

// Track operation duration (requires span)
ctx, span := autolemetry.Start(ctx, "operation")
start := time.Now()
// ... do work ...
autolemetry.SetDuration(span, start)
span.End()

// Set HTTP request attributes (requires span)
ctx, span := autolemetry.Start(ctx, "httpRequest")
autolemetry.SetHTTPRequestAttributes(span, r.Method, r.URL.Path, r.UserAgent())
span.End()

// Add event with attributes (alternative API, requires span)
ctx, span := autolemetry.Start(ctx, "operation")
autolemetry.AddEventWithAttributes(span, "cache_hit",
    "cache.key", "user:123",
    "cache.ttl", 3600,
)
span.End()

// Check if tracing is enabled
if autolemetry.IsTracingEnabled(ctx) {
    // Tracing is active
}

Available helpers:

  • SetAttribute(ctx, key, value) - Set single span attribute on current span
  • SetAttributes(ctx, attrs) - Set multiple span attributes on current span
  • AddEvent(ctx, name, attrs) - Add span event to current span
  • RecordError(ctx, err, attrs) - Record exception and set error status on current span
  • GetTraceID(ctx) - Get current trace ID as hex string
  • GetSpanID(ctx) - Get current span ID as hex string
  • SetDuration(span, start) - Set operation duration (requires span)
  • SetHTTPRequestAttributes(span, method, path, userAgent) - Set HTTP attributes (requires span)
  • AddEventWithAttributes(span, name, ...) - Add event with variadic attributes (requires span)
  • IsTracingEnabled(ctx) - Check if tracing is active

Status

Production ready. All core features implemented and tested.

Version: 0.1.0
Go: 1.21+
License: MIT

Version

Current version: v0.1.0

import "github.com/jagreehal/autolemetry-go"

version := autolemetry.GetVersion()

Dependencies

This library uses the latest stable versions of dependencies compatible with Go 1.21+:

  • OpenTelemetry: v1.38.0 (latest stable)
  • OpenTelemetry Contrib: v0.63.0 (latest)
  • Gin: v1.11.0 (latest)
  • Testify: v1.11.1 (latest)
  • gRPC: v1.75.0 (latest compatible with Go 1.23)

All dependencies are kept up-to-date and verified for compatibility.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

MIT License - see LICENSE file for details.

Acknowledgments

Built on top of the excellent OpenTelemetry Go project.

Documentation

Overview

Example

Example demonstrates basic usage of autolemetry.

ctx := context.Background()

// Initialize autolemetry
cleanup, err := autolemetry.Init(ctx,
	autolemetry.WithService("example-service"),
	autolemetry.WithEndpoint("localhost:4318"),
)
if err != nil {
	log.Fatal(err)
}
defer cleanup()

// Create a traced operation
_, span := autolemetry.Start(ctx, "example-operation")
defer span.End()

span.SetAttribute("example.key", "example-value")

fmt.Println("Tracing initialized")
Output:
Tracing initialized
Example (ErrorHandling)

Example_errorHandling demonstrates automatic error recording.

ctx := context.Background()

_, span := autolemetry.Start(ctx, "risky-operation")
defer span.End()

// Simulate an error
err := fmt.Errorf("something went wrong")
if err != nil {
	span.RecordError(err) // Automatically sets span status to ERROR
}

fmt.Println("Error recorded in span")
Output:
Error recorded in span
Example (Init)

Example_init demonstrates initialization with various options.

ctx := context.Background()

cleanup, err := autolemetry.Init(ctx,
	autolemetry.WithService("my-service"),
	autolemetry.WithServiceVersion("1.0.0"),
	autolemetry.WithEnvironment("production"),
	autolemetry.WithEndpoint("localhost:4318"),
	autolemetry.WithProtocol(autolemetry.ProtocolHTTP),
)
if err != nil {
	log.Fatal(err)
}
defer cleanup()

fmt.Println("Initialized with custom options")
Output:
Initialized with custom options
Example (InitWithConfig)

Example_initWithConfig demonstrates advanced configuration using Config directly. This is for advanced users who need full control over configuration.

ctx := context.Background()

// Get default config and customize it
cfg := autolemetry.DefaultConfig()
cfg.ServiceName = "advanced-service"
cfg.ServiceVersion = "2.0.0"
cfg.Environment = "production"
cfg.Endpoint = "otel-collector:4318"
cfg.Protocol = autolemetry.ProtocolHTTP
cfg.Insecure = false

// Initialize with custom config
cleanup, err := autolemetry.InitWithConfig(ctx, cfg)
if err != nil {
	log.Fatal(err)
}
defer cleanup()

fmt.Println("Initialized with custom Config")
Output:
Initialized with custom Config
Example (NestedSpans)

Example_nestedSpans demonstrates creating nested spans.

ctx := context.Background()

// Parent span
ctx, parentSpan := autolemetry.Start(ctx, "parent-operation")
defer parentSpan.End()

parentSpan.SetAttribute("level", "parent")

// Child span
_, childSpan := autolemetry.Start(ctx, "child-operation")
childSpan.SetAttribute("level", "child")
childSpan.End()

fmt.Println("Nested spans created")
Output:
Nested spans created
Example (Start)

Example_start demonstrates creating spans with Start.

ctx := context.Background()

// Start a new span
_, span := autolemetry.Start(ctx, "database-query")
defer span.End()

// Set attributes
span.SetAttribute("db.system", "postgresql")
span.SetAttribute("db.operation", "SELECT")
span.SetAttribute("db.table", "users")

fmt.Println("Span created with attributes")
Output:
Span created with attributes
Example (Trace)

Example_trace demonstrates using the Trace helper for automatic error handling.

ctx := context.Background()

// Use Trace helper with automatic error handling
result, err := autolemetry.Trace(ctx, "process-data",
	func(ctx context.Context, span autolemetry.Span) (string, error) {
		span.SetAttribute("operation", "processing")
		// Your business logic here
		return "processed-data", nil
	},
)

if err != nil {
	log.Fatal(err)
}

fmt.Println("Result:", result)
Output:
Result: processed-data
Example (TraceNoError)

Example_traceNoError demonstrates Trace helper for operations without errors.

ctx := context.Background()

result := autolemetry.TraceNoError(ctx, "calculation",
	func(ctx context.Context, span autolemetry.Span) int {
		span.SetAttribute("operation", "add")
		return 42 + 8
	},
)

fmt.Println("Result:", result)
Output:
Result: 50
Example (TraceVoid)

Example_traceVoid demonstrates Trace helper for operations that return only errors.

ctx := context.Background()

err := autolemetry.TraceVoid(ctx, "write-operation",
	func(ctx context.Context, span autolemetry.Span) error {
		span.SetAttribute("operation", "write")
		// Your operation here
		return nil
	},
)

if err == nil {
	fmt.Println("Operation completed successfully")
}
Output:
Operation completed successfully
Example (WithCircuitBreaker)

Example_withCircuitBreaker demonstrates circuit breaker configuration.

ctx := context.Background()

cleanup, err := autolemetry.Init(ctx,
	autolemetry.WithService("resilient-service"),
	autolemetry.WithCircuitBreaker(
		5,  // failure threshold
		3,  // success threshold
		30, // timeout in seconds
	),
)
if err != nil {
	log.Fatal(err)
}
defer cleanup()

fmt.Println("Circuit breaker enabled")
Output:
Circuit breaker enabled
Example (WithDebug)

Example_withDebug demonstrates debug mode for development.

ctx := context.Background()

cleanup, err := autolemetry.Init(ctx,
	autolemetry.WithService("debug-service"),
	autolemetry.WithDebug(true),
)
if err != nil {
	log.Fatal(err)
}
defer cleanup()

fmt.Println("Debug mode enabled")
Output:
Debug mode enabled
Example (WithRateLimit)

Example_withRateLimit demonstrates rate limiting configuration.

ctx := context.Background()

cleanup, err := autolemetry.Init(ctx,
	autolemetry.WithService("rate-limited-service"),
	autolemetry.WithRateLimit(100, 200), // 100 spans/sec, burst of 200
)
if err != nil {
	log.Fatal(err)
}
defer cleanup()

fmt.Println("Rate limiting enabled")
Output:
Rate limiting enabled

Index

Examples

Constants

View Source
const Version = "0.1.0"

Version is the current version of autolemetry-go.

Variables

This section is empty.

Functions

func AddEvent

func AddEvent(ctx context.Context, name string, attrs map[string]any)

AddEvent adds an event to the current span from context. This is a convenience function that doesn't require getting the span first.

func AddEventWithAttributes

func AddEventWithAttributes(span Span, name string, attrs ...any)

AddEventWithAttributes is a convenience function for adding events with attributes.

Example:

autolemetry.AddEventWithAttributes(span, "cache_hit",
    "cache.key", "user:123",
    "cache.ttl", 3600,
)

func DebugPrintf

func DebugPrintf(format string, args ...any)

DebugPrintf is exported for internal helpers (avoid cycles).

func DisableDebug

func DisableDebug()

DisableDebug disables debug mode.

func EnableDebug

func EnableDebug()

EnableDebug enables debug mode, which logs all span operations.

func GetOperationName

func GetOperationName(ctx context.Context) string

GetOperationName returns the operation/span name stored on context by Start/Trace helpers.

func GetSpanID

func GetSpanID(ctx context.Context) string

GetSpanID returns the current span ID as a hex string. Returns empty string if no active span exists.

func GetTraceID

func GetTraceID(ctx context.Context) string

GetTraceID returns the current trace ID as a hex string. Returns empty string if no active span exists.

func GetVersion

func GetVersion() string

GetVersion returns the current version of autolemetry-go.

func Init

func Init(ctx context.Context, opts ...Option) (func(), error)

Init initializes autolemetry with OpenTelemetry SDK using functional options. Returns a cleanup function that should be called on shutdown.

This is the recommended way to initialize autolemetry for most users.

Example:

cleanup, err := autolemetry.Init(ctx,
    autolemetry.WithService("my-service"),
    autolemetry.WithEndpoint("http://localhost:4318"),
)
if err != nil {
    log.Fatal(err)
}
defer cleanup()

func InitWithConfig

func InitWithConfig(ctx context.Context, cfg *Config) (func(), error)

InitWithConfig initializes autolemetry with a custom Config. This provides advanced users with full control over configuration.

Most users should use Init() with functional options instead.

Example:

cfg := autolemetry.DefaultConfig()
cfg.ServiceName = "my-service"
cfg.Endpoint = "custom:4318"
cfg.Sampler = trace.AlwaysSample() // Custom sampler
cleanup, err := autolemetry.InitWithConfig(ctx, cfg)
if err != nil {
    log.Fatal(err)
}
defer cleanup()

func IsDebugEnabled

func IsDebugEnabled() bool

IsDebugEnabled returns whether debug mode is enabled.

func IsProduction

func IsProduction() bool

func IsTracingEnabled

func IsTracingEnabled(ctx context.Context) bool

IsTracingEnabled checks if tracing is currently enabled. Returns true if a TracerProvider is set and not a no-op provider.

func RecordError

func RecordError(ctx context.Context, err error, attrs map[string]any)

RecordError records an error on the current span from context. This sets the span status to ERROR automatically. This is a convenience function that doesn't require getting the span first.

func RegisterQueueFactory

func RegisterQueueFactory(factory func(cfg *Config, subscribers []Subscriber) EventTracker)

RegisterQueueFactory registers a function to create analytics queues. This is called by the analytics package to avoid import cycles. Users should not call this directly.

func SetAttribute

func SetAttribute(ctx context.Context, key string, value any)

SetAttribute sets a single attribute on the current span from context. This is a convenience function that doesn't require getting the span first.

func SetAttributes

func SetAttributes(ctx context.Context, attrs map[string]any)

SetAttributes sets multiple attributes on the current span from context. This is a convenience function that doesn't require getting the span first.

func SetDuration

func SetDuration(span Span, start time.Time)

SetDuration sets the duration of an operation as a span attribute. This is useful for tracking operation performance.

Example:

start := time.Now()
// ... do work ...
autolemetry.SetDuration(span, start)

func SetHTTPRequestAttributes

func SetHTTPRequestAttributes(span Span, method, path, userAgent string)

SetHTTPRequestAttributes sets common HTTP request attributes on a span. This is a convenience function for HTTP handlers.

Example:

func handler(w http.ResponseWriter, r *http.Request) {
    ctx, span := autolemetry.Start(r.Context(), "handleRequest")
    defer span.End()
    autolemetry.SetHTTPRequestAttributes(span, r)
    // ... handle request ...
}

func ShouldEnableDebug

func ShouldEnableDebug(debug *bool) bool

ShouldEnableDebug decides whether debug should be enabled when not explicitly set. If debug is nil, enable in non-production by default.

func Trace

func Trace[T any](ctx context.Context, name string, fn func(context.Context, Span) (T, error)) (T, error)

Trace wraps a function with automatic span lifecycle management. The function receives the updated context and span. If the function returns an error, it's automatically recorded.

Example:

func GetUser(ctx context.Context, id string) (*User, error) {
    return autolemetry.Trace(ctx, "GetUser", func(ctx context.Context, span autolemetry.Span) (*User, error) {
        span.SetAttribute("user.id", id)
        return db.Users.FindByID(ctx, id)
    })
}

func TraceNoError

func TraceNoError[T any](ctx context.Context, name string, fn func(context.Context, Span) T) T

TraceNoError is like Trace but for functions that don't return errors.

func TraceVoid

func TraceVoid(ctx context.Context, name string, fn func(context.Context, Span) error) error

TraceVoid is like Trace but for functions that don't return a value.

func Track

func Track(ctx context.Context, event string, properties map[string]any)

Track sends an analytics event to the global queue (if configured). This is a convenience function that uses the queue created during Init(). If no subscribers were provided during Init(), this function does nothing.

Example:

autolemetry.Track(ctx, "user_signed_up", map[string]any{
    "user_id": "123",
    "plan":    "premium",
})

Types

type Config

type Config struct {
	// ServiceName is the name of your service (required)
	ServiceName string

	// ServiceVersion is the version of your service (optional)
	ServiceVersion string

	// Environment is the deployment environment (e.g., "production", "staging")
	Environment string

	// Endpoint is the OTLP endpoint URL (default: "localhost:4318")
	Endpoint string

	// Protocol is the OTLP protocol to use (http or grpc)
	Protocol Protocol

	// Insecure controls whether to use insecure connections (default: true for development)
	Insecure bool

	// Sampler is the trace sampler to use (default: AdaptiveSampler)
	Sampler trace.Sampler

	// RateLimiter limits span creation rate (optional)
	RateLimiter *ratelimit.TokenBucket

	// CircuitBreaker protects exporter from overload (optional)
	CircuitBreaker *circuitbreaker.CircuitBreaker

	// PIIRedactor redacts PII from span attributes (optional)
	PIIRedactor *redaction.PIIRedactor

	// UseAdaptiveSampler indicates whether adaptive sampling is enabled
	UseAdaptiveSampler bool

	// Subscribers are event subscribers (PostHog, Mixpanel, etc.)
	// If provided, a global event queue will be created automatically.
	Subscribers []Subscriber

	// BackendPreset enables vendor presets (datadog, honeycomb, grafana, default otlp).
	BackendPreset string

	// OTLPHeaders are additional headers sent to the exporter (API keys, datasets, etc.).
	OTLPHeaders map[string]string

	// Additional span exporters beyond the default OTLP exporter.
	SpanExporters []trace.SpanExporter

	// Additional span processors to attach.
	SpanProcessors []trace.SpanProcessor

	// Event queue tuning.
	EventQueueSize     int
	EventFlushInterval time.Duration
	EventCBThreshold   int
	EventBackoffMin    time.Duration
	EventBackoffMax    time.Duration
	EventCBReset       time.Duration
	EventMaxRetries    int
	EventJitter        time.Duration

	// Batch processor tuning knobs (match TS README).
	BatchTimeout       time.Duration
	MaxQueueSize       int
	MaxExportBatchSize int

	// Debug allows auto detection when nil.
	Debug *bool

	// Metrics control.
	MetricsEnabled  bool
	MetricExporters []metric.Exporter
	MetricInterval  time.Duration
}

Config holds autolemetry configuration.

Most users should use the functional options pattern with Init():

cleanup, err := autolemetry.Init(ctx,
    autolemetry.WithService("my-service"),
    autolemetry.WithEndpoint("localhost:4318"),
)

Advanced users can create and modify Config directly for more control:

cfg := autolemetry.DefaultConfig()
cfg.ServiceName = "my-service"
cfg.Endpoint = "custom:4318"
// ... customize further
cleanup, err := autolemetry.InitWithConfig(ctx, cfg)

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns a Config with sensible defaults. You can modify the returned Config and pass it to InitWithConfig.

Example:

cfg := autolemetry.DefaultConfig()
cfg.ServiceName = "my-service"
cfg.Environment = "production"
cleanup, err := autolemetry.InitWithConfig(ctx, cfg)

type DebugPrinter

type DebugPrinter struct {
	// contains filtered or unexported fields
}

DebugPrinter provides a structured way to print debug information.

func NewDebugPrinter

func NewDebugPrinter() *DebugPrinter

NewDebugPrinter creates a new debug printer.

func (*DebugPrinter) PrintSpan

func (d *DebugPrinter) PrintSpan(name string, ctx trace.SpanContext, attrs []attribute.KeyValue)

PrintSpan prints span information.

func (*DebugPrinter) PrintTrace

func (d *DebugPrinter) PrintTrace(traceID trace.TraceID, spans []string)

PrintTrace prints trace information.

type EventTracker

type EventTracker interface {
	Track(ctx context.Context, event string, properties map[string]any)
	Shutdown(ctx context.Context) error
}

EventTracker is an interface for tracking analytics events. This avoids import cycles by not importing the analytics package directly.

type Metric

type Metric struct {
	// contains filtered or unexported fields
}

Metric wraps an OTEL meter to provide lightweight counters/histograms with trace correlation.

func Meter

func Meter() Metric

Meter returns a Metric helper tied to the global provider.

func (Metric) Counter

func (m Metric) Counter(ctx context.Context, name string, value float64, attrs map[string]any)

Counter adds a delta to a named counter, attaching trace context if present.

func (Metric) Histogram

func (m Metric) Histogram(ctx context.Context, name string, value float64, attrs map[string]any)

Histogram records a value to a named histogram.

type Option

type Option func(*Config)

Option is a functional option for configuring autolemetry

func WithAdaptiveSampler

func WithAdaptiveSampler(opts ...sampling.AdaptiveSamplerOption) Option

WithAdaptiveSampler configures the adaptive sampler with custom options.

func WithBackend

func WithBackend(name string) Option

WithBackend enables a vendor preset ("datadog", "honeycomb", "grafana", "otlp"). Presets remain OTLP-first and only adjust endpoints/headers.

func WithBatchTimeout

func WithBatchTimeout(timeout time.Duration) Option

WithBatchTimeout overrides the batch processor timeout.

func WithCircuitBreaker

func WithCircuitBreaker(failureThreshold, successThreshold int, timeout time.Duration) Option

WithCircuitBreaker enables circuit breaker protection. failureThreshold is the number of failures before opening the circuit. successThreshold is the number of successes needed to close from half-open. timeout is how long to wait before attempting recovery.

func WithDebug

func WithDebug(enabled bool) Option

WithDebug enables debug mode, which logs all span operations to stderr.

func WithEndpoint

func WithEndpoint(endpoint string) Option

WithEndpoint sets the OTLP endpoint

func WithEnvironment

func WithEnvironment(env string) Option

WithEnvironment sets the deployment environment

func WithEventBackoff

func WithEventBackoff(min, max, reset time.Duration) Option

WithEventBackoff configures per-subscriber backoff and circuit reset.

func WithEventQueue

func WithEventQueue(size int, flushInterval time.Duration, circuitBreakerThreshold int) Option

WithEventQueue configures event queue buffer, flush interval (for retries), and breaker threshold.

func WithEventRetry

func WithEventRetry(maxRetries int, jitter time.Duration) Option

WithEventRetry configures max retries (0 = unlimited) and jitter.

func WithInsecure

func WithInsecure(insecure bool) Option

WithInsecure controls whether to use insecure connections

func WithMaxExportBatchSize

func WithMaxExportBatchSize(size int) Option

WithMaxExportBatchSize overrides exporter batch size.

func WithMaxQueueSize

func WithMaxQueueSize(size int) Option

WithMaxQueueSize overrides exporter queue size.

func WithMetricExporters

func WithMetricExporters(exporters ...metricSdk.Exporter) Option

WithMetricExporters appends custom metric exporters.

func WithMetricInterval

func WithMetricInterval(d time.Duration) Option

WithMetricInterval sets periodic reader interval.

func WithMetrics

func WithMetrics(enabled bool) Option

WithMetrics toggles metric export.

func WithOTLPHeaders

func WithOTLPHeaders(headers map[string]string) Option

WithOTLPHeaders adds custom OTLP headers (API keys, datasets, etc.).

func WithPIIRedaction

func WithPIIRedaction(opts ...redaction.PIIRedactorOption) Option

WithPIIRedaction enables PII redaction with optional configuration.

func WithProtocol

func WithProtocol(protocol Protocol) Option

WithProtocol sets the OTLP protocol (http or grpc)

func WithRateLimit

func WithRateLimit(rate float64, burst int) Option

WithRateLimit enables rate limiting for span creation. rate is the number of spans per second, burst is the maximum burst size.

func WithSampler

func WithSampler(sampler trace.Sampler) Option

WithSampler sets a custom sampler

func WithService

func WithService(name string) Option

WithService sets the service name

func WithServiceVersion

func WithServiceVersion(version string) Option

WithServiceVersion sets the service version

func WithSpanExporters

func WithSpanExporters(exporters ...trace.SpanExporter) Option

WithSpanExporters appends custom span exporters.

func WithSpanProcessors

func WithSpanProcessors(processors ...trace.SpanProcessor) Option

WithSpanProcessors appends custom span processors.

func WithSubscribers

func WithSubscribers(subscribers ...Subscriber) Option

WithSubscribers sets event subscribers. If provided, a global event queue will be created automatically. The queue will be shut down when the cleanup function from Init() is called.

Example:

cleanup, err := autolemetry.Init(ctx,
    autolemetry.WithService("my-service"),
    autolemetry.WithSubscribers(
        subscribers.NewPostHogSubscriber("phc_..."),
    ),
)
defer cleanup()

// Use the global Track function
autolemetry.Track(ctx, "user_signed_up", map[string]any{
    "user_id": "123",
})

type Protocol

type Protocol string

Protocol defines the OTLP protocol to use

const (
	ProtocolHTTP Protocol = "http"
	ProtocolGRPC Protocol = "grpc"
)

type Span

type Span interface {
	// SetAttribute sets an attribute (supports string, int, int64, float64, bool)
	SetAttribute(key string, value any)

	// AddEvent adds an event to the span
	AddEvent(name string, attrs ...attribute.KeyValue)

	// SetStatus sets the span status
	SetStatus(code codes.Code, description string)

	// RecordError records an error and sets span status to ERROR
	RecordError(err error)

	// End ends the span
	End()

	// SpanContext returns the span context
	SpanContext() trace.SpanContext

	// IsRecording returns whether the span is recording
	IsRecording() bool
}

Span wraps an OpenTelemetry span with ergonomic helpers

func Start

func Start(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, Span)

Start creates a new span and returns the updated context and span. The span should be ended with span.End() or defer span.End().

Example:

func CreateUser(ctx context.Context, data UserData) error {
    ctx, span := autolemetry.Start(ctx, "CreateUser")
    defer span.End()

    span.SetAttribute("user.email", data.Email)
    return db.Users.Create(ctx, data)
}

type Subscriber

type Subscriber interface {
	Send(ctx context.Context, event string, properties map[string]any) error
	Close() error
}

Subscriber is implemented by analytics subscribers (PostHog, Mixpanel, etc.). Defined at root to keep autolemetry API typed without import cycles.

Directories

Path Synopsis
examples
analytics command
basic command
gin-server command
http-server command
logging command
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL