Logging Package Cheatsheet
Code-verified reference forpackages/logging.
Core Pipeline
Cognesy\Logging\Pipeline\LoggingPipeline:
LoggingPipeline::create(): selffilter(EventFilter $filter): selfenrich(EventEnricher $enricher): selfformat(EventFormatter $formatter): selfwrite(LogWriter $writer): selfbuild(): callable(callable(Event): void)__invoke(): callable(returnsbuild())
build() snapshots the current pipeline configuration. Later builder mutations do not affect an already-built callable.
Minimal usage:
Contracts
EventFilter::__invoke(Event $event): boolEventEnricher::__invoke(Event $event): LogContextEventFormatter::__invoke(Event $event, LogContext $context): LogEntryLogWriter::__invoke(LogEntry $entry): voidContextProvider::getContext(): array
Value Objects
LogEntry:
LogEntry::create(string $level, string $message, array $context = [], ?DateTimeImmutable $timestamp = null, string $channel = 'default'): selfwithContext(array $additionalContext): selfwithLevel(string $level): selfwithMessage(string $message): selfwithChannel(string $channel): selfisLevel(string $level): boolisLevelOrAbove(string $minimumLevel): booljsonSerialize(): array
LogContext:
LogContext::fromEvent(Event $event, array $additionalContext = []): selfwithFrameworkContext(array $context): selfwithPerformanceMetrics(array $metrics): selfwithUserContext(array $context): selftoArray(): arrayjsonSerialize(): array
Built-In Filters
LogLevelFilter(string $minimumLevel = LogLevel::DEBUG)EventClassFilter(array $excludedClasses = [], array $includedClasses = [])EventHierarchyFilter(array $excludedClasses = [], array $includedClasses = [])CompositeFilter(EventFilter ...$filters)(AND logic)
EventHierarchyFilter helpers:
EventHierarchyFilter::httpEventsOnly(): selfEventHierarchyFilter::structuredOutputEventsOnly(): selfEventHierarchyFilter::excludeHttpDebug(): self
Built-In Enrichers
BaseEnricherLazyEnricher(Closure $contextProvider, string $contextKey = 'framework')LazyEnricher::framework(Closure $provider): selfLazyEnricher::metrics(Closure $provider): selfLazyEnricher::user(Closure $provider): self
Built-In Formatters
DefaultFormatter(string $messageTemplate = '{event_class}: {message}', string $channel = 'instructor')MessageTemplateFormatter(array $templates = [], string $defaultTemplate = '{event_name}', string $channel = 'instructor')
MessageTemplateFormatter:
{event_class},{event_name},{event_id}- event-data placeholders like
{method},{url} - framework placeholders like
{framework.request_id}
Built-In Writers
PsrLoggerWriter(LoggerInterface $logger)MonologChannelWriter(Logger $logger, bool $useEntryChannel = true)CallableWriter(Closure $writer)CallableWriter::create(callable $writer): selfCompositeWriter(LogWriter ...$writers)
Framework Factories
Config keys:channel(string)level(string)exclude_events(array<class-string>)include_events(array<class-string>)templates(array<string, string>)
SymfonyLoggingFactory:
create(ContainerInterface $container, LoggerInterface $logger, array $config = []): callabledefaultSetup(ContainerInterface $container, LoggerInterface $logger): callableproductionSetup(ContainerInterface $container, LoggerInterface $logger): callable
Wiretap Integration
Cognesy\Logging\Integrations\EventPipelineWiretap:
EventPipelineWiretap(mixed $pipeline)— wraps acallable(Event): voidpipeline__invoke(object $event): void— forwardsEventinstances to the pipeline, ignores non-Event objects
Zero-Config JSONL Logging (EventLog)
Cognesy\Logging\EventLog is a factory that replaces new EventDispatcher(...) in runtime default paths.
It automatically attaches a structured JSONL file sink when INSTRUCTOR_LOG_PATH is set in the environment.
Enabling
Usage in runtimes (internal)
EventLog::root() creates a plain dispatcher when no path is set — no I/O, zero cost in tests.
When INSTRUCTOR_LOG_PATH is set, it attaches a logging wiretap filtered at INFO level (default).
For child dispatchers that bubble to a root:
API
Cognesy\Logging\EventLog:
EventLog::enable(string|EventLogConfig $config): void— programmatic opt-in; call at bootstrapEventLog::disable(): void— reset programmatic opt-inEventLog::root(string $name, ?LoggerInterface $logger = null): CanHandleEventsEventLog::child(string $name, CanHandleEvents $parent): CanHandleEvents
File-backed defaults
Default values now come frompackages/logging/resources/config/event_log.yaml.
Override that file in app-level config by adding config/event_log.yaml.
Available knobs:
pathlevelincludeEventsexcludeEventsuseHierarchyFilterexcludeHttpDebugincludePayloadincludeCorrelationincludeEventMetadataincludeComponentMetadatastringClipLength
Log level and overrides
Default minimum level:INFO. Override via env:
JSONL format
Each line is a JSON object:Off by default
- No
INSTRUCTOR_LOG_PATH→EventLog::root()returns a plain dispatcher, no files written - No test detection heuristics — the empty path is the only gating signal
- Framework injections (Laravel, Symfony) pass
$eventsexplicitly →EventLog::root()never runs
Callsite conventions (internal)
There are three situations and each has its own correct pattern: 1. Runtime/builder with optional user-provided dispatcher Use?? — EventLog only runs when no dispatcher is provided:
EventLog::root() as the standalone default:
EventLog::child() here — that would attach EventLog to a dispatcher the user
already controls, which may have its own logging configured.
3. Zero-config static factory (no dispatcher parameter)
Always use EventLog::root() directly — there is no user-supplied dispatcher to respect:
Observability components (internal)
EventLogConfig— loadsevent_log.yamldefaults and applies env overridesFileJsonLogWriter— append-only JSONL sink; swallows write errors silentlyStructuredEventFormatter— normalizes Event → LogEntry with correlation fields
Framework Integrations
Laravel:- Laravel-specific logging integration lives in
packages/laravel.
Cognesy\Logging\Integrations\Symfony\InstructorLoggingBundleInstructorLoggingExtensionregistersinstructor_logging.pipeline_factoryandinstructor_logging.pipeline_listener.WiretapEventBusPassadds onewiretap()method call to the configured event bus service.
instructor_logging):
enabled(bool, defaulttrue)preset(default|production|custom)event_bus_service(string, defaultCognesy\Events\Contracts\CanHandleEvents)config.channel(string)config.level(emergency|alert|critical|error|warning|notice|info|debug)config.exclude_events(string[])config.include_events(string[])config.templates(array<string, string>)