mirror of
https://github.com/shlinkio/shlink.git
synced 2025-03-14 04:00:57 +03:00
Ensured different loggers are used for swoole and for the app regular logs
This commit is contained in:
parent
22b02de405
commit
282ffef200
5 changed files with 221 additions and 10 deletions
|
@ -7,6 +7,7 @@ use Monolog\Handler\RotatingFileHandler;
|
|||
use Monolog\Handler\StreamHandler;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Processor;
|
||||
use Zend\Expressive\Swoole\Log\AccessLogInterface;
|
||||
use const PHP_EOL;
|
||||
|
||||
return [
|
||||
|
@ -20,17 +21,18 @@ return [
|
|||
],
|
||||
|
||||
'handlers' => [
|
||||
'shlink_log_handler' => Common\Exec\ExecutionContext::currentContextIsSwoole() ? [
|
||||
'shlink_rotating_handler' => [
|
||||
'class' => RotatingFileHandler::class,
|
||||
'level' => Logger::INFO,
|
||||
'filename' => 'data/log/shlink_log.log',
|
||||
'max_files' => 30,
|
||||
'formatter' => 'dashed',
|
||||
],
|
||||
'swoole_access_handler' => [
|
||||
'class' => StreamHandler::class,
|
||||
'level' => Logger::INFO,
|
||||
'stream' => 'php://stdout',
|
||||
'formatter' => 'dashed',
|
||||
] : [
|
||||
'class' => RotatingFileHandler::class,
|
||||
'level' => Logger::INFO,
|
||||
'filename' => 'data/log/shlink_log.log',
|
||||
'formatter' => 'dashed',
|
||||
'max_files' => 30,
|
||||
],
|
||||
],
|
||||
|
||||
|
@ -45,9 +47,30 @@ return [
|
|||
|
||||
'loggers' => [
|
||||
'Shlink' => [
|
||||
'handlers' => ['shlink_log_handler'],
|
||||
'handlers' => ['shlink_rotating_handler'],
|
||||
'processors' => ['exception_with_new_line', 'psr3'],
|
||||
],
|
||||
'Swoole' => [
|
||||
'handlers' => ['swoole_access_handler'],
|
||||
'processors' => ['psr3'],
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'dependencies' => [
|
||||
'factories' => [
|
||||
'Logger_Shlink' => Common\Factory\LoggerFactory::class,
|
||||
'Logger_Swoole' => Common\Factory\LoggerFactory::class,
|
||||
|
||||
AccessLogInterface::class => Common\Logger\Swoole\AccessLogFactory::class,
|
||||
],
|
||||
],
|
||||
|
||||
'zend-expressive-swoole' => [
|
||||
'swoole-http-server' => [
|
||||
'logger' => [
|
||||
'logger_name' => 'Logger_Swoole',
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ return [
|
|||
|
||||
'logger' => [
|
||||
'handlers' => [
|
||||
'shlink_log_handler' => [
|
||||
'shlink_rotating_handler' => [
|
||||
'level' => Logger::DEBUG,
|
||||
],
|
||||
],
|
||||
|
|
|
@ -23,7 +23,6 @@ return [
|
|||
EntityManager::class => Factory\EntityManagerFactory::class,
|
||||
GuzzleClient::class => InvokableFactory::class,
|
||||
Cache::class => Factory\CacheFactory::class,
|
||||
'Logger_Shlink' => Factory\LoggerFactory::class,
|
||||
Filesystem::class => InvokableFactory::class,
|
||||
Reader::class => ConfigAbstractFactory::class,
|
||||
|
||||
|
|
51
module/Common/src/Logger/Swoole/AccessLogFactory.php
Normal file
51
module/Common/src/Logger/Swoole/AccessLogFactory.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shlinkio\Shlink\Common\Logger\Swoole;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Zend\Expressive\Swoole\Log;
|
||||
use Zend\ServiceManager\Exception\ServiceNotCreatedException;
|
||||
use Zend\ServiceManager\Exception\ServiceNotFoundException;
|
||||
use Zend\ServiceManager\Factory\FactoryInterface;
|
||||
|
||||
class AccessLogFactory implements FactoryInterface
|
||||
{
|
||||
/**
|
||||
* Create an object
|
||||
*
|
||||
* @param ContainerInterface $container
|
||||
* @param string $requestedName
|
||||
* @param null|array $options
|
||||
* @return object
|
||||
* @throws ServiceNotFoundException if unable to resolve the service.
|
||||
* @throws ServiceNotCreatedException if an exception is raised when creating a service.
|
||||
*/
|
||||
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
|
||||
{
|
||||
$config = $container->has('config') ? $container->get('config') : [];
|
||||
$config = $config['zend-expressive-swoole']['swoole-http-server']['logger'] ?? [];
|
||||
|
||||
return new Log\Psr3AccessLogDecorator(
|
||||
$this->getLogger($container, $config),
|
||||
$this->getFormatter($container, $config),
|
||||
$config['use-hostname-lookups'] ?? false
|
||||
);
|
||||
}
|
||||
|
||||
private function getLogger(ContainerInterface $container, array $config): LoggerInterface
|
||||
{
|
||||
$loggerName = $config['logger_name'] ?? LoggerInterface::class;
|
||||
return $container->has($loggerName) ? $container->get($loggerName) : new Log\StdoutLogger();
|
||||
}
|
||||
|
||||
private function getFormatter(ContainerInterface $container, array $config): Log\AccessLogFormatterInterface
|
||||
{
|
||||
if ($container->has(Log\AccessLogFormatterInterface::class)) {
|
||||
return $container->get(Log\AccessLogFormatterInterface::class);
|
||||
}
|
||||
|
||||
return new Log\AccessLogFormatter($config['format'] ?? Log\AccessLogFormatter::FORMAT_COMMON);
|
||||
}
|
||||
}
|
138
module/Common/test/Logger/Swoole/AccessLogFactoryTest.php
Normal file
138
module/Common/test/Logger/Swoole/AccessLogFactoryTest.php
Normal file
|
@ -0,0 +1,138 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ShlinkioTest\Shlink\Common\Logger\Swoole;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use ReflectionObject;
|
||||
use Shlinkio\Shlink\Common\Logger\Swoole\AccessLogFactory;
|
||||
use Zend\Expressive\Swoole\Log\AccessLogFormatter;
|
||||
use Zend\Expressive\Swoole\Log\AccessLogFormatterInterface;
|
||||
use Zend\Expressive\Swoole\Log\Psr3AccessLogDecorator;
|
||||
use Zend\Expressive\Swoole\Log\StdoutLogger;
|
||||
use Zend\ServiceManager\ServiceManager;
|
||||
use function is_string;
|
||||
|
||||
class AccessLogFactoryTest extends TestCase
|
||||
{
|
||||
/** @var AccessLogFactory */
|
||||
private $factory;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->factory = new AccessLogFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function createsService()
|
||||
{
|
||||
$service = ($this->factory)(new ServiceManager(), '');
|
||||
$this->assertInstanceOf(Psr3AccessLogDecorator::class, $service);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider provideLoggers
|
||||
* @param array $config
|
||||
* @param string|LoggerInterface $expectedLogger
|
||||
*/
|
||||
public function wrapsProperLogger(array $config, $expectedLogger)
|
||||
{
|
||||
$service = ($this->factory)(new ServiceManager(['services' => $config]), '');
|
||||
|
||||
$ref = new ReflectionObject($service);
|
||||
$loggerProp = $ref->getProperty('logger');
|
||||
$loggerProp->setAccessible(true);
|
||||
$logger = $loggerProp->getValue($service);
|
||||
|
||||
if (is_string($expectedLogger)) {
|
||||
$this->assertInstanceOf($expectedLogger, $logger);
|
||||
} else {
|
||||
$this->assertSame($expectedLogger, $logger);
|
||||
}
|
||||
}
|
||||
|
||||
public function provideLoggers(): iterable
|
||||
{
|
||||
yield 'without-any-logger' => [[], StdoutLogger::class];
|
||||
yield 'with-standard-logger' => (function () {
|
||||
$logger = new NullLogger();
|
||||
return [[LoggerInterface::class => $logger], $logger];
|
||||
})();
|
||||
yield 'with-custom-logger' => (function () {
|
||||
$logger = new NullLogger();
|
||||
return [[
|
||||
'config' => [
|
||||
'zend-expressive-swoole' => [
|
||||
'swoole-http-server' => [
|
||||
'logger' => [
|
||||
'logger_name' => 'my-logger',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'my-logger' => $logger,
|
||||
], $logger];
|
||||
})();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider provideFormatters
|
||||
* @param array $config
|
||||
* @param string|AccessLogFormatterInterface $expectedFormatter
|
||||
*/
|
||||
public function wrappsProperFormatter(array $config, $expectedFormatter, string $expectedFormat)
|
||||
{
|
||||
$service = ($this->factory)(new ServiceManager(['services' => $config]), '');
|
||||
|
||||
$ref = new ReflectionObject($service);
|
||||
$formatterProp = $ref->getProperty('formatter');
|
||||
$formatterProp->setAccessible(true);
|
||||
$formatter = $formatterProp->getValue($service);
|
||||
|
||||
$ref = new ReflectionObject($formatter);
|
||||
$formatProp = $ref->getProperty('format');
|
||||
$formatProp->setAccessible(true);
|
||||
$format = $formatProp->getValue($formatter);
|
||||
|
||||
if (is_string($expectedFormatter)) {
|
||||
$this->assertInstanceOf($expectedFormatter, $formatter);
|
||||
} else {
|
||||
$this->assertSame($expectedFormatter, $formatter);
|
||||
}
|
||||
$this->assertSame($expectedFormat, $format);
|
||||
}
|
||||
|
||||
public function provideFormatters(): iterable
|
||||
{
|
||||
yield 'with-registered-formatter-and-default-format' => (function () {
|
||||
$formatter = new AccessLogFormatter();
|
||||
return [[AccessLogFormatterInterface::class => $formatter], $formatter, AccessLogFormatter::FORMAT_COMMON];
|
||||
})();
|
||||
yield 'with-registered-formatter-and-custom-format' => (function () {
|
||||
$formatter = new AccessLogFormatter(AccessLogFormatter::FORMAT_AGENT);
|
||||
return [[AccessLogFormatterInterface::class => $formatter], $formatter, AccessLogFormatter::FORMAT_AGENT];
|
||||
})();
|
||||
yield 'with-no-formatter-and-not-configured-format' => [
|
||||
[],
|
||||
AccessLogFormatter::class,
|
||||
AccessLogFormatter::FORMAT_COMMON,
|
||||
];
|
||||
yield 'with-no-formatter-and-configured-format' => [[
|
||||
'config' => [
|
||||
'zend-expressive-swoole' => [
|
||||
'swoole-http-server' => [
|
||||
'logger' => [
|
||||
'format' => AccessLogFormatter::FORMAT_COMBINED_DEBIAN,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
], AccessLogFormatter::class, AccessLogFormatter::FORMAT_COMBINED_DEBIAN];
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue