diff --git a/CHANGELOG.md b/CHANGELOG.md index 5852fe0e..364d22ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 2.1.2 under development +- New #125: Add optional `$levels` parameter to `Target` constructor allowing log level filtering at instantiation (@samdark) - Chg #126: Add `ext-psr` to `conflict` section in `composer.json` (@samdark) ## 2.1.1 June 03, 2025 @@ -13,7 +14,7 @@ - New #104: Add new static methods `Logger::assertLevelIsValid()`, `Logger::assertLevelIsString()` and `Logger::assertLevelIsSupported()` (@vjik) -- New #108: Support of nested values in message templates' variables, e. g. `{foo.bar}` (@vjik) +- New #108: Support of nested values in message templates' variables, e.g. `{foo.bar}` (@vjik) - New #109, #113, #116: Add context providers (@vjik) - New #111: Add `DateTime` and `DateTimeImmutable` support as time in log context (@vjik) - New #112: Add `Message::category()` method and `Message::DEFAULT_CATEGORY` constant, deprecate diff --git a/src/PsrTarget.php b/src/PsrTarget.php index 486aff1e..36228535 100644 --- a/src/PsrTarget.php +++ b/src/PsrTarget.php @@ -15,10 +15,11 @@ final class PsrTarget extends Target * Sets the PSR-3 logger used to save messages of this target. * * @param LoggerInterface $logger The logger instance to be used for messages processing. + * @param string[] $levels The {@see \Psr\Log\LogLevel log message levels} that this target is interested in. */ - public function __construct(private LoggerInterface $logger) + public function __construct(private LoggerInterface $logger, array $levels = []) { - parent::__construct(); + parent::__construct($levels); } /** diff --git a/src/StreamTarget.php b/src/StreamTarget.php index e9fd8c05..677ddb78 100644 --- a/src/StreamTarget.php +++ b/src/StreamTarget.php @@ -27,10 +27,11 @@ final class StreamTarget extends Target { /** * @param resource|string $stream A string stream identifier or a stream resource. + * @param string[] $levels The {@see \Psr\Log\LogLevel log message levels} that this target is interested in. */ - public function __construct(private $stream = 'php://stdout') + public function __construct(private $stream = 'php://stdout', array $levels = []) { - parent::__construct(); + parent::__construct($levels); } protected function export(): void diff --git a/src/Target.php b/src/Target.php index 0ecca2f2..cea39809 100644 --- a/src/Target.php +++ b/src/Target.php @@ -81,11 +81,14 @@ abstract protected function export(): void; /** * When defining a constructor in child classes, you must call `parent::__construct()`. + * + * @param string[] $levels The {@see \Psr\Log\LogLevel log message levels} that this target is interested in. */ - public function __construct() + public function __construct(array $levels = []) { $this->categories = new CategoryFilter(); $this->formatter = new Formatter(); + $this->setLevels($levels); } /** @@ -147,7 +150,7 @@ public function setExcept(array $except): self } /** - * Sets a list of log message levels that current target is interested in. + * Sets a list of {@see \Psr\Log\LogLevel log message levels} that current target is interested in. * * @param string[] $levels The list of log message levels. * diff --git a/tests/PsrTargetTest.php b/tests/PsrTargetTest.php index 490114cc..69664bb5 100644 --- a/tests/PsrTargetTest.php +++ b/tests/PsrTargetTest.php @@ -56,4 +56,30 @@ public function testPsrLogInterfaceMethods(string $level, string $message, array $this->target->collect([new Message($level, $message, $context)], true); $this->expectOutputString("{$level}: {$message}: " . json_encode($context, JSON_THROW_ON_ERROR)); } + + public function testSetLevelsViaConstructor(): void + { + $target = new PsrTarget( + new class () implements LoggerInterface { + use LoggerTrait; + + public function log($level, $message, array $context = []): void + { + echo "$level: $message"; + } + }, + [LogLevel::ERROR, LogLevel::INFO] + ); + + $target->collect( + [ + new Message(LogLevel::INFO, 'message-1', ['foo' => 'bar']), + new Message(LogLevel::DEBUG, 'message-2', ['foo' => true]), + new Message(LogLevel::ERROR, 'message-3', ['foo' => 1]), + ], + true + ); + + $this->expectOutputString('info: message-1error: message-3'); + } } diff --git a/tests/StreamTargetTest.php b/tests/StreamTargetTest.php index 7281704b..916aeb75 100644 --- a/tests/StreamTargetTest.php +++ b/tests/StreamTargetTest.php @@ -100,4 +100,21 @@ private function exportStreamTarget(StreamTarget $target): void true ); } + + public function testSetLevelsViaConstructor(): void + { + $target = new StreamTarget('php://output', [LogLevel::ERROR, LogLevel::INFO]); + $target->setFormat(static fn (Message $message) => "[{$message->level()}] {$message->message()}"); + + $target->collect( + [ + new Message(LogLevel::INFO, 'message-1', ['foo' => 'bar']), + new Message(LogLevel::DEBUG, 'message-2', ['foo' => true]), + new Message(LogLevel::ERROR, 'message-3', ['foo' => 1]), + ], + true + ); + + $this->expectOutputString("[info] message-1\n[error] message-3\n"); + } } diff --git a/tests/TargetTest.php b/tests/TargetTest.php index 50dfa3fa..9612390d 100644 --- a/tests/TargetTest.php +++ b/tests/TargetTest.php @@ -461,6 +461,37 @@ public function testFormatMessageThrowExceptionForPrefixCallableReturnNotBoolean $this->target->formatMessages(); } + public function testSetLevelsViaConstructor(): void + { + $target = new DummyTarget([LogLevel::ERROR, LogLevel::WARNING]); + $logger = new Logger([$target]); + + $logger->setFlushInterval(1); + $logger->log(LogLevel::INFO, 'testInfo'); + $logger->log(LogLevel::ERROR, 'testError'); + $logger->log(LogLevel::WARNING, 'testWarning'); + $logger->log(LogLevel::DEBUG, 'testDebug'); + + $messages = $target->getMessages(); + $this->assertCount(2, $messages); + $this->assertSame('testError', $messages[0]->message()); + $this->assertSame('testWarning', $messages[1]->message()); + } + + public function testSetLevelsViaConstructorWithEmptyArray(): void + { + $target = new DummyTarget([]); + $logger = new Logger([$target]); + + $logger->setFlushInterval(1); + $logger->log(LogLevel::INFO, 'testInfo'); + $logger->log(LogLevel::ERROR, 'testError'); + $logger->log(LogLevel::DEBUG, 'testDebug'); + + $messages = $target->getMessages(); + $this->assertCount(3, $messages); + } + private function collectOneAndExport(string $level, string $message, array $context = []): void { $this->target->collect([new Message($level, $message, $context)], true); diff --git a/tests/TestAsset/DummyTarget.php b/tests/TestAsset/DummyTarget.php index 8de65e9d..f311831f 100644 --- a/tests/TestAsset/DummyTarget.php +++ b/tests/TestAsset/DummyTarget.php @@ -14,9 +14,9 @@ final class DummyTarget extends Target private array $exportMessages = []; private Formatter $exportFormatter; - public function __construct() + public function __construct(array $levels = []) { - parent::__construct(); + parent::__construct($levels); $this->exportFormatter = new Formatter(); }