can use deduplication handler, allow custom configuration for special handlers
This commit is contained in:
parent
9adef0b900
commit
7911327256
@ -11,3 +11,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- initial implementation
|
- initial implementation
|
||||||
- can create a custom Logger instance rotating or static
|
- can create a custom Logger instance rotating or static
|
||||||
- combined logger (OXID and configured stream)
|
- combined logger (OXID and configured stream)
|
||||||
|
- can combine with special handlers (buffered, onErrorOnly, deduplicated)
|
||||||
|
32
README.md
32
README.md
@ -15,8 +15,36 @@ composer require d3/logger-factory
|
|||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
$loggerFactory = loggerFactory::create();
|
use D3\LoggerFactory\LoggerFactory;
|
||||||
$logger = $loggerFactory->getFileLogger('myPluginLogger', 'plugin_requests.log', Logger::DEBUG, 5);
|
|
||||||
|
$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]
|
## Licence of this software (Logger factory) [MIT]
|
||||||
|
@ -18,8 +18,10 @@ declare(strict_types=1);
|
|||||||
namespace D3\LoggerFactory;
|
namespace D3\LoggerFactory;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Monolog\Handler\AbstractHandler;
|
||||||
use Monolog\Handler\AbstractProcessingHandler;
|
use Monolog\Handler\AbstractProcessingHandler;
|
||||||
use Monolog\Handler\BufferHandler;
|
use Monolog\Handler\BufferHandler;
|
||||||
|
use Monolog\Handler\DeduplicationHandler;
|
||||||
use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
|
use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
|
||||||
use Monolog\Handler\FingersCrossedHandler;
|
use Monolog\Handler\FingersCrossedHandler;
|
||||||
use Monolog\Handler\RotatingFileHandler;
|
use Monolog\Handler\RotatingFileHandler;
|
||||||
@ -32,6 +34,15 @@ class LoggerFactory
|
|||||||
{
|
{
|
||||||
public const SPECIAL_HANDLERS_BUFFERING = 'buffering';
|
public const SPECIAL_HANDLERS_BUFFERING = 'buffering';
|
||||||
public const SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY = 'logOnErrorOnly';
|
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
|
public static function create(): LoggerFactory
|
||||||
{
|
{
|
||||||
@ -117,25 +128,54 @@ class LoggerFactory
|
|||||||
public function applySpecialHandlers(
|
public function applySpecialHandlers(
|
||||||
AbstractProcessingHandler $handler,
|
AbstractProcessingHandler $handler,
|
||||||
array $specialHandlers = []
|
array $specialHandlers = []
|
||||||
): AbstractProcessingHandler
|
): AbstractHandler
|
||||||
{
|
{
|
||||||
if (in_array(self::SPECIAL_HANDLERS_BUFFERING, $specialHandlers, true)) {
|
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)) {
|
if (in_array(self::SPECIAL_HANDLERS_LOG_ON_ERROR_ONLY, $specialHandlers, true)) {
|
||||||
$handler = $this->setLogItemsOnErrorOnly($handler);
|
$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;
|
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(
|
public function setLogItemsOnErrorOnly(
|
||||||
AbstractProcessingHandler $handler,
|
AbstractHandler $handler,
|
||||||
int $activationLevel = Logger::ERROR
|
int $activationLevel = Logger::ERROR
|
||||||
): FingersCrossedHandler
|
): FingersCrossedHandler
|
||||||
{
|
{
|
||||||
@ -144,4 +184,13 @@ class LoggerFactory
|
|||||||
new ErrorLevelActivationStrategy($activationLevel)
|
new ErrorLevelActivationStrategy($activationLevel)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function makeUnique(
|
||||||
|
AbstractHandler $handler,
|
||||||
|
int $deduplicationLevel = Logger::ERROR,
|
||||||
|
int $time = 60
|
||||||
|
): DeduplicationHandler
|
||||||
|
{
|
||||||
|
return new DeduplicationHandler($handler, null, $deduplicationLevel, $time);
|
||||||
|
}
|
||||||
}
|
}
|
@ -4,6 +4,9 @@ namespace D3\LoggerFactory\tests;
|
|||||||
|
|
||||||
use D3\LoggerFactory\LoggerFactory;
|
use D3\LoggerFactory\LoggerFactory;
|
||||||
use Generator;
|
use Generator;
|
||||||
|
use Monolog\Handler\BufferHandler;
|
||||||
|
use Monolog\Handler\DeduplicationHandler;
|
||||||
|
use Monolog\Handler\FingersCrossedHandler;
|
||||||
use Monolog\Handler\RotatingFileHandler;
|
use Monolog\Handler\RotatingFileHandler;
|
||||||
use Monolog\Handler\StreamHandler;
|
use Monolog\Handler\StreamHandler;
|
||||||
use Monolog\Logger;
|
use Monolog\Logger;
|
||||||
@ -34,7 +37,10 @@ class LoggerFactoryTest extends ApiTestCase
|
|||||||
*/
|
*/
|
||||||
public function testGetFileLogger(int $logLevel, ?int $maxFiles, string $expectedHandlerClass): void
|
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 */
|
/** @var Logger|MockObject $logger */
|
||||||
$logger = $this->callMethod(
|
$logger = $this->callMethod(
|
||||||
@ -63,7 +69,10 @@ class LoggerFactoryTest extends ApiTestCase
|
|||||||
*/
|
*/
|
||||||
public function testGetCombinedOxidAndFileLoggerWithoutOxid(): void
|
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);
|
$this->expectException(RuntimeException::class);
|
||||||
|
|
||||||
@ -102,11 +111,14 @@ class LoggerFactoryTest extends ApiTestCase
|
|||||||
* @throws ReflectionException
|
* @throws ReflectionException
|
||||||
* @covers \D3\LoggerFactory\LoggerFactory::getCombinedOxidAndFileLogger
|
* @covers \D3\LoggerFactory\LoggerFactory::getCombinedOxidAndFileLogger
|
||||||
*/
|
*/
|
||||||
public function testAddCombinedOxidAndFileLoggerInOxid(): void
|
public function testGetCombinedOxidAndFileLoggerInOxid(): void
|
||||||
{
|
{
|
||||||
require_once __DIR__.'/Helpers/classAliases.php';
|
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(
|
$logger = $this->callMethod(
|
||||||
$sut,
|
$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]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user