diff --git a/src/CustomChannel.php b/src/CustomChannel.php index 0b21c8e..bdf9915 100644 --- a/src/CustomChannel.php +++ b/src/CustomChannel.php @@ -57,7 +57,7 @@ public function getHandlers(): array /** * {@inheritdoc} */ - public function pushProcessor($callback): MonologLogger + public function pushProcessor(callable $callback): MonologLogger { return $this->parentLogger->pushProcessor($callback); } @@ -195,7 +195,7 @@ public function addEmergency($message, array $context = []): void * * @return bool Whether the record has been processed */ - public function isHandling($level): bool + public function isHandling(int $level): bool { return $this->parentLogger->isHandling($level); } diff --git a/src/DI/MonologExtension.php b/src/DI/MonologExtension.php index 2a1dd14..beae640 100644 --- a/src/DI/MonologExtension.php +++ b/src/DI/MonologExtension.php @@ -17,14 +17,15 @@ use Kdyby\Monolog\Processor\TracyUrlProcessor; use Kdyby\Monolog\Tracy\BlueScreenRenderer; use Kdyby\Monolog\Tracy\MonologAdapter; +use Nette; use Nette\Configurator; use Nette\DI\Compiler; -use Nette\DI\Config\Helpers; -use Nette\DI\Definitions\ServiceDefinition; use Nette\DI\Helpers as DIHelpers; use Nette\DI\Statement; use Nette\PhpGenerator\ClassType as ClassTypeGenerator; use Nette\PhpGenerator\PhpLiteral; +use Nette\Schema\Expect; +use Nette\Schema\Schema; use Psr\Log\LoggerAwareInterface; use Tracy\Debugger; use Tracy\ILogger; @@ -41,28 +42,29 @@ class MonologExtension extends \Nette\DI\CompilerExtension const TAG_PROCESSOR = 'monolog.processor'; const TAG_PRIORITY = 'monolog.priority'; - /** - * @var mixed[] - */ - private $defaults = [ - 'handlers' => [], - 'processors' => [], - 'name' => 'app', - 'hookToTracy' => TRUE, - 'tracyBaseUrl' => NULL, - 'usePriorityProcessor' => TRUE, - // 'registerFallback' => TRUE, - 'accessPriority' => ILogger::INFO, - ]; + /** @var array */ + protected $config = []; + + public function getConfigSchema(): Schema + { + return Expect::structure([ + 'handlers' => Expect::anyOf(Expect::arrayOf('Nette\DI\Definitions\Statement'), 'false')->default([]), + 'processors' => Expect::anyOf(Expect::arrayOf('Nette\DI\Definitions\Statement'), 'false')->default([]), + 'name' => Expect::string('app'), + 'hookToTracy' => Expect::bool(TRUE), + 'tracyBaseUrl' => Expect::string(), + 'usePriorityProcessor' => Expect::bool(TRUE), + 'accessPriority' => Expect::string(ILogger::INFO), + 'logDir' => Expect::string(), + ])->castTo('array'); + } public function loadConfiguration(): void { $builder = $this->getContainerBuilder(); - - $config = $this->validateConfig($this->defaults); - $config['logDir'] = self::resolveLogDir($builder->parameters); + $this->config['logDir'] = self::resolveLogDir($builder->parameters); + $config = $this->config; self::createDirectory($config['logDir']); - $this->setConfig($config); if (!isset($builder->parameters[$this->name]) || (is_array($builder->parameters[$this->name]) && !isset($builder->parameters[$this->name]['name']))) { $builder->parameters[$this->name]['name'] = $config['name']; @@ -101,6 +103,7 @@ public function loadConfiguration(): void $this->loadHandlers($config); $this->loadProcessors($config); + $this->setConfig($config); } protected function loadHandlers(array $config): void @@ -109,12 +112,9 @@ protected function loadHandlers(array $config): void foreach ($config['handlers'] as $handlerName => $implementation) { - $sd = new ServiceDefinition(); - $sd->setFactory($implementation)->setAutowired(FALSE); - $serviceName = $this->prefix('handler.' . $handlerName); - $builder->addDefinition($serviceName, $sd); - - $builder->getDefinition($serviceName) + $builder->addDefinition($this->prefix('handler.' . $handlerName)) + ->setFactory($implementation) + ->setAutowired(FALSE) ->addTag(self::TAG_HANDLER) ->addTag(self::TAG_PRIORITY, is_numeric($handlerName) ? $handlerName : 0); } @@ -175,17 +175,15 @@ public function beforeCompile(): void $logger->addSetup('pushProcessor', ['@' . $serviceName]); } - // This part of code used deprecated methods, that were removed in Nette 3.0 - // Rewritten so that the output is same as before - $originalConfig = Helpers::merge($this->getConfig(), DIHelpers::expand($this->defaults, $builder->parameters)); - /** @var array $config */ - $config = Helpers::merge($originalConfig, DIHelpers::expand(['registerFallback' => empty($handlers)], $builder->parameters)); + if (empty($handlers) && !array_key_exists('registerFallback', $this->config)) { + $this->config['registerFallback'] = TRUE; + } - if (array_key_exists('registerFallback', $config) && !empty($config['registerFallback'])) { + if (array_key_exists('registerFallback', $this->config) && !empty($this->config['registerFallback'])) { $logger->addSetup('pushHandler', [ new Statement(FallbackNetteHandler::class, [ - 'appName' => $config['name'], - 'logDir' => $config['logDir'], + 'appName' => $this->config['name'], + 'logDir' => $this->config['logDir'], ]), ]); } @@ -214,7 +212,7 @@ public function afterCompile(ClassTypeGenerator $class): void { $initialize = $class->getMethod('initialize'); - if (Debugger::$logDirectory === NULL && isset($this->config['logDir'])) { + if (Debugger::$logDirectory === NULL && array_key_exists('logDir', $this->config)) { $initialize->addBody('?::$logDirectory = ?;', [new PhpLiteral(Debugger::class), $this->config['logDir']]); } } diff --git a/tests/KdybyTests/Monolog/ExtensionTest.phpt b/tests/KdybyTests/Monolog/ExtensionTest.phpt index 0156540..7ea03d6 100644 --- a/tests/KdybyTests/Monolog/ExtensionTest.phpt +++ b/tests/KdybyTests/Monolog/ExtensionTest.phpt @@ -77,6 +77,33 @@ class ExtensionTest extends \Tester\TestCase $logger->addWarning('exception message 1', ['exception' => new \Exception('exception message 1')]); + $logger->addDebug('logger message 5'); + $logger->addDebug('logger message 6', ['channel' => 'custom']); + + $logger->addNotice('logger message 7'); + $logger->addNotice('logger message 8', ['channel' => 'custom']); + + $logger->addCritical('logger message 9'); + $logger->addCritical('logger message 10', ['channel' => 'custom']); + + $logger->addAlert('logger message 11'); + $logger->addAlert('logger message 12', ['channel' => 'custom']); + + $logger->addEmergency('logger message 13'); + $logger->addEmergency('logger message 14', ['channel' => 'custom']); + + $logger->warn('exception message 2', ['exception' => new \Exception('exception message 2')]); + $logger->warn('logger message 16', ['channel' => 'custom']); + + $logger->err('logger message 17'); + $logger->err('logger message 18', ['channel' => 'custom']); + + $logger->crit('logger message 19'); + $logger->crit('logger message 20', ['channel' => 'custom']); + + $logger->emerg('logger message 21'); + $logger->emerg('logger message 22', ['channel' => 'custom']); + Assert::match( '[%a%] tracy message 1 {"at":"%a%"} []' . "\n" . '[%a%] Exception: tracy exception message 2 in %a%:%d% {"at":"%a%","exception":"%a%","tracy_filename":"exception-%a%.html","tracy_created":true} []' . "\n" . @@ -85,24 +112,114 @@ class ExtensionTest extends \Tester\TestCase ); Assert::match( - '[%a%] exception message 1 {"exception":"%a%","tracy_filename":"exception-%a%.html","tracy_created":true} []', + '[%a%] exception message 1 {"exception":"%a%","tracy_filename":"exception-%a%.html","tracy_created":true} []' . "\n" . + '[%a%] exception message 2 {"exception":"%a%","tracy_filename":"exception-%a%.html","tracy_created":true} []', file_get_contents(TEMP_DIR . '/warning.log') ); Assert::match( '[%a%] tracy message 2 {"at":"%a%"} []' . "\n" . '[%a%] Exception: tracy exception message 1 in %a%:%d% {"at":"%a%","exception":"%a%","tracy_filename":"exception-%a%.html","tracy_created":true} []' . "\n" . - '[%a%] logger message 3 [] []', + '[%a%] logger message 3 [] []' . "\n" . + '[%a%] logger message 17 [] []', file_get_contents(TEMP_DIR . '/error.log') ); Assert::match( '[%a%] INFO: logger message 2 [] []' . "\n" . - '[%a%] ERROR: logger message 4 [] []', + '[%a%] ERROR: logger message 4 [] []' . "\n" . + '[%a%] DEBUG: logger message 6 [] []' . "\n" . + '[%a%] NOTICE: logger message 8 [] []' . "\n" . + '[%a%] CRITICAL: logger message 10 [] []' . "\n" . + '[%a%] ALERT: logger message 12 [] []' . "\n" . + '[%a%] EMERGENCY: logger message 14 [] []' . "\n" . + '[%a%] WARNING: logger message 16 [] []' . "\n" . + '[%a%] ERROR: logger message 18 [] []' . "\n" . + '[%a%] CRITICAL: logger message 20 [] []' . "\n" . + '[%a%] EMERGENCY: logger message 22 [] []' . "\n", file_get_contents(TEMP_DIR . '/custom.log') ); - Assert::count(3, glob(TEMP_DIR . '/exception-*.html')); + Assert::match( + '[%a%] logger message 5 [] []' . "\n", + file_get_contents(TEMP_DIR . '/debug.log') + ); + + Assert::match( + '[%a%] logger message 7 [] []' . "\n", + file_get_contents(TEMP_DIR . '/notice.log') + ); + + Assert::match( + '[%a%] logger message 9 [] []' . "\n" . + '[%a%] logger message 19 [] []', + file_get_contents(TEMP_DIR . '/critical.log') + ); + + Assert::match( + '[%a%] logger message 11 [] []' . "\n", + file_get_contents(TEMP_DIR . '/alert.log') + ); + + Assert::match( + '[%a%] logger message 13 [] []' . "\n" . + '[%a%] logger message 21 [] []' . "\n", + file_get_contents(TEMP_DIR . '/emergency.log') + ); + + Assert::count(4, glob(TEMP_DIR . '/exception-*.html')); + + // TEST FOR CUSTOM CHANNEL + + $channel = $logger->channel('test'); + Assert::type('Kdyby\Monolog\CustomChannel', $channel); + Assert::match('test', $channel->getName()); + + $channel->addInfo('custom channel message 1'); + $channel->addError('custom channel message 2'); + $channel->addWarning('custom channel message 3'); + $channel->addDebug('custom channel message 4'); + $channel->addNotice('custom channel message 5'); + $channel->addCritical('custom channel message 6'); + $channel->addAlert('custom channel message 7'); + $channel->addEmergency('custom channel message 8'); + + $channel->debug('custom channel message 9'); + $channel->info('custom channel message 10'); + $channel->notice('custom channel message 11'); + $channel->warn('custom channel message 12'); + $channel->warning('custom channel message 13'); + $channel->err('custom channel message 14'); + $channel->error('custom channel message 15'); + $channel->crit('custom channel message 16'); + $channel->critical('custom channel message 17'); + $channel->alert('custom channel message 18'); + $channel->emerg('custom channel message 19'); + $channel->emergency('custom channel message 20'); + + Assert::match( + '[%a%] INFO: custom channel message 1 [] []' . "\n" . + '[%a%] ERROR: custom channel message 2 [] []' . "\n" . + '[%a%] WARNING: custom channel message 3 [] []' . "\n" . + '[%a%] DEBUG: custom channel message 4 [] []' . "\n" . + '[%a%] NOTICE: custom channel message 5 [] []' . "\n" . + '[%a%] CRITICAL: custom channel message 6 [] []' . "\n" . + '[%a%] ALERT: custom channel message 7 [] []' . "\n" . + '[%a%] EMERGENCY: custom channel message 8 [] []' . "\n" . + '[%a%] DEBUG: custom channel message 9 [] []' . "\n" . + '[%a%] INFO: custom channel message 10 [] []' . "\n" . + '[%a%] NOTICE: custom channel message 11 [] []' . "\n" . + '[%a%] WARNING: custom channel message 12 [] []' . "\n" . + '[%a%] WARNING: custom channel message 13 [] []' . "\n" . + '[%a%] ERROR: custom channel message 14 [] []' . "\n" . + '[%a%] ERROR: custom channel message 15 [] []' . "\n" . + '[%a%] CRITICAL: custom channel message 16 [] []' . "\n" . + '[%a%] CRITICAL: custom channel message 17 [] []' . "\n" . + '[%a%] ALERT: custom channel message 18 [] []' . "\n" . + '[%a%] EMERGENCY: custom channel message 19 [] []' . "\n" . + '[%a%] EMERGENCY: custom channel message 20 [] []' . "\n", + file_get_contents(TEMP_DIR . '/test.log') + ); } public function testHandlersSorting()