logging

package
v0.3.0-alpha.1 Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 16 Imported by: 0

README

gokit/logging

Production-ready structured logging built on zerolog.

Features

  • Structured JSON / console output
  • Sensitive data masking (on by default)
  • Rate-based log sampling (burst + thereafter)
  • Per-module log level overrides
  • OpenTelemetry Logs bridge (OTLP export)
  • Unified log schema (consistent across gokit, pykit, rskit)
  • Context propagation (trace ID, span ID, correlation ID)

Quick Start

package main

import "github.com/kbukum/gokit/logging"

func main() {
    // Default logger — masking enabled, console format, info level
    log := logging.NewDefault("my-service")
    log.Info("server started", logging.Fields("port", 8080))

    // Component-scoped logger
    dbLog := log.WithComponent("database")
    dbLog.Debug("query executed", logging.DurationFields("select", elapsed))

    // Package-level functions use the immutable process default (logging.Default())
    logging.Info("using package-level default logger")

    // Sensitive data is automatically redacted
    log.Info("user login", logging.Fields("password", "hunter2"))
    // output: password=***REDACTED***
}

Configuration

logging:
  level: info              # debug | info | warn | error | fatal | trace
  format: json             # json | console | text
  output: stdout           # stdout | stderr
  no_color: false
  timestamp: true
  caller: false
  stacktrace: false
  service_name: my-service

  # File rotation (optional)
  max_size: 100            # megabytes
  max_backups: 3
  max_age: 28              # days
  compress: false

  # Sensitive data masking
  masking:
    enabled: true           # on by default
    field_names:             # additional field names to redact
      - my_secret_field
    value_patterns:          # additional regex patterns
      - 'MYSECRET_[A-Z0-9]{20}'
    replacement: "***REDACTED***"
    preserve_last: 0         # preserve last N chars (0 = full redaction)

  # Rate-based sampling
  sampling:
    enabled: false
    initial_rate: 100        # allow first N per second per level
    thereafter_rate: 100     # then keep every Nth

  # Per-module log level overrides
  module_levels:
    database: debug
    kafka: warn
    auth: trace

  # OpenTelemetry OTLP export
  otlp:
    enabled: false
    endpoint: "localhost:4317"
    protocol: grpc           # grpc | http
    insecure: false
    headers:
      x-api-key: "my-key"

Masking

Masking is enabled by default. Every log field is checked against sensitive field names (case-insensitive) and value patterns (regex). If a match is found, the value is replaced before it reaches any output sink.

Default Masked Fields
# Field Name Description
1 password User passwords
2 secret Generic secrets
3 token Generic tokens
4 api_key API keys
5 apikey API keys (alternate)
6 api-key API keys (hyphenated)
7 authorization Auth headers
8 auth_token Authentication tokens
9 access_token OAuth access tokens
10 refresh_token OAuth refresh tokens
11 private_key Private keys
12 ssn Social Security numbers
13 credit_card Credit card numbers
14 card_number Card numbers (alternate)
15 cvv Card verification values
16 pin Personal identification numbers
Value Patterns

These patterns detect sensitive data regardless of field name:

# Pattern Example Input Masked Output
1 JWT eyJhbGci...payload...sig [JWT_REDACTED]
2 Bearer token Bearer abc123def Bearer [REDACTED]
3 AWS Access Key AKIAIOSFODNN7EXAMPLE [AWS_KEY_REDACTED]
4 Credit Card 4111-1111-1111-1234 ****-****-****-1234
5 SSN 123-45-6789 ***-**-****
6 Email user@example.com ***@***.***
7 Hex Secret (32+) a1b2c3d4e5f6... (32+ hex chars) [HEX_REDACTED]
Adding Custom Fields and Patterns
masking:
  field_names:
    - my_internal_token
    - employee_id
  value_patterns:
    - 'MYSVC_[A-Za-z0-9]{32}'
Partial Masking

Use preserve_last to keep the last N characters visible:

masking:
  preserve_last: 4

This turns "password": "hunter2" into "password": "***REDACTED***ter2".

Sampling

Sampling reduces log volume in high-throughput services. When enabled, each log level gets an independent counter per one-second window:

  1. Burst — the first initial_rate messages per second per level pass through unconditionally.
  2. Thereafter — after the burst, only every thereafter_rate-th message is kept.
sampling:
  enabled: true
  initial_rate: 100     # allow first 100/sec per level
  thereafter_rate: 10   # then keep every 10th

When to use: Enable sampling on hot-path services producing thousands of log lines per second. Leave disabled for low-volume services or during debugging.

Sampling uses zerolog's BurstSampler under the hood:

// Equivalent to:
&zerolog.BurstSampler{
    Burst:       100,
    Period:      time.Second,
    NextSampler: &zerolog.BasicSampler{N: 100},
}

Module Levels

Override the global log level for specific components. Useful for silencing noisy dependencies or enabling debug output for a single subsystem.

logging:
  level: info
  module_levels:
    database: debug     # verbose DB logs
    kafka: warn         # suppress Kafka noise
    auth: trace         # detailed auth tracing
// Programmatic usage
log := logging.New(cfg, "my-service")

// WithComponent applies the module-level override automatically
dbLog := log.WithComponent("database")   // → debug level
kafkaLog := log.WithComponent("kafka")   // → warn level

Module levels are configured via the module_levels map (config or logging.Config) and applied automatically by WithComponent. The underlying ModuleLevelManager is thread-safe; its SetLevel() is used internally when levels are established from configuration.

OTLP Export

The OpenTelemetry Logs bridge sends log records to an OTLP collector alongside your local output. Logs are emitted via the OTel SDK LoggerProvider with batch processing.

Setup
otlp:
  enabled: true
  endpoint: "otel-collector:4317"
  protocol: grpc        # grpc | http
  insecure: true        # skip TLS for dev
  headers:
    Authorization: "Bearer my-token"
Programmatic Usage
cfg := &logging.Config{
    Level:       "info",
    Format:      "json",
    ServiceName: "my-service",
    OTLP: logging.OTLPConfig{
        Enabled:  true,
        Endpoint: "localhost:4317",
        Protocol: "grpc",
        Insecure: true,
    },
}
log := logging.New(cfg, "my-service")
defer log.Close()  // flush pending OTLP logs on shutdown

log.Info("order created", logging.Fields("order_id", "abc-123"))
Graceful Shutdown

Always call Close() before process exit to flush buffered log records:

log := logging.New(cfg, "my-service")
defer log.Close()

Unified Schema

All three kits (gokit, pykit, rskit) share the same structured field names:

Field Constant Description
service FieldService Service name
environment FieldEnvironment Deployment environment
version FieldVersion Service version
component FieldComponent Logical component
trace_id FieldTraceID Distributed trace ID
span_id FieldSpanID Span ID within trace
correlation_id FieldCorrelationID Cross-service correlation
request_id FieldRequestID HTTP request ID
user_id FieldUserID User identifier
session_id FieldSessionID Session identifier
operation FieldOperation Operation name
status FieldStatus Operation status
error FieldError Error message
duration_ms FieldDuration Duration in milliseconds
timestamp FieldTimestamp ISO 8601 timestamp
level FieldLevel Log level
message FieldMessage Log message
ServiceFields Helper

Attach standard service identification to any log entry:

svcFields := logging.ServiceFields("order-svc", "production", "1.2.3")
log.Info("service started", svcFields)
// → {"service":"order-svc","environment":"production","version":"1.2.3",...}
Field Helpers
// Build fields from key-value pairs
logging.Fields("op", "save", "id", 42)

// Error fields
logging.ErrorFields("db.connect", err)

// Duration fields
logging.DurationFields("query", 150*time.Millisecond)

// Merge helpers
fields := logging.Fields("op", "save")
logging.MergeWithError(fields, err)
logging.MergeWithDuration(fields, elapsed)

Custom Masker

Implement the Masker interface to provide your own masking logic:

type Masker interface {
    MaskValue(key string, value string) string
}
type MyMasker struct{}

func (m *MyMasker) MaskValue(key, value string) string {
    if key == "internal_id" {
        return "***"
    }
    return value
}

log := logging.New(cfg, "my-service")
log = log.WithMasker(&MyMasker{})
log.Info("event", logging.Fields("internal_id", "secret-123"))
// → internal_id=***

API Reference

Function / Type Description
New(cfg, name) Create logger from config
NewDefault(name) Create logger with defaults
NewFromEnv(name) Create logger from LOG_LEVEL, LOG_FORMAT env vars
Default() Access the process-wide default logger (immutable)
WithContext(ctx) Enrich with trace/span/request IDs from context
ContextWith*(ctx, id) Inject trace/span/request/user/correlation ID into a context
ComponentSpan(ctx, name) Component-tagged logger enriched from context
RequestSpan(ctx, method, path, requestID) Logger enriched with HTTP request metadata
WithComponent(name) Tag with component + apply module level
WithFields(map) Add structured fields
WithError(err) Add error field
WithMasker(m) Set custom masker
WithOTLP(provider) Attach OTLP provider
Close() Flush OTLP and shut down
Debug / Info / Warn / Error / Fatal Log at level

⬅ Back to main README

Documentation

Overview

Package logging provides structured logging for gokit applications using zerolog.

It supports multiple output formats (JSON, console), log level configuration, and component-scoped loggers with structured fields.

Configuration

logging:
  level: "info"
  format: "json"

Usage

log := logging.NewDefault("my-service")
log.Info("operation completed", logging.Fields("key", "value"))

// Component-scoped logger derived from a base logger.
dbLog := log.WithComponent("database")
dbLog.Debug("query executed")

Context and filtering

ContextWithTraceID and its siblings carry trace, span, request, user, and correlation IDs on a context; ComponentSpan and RequestSpan derive loggers enriched from that context. BuildDirectives and ParseDirectives convert between a base level plus per-module overrides and the compact directive string used to configure level filtering from the environment.

Index

Examples

Constants

View Source
const (
	FieldComponent     = "component"
	FieldTraceID       = "trace_id"
	FieldSpanID        = "span_id"
	FieldRequestID     = "request_id"
	FieldCorrelationID = "correlation_id"
	FieldUserID        = "user_id"
	FieldSessionID     = "session_id"
	FieldOperation     = "operation"
	FieldStatus        = "status"
	FieldError         = "error"
	FieldDuration      = "duration_ms"
	FieldPlatform      = "platform"
	FieldPhase         = "phase"
	FieldContainerID   = "container_id"
	FieldEmail         = "email"
	FieldHTTPMethod    = "http.method"
	FieldHTTPPath      = "http.path"

	// Unified schema fields — consistent across gokit, rskit, and pykit.
	FieldService     = "service"
	FieldEnvironment = "environment"
	FieldTimestamp   = "timestamp"
	FieldLevel       = "level"
	FieldMessage     = "message"
	FieldVersion     = "version"
)

Standard field key constants for structured logging.

View Source
const (
	FormatPretty = "pretty"
	BooleanTrue  = "true"
)

Variables

This section is empty.

Functions

func BuildDirectives

func BuildDirectives(baseLevel string, moduleLevels map[string]string) string

BuildDirectives renders a base level and a set of per-module overrides into a single comma-separated directive string, e.g. "info,sqlx=warn,hyper=error". The base level comes first and module directives follow in sorted order, so the output is deterministic and stable across runs. This mirrors the RUST_LOG / env-filter grammar used by the sibling kits, giving gokit a portable interchange form for per-module log configuration. When there are no module overrides the base level is returned alone.

func ContextWithCorrelationID

func ContextWithCorrelationID(ctx context.Context, id string) context.Context

ContextWithCorrelationID returns a context carrying the correlation ID, which (*Logger).WithContext folds into the correlation_id field.

func ContextWithRequestID

func ContextWithRequestID(ctx context.Context, id string) context.Context

ContextWithRequestID returns a context carrying the request ID, which (*Logger).WithContext folds into the request_id field.

func ContextWithSpanID

func ContextWithSpanID(ctx context.Context, id string) context.Context

ContextWithSpanID returns a context carrying the span ID, which (*Logger).WithContext folds into the span_id field.

func ContextWithTraceID

func ContextWithTraceID(ctx context.Context, id string) context.Context

ContextWithTraceID returns a context carrying the trace ID, which (*Logger).WithContext folds into the trace_id field.

func ContextWithUserID

func ContextWithUserID(ctx context.Context, id string) context.Context

ContextWithUserID returns a context carrying the user ID, which (*Logger).WithContext folds into the user_id field.

func Debug

func Debug(msg string, fields ...map[string]any)

func DebugCtx

func DebugCtx(ctx context.Context, msg string, fields ...map[string]any)

func DurationFields

func DurationFields(op string, d time.Duration) map[string]any

DurationFields creates fields for a timed operation.

func Error

func Error(msg string, fields ...map[string]any)

func ErrorCtx

func ErrorCtx(ctx context.Context, msg string, fields ...map[string]any)

func ErrorFields

func ErrorFields(op string, err error) map[string]any

ErrorFields creates fields for an operation that failed.

Example
package main

import (
	"fmt"

	"github.com/kbukum/gokit/logging"
)

func main() {
	f := logging.ErrorFields("save_user", fmt.Errorf("db offline"))
	fmt.Println(f["operation"], f["error"])
}
Output:
save_user db offline

func Fatal

func Fatal(msg string, fields ...map[string]any)

func FatalCtx

func FatalCtx(ctx context.Context, msg string, fields ...map[string]any)

func Fields

func Fields(kvs ...any) map[string]any

Fields builds a map[string]any from alternating key-value pairs.

logger.Info("done", logger.Fields("op", "save", "id", 42))
Example
package main

import (
	"fmt"

	"github.com/kbukum/gokit/logging"
)

func main() {
	f := logging.Fields("user_id", 42, "tenant", "acme")
	fmt.Println(f["user_id"], f["tenant"])
}
Output:
42 acme

func GetLoggerZ

func GetLoggerZ() zerolog.Logger

GetLoggerZ returns the underlying zerolog.Logger from the default logger.

func Info

func Info(msg string, fields ...map[string]any)

func InfoCtx

func InfoCtx(ctx context.Context, msg string, fields ...map[string]any)

func MergeWithDuration

func MergeWithDuration(fields map[string]any, d time.Duration) map[string]any

MergeWithDuration adds a duration field to an existing map.

func MergeWithError

func MergeWithError(fields map[string]any, err error) map[string]any

MergeWithError adds an error field to an existing map.

func NewSampler

func NewSampler(cfg SamplingConfig) zerolog.Sampler

NewSampler creates a zerolog sampler from SamplingConfig. It uses a BurstSampler that allows an initial burst of messages per period, then falls back to sampling every Nth message thereafter.

func ParseDirectives

func ParseDirectives(directives string) (baseLevel string, moduleLevels map[string]string)

ParseDirectives is the inverse of BuildDirectives. It splits a directive string into the base level and the per-module overrides, so a value carried in an environment variable such as LOG_LEVEL="info,sqlx=warn" can be turned back into structured configuration. A bare "module=level" token with no leading base level yields an empty base level and that override; empty tokens are ignored.

func ServiceFields

func ServiceFields(service, environment, version string) map[string]any

ServiceFields creates the standard service identification fields for the unified log schema (consistent across gokit, rskit, and pykit).

func Warn

func Warn(msg string, fields ...map[string]any)

func WarnCtx

func WarnCtx(ctx context.Context, msg string, fields ...map[string]any)

Types

type ClientComponent

type ClientComponent struct {
	Name   string
	Target string // "gRPC:9090", "HTTP:8080"
	Status string
}

ClientComponent represents an external client (gRPC, HTTP, etc.).

type ComponentRegistry

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

ComponentRegistry tracks components during bootstrap for summary display.

func NewComponentRegistry

func NewComponentRegistry() *ComponentRegistry

NewComponentRegistry creates a new component registry.

func (*ComponentRegistry) APIPrefix

func (r *ComponentRegistry) APIPrefix() string

APIPrefix returns the configured API prefix.

func (*ComponentRegistry) Clients

func (r *ComponentRegistry) Clients() []ClientComponent

Clients returns all registered client components.

func (*ComponentRegistry) Consumers

func (r *ComponentRegistry) Consumers() []ConsumerComponent

Consumers returns all registered consumer components.

func (*ComponentRegistry) Handlers

func (r *ComponentRegistry) Handlers() []HandlerComponent

Handlers returns all registered handler components.

func (*ComponentRegistry) Infrastructure

func (r *ComponentRegistry) Infrastructure() []InfraComponent

Infrastructure returns all registered infrastructure components.

func (*ComponentRegistry) RegisterClient

func (r *ComponentRegistry) RegisterClient(name, target, status string)

RegisterClient registers an external client.

func (*ComponentRegistry) RegisterConsumer

func (r *ComponentRegistry) RegisterConsumer(c ConsumerComponent)

RegisterConsumer registers a message consumer.

func (*ComponentRegistry) RegisterHandler

func (r *ComponentRegistry) RegisterHandler(method, path, handler string)

RegisterHandler registers an HTTP handler.

func (*ComponentRegistry) RegisterInfrastructure

func (r *ComponentRegistry) RegisterInfrastructure(name, componentType, status, details string)

RegisterInfrastructure registers an infrastructure component.

func (*ComponentRegistry) RegisterRepository

func (r *ComponentRegistry) RegisterRepository(name, store, status string)

RegisterRepository registers a repository component.

func (*ComponentRegistry) RegisterService

func (r *ComponentRegistry) RegisterService(name, status string, dependencies []string)

RegisterService registers a service component.

func (*ComponentRegistry) Repositories

func (r *ComponentRegistry) Repositories() []RepositoryComponent

Repositories returns all registered repository components.

func (*ComponentRegistry) Services

func (r *ComponentRegistry) Services() []ServiceComponent

Services returns all registered service components.

func (*ComponentRegistry) SetAPIPrefix

func (r *ComponentRegistry) SetAPIPrefix(prefix string)

SetAPIPrefix sets the API prefix (for example "/api/v1") for route grouping.

func (*ComponentRegistry) SetHandlers

func (r *ComponentRegistry) SetHandlers(handlers []HandlerComponent)

SetHandlers replaces the handler list (useful when collecting routes dynamically).

func (*ComponentRegistry) StartTime

func (r *ComponentRegistry) StartTime() time.Time

StartTime returns the registry creation time (bootstrap start).

type Config

type Config struct {
	Level        string            `yaml:"level" mapstructure:"level"`
	Format       string            `yaml:"format" mapstructure:"format"`
	Output       string            `yaml:"output" mapstructure:"output"`
	NoColor      bool              `yaml:"no_color" mapstructure:"no_color"`
	Timestamp    bool              `yaml:"timestamp" mapstructure:"timestamp"`
	Caller       bool              `yaml:"caller" mapstructure:"caller"`
	Stacktrace   bool              `yaml:"stacktrace" mapstructure:"stacktrace"`
	MaxSize      int               `yaml:"max_size" mapstructure:"max_size"`       // megabytes
	MaxBackups   int               `yaml:"max_backups" mapstructure:"max_backups"` // number of backups
	MaxAge       int               `yaml:"max_age" mapstructure:"max_age"`         // days
	Compress     bool              `yaml:"compress" mapstructure:"compress"`
	LocalTime    bool              `yaml:"local_time" mapstructure:"local_time"`
	ServiceName  string            `yaml:"service_name" mapstructure:"service_name"` // used as tag in log output
	Environment  string            `yaml:"environment" mapstructure:"environment"`   // deployment environment (e.g. development, staging, production)
	Version      string            `yaml:"version" mapstructure:"version"`           // service version (e.g. 1.0.0)
	Masking      MaskingConfig     `yaml:"masking" mapstructure:"masking"`
	Sampling     SamplingConfig    `yaml:"sampling" mapstructure:"sampling"`
	ModuleLevels map[string]string `yaml:"module_levels" mapstructure:"module_levels"` // e.g., {"database": "debug", "kafka": "warn"}
	OTLP         OTLPConfig        `yaml:"otlp" mapstructure:"otlp"`
}

Config contains logging configuration.

func (*Config) ApplyDefaults

func (c *Config) ApplyDefaults()

ApplyDefaults applies default values to logging configuration.

func (*Config) Validate

func (c *Config) Validate() error

Validate validates logging configuration.

type ConsumerComponent

type ConsumerComponent struct {
	Name       string
	Group      string
	Topic      string
	Partitions int
	Status     string
}

ConsumerComponent represents a message consumer (e.g. Kafka).

type DefaultMasker

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

DefaultMasker provides field-name and value-pattern based sensitive data masking. It is safe for concurrent use after construction (all fields are read-only).

func NewDefaultMasker

func NewDefaultMasker(cfg MaskingConfig) *DefaultMasker

NewDefaultMasker creates a DefaultMasker from the given MaskingConfig. All regexps are compiled at construction time via regexp.MustCompile.

func (*DefaultMasker) MaskFields

func (m *DefaultMasker) MaskFields(fields map[string]any) map[string]any

MaskFields masks all values in a map, returning a new map. String values are masked directly. Non-string values are converted to a string representation, checked for sensitive patterns, and replaced with the masked string if a pattern matches.

func (*DefaultMasker) MaskValue

func (m *DefaultMasker) MaskValue(key, value string) string

MaskValue masks a single value based on its field key and content. If the key matches a sensitive field name, the full replacement is returned. Otherwise each value pattern is tested and the first match wins.

type HandlerComponent

type HandlerComponent struct {
	Method  string // "GET", "POST", etc.
	Path    string
	Handler string
}

HandlerComponent represents an HTTP handler/route.

type InfraComponent

type InfraComponent struct {
	Name    string
	Type    string // "database", "kafka", "redis", "server"
	Status  string // "active", "inactive", "error"
	Details string
}

InfraComponent represents an infrastructure dependency (database, cache, broker, etc.).

type Logger

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

Logger wraps zerolog.Logger with additional context.

func ComponentSpan

func ComponentSpan(ctx context.Context, name string) *Logger

ComponentSpan returns a component-tagged logger from the default logger.

func Default

func Default() *Logger

Default returns the process default logger, constructing it on first use. Prefer injecting an explicit *Logger; use Default only for incidental logging where threading a logger through the call site adds no value.

func New

func New(cfg *Config, serviceName string) *Logger

New creates a new logger instance with configuration.

func NewDefault

func NewDefault(serviceName string) *Logger

NewDefault creates a logger with default configuration.

func NewFromEnv

func NewFromEnv(serviceName string) *Logger

NewFromEnv creates a logger configured from environment variables.

func RequestSpan

func RequestSpan(ctx context.Context, method, path, requestID string) *Logger

RequestSpan returns a request-enriched logger from the default logger.

func WithComponent

func WithComponent(name string) *Logger

WithComponent returns a component-tagged logger from the default logger.

func WithContext

func WithContext(ctx context.Context) *Logger

WithContext returns a context-enriched logger from the default logger.

func (*Logger) Close

func (l *Logger) Close() error

Close gracefully shuts down the OTLP provider, flushing pending logs.

func (*Logger) ComponentSpan

func (l *Logger) ComponentSpan(ctx context.Context, name string) *Logger

ComponentSpan returns a logger tagged with the component name and enriched with any identifiers already present in ctx — the gokit equivalent of rskit-logging's component_span.

func (*Logger) Debug

func (l *Logger) Debug(msg string, fields ...map[string]any)

Debug logs a debug message.

For request- or operation-scoped logging that should propagate cancellation and trace correlation to OTLP, prefer DebugCtx.

func (*Logger) DebugCtx

func (l *Logger) DebugCtx(ctx context.Context, msg string, fields ...map[string]any)

DebugCtx logs a debug message and propagates ctx to the OTLP exporter.

func (*Logger) Error

func (l *Logger) Error(msg string, fields ...map[string]any)

Error logs an error message. Prefer ErrorCtx when a context is in scope.

func (*Logger) ErrorCtx

func (l *Logger) ErrorCtx(ctx context.Context, msg string, fields ...map[string]any)

ErrorCtx logs an error message and propagates ctx to the OTLP exporter.

func (*Logger) Fatal

func (l *Logger) Fatal(msg string, fields ...map[string]any)

Fatal logs a fatal message and exits. Prefer FatalCtx when a context is in scope.

func (*Logger) FatalCtx

func (l *Logger) FatalCtx(ctx context.Context, msg string, fields ...map[string]any)

FatalCtx logs a fatal message and exits, propagating ctx to the OTLP exporter.

func (*Logger) GetLogger

func (l *Logger) GetLogger() zerolog.Logger

GetLogger returns the underlying zerolog.Logger.

func (*Logger) Info

func (l *Logger) Info(msg string, fields ...map[string]any)

Info logs an info message. Prefer InfoCtx when a context is in scope.

func (*Logger) InfoCtx

func (l *Logger) InfoCtx(ctx context.Context, msg string, fields ...map[string]any)

InfoCtx logs an info message and propagates ctx to the OTLP exporter.

func (*Logger) RequestSpan

func (l *Logger) RequestSpan(ctx context.Context, method, path, requestID string) *Logger

RequestSpan returns a logger enriched with HTTP request metadata and any identifiers already present in ctx — the gokit equivalent of rskit-logging's request_span.

func (*Logger) Warn

func (l *Logger) Warn(msg string, fields ...map[string]any)

Warn logs a warning message. Prefer WarnCtx when a context is in scope.

func (*Logger) WarnCtx

func (l *Logger) WarnCtx(ctx context.Context, msg string, fields ...map[string]any)

WarnCtx logs a warning message and propagates ctx to the OTLP exporter.

func (*Logger) WithComponent

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

WithComponent returns a logger tagged with a component name. If a per-module log level override exists for the component, it is applied.

func (*Logger) WithContext

func (l *Logger) WithContext(ctx context.Context) *Logger

WithContext returns a logger enriched with trace/span/request IDs from context.

func (*Logger) WithError

func (l *Logger) WithError(err error) *Logger

WithError returns a logger with an error field.

func (*Logger) WithFields

func (l *Logger) WithFields(fields map[string]any) *Logger

WithFields returns a logger with additional fields.

func (*Logger) WithMasker

func (l *Logger) WithMasker(m Masker) *Logger

WithMasker returns a new Logger with the given Masker applied.

func (*Logger) WithOTLP

func (l *Logger) WithOTLP(provider *OTLPProvider) *Logger

WithOTLP returns a new Logger with the given OTLPProvider attached.

type Masker

type Masker interface {
	MaskValue(key, value string) string
}

Masker is the interface for sensitive data masking adapters.

type MaskingConfig

type MaskingConfig struct {
	Enabled       bool     `yaml:"enabled" mapstructure:"enabled"`
	FieldNames    []string `yaml:"field_names" mapstructure:"field_names"`       // Additional field names to mask
	ValuePatterns []string `yaml:"value_patterns" mapstructure:"value_patterns"` // Additional regex patterns
	Replacement   string   `yaml:"replacement" mapstructure:"replacement"`
	PreserveLast  int      `yaml:"preserve_last" mapstructure:"preserve_last"` // Preserve last N chars for partial masking
}

MaskingConfig contains configuration for sensitive data masking.

type ModuleLevelManager

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

ModuleLevelManager manages per-module log level overrides. It is safe for concurrent use.

func NewModuleLevelManager

func NewModuleLevelManager(levels map[string]string) *ModuleLevelManager

NewModuleLevelManager creates a manager from a map of module names to level strings. Unrecognized level strings are silently ignored.

func (*ModuleLevelManager) Level

func (m *ModuleLevelManager) Level(module string) (zerolog.Level, bool)

Level returns the override level for a module. The second return value is false if no override exists.

func (*ModuleLevelManager) SetLevel

func (m *ModuleLevelManager) SetLevel(module, level string)

SetLevel dynamically sets a module's log level. An unrecognized level string is silently ignored.

type OTLPConfig

type OTLPConfig struct {
	Enabled  bool              `yaml:"enabled" mapstructure:"enabled"`   // Default: false
	Endpoint string            `yaml:"endpoint" mapstructure:"endpoint"` // e.g., "localhost:4317"
	Protocol string            `yaml:"protocol" mapstructure:"protocol"` // "grpc" or "http" (default: "grpc")
	Insecure bool              `yaml:"insecure" mapstructure:"insecure"` // Skip TLS (for dev)
	Headers  map[string]string `yaml:"headers" mapstructure:"headers"`   // Auth headers
}

OTLPConfig configures the OpenTelemetry OTLP log export bridge.

type OTLPProvider

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

OTLPProvider manages the OpenTelemetry LoggerProvider for OTLP export.

func NewOTLPProvider

func NewOTLPProvider(cfg OTLPProviderConfig) (*OTLPProvider, error)

NewOTLPProvider creates and starts an OTLP log provider.

func (*OTLPProvider) EmitLog

func (p *OTLPProvider) EmitLog(ctx context.Context, level, message string, fields map[string]any)

EmitLog sends a log record to the OTLP collector.

ctx is propagated to the OTel exporter so that cancellation, deadlines, and trace correlation flow through to telemetry. Pass context.Background() only for emit sites where no request-scoped context is available (e.g. startup banners, signal handlers).

func (*OTLPProvider) Shutdown

func (p *OTLPProvider) Shutdown(ctx context.Context) error

Shutdown gracefully shuts down the OTLP provider, flushing pending logs.

type OTLPProviderConfig

type OTLPProviderConfig struct {
	Exporter    OTLPConfig
	ServiceName string
	Environment string
	Version     string
}

OTLPProviderConfig configures an OTLP log provider and its service resource attributes.

type Registry

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

Registry is an injected collection of component-scoped loggers derived from a base logger. It replaces the previous package-global logger registry: callers construct a Registry via NewRegistry and pass it explicitly, so there is no mutable package-level state shared across unrelated components.

func NewRegistry

func NewRegistry(base *Logger) *Registry

NewRegistry creates a Registry backed by base. When base is nil the process default logger is used so the registry is always usable.

func (*Registry) Base

func (r *Registry) Base() *Logger

Base returns the base logger the registry derives component loggers from.

func (*Registry) Get

func (r *Registry) Get(name string) *Logger

Get returns the logger registered under name. When no logger is registered it derives one from the base logger tagged with the component name, caches it, and returns it. Get never returns nil.

func (*Registry) Register

func (r *Registry) Register(name string, l *Logger)

Register stores a named logger, overriding any previously registered or derived logger for that name.

type RepositoryComponent

type RepositoryComponent struct {
	Name   string
	Store  string // "PostgreSQL", "Redis", etc.
	Status string
}

RepositoryComponent represents a data-access repository.

type SamplingConfig

type SamplingConfig struct {
	Enabled        bool `yaml:"enabled" mapstructure:"enabled"`                 // Default: false
	InitialRate    int  `yaml:"initial_rate" mapstructure:"initial_rate"`       // Log first N per second per level
	ThereafterRate int  `yaml:"thereafter_rate" mapstructure:"thereafter_rate"` // Then log every Nth
}

SamplingConfig controls rate-based log sampling to reduce volume in high-throughput scenarios.

type ServiceComponent

type ServiceComponent struct {
	Name         string
	Status       string // "lazy", "initialized", "active"
	Dependencies []string
}

ServiceComponent represents a business-logic service.

Jump to

Keyboard shortcuts

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