logging

package
v0.9.12 Latest Latest
Warning

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

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

Documentation

Overview

Package logging provides the structured logger used throughout keel.

The early-boot logging problem

Logging has a chicken-and-egg problem: the user's log configuration (level, JSON format, remote sink) lives in the config file, but the config file must itself be loaded and parsed — a process that needs a working logger to report errors. The Linux kernel faces the same issue: earlycon/printk emit to a hard-wired serial port long before the kernel's logging subsystem is initialised; once the full driver stack is up, the kernel switches to the configured console.

Keel follows the same pattern across three phases:

Phase 1 — bootstrap (earlycon equivalent):
  logging.New(logging.Config{JSON: true}) creates a logger at "info" level
  writing to stdout. This is called before any user configuration is known.
  All CLI flag parsing and config load errors are emitted through this
  logger. It is unconditional — it never fails.

Phase 2 — reconfigure (driver handoff):
  Once the config file is loaded and validated, Server.Run calls
  Logger.Reconfigure with the user's level, JSON flag, and (if a remote
  sink is configured) a new io.MultiWriter(stdout, remoteSink). From this
  point forward the user's settings are in effect. Logs emitted during
  Phase 1 are never lost — they went to stdout before reconfiguration.

Phase 3 — live reload (SIGHUP / POST /admin/reload):
  Server.Reload calls Reconfigure again with the updated config. Level and
  JSON flag change atomically. The output writer is preserved (cfg.Out is
  nil on reload calls) — the remote-sink goroutine is already running and
  must not be re-initialised mid-flight.

Reconfigure is concurrency-safe: the level field is updated via sync/atomic (so filtering decisions are lock-free in the hot path) and the json/out fields are updated under a mutex.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewSyslogSink

func NewSyslogSink(endpoint string) (io.Writer, error)

NewSyslogSink dials a remote syslog endpoint over TCP and returns an io.Writer that formats lines as RFC 5424 syslog messages. Returns nil, err if the dial fails.

func ParseLevel added in v0.9.6

func ParseLevel(s string) (int32, error)

ParseLevel converts a level name ("debug", "info", "warn", "error") to its internal ordinal. Case-insensitive. An empty string maps to "info". Returns levelInfo and a non-nil error for unknown names.

Types

type Config

type Config struct {
	JSON  bool
	Level string    // "debug", "info", "warn", "error" (default "info")
	Out   io.Writer // nil → os.Stdout; ignored by Reconfigure when nil
}

Config carries the options accepted by New and Reconfigure.

type HTTPSink

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

HTTPSink is an io.Writer that buffers log lines and POSTs them in batches to an HTTP endpoint. Writes are non-blocking: lines are dropped when the buffer is full and counted by DropsTotal.

func NewHTTPSink

func NewHTTPSink(endpoint string, bufCap int, flushInterval time.Duration) *HTTPSink

NewHTTPSink creates an HTTPSink. bufCap is the number of log lines to buffer; flushInterval controls how often buffered lines are sent even if not full.

func (*HTTPSink) DropsTotal

func (s *HTTPSink) DropsTotal() int64

DropsTotal returns the number of lines dropped due to buffer overflow.

func (*HTTPSink) Run

func (s *HTTPSink) Run(ctx context.Context)

Run processes buffered lines until ctx is cancelled, flushing on each flushInterval tick or when a batch of 100 lines accumulates. On cancellation the remaining buffer is flushed before returning.

func (*HTTPSink) Write

func (s *HTTPSink) Write(b []byte) (int, error)

Write buffers b for asynchronous delivery. It always returns (len(b), nil); if the buffer is full the line is silently dropped and DropsTotal incremented.

type Logger

type Logger struct {
	ExitFn func(int) // injectable; defaults to os.Exit
	// contains filtered or unexported fields
}

Logger is a minimal structured logger. All methods are safe for concurrent use.

func New

func New(cfg Config) *Logger

New constructs a Logger from cfg. An unknown Level defaults to "info".

func (*Logger) Debug added in v0.9.6

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

func (*Logger) Error

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

func (*Logger) Exit added in v0.9.6

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

Exit always logs (bypasses level filter) then terminates the process cleanly.

func (*Logger) Fatal

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

Fatal always logs (bypasses level filter) then terminates the process.

func (*Logger) Info

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

func (*Logger) Reconfigure added in v0.9.6

func (l *Logger) Reconfigure(cfg Config) error

Reconfigure atomically applies a new level and JSON flag. If cfg.Out is non-nil, the output writer is also replaced. Returns an error if cfg.Level is unrecognised; the previous level is preserved.

func (*Logger) Warn

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

Jump to

Keyboard shortcuts

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