can use deduplication handler, allow custom configuration for special handlers

Dieser Commit ist enthalten in:
Daniel Seifert 2025-02-07 16:31:18 +01:00
Ursprung 9adef0b900
Commit 7911327256
Signiert von: DanielS
GPG-Schlüssel-ID: 6A513E13AEE66170
4 geänderte Dateien mit 214 neuen und 11 gelöschten Zeilen

Datei anzeigen

@ -11,3 +11,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- initial implementation
- can create a custom Logger instance rotating or static
- combined logger (OXID and configured stream)
- can combine with special handlers (buffered, onErrorOnly, deduplicated)

Datei anzeigen

@ -15,8 +15,36 @@ composer require d3/logger-factory
## Usage
```
$loggerFactory = loggerFactory::create();
$logger = $loggerFactory->getFileLogger('myPluginLogger', 'plugin_requests.log', Logger::DEBUG, 5);
use D3\LoggerFactory\LoggerFactory;
$loggerFactory = LoggerFactory::create();
$logger = $loggerFactory->getFileLogger(
'myPluginLogger',
'plugin_requests.log',
Logger::DEBUG,
5
);
```
### Use of the special handler
```
use D3\LoggerFactory\LoggerFactory;
$loggerFactory = LoggerFactory::create();
$logger = $loggerFactory->getFileLogger(
'myPluginLogger',
'plugin_requests.log',
Logger::DEBUG,
5,
[
LoggerFactory::SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY, // simple default implementation
LoggerFactory::SPECIAL_HANDLERS_BUFFERING,
LoggerFactory::SPECIAL_HANDLERS_MAKE_UNIQUE => [ // advanced custom implementation
LoggerFactory::MAKEUNIQUE_OPTION_LEVEL => Logger::INFO
],
]
);
```
## Licence of this software (Logger factory) [MIT]

Datei anzeigen

@ -18,8 +18,10 @@ declare(strict_types=1);
namespace D3\LoggerFactory;
use Exception;
use Monolog\Handler\AbstractHandler;
use Monolog\Handler\AbstractProcessingHandler;
use Monolog\Handler\BufferHandler;
use Monolog\Handler\DeduplicationHandler;
use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
use Monolog\Handler\FingersCrossedHandler;
use Monolog\Handler\RotatingFileHandler;
@ -32,6 +34,15 @@ class LoggerFactory
{
public const SPECIAL_HANDLERS_BUFFERING = 'buffering';
public const SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY = 'logOnErrorOnly';
public const SPECIAL_HANDLERS_MAKE_UNIQUE = 'makeUnique';
public const BUFFERING_OPTION_LIMIT = 'bufferLimit';
public const BUFFERING_OPTION_LEVEL = 'loglevel';
public const LOGONERRORONLY_LEVEL = 'activationLevel';
public const MAKEUNIQUE_OPTION_LEVEL = 'loglevel';
public const MAKEUNIQUE_OPTION_TIME = 'time';
public static function create(): LoggerFactory
{
@ -117,25 +128,54 @@ class LoggerFactory
public function applySpecialHandlers(
AbstractProcessingHandler $handler,
array $specialHandlers = []
): AbstractProcessingHandler
): AbstractHandler
{
if (in_array(self::SPECIAL_HANDLERS_BUFFERING, $specialHandlers, true)) {
$handler = $this->setLogItemsOnErrorOnly($handler);
$handler = $this->setBuffering($handler);
} elseif (in_array(self::SPECIAL_HANDLERS_BUFFERING, array_keys($specialHandlers), true)) {
$options = $specialHandlers[self::SPECIAL_HANDLERS_BUFFERING];
$handler = $this->setBuffering(
$handler,
$options[self::BUFFERING_OPTION_LIMIT] ?? 0,
$options[self::BUFFERING_OPTION_LEVEL] ?? Logger::DEBUG
);
}
if (in_array(self::SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY, $specialHandlers, true)) {
$handler = $this->setLogItemsOnErrorOnly($handler);
} elseif (in_array(self::SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY, array_keys($specialHandlers), true)) {
$options = $specialHandlers[self::SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY];
$handler = $this->setLogItemsOnErrorOnly(
$handler,
$options[self::LOGONERRORONLY_LEVEL] ?? Logger::ERROR
);
}
if (in_array(self::SPECIAL_HANDLERS_MAKE_UNIQUE, $specialHandlers, true)) {
$handler = $this->makeUnique($handler);
} elseif (in_array(self::SPECIAL_HANDLERS_MAKE_UNIQUE, array_keys($specialHandlers), true)) {
$options = $specialHandlers[self::SPECIAL_HANDLERS_MAKE_UNIQUE];
$handler = $this->makeUnique(
$handler,
$options[self::MAKEUNIQUE_OPTION_LEVEL] ?? Logger::ERROR,
$options[self::MAKEUNIQUE_OPTION_TIME] ?? 60
);
}
return $handler;
}
public function setBuffering(AbstractProcessingHandler $handler): BufferHandler
public function setBuffering(
AbstractHandler $handler,
int $bufferLimit = 0,
int $loglevel = Logger::DEBUG
): BufferHandler
{
return new BufferHandler($handler);
return new BufferHandler($handler, $bufferLimit, $loglevel);
}
public function setLogItemsOnErrorOnly(
AbstractProcessingHandler $handler,
AbstractHandler $handler,
int $activationLevel = Logger::ERROR
): FingersCrossedHandler
{
@ -144,4 +184,13 @@ class LoggerFactory
new ErrorLevelActivationStrategy($activationLevel)
);
}
public function makeUnique(
AbstractHandler $handler,
int $deduplicationLevel = Logger::ERROR,
int $time = 60
): DeduplicationHandler
{
return new DeduplicationHandler($handler, null, $deduplicationLevel, $time);
}
}

Datei anzeigen

@ -4,6 +4,9 @@ namespace D3\LoggerFactory\tests;
use D3\LoggerFactory\LoggerFactory;
use Generator;
use Monolog\Handler\BufferHandler;
use Monolog\Handler\DeduplicationHandler;
use Monolog\Handler\FingersCrossedHandler;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
@ -34,7 +37,10 @@ class LoggerFactoryTest extends ApiTestCase
*/
public function testGetFileLogger(int $logLevel, ?int $maxFiles, string $expectedHandlerClass): void
{
$sut = LoggerFactory::create();
$sut = $this->getMockBuilder(LoggerFactory::class)
->onlyMethods(['applySpecialHandlers'])
->getMock();
$sut->expects($this->once())->method('applySpecialHandlers')->willReturnArgument(0);
/** @var Logger|MockObject $logger */
$logger = $this->callMethod(
@ -63,7 +69,10 @@ class LoggerFactoryTest extends ApiTestCase
*/
public function testGetCombinedOxidAndFileLoggerWithoutOxid(): void
{
$sut = LoggerFactory::create();
$sut = $this->getMockBuilder(LoggerFactory::class)
->onlyMethods(['applySpecialHandlers'])
->getMock();
$sut->expects($this->never())->method('applySpecialHandlers')->willReturnArgument(0);
$this->expectException(RuntimeException::class);
@ -102,11 +111,14 @@ class LoggerFactoryTest extends ApiTestCase
* @throws ReflectionException
* @covers \D3\LoggerFactory\LoggerFactory::getCombinedOxidAndFileLogger
*/
public function testAddCombinedOxidAndFileLoggerInOxid(): void
public function testGetCombinedOxidAndFileLoggerInOxid(): void
{
require_once __DIR__.'/Helpers/classAliases.php';
$sut = LoggerFactory::create();
$sut = $this->getMockBuilder(LoggerFactory::class)
->onlyMethods(['applySpecialHandlers'])
->getMock();
$sut->expects($this->exactly(2))->method('applySpecialHandlers')->willReturnArgument(0);
$logger = $this->callMethod(
$sut,
@ -138,4 +150,117 @@ class LoggerFactoryTest extends ApiTestCase
)
);
}
/**
* @test
* @covers \D3\LoggerFactory\LoggerFactory::applySpecialHandlers
* @throws ReflectionException
* @dataProvider applySpecialHandlersDataProvider
*/
public function testApplySpecialHandlers(array $options, string $expectedClass): void
{
$sut = LoggerFactory::create();
$handler = $this->getMockBuilder(StreamHandler::class)
->disableOriginalConstructor()
->getMock();
$this->assertInstanceOf(
$expectedClass,
$this->callMethod(
$sut,
'applySpecialHandlers',
[$handler, $options]
)
);
}
public static function applySpecialHandlersDataProvider(): Generator
{
yield 'empty config' => [[], StreamHandler::class];
yield 'simple buffering' => [[LoggerFactory::SPECIAL_HANDLERS_BUFFERING], BufferHandler::class];
yield 'advanced buffering' => [
[LoggerFactory::SPECIAL_HANDLERS_BUFFERING => [LoggerFactory::BUFFERING_OPTION_LIMIT => 10]],
BufferHandler::class
];
yield 'simple logOnErrorOnly' => [[LoggerFactory::SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY], FingersCrossedHandler::class];
yield 'advanced logOnErrorOnly' => [
[LoggerFactory::SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY => [LoggerFactory::LOGONERRORONLY_LEVEL => Logger::DEBUG]],
FingersCrossedHandler::class
];
yield 'simple deduplicate' => [[LoggerFactory::SPECIAL_HANDLERS_MAKE_UNIQUE], DeduplicationHandler::class];
yield 'advanced deduplicate' => [
[LoggerFactory::SPECIAL_HANDLERS_MAKE_UNIQUE => [LoggerFactory::MAKEUNIQUE_OPTION_TIME => 30]],
DeduplicationHandler::class
];
}
/**
* @test
* @throws ReflectionException
* @covers \D3\LoggerFactory\LoggerFactory::setBuffering
*/
public function testSetBuffering(): void
{
$sut = LoggerFactory::create();
$handler = $this->getMockBuilder(StreamHandler::class)
->disableOriginalConstructor()
->getMock();
$this->assertInstanceOf(
BufferHandler::class,
$this->callMethod(
$sut,
'setBuffering',
[$handler]
)
);
}
/**
* @test
* @throws ReflectionException
* @covers \D3\LoggerFactory\LoggerFactory::setLogItemsOnErrorOnly
*/
public function testSetLogItemsOnErrorOnly(): void
{
$sut = LoggerFactory::create();
$handler = $this->getMockBuilder(StreamHandler::class)
->disableOriginalConstructor()
->getMock();
$this->assertInstanceOf(
FingersCrossedHandler::class,
$this->callMethod(
$sut,
'setLogItemsOnErrorOnly',
[$handler]
)
);
}
/**
* @test
* @throws ReflectionException
* @covers \D3\LoggerFactory\LoggerFactory::makeUnique
*/
public function testMakeUnique(): void
{
$sut = LoggerFactory::create();
$handler = $this->getMockBuilder(StreamHandler::class)
->disableOriginalConstructor()
->getMock();
$this->assertInstanceOf(
DeduplicationHandler::class,
$this->callMethod(
$sut,
'makeUnique',
[$handler]
)
);
}
}