otello

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Apr 20, 2026 License: MIT Imports: 32 Imported by: 0

README

otello

Unified observability library for Go backends. Provides tracing (Tempo), logging (Loki), metrics (Prometheus), and continuous profiling (Pyroscope) with standardized business context propagation.

Install

go get github.com/Heer0/otello

Quick Start

Tracing only (minimal)
shutdown, err := otello.Init(otello.Config{
    Service:   "my-service",
    Namespace: "my-ns",
})
if err != nil {
    log.Fatal().Err(err).Msg("otello init failed")
}
defer shutdown(ctx)
Full stack (tracing + logging + metrics + profiling)
shutdown, err := otello.Init(otello.Config{
    Service:   "my-service",
    Namespace: "my-ns",
    Loki:      &otello.LokiConfig{},
    Metrics:   &otello.MetricsConfig{},
    Pyroscope: &otello.PyroscopeConfig{},
})
defer shutdown(ctx)

Configuration

Field Env Var Default
TraceEndpoint OTEL_EXPORTER_OTLP_ENDPOINT tempo.telemetry.svc.cluster.local:4317
Loki.Endpoint LOKI_ENDPOINT http://loki.telemetry.svc.cluster.local:3100
Pyroscope.Endpoint PYROSCOPE_ENDPOINT http://pyroscope.telemetry.svc.cluster.local:4040

Business Context

Standardized attributes propagated across spans, logs, and metrics:

ctx = otello.WithBusinessContext(ctx, otello.BusinessContext{
    UserID:    "user-123",
    TenantID:  "tenant-456",
    Operation: "createCustomer",
    Entity:    "customer",
    EntityID:  "cust-789",
})

HTTP Middleware

net/http
handler := middleware.HTTP()(myHandler)
chi
r := chi.NewRouter()
r.Use(middleware.Chi())
Ignore paths/methods
r.Use(middleware.HTTP(middleware.HTTPConfig{
    IgnorePaths:   []string{"/health", "/metrics"},
    IgnoreMethods: []string{"OPTIONS"},
}))

GraphQL (gqlgen)

srv.Use(middleware.GqlgenExtension("my-graphql", middleware.GqlgenConfig{
    TraceFields: true,
}))

GORM

// Tracing only
otello.InitGORM(db)

// With slow query metrics + pool stats
sqlDB, _ := db.DB()
otello.InitGORMWithMetrics(db, sqlDB, 200*time.Millisecond)

Prometheus Metrics

r.Handle("/metrics", otello.MetricsHandler())

Continuous Profiling (Pyroscope)

When Pyroscope is set in the config, CPU, memory, goroutine, and mutex profiles are continuously pushed to Pyroscope.

The HTTP and GraphQL middlewares automatically tag profiles with endpoint and operation labels, so you can filter flamegraphs per route or GraphQL operation in Grafana.

NATS Propagation

// Producer
headers := otello.InjectTraceContext(ctx)
msg := &nats.Msg{Header: nats.Header(headers)} // adapt as needed

// Consumer
ctx = otello.ExtractTraceContext(ctx, otello.MapCarrier(receivedHeaders))

Span Helpers

// Auto-close pattern
ctx, end := otello.StartSpan(ctx, "processOrder")
defer end(err)

// Manual span control
ctx, span := otello.TraceOperation(ctx, "uploadFile",
    otello.AttrEntity.String("document"),
)
defer span.End()

Traced Logging

logger := otello.TracedLogger(ctx, baseLogger)
logger.Info().Msg("processing request") // includes trace_id, span_id, user_id, tenant_id

Documentation

Overview

Package otello provides unified observability (tracing, logging, metrics) for Go backends. It exports directly to Tempo (gRPC) and Loki (HTTP), with Prometheus scrape for metrics.

Index

Constants

View Source
const (
	AttrUserID    = attribute.Key("app.user.id")
	AttrTenantID  = attribute.Key("app.tenant.id")
	AttrOperation = attribute.Key("app.operation")
	AttrEntity    = attribute.Key("app.entity.type")
	AttrEntityID  = attribute.Key("app.entity.id")
)

Standardized OTEL attribute keys for business context.

Variables

This section is empty.

Functions

func EndSpanWithError

func EndSpanWithError(span trace.Span, err error)

EndSpanWithError ends a span, recording the error if non-nil.

func ExtractTraceContext

func ExtractTraceContext(ctx context.Context, carrier MapCarrier) context.Context

ExtractTraceContext extracts trace context from a MapCarrier into the context.

func GetLogger

func GetLogger() zerolog.Logger

GetLogger returns the global zerolog.Logger configured by Init.

func HTTPMiddleware

func HTTPMiddleware() func(http.Handler) http.Handler

HTTPMiddleware returns a net/http middleware for tracing and metrics.

func InitGORM

func InitGORM(db *gorm.DB)

InitGORM registers the otello tracing and metrics plugin on the given GORM db.

func InitGORMWithMetrics

func InitGORMWithMetrics(db *gorm.DB, sqlDB *sql.DB, slowThreshold time.Duration)

InitGORMWithMetrics registers tracing + slow query metrics + DB pool metrics. Pass the underlying *sql.DB for pool stats collection.

func MetricsHandler

func MetricsHandler() http.Handler

MetricsHandler returns an http.Handler that serves Prometheus metrics. Returns nil if metrics are not enabled.

func RegisterRuntimeMetrics

func RegisterRuntimeMetrics(meter metric.Meter) error

RegisterRuntimeMetrics registers Go runtime metrics (goroutines, heap) on the given meter.

func SetError

func SetError(span trace.Span, err error)

SetError records an error on the current span.

func SetSuccess

func SetSuccess(span trace.Span)

SetSuccess marks the current span as successful.

func SetupZerolog

func SetupZerolog(cfg *Config) (zerolog.Logger, func())

SetupZerolog configures zerolog with a multi-writer that outputs to stderr and optionally to Loki for real-time log shipping.

func StartSpan

func StartSpan(ctx context.Context, name string, attrs ...attribute.KeyValue) (context.Context, func(error))

StartSpan starts a new span and returns the context and an end function. Call the end function with the error (or nil) when done.

ctx, end := otello.StartSpan(ctx, "myOperation")
defer end(err)

func TraceOperation

func TraceOperation(ctx context.Context, name string, attrs ...attribute.KeyValue) (context.Context, trace.Span)

TraceOperation starts a span and returns the context and span for manual control.

ctx, span := otello.TraceOperation(ctx, "processOrder", otello.AttrEntity.String("order"))
defer span.End()

func TracedLogger

func TracedLogger(ctx context.Context, logger zerolog.Logger) zerolog.Logger

TracedLogger returns a zerolog.Logger enriched with trace/span IDs from the context.

func WithBusinessContext

func WithBusinessContext(ctx context.Context, bc BusinessContext) context.Context

WithBusinessContext injects a BusinessContext into the context.

Types

type BusinessContext

type BusinessContext struct {
	UserID    string
	TenantID  string
	Operation string
	Entity    string
	EntityID  string
}

BusinessContext carries standardized business attributes across the stack.

func BusinessContextFromCtx

func BusinessContextFromCtx(ctx context.Context) (BusinessContext, bool)

BusinessContextFromCtx extracts the BusinessContext from the context.

func (BusinessContext) ApplyToSpan

func (bc BusinessContext) ApplyToSpan(span trace.Span)

ApplyToSpan sets business context attributes on the given span.

func (BusinessContext) Attributes

func (bc BusinessContext) Attributes() []attribute.KeyValue

Attributes returns the non-empty business context fields as OTEL attributes.

type Config

type Config struct {
	// Service is the name of the service (e.g., "my-backend"). Required.
	Service string
	// Version of the service. Defaults to "1.0.0".
	Version string
	// Namespace is the k8s namespace, used as Loki label and OTEL resource attribute.
	Namespace string

	// TraceEndpoint overrides OTEL_EXPORTER_OTLP_ENDPOINT env var.
	// Default: "tempo.telemetry.svc.cluster.local:4317"
	TraceEndpoint string

	// Loki enables log export to Loki. nil = disabled.
	Loki *LokiConfig

	// Metrics enables Prometheus metrics scrape endpoint. nil = disabled.
	Metrics *MetricsConfig

	// Pyroscope enables continuous profiling. nil = disabled.
	Pyroscope *PyroscopeConfig
}

Config configures the otello observability stack.

type LokiConfig

type LokiConfig struct {
	// Endpoint overrides LOKI_ENDPOINT env var.
	// Default: "http://loki.telemetry.svc.cluster.local:3100"
	Endpoint string
}

LokiConfig configures the Loki log exporter.

type LokiLogExporter

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

LokiLogExporter implements sdklog.Exporter and pushes logs to Loki via HTTP. Deprecated: Use the zerolog LokiWriter integration instead (automatic via Init).

func NewLokiLogExporter

func NewLokiLogExporter(endpoint string, service, namespace string) *LokiLogExporter

NewLokiLogExporter creates a new exporter that pushes to Loki's push API. Deprecated: Use the zerolog LokiWriter integration instead (automatic via Init).

func (*LokiLogExporter) Export

func (e *LokiLogExporter) Export(ctx context.Context, records []sdklog.Record) error

Export sends log records to Loki grouped by their label sets.

func (*LokiLogExporter) ForceFlush

func (e *LokiLogExporter) ForceFlush(_ context.Context) error

ForceFlush forces a flush of pending logs.

func (*LokiLogExporter) Shutdown

func (e *LokiLogExporter) Shutdown(_ context.Context) error

Shutdown flushes pending logs.

type MapCarrier

type MapCarrier map[string]string

MapCarrier implements propagation.TextMapCarrier for use with NATS headers or any map[string]string transport.

func InjectTraceContext

func InjectTraceContext(ctx context.Context) MapCarrier

InjectTraceContext injects the current trace context into a MapCarrier suitable for NATS headers or similar transports.

func (MapCarrier) Get

func (c MapCarrier) Get(key string) string

func (MapCarrier) Keys

func (c MapCarrier) Keys() []string

func (MapCarrier) Set

func (c MapCarrier) Set(key, value string)

type MetricsConfig

type MetricsConfig struct{}

MetricsConfig enables Prometheus metrics.

type PyroscopeConfig

type PyroscopeConfig struct {
	// Endpoint overrides PYROSCOPE_ENDPOINT env var.
	// Default: "http://pyroscope.telemetry.svc.cluster.local:4040"
	Endpoint string
}

PyroscopeConfig configures continuous profiling via Pyroscope.

type ShutdownFunc

type ShutdownFunc func(ctx context.Context) error

ShutdownFunc is the function returned by Init to gracefully shut down all providers.

func Init

func Init(cfg Config) (ShutdownFunc, error)

Init initializes the otello observability stack. It returns a shutdown function that must be called on application exit.

shutdown, err := otello.Init(otello.Config{Service: "my-svc", Namespace: "my-ns"})
if err != nil { log.Fatal().Err(err).Msg("otello init failed") }
defer shutdown(ctx)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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