logger

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jun 8, 2026 License: MIT Imports: 18 Imported by: 2

README

logger

A structured logging package with multiple backend implementations, context propagation, and GCP Cloud Logging support.

Logger Interface

All implementations satisfy the Logger interface:

type Logger interface {
    With(metadata map[string]interface{}) Logger
    WithFields(args ...interface{}) Logger
    WithPrefix(prefix string) Logger
    WithContext(ctx context.Context) Logger
    Trace(msg string, args ...interface{})
    Debug(msg string, args ...interface{})
    Info(msg string, args ...interface{})
    Warn(msg string, args ...interface{})
    Error(msg string, args ...interface{})
    Fatal(msg string, args ...interface{})
    Flush() error
}

Log Levels

Eight levels, controlled via the SM_LOG_LEVEL environment variable (case-insensitive, defaults to debug):

trace | debug | info | warn | error | panic | fatal | none

Note: The zap logger defaults to info when SM_LOG_LEVEL is not set (see Zap Logger below). Other implementations default to debug.

level := logger.ParseLogLevel("info")
level := logger.GetLevelFromEnv() // reads SM_LOG_LEVEL

Implementations

High-performance structured logger built on uber-go/zap. Produces JSON output suitable for production and Cloud Logging.

// Default — Info level, GCP trace correlation enabled
log := logger.NewZapLogger()

// With explicit level
log := logger.NewZapLogger(logger.WithLevel(logger.LevelDebug))

// With initial fields
log := logger.NewZapLogger(logger.WithFields(map[string]interface{}{
    "service": "api",
    "version": "1.2.0",
}))

// Disable GCP trace correlation
log := logger.NewZapLogger(logger.WithGCPTraceCorrelation(false))
Default Log Level

The zap logger defaults to Info when no level is specified and SM_LOG_LEVEL is not set. This differs from other implementations which default to Debug. The priority is:

  1. WithLevel(...) option — highest priority
  2. SM_LOG_LEVEL environment variable
  3. Info — fallback default
GCP Trace Correlation

GCP trace correlation is enabled by default. When enabled, WithContext(ctx) and FromContext(ctx) automatically enrich log entries with OpenTelemetry trace/span IDs as GCP-compatible fields:

  • logging.googleapis.com/trace
  • logging.googleapis.com/spanId
  • logging.googleapis.com/trace_sampled

This allows Cloud Logging to correlate log entries with distributed traces. To disable:

log := logger.NewZapLogger(logger.WithGCPTraceCorrelation(false))

NewZapGCloudLogger() is an alias for NewZapLogger() — both behave identically.

Sampling

Zap enables sampling by default to protect against log flooding. Sampling is per-second, per-message (same level + message text):

  • Initial: 100 — the first 100 entries are always logged
  • Thereafter: 100 — after the initial 100, every 100th entry is logged; the rest are dropped

This means a single log line must fire >100 times per second before any entries are dropped. To disable sampling:

log := logger.NewZapLogger(logger.WithSampling(nil))
Console Logger

Colorized terminal output for local development. Supports sinks for writing logs to an additional io.Writer.

log := logger.NewConsoleLogger()                    // level from SM_LOG_LEVEL
log := logger.NewConsoleLogger(logger.LevelTrace)   // explicit level

// Attach a sink (e.g. file)
sinkLog := logger.NewConsoleLogger()
sinkLog.SetSink(file, logger.LevelDebug)
JSON Logger

Structured JSON output compatible with GCP Cloud Logging format.

log := logger.NewJSONLogger()
log := logger.NewGCloudLogger()                     // alias for NewJSONLogger
log := logger.NewJSONLoggerWithSink(sink, logger.LevelInfo) // sink-only, no console
Multi Logger

Fan-out to multiple loggers simultaneously.

log := logger.NewMultiLogger(
    logger.NewConsoleLogger(),
    logger.NewZapLogger(),
)
Test Logger

Captures log entries in memory for assertions in tests.

log := logger.NewTestLogger()
log.Info("hello %s", "world")

entry := log.Logs[0]
// entry.Severity == "INFO"
// entry.Message  == "hello %s"

Enriching Logs

// Structured metadata (map)
log = log.With(map[string]interface{}{"requestID": "abc-123"})

// Key-value pairs (variadic)
log = log.WithFields("user", "alice", "action", "login")

// Named prefix (shows as component/named logger)
log = log.WithPrefix("auth")

Context Integration

Store and retrieve loggers from context.Context. FromContext automatically enriches logs with OpenTelemetry trace/span IDs (since GCP trace correlation is enabled by default).

// Store logger in context
ctx = logger.ToContext(ctx, log)

// Retrieve (returns default zap logger if none stored)
// Automatically adds trace/span IDs from context
log := logger.FromContext(ctx)

// Manual trace enrichment (same as what FromContext does)
log = log.WithContext(ctx)

Flushing

Call Flush() before application exit to ensure buffered entries are written (important for the zap logger).

defer log.Flush()

Utilities

KV converts variadic key-value pairs into a map[string]interface{}:

m := logger.KV("key1", "val1", "key2", 42)
// map[string]interface{}{"key1": "val1", "key2": 42}

Documentation

Index

Constants

View Source
const (
	Reset       = "\033[0m"
	Gray        = "\033[1;30m"
	Red         = "\033[31m"
	Green       = "\033[32m"
	Yellow      = "\033[33m"
	Blue        = "\033[34m"
	Magenta     = "\033[35m"
	Cyan        = "\033[36m"
	White       = "\033[37m"
	BlueBold    = "\033[34;1m"
	MagentaBold = "\033[35;1m"
	RedBold     = "\033[31;1m"
	YellowBold  = "\033[33;1m"
	WhiteBold   = "\033[37;1m"
	CyanBold    = "\033[36;1m"
	Purple      = "\u001b[38;5;200m"
)

Variables

This section is empty.

Functions

func KV added in v0.1.0

func KV(args ...interface{}) map[string]interface{}

func NewZapTestLogger added in v0.1.0

func NewZapTestLogger(w io.Writer, opts ...ZapOption) *zapLogger

func ToContext added in v0.1.0

func ToContext(ctx context.Context, l Logger) context.Context

Types

type JSONLogEntry added in v0.0.65

type JSONLogEntry struct {
	Timestamp time.Time              `json:"timestamp,omitempty"`
	Message   string                 `json:"message"`
	Severity  string                 `json:"severity,omitempty"`
	Trace     string                 `json:"logging.googleapis.com/trace,omitempty"`
	Metadata  map[string]interface{} `json:"metadata,omitempty"`
	// Logs Explorer allows filtering and display of this as `jsonPayload.component`.
	Component string `json:"component,omitempty"`
	// contains filtered or unexported fields
}

JSONLogEntry defines a log entry this is modeled after the JSON format expected by Cloud Logging https://github.com/GoogleCloudPlatform/golang-samples/blob/08bc985b4973901c09344eabbe9d7d5add7dc656/run/logging-manual/main.go

func (JSONLogEntry) String added in v0.0.65

func (e JSONLogEntry) String() string

String renders an entry structure to the JSON format expected by Cloud Logging.

type LogLevel added in v0.0.54

type LogLevel int

LogLevel defines the level of logging

const (
	LevelTrace LogLevel = iota
	LevelDebug
	LevelInfo
	LevelWarn
	LevelError
	LevelPanic
	LevelFatal
	LevelNone
)

func GetLevelFromEnv added in v0.0.74

func GetLevelFromEnv() LogLevel

GetLevelFromEnv reads the SM_LOG_LEVEL environment variable and converts it to a LogLevel.

func ParseLogLevel added in v0.1.0

func ParseLogLevel(s string) LogLevel

ParseLogLevel converts a string to a LogLevel. Case-insensitive. Returns LevelDebug for unrecognized values.

type Logger

type Logger interface {
	// With will return a new logger using metadata as the base context
	With(metadata map[string]interface{}) Logger
	// WithFields will return a new logger with the given key-value pairs as context
	WithFields(args ...interface{}) Logger
	// WithPrefix will return a new logger with a prefix prepended to the message
	WithPrefix(prefix string) Logger
	// WithContext returns a new logger enriched with context information (e.g., trace IDs)
	WithContext(ctx context.Context) Logger
	// Trace level logging
	Trace(msg string, args ...interface{})
	// Debug level logging
	Debug(msg string, args ...interface{})
	// Info level logging
	Info(msg string, args ...interface{})
	// Warning level logging
	Warn(msg string, args ...interface{})
	// Error level logging
	Error(msg string, args ...interface{})
	// Fatal level logging and exit with code 1
	Fatal(msg string, args ...interface{})
	// Flush flushes any buffered log entries
	Flush() error
}

Logger is an interface for logging

func FromContext added in v0.1.0

func FromContext(ctx context.Context) Logger

func NewGCloudLogger

func NewGCloudLogger() Logger

NewGCloudLogger returns a new Logger instance which can be used for structured google cloud logging

func NewGCloudLoggerWithSink added in v0.0.11

func NewGCloudLoggerWithSink(sink Sink, level LogLevel) Logger

NewGCloudLoggerWithSink returns a new Logger instance using a sink and suppressing the console logging

func NewJSONLogger added in v0.0.65

func NewJSONLogger(levels ...LogLevel) Logger

NewJSONLogger returns a new Logger instance which can be used for structured logging

func NewMultiLogger added in v0.0.65

func NewMultiLogger(loggers ...Logger) Logger

func NewZapGCloudLogger added in v0.1.0

func NewZapGCloudLogger(opts ...ZapOption) Logger

NewZapGCloudLogger returns a new zap-based Logger for structured Google Cloud logging with GCP trace correlation enabled by default.

func NewZapLogger added in v0.1.0

func NewZapLogger(opts ...ZapOption) Logger

type Sink added in v0.0.10

type Sink io.Writer

type SinkLogger added in v0.0.65

type SinkLogger interface {
	Logger
	// SetSink will set the sink, and level to sink
	SetSink(sink Sink, level LogLevel)
}

func NewConsoleLogger

func NewConsoleLogger(levels ...LogLevel) SinkLogger

NewConsoleLogger returns a new Logger instance which will log to the console

func NewJSONLoggerWithSink added in v0.0.65

func NewJSONLoggerWithSink(sink Sink, level LogLevel) SinkLogger

NewJSONLoggerWithSink returns a new Logger instance using a sink and suppressing the console logging

type TestLogEntry

type TestLogEntry struct {
	Severity  string
	Message   string
	Arguments []interface{}
}

type TestLogger

type TestLogger struct {
	Logs []TestLogEntry
	// contains filtered or unexported fields
}

func NewTestLogger

func NewTestLogger() *TestLogger

NewTestLogger returns a new Logger instance useful for testing

func (*TestLogger) Debug

func (c *TestLogger) Debug(msg string, args ...interface{})

func (*TestLogger) Error

func (c *TestLogger) Error(msg string, args ...interface{})

func (*TestLogger) Fatal added in v0.0.60

func (c *TestLogger) Fatal(msg string, args ...interface{})

func (*TestLogger) Flush added in v0.1.0

func (c *TestLogger) Flush() error

func (*TestLogger) Info

func (c *TestLogger) Info(msg string, args ...interface{})

func (*TestLogger) Log

func (c *TestLogger) Log(level string, msg string, args ...interface{})

func (*TestLogger) Trace

func (c *TestLogger) Trace(msg string, args ...interface{})

func (*TestLogger) Warn

func (c *TestLogger) Warn(msg string, args ...interface{})

func (*TestLogger) With

func (c *TestLogger) With(metadata map[string]interface{}) Logger

func (*TestLogger) WithContext added in v0.1.0

func (c *TestLogger) WithContext(_ context.Context) Logger

func (*TestLogger) WithFields added in v0.1.0

func (c *TestLogger) WithFields(args ...interface{}) Logger

func (*TestLogger) WithPrefix added in v0.0.13

func (c *TestLogger) WithPrefix(prefix string) Logger

WithPrefix will return a new logger with a prefix prepended to the message

func (*TestLogger) WithSink added in v0.0.10

func (c *TestLogger) WithSink(sink Sink, level LogLevel) Logger

type ZapOption added in v0.1.0

type ZapOption func(*zapConfig)

func WithFields added in v0.1.0

func WithFields(fields map[string]interface{}) ZapOption

func WithGCPTraceCorrelation added in v0.1.0

func WithGCPTraceCorrelation(enabled bool) ZapOption

func WithLevel added in v0.1.0

func WithLevel(level LogLevel) ZapOption

Jump to

Keyboard shortcuts

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