obs

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Sep 7, 2026 License: Apache-2.0 Imports: 28 Imported by: 0

README ΒΆ

Nexss Observability πŸ”­

Go Reference

Zero-Touch Telemetry and Pragmatic Observability for High-Performance Go Applications.

nexssp/observability separates application infrastructure concerns from your core business domain rules [1]. By utilizing Go's native context.Context propagation and the nexssp/kernel zero-allocation AnyHook execution hooks, we achieve full metric tracking, distributed tracing, and structured contextual logging without introducing external SDK dependencies into your business logic [1].

πŸ—οΈ Architecture Philosophy

Observability is an infrastructure concern, not a domain concern.

We strictly forbid polluting business logic (kernel/action handlers) with tracing setup, metric counters, or correlation ID extraction.

Instead, this package utilizes the Kernel's AnyHook interface to intercept executions at the boundary.

Telemetry Stack Integration:
  • Prometheus Metrics: Automatic action_latency_ms and action_errors_total on every action.
  • OpenTelemetry Traces: Spans automatically created and closed for every action invocation.
  • Contextual Logging: log/slog automatically enriched with trace_id, span_id, and action names.
  • Transparent Propagation: Wrapped DB drivers and HTTP clients that automatically extract/inject W3C trace headers.
  • Health Aggregation: A unified /healthz endpoint with strict timeouts to prevent cascading infrastructure failures.

🀯 The Magic of Nexss: "Zero-Touch" Telemetry

In traditional microservices, observability is a disease that infects your business logic. Developers are forced to become infrastructure experts, mixing OpenTelemetry APIs, Prometheus counters, and context extraction directly into their domain code.

❌ The "Old Way" (Spaghetti Code)

Look at a standard Go handler. Over 70% of this code is infrastructure boilerplate.

func CreateOrder(ctx context.Context, req OrderReq) (OrderRes, error) {
    // 1. Tracing Boilerplate
    ctx, span := tracer.Start(ctx, "CreateOrder")
    defer span.End()

    // 2. Metrics Boilerplate
    start := time.Now()
    defer func() {
        requestLatency.WithLabelValues("CreateOrder").Observe(time.Since(start).Seconds())
    }()

    // 3. Logging Boilerplate
    log.With("trace_id", span.SpanContext().TraceID().String()).Info("creating order")

    // --- FINALLY, THE ACTUAL BUSINESS LOGIC ---
    err := db.ExecContext(ctx, "INSERT INTO orders...", req.ID)
    if err != nil {
        errorCounter.WithLabelValues("CreateOrder").Inc() // More boilerplate
        span.RecordError(err)                             // More boilerplate
        return OrderRes{}, err
    }
    return OrderRes{Status: "created"}, nil
}
✨ The "Nexss Way" (Pristine Domain Logic)

In Nexss, your developers never write a single line of tracing or metrics code. They write pure business logic.

var CreateOrder = action.New("order.create", func(ctx context.Context, req OrderReq) (OrderRes, error) {

    // 1. Contextual Logger automatically knows the Trace ID!
    logger.InfoContext(ctx, "creating order")

    // 2. Passing 'ctx' automatically creates a Child Span for the DB query!
    err := db.ExecContext(ctx, "INSERT INTO orders...", req.ID)
    if err != nil {
        return OrderRes{}, err
    }

    return OrderRes{Status: "created"}, nil
}).Build()
πŸͺ„ How is this possible? (The AnyHook Architecture)

Where did the OpenTelemetry spans and Prometheus metrics go? They are completely decoupled.

Instead of hardcoding infrastructure into the action, you plug it in at the gateway boundary during server boot using the lock-free AnyHook interface:

// Wire infrastructure ONCE in main.go
telemetryPlugin := actionhook.New(obsProvider)

// Instantly instrument EVERY action in your app
CreateOrder.AddAnyHook(telemetryPlugin)

When CreateOrder runs, the Nexss Kernel does the following with zero heap allocations:

  1. Interceptor Fires: The hook generates the OTel Span and starts the Prometheus timer.
  2. Context Injection: The hook silently places the active trace into the standard context.Context.
  3. Execution: Your pristine business logic runs. The wrapped dbtrace.DB finds the trace in the context and attaches its queries to it.
  4. Cleanup: The hook catches any returned errors, increments failure metrics, logs the stack trace, and closes the span.

⚑ SRE Edge Cases Covered

1. Panic Isolation inside Sub-Spans

When creating manual spans inside your code, Go's panic recovery may bypass the standard closure function, causing orphan spans. We use deferred named-error processing to capture panics:

import obs "github.com/nexssp/observability"

func ParseComplexJSON(ctx context.Context, data []byte) (res string, err error) {
    ctx, endSpan := obs.StartSpan(ctx, "json.parse")
    defer func() {
        if r := recover(); r != nil {
            err = xerr.PanicRecovery(r)
        }
        endSpan(err) // Safely closes the span and records the recovered panic
    }()

    // ... code that might panic ...
}
2. Dynamic Span Enrichment

Because the context contains standard OpenTelemetry data, you can dynamically add tags or attributes to the current running span anywhere in your business logic without vendor lock-in.

import "go.opentelemetry.io/otel/trace"
import "go.opentelemetry.io/otel/attribute"

// Enrich the active span (if present)
if span := trace.SpanFromContext(ctx); span.IsRecording() {
    span.SetAttributes(
        attribute.String("user.tier", "VIP"),
        attribute.Float64("payment.amount", 250.00),
    )
}
3. Non-Blocking Async Trace Detachment

Launching background goroutines with standard request contexts is dangerousβ€”when the client request ends, the context cancels, killing any downstream background traces. We use trace detachment to let background operations execute under independent lifecycles while preserving tracing context:

import "github.com/nexssp/kernel/xctx"

func HandleRequest(ctx context.Context) {
    // Clone trace context without cancellation to prevent background tracing failure
    asyncCtx := xctx.CloneForAsync(ctx)

    go func() {
        ctx, endSpan := obs.StartSpan(asyncCtx, "async.background_cleanup")
        defer endSpan()

        // Executes safely even if the main client request has exited
        processCleanup(ctx)
    }()
}

License

Apache License 2.0. See LICENSE for details.

Documentation ΒΆ

Overview ΒΆ

Package obs provides OpenTelemetry-based tracing, metrics, contextual logging, and readiness health probes.

Package obs provides tracing hooks for framework action execution.

Package obs provides interfaces for observability components.

Package obs provides OpenTelemetry contextual logging.

Package obs initializes OpenTelemetry meters, tracers, Prometheus registries, and health endpoints.

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

This section is empty.

Functions ΒΆ

func FormatDuration ΒΆ

func FormatDuration(d time.Duration) string

func SpanID ΒΆ

func SpanID(ctx context.Context) string

SpanID extracts active span ID from context as string (or returns empty).

func StartSpan ΒΆ

func StartSpan(ctx context.Context, name string, detail ...string) (context.Context, func(err ...error))

StartSpan creates a child OpenTelemetry span with start offsets for visual timelines.

func TraceID ΒΆ

func TraceID(ctx context.Context) string

TraceID extracts active trace ID from context as string (or returns empty).

func WithCollector ΒΆ

func WithCollector(ctx context.Context) (context.Context, *activeTraceCollector)

Types ΒΆ

type CompletedSpan ΒΆ

type CompletedSpan struct {
	Name          string `json:"name"`
	Status        string `json:"status"` // "OK" or "ERROR"
	StartOffsetUs int64  `json:"start_offset_us"`
	StartOffsetNs int64  `json:"start_offset_ns"`
	DurationUs    int64  `json:"duration_us"`
	DurationNs    int64  `json:"duration_ns"`
	Duration      string `json:"duration"`
	Detail        string `json:"detail,omitempty"`
}

type Config ΒΆ

type Config struct {
	ServiceName        string
	NodeID             string
	Env                string
	OTLPEndpoint       string
	OTLPHeaders        map[string]string
	OTLPInsecure       bool
	SampleRatio        float64
	HealthCheckTimeout time.Duration

	PrometheusRegistry *prometheus.Registry
	MetricsPrefix      string
	MetricsNamespace   string
	MetricsSubsystem   string
	HistogramBuckets   []float64
	LoggerHandler      slog.Handler
}

Config holds observability initialization parameters.

func LoadConfigFromEnv ΒΆ

func LoadConfigFromEnv() Config

LoadConfigFromEnv builds Config from standard environment variables.

type ContextHandler ΒΆ

type ContextHandler struct {
	Handler slog.Handler
}

ContextHandler wraps a slog.Handler to inject active trace and span IDs into log records.

func NewContextHandler ΒΆ

func NewContextHandler(base slog.Handler) *ContextHandler

NewContextHandler constructs a ContextHandler around a base slog.Handler.

func (*ContextHandler) Enabled ΒΆ

func (h *ContextHandler) Enabled(ctx context.Context, level slog.Level) bool

Enabled reports whether the handler handles records at the given level.

func (*ContextHandler) Handle ΒΆ

func (h *ContextHandler) Handle(ctx context.Context, r slog.Record) error

Handle injects OpenTelemetry trace context and action metadata into the slog.Record.

func (*ContextHandler) WithAttrs ΒΆ

func (h *ContextHandler) WithAttrs(attrs []slog.Attr) slog.Handler

WithAttrs returns a new ContextHandler whose attributes include given attrs.

func (*ContextHandler) WithGroup ΒΆ

func (h *ContextHandler) WithGroup(name string) slog.Handler

WithGroup returns a new ContextHandler with the given group name appended.

type HealthChecker ΒΆ

type HealthChecker interface {
	Check(ctx context.Context) error
}

HealthChecker defines a component that can be polled for readiness.

type HealthRegistry ΒΆ

type HealthRegistry interface {
	RegisterCheck(name string, check func(ctx context.Context) error)
	HealthHandler() http.Handler
}

HealthRegistry allows dynamic registration of system readiness probes.

type Hook ΒΆ

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

Hook instruments action executions with OpenTelemetry spans and metrics.

func (*Hook) After ΒΆ

func (h *Hook) After(ctx context.Context, err error)

After ends the OpenTelemetry span and records latency/error metrics.

func (*Hook) Before ΒΆ

func (h *Hook) Before(ctx context.Context, action string, meta map[string]string) context.Context

Before starts an OpenTelemetry span before action invocation.

type Option ΒΆ

type Option func(*Config)

func WithLoggerHandler ΒΆ

func WithLoggerHandler(handler slog.Handler) Option

func WithMetricsPrefix ΒΆ

func WithMetricsPrefix(prefix string) Option

func WithPrometheusRegistry ΒΆ

func WithPrometheusRegistry(reg *prometheus.Registry) Option

type Provider ΒΆ

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

Provider manages OpenTelemetry meters, tracers, and health checks.

func Auto ΒΆ

func Auto() (*Provider, func(context.Context) error, error)

Auto initializes standard observability using environment configuration.

func AutoWithOptions ΒΆ

func AutoWithOptions(opts ...Option) (*Provider, func(context.Context) error, error)

AutoWithOptions initializes observability with optional functional modifications.

func New ΒΆ

func New(ctx context.Context, cfg Config, opts ...Option) (*Provider, error)

New constructs Provider with OpenTelemetry tracer, meter, and Prometheus registry.

func NewWithShutdown ΒΆ

func NewWithShutdown(cfg Config) (*Provider, func(context.Context) error, error)

NewWithShutdown instantiates Provider alongside an explicit cleanup function.

func (*Provider) Config ΒΆ

func (p *Provider) Config() Config

Config exposes active Provider configuration.

func (*Provider) Handler ΒΆ

func (p *Provider) Handler() slog.Handler

Handler returns the ContextHandler.

func (*Provider) HealthHandler ΒΆ

func (p *Provider) HealthHandler() http.Handler

HealthHandler serves JSON HTTP readiness probe responses.

func (*Provider) Hook ΒΆ

func (p *Provider) Hook() *Hook

Hook initializes an execution Hook from the Provider.

func (*Provider) Logger ΒΆ

func (p *Provider) Logger() *slog.Logger

Logger returns the configured contextual slog logger.

func (*Provider) MetricsHandler ΒΆ

func (p *Provider) MetricsHandler() http.Handler

MetricsHandler provides standard HTTP handler for Prometheus scraping.

func (*Provider) RegisterCheck ΒΆ

func (p *Provider) RegisterCheck(name string, checkFunc func(context.Context) error)

RegisterCheck attaches a readiness health probe.

type TraceRecord ΒΆ

type TraceRecord struct {
	TraceID         string          `json:"trace_id"`
	Action          string          `json:"action"`
	Transport       string          `json:"transport"`
	Timestamp       time.Time       `json:"timestamp"`
	TotalDurationUs int64           `json:"total_duration_us"`
	Duration        string          `json:"duration"`
	Status          string          `json:"status"`
	Spans           []CompletedSpan `json:"spans"`
}

func TraceRecordFromContext ΒΆ

func TraceRecordFromContext(ctx context.Context, actionName, transportName string, err error) (TraceRecord, bool)

TraceRecordFromContext builds a complete, machine-readable trace record (timeline) from the context. Returns false if there was no active collector in the context (WithCollector).

type Tracer ΒΆ

type Tracer interface {
	Span(ctx context.Context, name string) (context.Context, func(error))
}

Tracer defines custom span generation wrappers.

Directories ΒΆ

Path Synopsis
Package actionhook adapts *obs.Hook to the framework action system.
Package actionhook adapts *obs.Hook to the framework action system.
Package dbtrace provides OpenTelemetry tracing wrappers for database/sql operations.
Package dbtrace provides OpenTelemetry tracing wrappers for database/sql operations.
Package events provides business telemetry event emission.
Package events provides business telemetry event emission.
examples
Package httptrace provides OpenTelemetry instrumentation wrappers for http Clients and Transports.
Package httptrace provides OpenTelemetry instrumentation wrappers for http Clients and Transports.

Jump to

Keyboard shortcuts

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