Documentation
¶
Overview ¶
Package logging owns the server's klog wiring and the runtime-reloadable log destination (file, stderr, or discard).
The whole package exists so that runtime reloads — log_file rotations on SIGHUP — never call klog.SetLoggerWithOptions. klog's own contract states that "modifying the logger is not thread-safe and should be done while no other goroutines invoke log calls, usually during program initialization." We honor that by configuring klog exactly once in New and routing every subsequent reload through a mutex-guarded writer that the textlogger writes to.
Index ¶
Constants ¶
const StderrSentinel = "stderr"
StderrSentinel is the magic value users put in log_file to route logs to stderr without opening a file on disk.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type LogProvider ¶ added in v0.0.64
LogProvider is implemented by providers that buffer log records and need a graceful shutdown to flush them (e.g. *sdklog.LoggerProvider).
type Option ¶ added in v0.0.64
type Option func(*sinkOptions)
Option configures optional Sink behavior.
func WithOtelLogSink ¶ added in v0.0.64
func WithOtelLogSink(sink logr.LogSink, provider LogProvider) Option
WithOtelLogSink adds an OpenTelemetry logr bridge sink alongside the text logger. When set, every klog call is forwarded to both the text logger (which writes through the Sink's io.Writer) and the OTel bridge (which exports log records via the OTel SDK). The text logger is always the primary — OTel failures never block local logging.
The provider is shut down by Sink.Close to flush pending log records.
type Sink ¶
type Sink struct {
// contains filtered or unexported fields
}
Sink is the runtime-reloadable log destination. It implements io.Writer so the textlogger can write through it; reloads swap the underlying writer and close the previous file (if any).
Construct with New. Reload on SIGHUP. Close on shutdown.
func New ¶
New configures klog and returns a Sink ready to use.
httpOut is the writer used in HTTP mode when log_file is unset (typically os.Stdout). errOut is the writer used when log_file is "stderr" (typically os.Stderr). In stdio mode without log_file the sink writes to io.Discard so klog stays out of the protocol channel.
New must be called at most once per process (outside of tests, which guard with klog.CaptureState/Restore). It mutates klog's package-level logger and rebinds a fresh FlagSet to klog's globals; a second New would leave the previous Sink's flag bindings dangling and reset klog's writer behind its back. Production wires a single Sink in cmd.Complete and reuses it for the process lifetime.
On error, the caller does not need to Close — no file is opened.
func (*Sink) Close ¶
Close releases the current log file, if any. It is idempotent and re-routes the writer to errOut first so that any klog call after Close (e.g. an error log emitted by the caller's defer when Close itself returns an error) lands somewhere visible instead of being swallowed by the file descriptor we are about to close.
When an OTel LogProvider is configured, Close shuts it down first so pending log records are flushed to the backend while the text sink is still active.
func (*Sink) Reload ¶
func (s *Sink) Reload(cfg *config.StaticConfig) error
Reload re-applies cfg to the running sink: it opens the new log file (if any), swaps the writer, closes the previous file, and updates klog's verbosity.
Reload is intended to be called by a single goroutine (the SIGHUP handler). mu makes each swap+close safe against concurrent Writes, but two concurrent Reloads could still interleave their open-then-swap and leave the sink pointing at an already-closed file. The package assumes a single reloader.
The returned error reflects only the destination swap (open-file failure). On error, the previous destination is preserved unchanged. A verbosity-update failure after a successful destination swap is logged via klog.Warningf rather than returned, so the caller's success/failure decision lines up cleanly with whether logs are now landing in the right place. In practice klog.Level.Set never fails on strconv.Itoa output, so this is a defensive path.