Package · logger

API Reference

Every public class and method in Winter Logger. All types live under the Flytachi\Winter\Logger namespace.

LoggerManager

Builds and caches one Monolog channel per config entry. Immutable at the config level — the with* methods return new instances. Each channel it builds automatically gets a ContextInjectingProcessor.

Constructor

php
new LoggerManager(
  ContextStorage $contextStorage,
  array          $channels = []
)
Parameter Type Default Description
$contextStorage ContextStorage Runtime context isolation (ProcessContext / CoroutineContext).
$channels array<string, array> [] Channel configs keyed by channel name. See Channel config.

Methods

Method Returns Description
channel(string $name) LoggerInterface Build (lazily) and cache the channel logger. Throws InvalidArgumentException if $name isn’t configured. Returns NullLogger if Monolog is absent.
hasChannel(string $name) bool Whether $name is registered.
contextStorage() ContextStorage The current context storage.
withContextStorage(ContextStorage $s) self New manager, same channels, different storage.
withChannel(string $name, array $config) self New manager with one channel added or overridden.
flush() void Drop all cached channel instances; rebuilt lazily on next channel().

Lazy & cached

channel() builds the Monolog instance on first call and caches it; later calls return the same object. flush() clears that cache — useful after a config reload in a daemon.

LoggerFactory

Static, Java-style facade. Not instantiable. Holds the active manager, the default channel (initially 'cli'), and a per-class logger cache keyed by "channel:FQCN".

Setup methods

Method Returns Description
setManager(LoggerManager $m) void Register the manager. Call once at bootstrap. Clears the cache.
setDefaultChannel(string $ch) void Set the channel used when none is given. Clears the cache.
setContextStorage(ContextStorage $s) void Swap storage on the current manager (same channels). Clears the cache.
addChannel(string $name, array $cfg) void Add/override a channel on the current manager. Clears the cache.
reset() void Clear only the per-class logger cache.

Access methods

php
getLogger(string|object $class, ?string $channel = null): LoggerInterface

Per-class logger. $class may be an FQCN string, a ::class constant, or an object (its class is used). Cached per "channel:FQCN".

  • If $channel is given and registered → uses it.
  • If $channel is null or unregistered → falls back to the default channel (no throw).
  • Renders (ShortName) in the line; stores the full FQCN in context['class'].
Method Returns Description
channel(string $name) LoggerInterface Raw channel logger, no class label. Throws if $name is unregistered.
logger() LoggerInterface Raw logger for the current default channel (used by Log).
contextStorage() ContextStorage The current manager’s context storage.

getLogger falls back, channel does not

getLogger($c, 'missing') silently uses the default channel. channel('missing') throws InvalidArgumentException. Uninitialized factory (setManager never called) throws RuntimeException.

Log

Static facade — a one-liner shortcut to the default channel via LoggerFactory::logger(). Not instantiable, no class label attached.

Method Signature
Log::debug (string $message, array $context = []): void
Log::info (string $message, array $context = []): void
Log::notice (string $message, array $context = []): void
Log::warning (string $message, array $context = []): void
Log::error (string $message, array $context = []): void
Log::critical (string $message, array $context = []): void
Log::alert (string $message, array $context = []): void

No Log::emergency

The Log facade covers debug through alert. For the emergency level, go through a logger instance — e.g. LoggerFactory::logger()->emergency(...) or getLogger(self::class)->emergency(...), which are full PSR-3 loggers.

Logger

The PSR-3 wrapper returned by the manager and factory. Implements Flytachi\Winter\Logger\Contracts\LoggerInterface (which extends Psr\Log\LoggerInterface). Merges bound context into every call.

Constructor

php
new Logger(
  \Monolog\Logger  $monolog,
  ContextStorage   $contextStorage,
  array            $boundContext = []
)

Methods

Method Returns Description
withContext(array $context) static New logger with $context merged into every call. Does not mutate the original.
log(mixed $level, string|Stringable $message, array $context = []) void PSR-3 log. Bound context is merged under the call’s context (call wins on key clash).
monolog() \Monolog\Logger The underlying Monolog instance (to push processors/handlers).

Plus all PSR-3 level shortcuts (debug, info, notice, warning, error, critical, alert, emergency) via Monolog’s LoggerTrait.

php
$log = LoggerFactory::getLogger(self::class)->withContext(['request_id' => $id]);
$log->info('processing');   // carries request_id

ContextStorage

Interface for per-execution-unit context. Namespace Flytachi\Winter\Logger\Contracts.

Method Returns Description
set(string $key, mixed $value) void Store a field.
get(string $key, mixed $default = null) mixed Read a field.
all() array Snapshot of all fields.
forget(string $key) void Remove one field.
clear() void Remove all fields. Call at the end of every request/job/coroutine.

ProcessContext

One flat array per process. Safe for FPM (request = process) and CLI one-shots. In daemon loops, clear() between iterations. Not safe for Swoole.

CoroutineContext

Backs storage with Swoole\Coroutine::getContext() — one bag per coroutine, auto-destroyed when the coroutine ends. Falls back to a static array outside a coroutine (bootstrap, onWorkerStart). Requires ext-swoole. See Swoole coroutines.

Processors

Namespace Flytachi\Winter\Logger\Processor. Both implement Monolog’s ProcessorInterface.

ContextInjectingProcessor

Added to every channel automatically. Merges the ContextStorage snapshot into each record’s extra. Early-exits (zero overhead) when no context is set.

php
new ContextInjectingProcessor(ContextStorage $storage)

SensitiveMaskingProcessor

Optional. Redacts sensitive keys (case-insensitive, recursive) in context and extra, replacing values with ***.

php
new SensitiveMaskingProcessor(array $extraKeys = [])

$extraKeys are merged with the defaults. See Masked keys and Mask sensitive data.

Factories

Namespace Flytachi\Winter\Logger\Factory.

HandlerFactory

php
HandlerFactory::make(array $config): \Monolog\Handler\HandlerInterface

Maps output to a handler: stdout/stderrSafeStreamHandler, syslogSyslogHandler, fileRotatingFileHandler, nullNullHandler. Throws InvalidArgumentException on an unknown output, or when output=file without file_path.

FormatterFactory

php
FormatterFactory::make(string $format, bool $appendNewline = true): \Monolog\Formatter\FormatterInterface

'line'SpringLineFormatter, 'json' → Monolog JsonFormatter (newline batch mode). Pass $appendNewline = false for syslog (it frames messages itself). Throws InvalidArgumentException on an unknown format.

Handler & formatter

  • SafeStreamHandler (Flytachi\Winter\Logger\Handler) — extends Monolog’s StreamHandler; overrides streamWrite() to use @fwrite and never throw on a broken stream. See Output & broken pipe.
  • SpringLineFormatter (Flytachi\Winter\Logger\Formatter) — the Spring Boot-style line format. Constructor: new SpringLineFormatter(bool $appendNewline = true). See Log format.