Skip to content

Commit

Permalink
feature #357 Set log level from parameter or envvar. (dbrumann)
Browse files Browse the repository at this point in the history
This PR was merged into the 3.x-dev branch.

Discussion
----------

Set log level from parameter or envvar.

This PR is yet another attempt at solving issue #220, just like #245 and #289 before.

Sorry, for opening yet another PR for this, but since there wasn't much activity I figured I give it a go.

Commits
-------

541e6e5 Allow log level from envvar or parameter
  • Loading branch information
lyrixx committed Oct 6, 2020
2 parents 365b6fa + 541e6e5 commit e495f5c
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 10 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
@@ -1,6 +1,7 @@
## 3.6.0 (xxxx-xx-xx)

* Add support for Symfony Mailer
* Added support for Symfony Mailer
* Added support for setting log levels from parameters or environment variables

## 3.5.0 (2019-11-13)

Expand Down
39 changes: 31 additions & 8 deletions DependencyInjection/MonologExtension.php
Expand Up @@ -23,6 +23,7 @@
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
Expand All @@ -41,9 +42,31 @@ class MonologExtension extends Extension

private $swiftMailerHandlers = [];

private function levelToMonologConst($level)
private function levelToMonologConst($level, ContainerBuilder $container)
{
return is_int($level) ? $level : constant('Monolog\Logger::'.strtoupper($level));
if (null === $level || is_numeric($level)) {
return $level;
}

if (defined('Monolog\Logger::'.strtoupper($level))) {
return constant('Monolog\Logger::' . strtoupper($level));
}

if ($container->hasParameter($level)) {
return $this->levelToMonologConst($container->getParameter($level), $container);
}

try {
$logLevel = $container->resolveEnvPlaceholders($level, true);
} catch (ParameterNotFoundException $notFoundException) {
throw new \InvalidArgumentException(sprintf('Could not match "%s" to a log level.', $level));
}

if ($logLevel !== '') {
return $this->levelToMonologConst($logLevel, $container);
}

throw new \InvalidArgumentException(sprintf('Could not match "%s" to a log level.', $level));
}

/**
Expand Down Expand Up @@ -169,7 +192,7 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
$handlerClass = $this->getHandlerClassByType($handler['type']);
$definition = new Definition($handlerClass);

$handler['level'] = $this->levelToMonologConst($handler['level']);
$handler['level'] = $this->levelToMonologConst($handler['level'], $container);

if ($handler['include_stacktraces']) {
$definition->setConfigurator(['Symfony\\Bundle\\MonologBundle\\MonologBundle', 'includeStacktraces']);
Expand Down Expand Up @@ -383,9 +406,9 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
break;

case 'fingers_crossed':
$handler['action_level'] = $this->levelToMonologConst($handler['action_level']);
$handler['action_level'] = $this->levelToMonologConst($handler['action_level'], $container);
if (null !== $handler['passthru_level']) {
$handler['passthru_level'] = $this->levelToMonologConst($handler['passthru_level']);
$handler['passthru_level'] = $this->levelToMonologConst($handler['passthru_level'], $container);
}
$nestedHandlerId = $this->getHandlerId($handler['handler']);
$this->markNestedHandler($nestedHandlerId);
Expand Down Expand Up @@ -429,10 +452,10 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
break;

case 'filter':
$handler['min_level'] = $this->levelToMonologConst($handler['min_level']);
$handler['max_level'] = $this->levelToMonologConst($handler['max_level']);
$handler['min_level'] = $this->levelToMonologConst($handler['min_level'], $container);
$handler['max_level'] = $this->levelToMonologConst($handler['max_level'], $container);
foreach (array_keys($handler['accepted_levels']) as $k) {
$handler['accepted_levels'][$k] = $this->levelToMonologConst($handler['accepted_levels'][$k]);
$handler['accepted_levels'][$k] = $this->levelToMonologConst($handler['accepted_levels'][$k], $container);
}

$nestedHandlerId = $this->getHandlerId($handler['handler']);
Expand Down
87 changes: 86 additions & 1 deletion Tests/DependencyInjection/MonologExtensionTest.php
Expand Up @@ -18,6 +18,7 @@
use Symfony\Bundle\MonologBundle\DependencyInjection\Compiler\LoggerChannelPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\HttpFoundation\RequestStack;
Expand Down Expand Up @@ -611,10 +612,94 @@ public function v1AddedDataProvider()
];
}

public function testLogLevelfromInvalidparameterThrowsException()
{
$container = new ContainerBuilder();
$loader = new MonologExtension();
$config = [['handlers' => ['main' => ['type' => 'stream', 'level' => '%some_param%']]]];

protected function getContainer(array $config = [], array $thirdPartyDefinitions = [])
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Could not match "%some_param%" to a log level.');

$loader->load($config, $container);
}

/**
* @dataProvider provideLoglevelParameterConfig
*/
public function testLogLevelfromParameter(array $parameters, array $config, $expectedClass, array $expectedArgs)
{
$container = new ContainerBuilder();
foreach ($parameters as $name => $value) {
$container->setParameter($name, $value);
}
$loader = new MonologExtension();
$config = [['handlers' => ['main' => $config]]];
$loader->load($config, $container);

$definition = $container->getDefinition('monolog.handler.main');
$this->assertDICDefinitionClass($definition, $expectedClass);
$this->assertDICConstructorArguments($definition, $expectedArgs);
}

public function provideLoglevelParameterConfig()
{
return [
'browser console with parameter level' => [
['%log_level%' => 'info'],
['type' => 'browser_console', 'level' => '%log_level%'],
'Monolog\Handler\BrowserConsoleHandler',
[200, true]
],
'browser console with envvar level' => [
['%env(LOG_LEVEL)%' => 'info'],
['type' => 'browser_console', 'level' => '%env(LOG_LEVEL)%'],
'Monolog\Handler\BrowserConsoleHandler',
[200, true]
],
'stream with envvar level null or "~" (in yaml config)' => [
['%env(LOG_LEVEL)%' => null],
['type' => 'stream', 'level' => '%env(LOG_LEVEL)%'],
'Monolog\Handler\StreamHandler',
[
'%kernel.logs_dir%/%kernel.environment%.log',
null,
true,
null,
false,
]
],
'stream with envvar level' => [
['%env(LOG_LEVEL)%' => '400'],
['type' => 'stream', 'level' => '%env(LOG_LEVEL)%'],
'Monolog\Handler\StreamHandler',
[
'%kernel.logs_dir%/%kernel.environment%.log',
400,
true,
null,
false,
]
],
'stream with envvar and fallback parameter' => [
['%env(LOG_LEVEL)%' => '500', '%log_level%' => '%env(LOG_LEVEL)%'],
['type' => 'stream', 'level' => '%log_level%'],
'Monolog\Handler\StreamHandler',
[
'%kernel.logs_dir%/%kernel.environment%.log',
500,
true,
null,
false,
]
],
];
}


protected function getContainer(array $config = [], array $thirdPartyDefinitions = [])
{
$container = new ContainerBuilder(new EnvPlaceholderParameterBag());
foreach ($thirdPartyDefinitions as $id => $definition) {
$container->setDefinition($id, $definition);
}
Expand Down

0 comments on commit e495f5c

Please sign in to comment.