Skip to content

Integrating slog and deprecating ad-hoc logging functions #14

@danielorbach

Description

@danielorbach

The lifecycle logging API consists of Log, Logf, Error, and Errorf functions that wrap a generic logger interface with string formatting. This approach predates Go's structured logging standard and shows its age. The functions provide no structure, no log levels, no context propagation, and no integration with modern observability tooling. As Go 1.21 introduced log/slog as the standard structured logging package, we should align with the ecosystem rather than maintaining our own ad-hoc logging abstraction.

The current logging functions force string formatting at call sites, discarding type information that structured logging preserves. When a component logs an error with l.Error(err), we format it immediately into a string prefixed with "error: ". This loses the error's structure, stack traces, and wrapped context that slog could preserve as structured fields. Similarly, l.Logf("processing message %d", id) bakes the message ID into an unstructured string rather than emitting a structured log entry with a message_id field.

Beyond structure, the API lacks log levels. Every log entry has equal weight, making it difficult to filter output by severity in production. We need debug logs during development, info logs for operational visibility, warnings for degraded conditions, and errors for failures. The current Log and Error functions provide only two implicit levels, with no support for standard severities that operators expect from production systems.

Integration with OpenTelemetry presents another gap. While lifecycle already uses OpenTelemetry for tracing (calling span.RecordError(err) in the Error function), the logging doesn't correlate with traces. Slog handlers can bridge this gap, emitting trace_id and span_id fields automatically so that logs and traces link together in observability platforms. The current string-based logging offers no such integration points.

Migration requires careful deprecation. The existing logging functions appear throughout component implementations and tests. We cannot simply remove them without breaking every component. The transition should introduce slog-based logging alongside the old API, encourage migration through documentation and examples, and eventually deprecate the string-based functions once adoption is widespread. The new API should make structured logging natural while supporting existing logging patterns during the transition.

Acceptance Criteria

  • log/slog is integrated as the standard logging mechanism
  • Lifecycle exposes slog.Logger for component use
  • Log levels (debug, info, warn, error) are supported and documented
  • Structured logging examples demonstrate best practices
  • OpenTelemetry correlation is documented and demonstrated
  • Existing logging functions (Log, Logf, Error, Errorf) are deprecated with migration guidance
  • Tests and examples are updated to use slog patterns

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions