$handlers Array von Log-Handlern * @param ProcessorManager $processorManager Processor Manager für die Verarbeitung * @param LogContextManager|null $contextManager Optional: Context Manager für automatische Kontext-Anreicherung */ public function __construct( private Clock $clock, private LogLevel $minLevel = LogLevel::DEBUG, /** @var LogHandler[] */ private array $handlers = [], private ProcessorManager $processorManager = new ProcessorManager(), private ?LogContextManager $contextManager = null, ) { // Channel-Logger-Registry initialisieren $this->channelRegistry = new ChannelLoggerRegistry($this); } public function debug(string $message, ?LogContext $context = null): void { $this->log(LogLevel::DEBUG, $message, $context); } public function info(string $message, ?LogContext $context = null): void { $this->log(LogLevel::INFO, $message, $context); } public function notice(string $message, ?LogContext $context = null): void { $this->log(LogLevel::NOTICE, $message, $context); } public function warning(string $message, ?LogContext $context = null): void { $this->log(LogLevel::WARNING, $message, $context); } public function error(string $message, ?LogContext $context = null): void { $this->log(LogLevel::ERROR, $message, $context); } public function critical(string $message, ?LogContext $context = null): void { $this->log(LogLevel::CRITICAL, $message, $context); } public function alert(string $message, ?LogContext $context = null): void { $this->log(LogLevel::ALERT, $message, $context); } public function emergency(string $message, ?LogContext $context = null): void { $this->log(LogLevel::EMERGENCY, $message, $context); } /** * Log-Nachricht mit beliebigem Level erstellen * * @param LogLevel $level Log-Level * @param string $message Log-Nachricht * @param LogContext|null $context Strukturierter LogContext * @throws DateMalformedStringException */ public function log(LogLevel $level, string $message, ?LogContext $context = null): void { $this->createAndProcessRecord($level, $message, $context); } /** * Loggt in einen spezifischen Channel * * @internal Wird von ChannelLogger verwendet */ public function logToChannel(LogChannel $channel, LogLevel $level, string $message, ?LogContext $context = null): void { $this->createAndProcessRecord($level, $message, $context, $channel->value); } /** * Erstellt und verarbeitet einen Log-Record * * @param LogLevel $level Log-Level * @param string $message Log-Nachricht * @param LogContext|null $context Strukturierter LogContext * @param string|null $channel Optional: Channel-Name * @throws DateMalformedStringException */ private function createAndProcessRecord(LogLevel $level, string $message, ?LogContext $context = null, ?string $channel = null): void { // Wenn kein Context übergeben, leeren Context erstellen if ($context === null) { $context = LogContext::empty(); } // Prüfen ob Level hoch genug ist if ($level->isLowerThan($this->minLevel)) { return; } // LogContext automatisch mit aktuellem Context anreichern $finalContext = $this->enrichWithCurrentContext($context); // Log-Record erstellen $record = new LogRecord( message: $message, context: $finalContext, level: $level, timestamp: $this->clock->now(), channel: $channel ); // Record durch alle Processors verarbeiten $processedRecord = $this->processorManager->processRecord($record); // Alle Handler durchlaufen foreach ($this->handlers as $handler) { if ($handler->isHandling($processedRecord)) { $array = explode('\\',$handler::class); $handlerName = end($array); // Log-Record erstellen $record = new LogRecord( message: $handlerName . ' --- ' . $message, context: $finalContext, level: $level, timestamp: $this->clock->now(), channel: $channel ); $processedRecord = $this->processorManager->processRecord($record); $handler->handle($processedRecord); } } } /** * Reichert den übergebenen Context mit dem aktuellen Context vom LogContextManager an */ private function enrichWithCurrentContext(LogContext $context): LogContext { // Wenn kein ContextManager verfügbar ist, Context unverändert zurückgeben if ($this->contextManager === null) { return $context; } $currentContext = $this->contextManager->getCurrentContext(); // Wenn der übergebene Context ein LogContext ist, mit aktuellem Context mergen return $currentContext->merge($context); } /** * Holt einen ChannelLogger für einen spezifischen Channel */ public function channel(LogChannel|string $channel): Logger&HasChannel { return $this->channelRegistry->get($channel); } /** * Gibt die aktuelle Konfiguration des Loggers zurück */ public function getConfiguration(): array { return [ 'minLevel' => $this->minLevel->value, 'handlers' => array_map(fn (LogHandler $h) => get_class($h), $this->handlers), 'processors' => $this->processorManager->getProcessorList(), 'registeredChannels' => $this->channelRegistry->getRegisteredChannels(), ]; } }