logging

package
v0.0.0-...-89a91f3 Latest Latest
Warning

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

Go to latest
Published: Jan 6, 2025 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package logging provides a thin wrapper around [OpenTelemetry]'s logging sdk with a log/slog interface.

The logger instance is meant to be initialized as a singleton and injected into the context during the initialization of the application. It provides structured logging with support for different log levels, error handling with stack traces, and OpenTelemetry integration.

Every function that wants to log messages should use the logging.FromContext helper to obtain the logger instance. The logger supports INFO, DEBUG, WARN and ERROR levels, with structured fields and automatic error details extraction.

example usage

// initialize logger instance
logger, err := logging.NewLogger(
	"service",
	"environment",
	"version",
	logging.WithLevel(slog.LevelDebug),
)
if err != nil {
	return fmt.Errorf("failed to initialize logger: %w", err)
}

// inject logger into context
ctx := logging.NewContext(context.Background(), logger)

// anywhere else in the code
logger := logging.FromContext(ctx)
logger.Info("event_name", "Processing request", slog.String("request_id", "abc123"))

// logging errors with automatic stack traces
if err := someOperation(); err != nil {
	logger.Error(err, "operation_failed", "Operation failed", slog.String("op", "process"))
}

Index

Constants

View Source
const (
	TagErrMessage string = "error.message"
	TagErrKind           = "error.kind"
	TagErrStack          = "error.stack"
)

Variables

This section is empty.

Functions

func BindContext

func BindContext(ctx context.Context, fields ...any) context.Context

BindContext creates a new context with a logger containing the provided fields. This is useful when you want to add context-specific fields to all subsequent log entries in a particular code path. The fields are added to a copy of the logger from the input context, and a new context carrying the updated logger is returned.

func NewContext

func NewContext(parent context.Context, logger *Logger) context.Context

NewContext returns a new context.Context that carries the provided logger. This function should be used during application initialization to inject the logger instance into the context that will be passed throughout the application.

func NewFancyHandler

func NewFancyHandler(w io.Writer, opts *FancyLoggerOptions) slog.Handler

NewHandler creates a slog.Handler that writes tinted logs to Writer w, using the default options. If opts is nil, the default options are used.

func NewStdOutProcessor

func NewStdOutProcessor(handler slog.Handler) sdk.Processor

NewStdOutProcessor creates a new processor that writes logs to stdout using fancy formatting

Types

type FancyLoggerOptions

type FancyLoggerOptions struct {
	// Enable source code location (Default: false)
	AddSource bool

	// Minimum level to log (Default: slog.LevelInfo)
	Level slog.Leveler

	// ReplaceAttr is called to rewrite each non-group attribute before it is logged.
	// See https://pkg.go.dev/log/slog#HandlerOptions for details.
	ReplaceAttr func(groups []string, attr slog.Attr) slog.Attr

	// Time format (Default: time.StampMilli)
	TimeFormat string

	// Disable color (Default: false)
	NoColor bool
}

FancyLoggerOptions for a slog.Handler that writes tinted logs. A zero FancyLoggerOptions consists entirely of default values.

FancyLoggerOptions can be used as a drop-in replacement for slog.HandlerOptions.

type Logger

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

func FromContext

func FromContext(ctx context.Context) *Logger

FromContext extracts the logger from the provided context. This is the recommended way to obtain a logger instance for logging. If no logger is found in the context, it returns a new no-op logger that safely discards all log messages.

func NewLogger

func NewLogger(service, env, version string, opts ...LoggerOption) (*Logger, func(context.Context) error, error)

NewLogger creates a new structured logger with the given service name, environment and version. It initializes the logger with OpenTelemetry integration and default settings. The logger can be customized using options like WithLevel, WithHandler, WithStdoutExporter, and WithOtlpExporter.

Returns the logger instance, a shutdown function, and any error that occurred during initialization. The shutdown function should be called when the application is shutting down to ensure all logs are flushed.

func NewNopLogger

func NewNopLogger() *Logger

NewNopLogger returns a logger that discards all log messages. This is useful for testing or when logging is not needed. The returned logger implements all Logger methods but performs no operations.

func (*Logger) Debug

func (l *Logger) Debug(event, message string, fields ...any)

Debug logs a message at DEBUG level with the given event type and optional fields. Debug logs are only emitted if the logger level is set to DEBUG or lower. The event type is added as a structured field named "event".

func (*Logger) Error

func (l *Logger) Error(err error, event, message string, fields ...any)

Error logs a message at ERROR level with the given error, event type and optional fields. It automatically extracts and adds the following error details as structured fields:

  • error.message: The error message from err.Error()
  • error.kind: The type of the error
  • error.stack: A formatted stack trace from the point of the error

func (*Logger) Info

func (l *Logger) Info(event, message string, fields ...any)

Info logs a message at INFO level with the given event type and optional fields. The event type is added as a structured field named "event" to help categorize and filter log entries.

func (*Logger) Warn

func (l *Logger) Warn(event, message string, fields ...any)

Warn logs a message at WARN level with the given event type and optional fields. The event type is added as a structured field named "event" to help categorize and filter log entries.

func (*Logger) With

func (l *Logger) With(fields ...any) *Logger

With returns a new Logger with the given fields added to every log message. The fields are added as structured logging fields and will be present in all subsequent log entries made through the returned logger.

func (*Logger) WithGroup

func (l *Logger) WithGroup(name string) *Logger

WithGroup creates a new Logger with the given group name. All subsequent log entries will be grouped under this name in the structured output.

type LoggerOption

type LoggerOption func(*Logger) error

func WithHandler

func WithHandler(handler slog.Handler) LoggerOption

WithHandler configures the logger to use a custom slog.Handler. The handler will be wrapped with OpenTelemetry integration to ensure all logs are properly instrumented.

func WithLevel

func WithLevel(level slog.Level) LoggerOption

WithLevel sets the minimum log level for the logger. Any log entry with a level below this threshold will be discarded. The default level is INFO. This option can be used to change the level at any time during the logger's lifecycle.

func WithOtlpExporter

func WithOtlpExporter(ctx context.Context, host string, port int) LoggerOption

WithOtlpExporter configures the logger to export logs via OTLP/gRPC to the specified endpoint. This enables integration with OpenTelemetry collectors and observability platforms.

This option should only be used to initialize the tracer and it's not safe for concurrent use.

func WithStdoutExporter

func WithStdoutExporter(handler slog.Handler) LoggerOption

WithStdoutExporter configures the logger to output logs to stdout using the provided handler for formatting. This is useful for local development and debugging.

This option should only be used to initialize the tracer and it's not safe for concurrent use.

Jump to

Keyboard shortcuts

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