diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a70bbd3..7ed1f3d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Fixed psr-3 processing being applied to all handlers, only leaf ones are now processing * Fixed regression when `app` channel is defined explicitly * Fixed handlers marked as nested not being ignored properly from the stack +* Added support for Redis configuration ## 3.3.1 (2018-11-04) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index ff023175..4eea7fe1 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -88,6 +88,21 @@ * - [level]: level name or int value, defaults to DEBUG * - [bubble]: bool, defaults to true * + * - redis: + * - redis: + * - id: optional if host is given + * - host: 127.0.0.1 + * - password: null + * - port: 6379 + * - database: 0 + * - key_name: monolog_redis + * + * - predis: + * - redis: + * - id: optional if host is given + * - host: tcp://10.0.0.1:6379 + * - key_name: monolog_redis + * * - fingers_crossed: * - handler: the wrapped handler's name * - [action_level|activation_strategy]: minimum level or service id to activate the handler, defaults to WARNING @@ -522,6 +537,44 @@ public function getConfigTreeBuilder() ->scalarNode('index')->defaultValue('monolog')->end() // elasticsearch ->scalarNode('document_type')->defaultValue('logs')->end() // elasticsearch ->scalarNode('ignore_error')->defaultValue(false)->end() // elasticsearch + ->arrayNode('redis') + ->canBeUnset() + ->beforeNormalization() + ->ifString() + ->then(function ($v) { return array('id' => $v); }) + ->end() + ->children() + ->scalarNode('id')->end() + ->scalarNode('host')->end() + ->scalarNode('password')->defaultNull()->end() + ->scalarNode('port')->defaultValue(6379)->end() + ->scalarNode('database')->defaultValue(0)->end() + ->scalarNode('key_name')->defaultValue('monolog_redis')->end() + ->end() + ->validate() + ->ifTrue(function ($v) { + return !isset($v['id']) && !isset($v['host']); + }) + ->thenInvalid('What must be set is either the host or the service id of the Redis client.') + ->end() + ->end() // redis + ->arrayNode('predis') + ->canBeUnset() + ->beforeNormalization() + ->ifString() + ->then(function ($v) { return array('id' => $v); }) + ->end() + ->children() + ->scalarNode('id')->end() + ->scalarNode('host')->end() + ->end() + ->validate() + ->ifTrue(function ($v) { + return !isset($v['id']) && !isset($v['host']); + }) + ->thenInvalid('What must be set is either the host or the service id of the Predis client.') + ->end() + ->end() // predis ->arrayNode('config') ->canBeUnset() ->prototype('scalar')->end() @@ -849,6 +902,14 @@ public function getConfigTreeBuilder() ->ifTrue(function ($v) { return 'server_log' === $v['type'] && empty($v['host']); }) ->thenInvalid('The host has to be specified to use a ServerLogHandler') ->end() + ->validate() + ->ifTrue(function ($v) { return 'redis' === $v['type'] && empty($v['redis']); }) + ->thenInvalid('The host has to be specified to use a RedisLogHandler') + ->end() + ->validate() + ->ifTrue(function ($v) { return 'predis' === $v['type'] && empty($v['redis']); }) + ->thenInvalid('The host has to be specified to use a RedisLogHandler') + ->end() ->end() ->validate() ->ifTrue(function ($v) { return isset($v['debug']); }) diff --git a/DependencyInjection/MonologExtension.php b/DependencyInjection/MonologExtension.php index 14b00662..ab8ca555 100644 --- a/DependencyInjection/MonologExtension.php +++ b/DependencyInjection/MonologExtension.php @@ -311,6 +311,43 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler $handler['bubble'], )); break; + case 'redis': + case 'predis': + if (isset($handler['redis']['id'])) { + $clientId = $handler['redis']['id']; + } elseif ('redis' === $handler['type']) { + if (!class_exists(\Redis::class)) { + throw new \RuntimeException('The \Redis class is not available.'); + } + + $client = new Definition(\Redis::class); + $client->addMethodCall('connect', array($handler['redis']['host'], $handler['redis']['port'])); + $client->addMethodCall('auth', array($handler['redis']['password'])); + $client->addMethodCall('select', array($handler['redis']['database'])); + $client->setPublic(false); + $clientId = uniqid('monolog.redis.client.', true); + $container->setDefinition($clientId, $client); + } else { + if (!class_exists(\Predis\Client::class)) { + throw new \RuntimeException('The \Predis\Client class is not available.'); + } + + $client = new Definition(\Predis\Client::class); + $client->setArguments(array( + $handler['redis']['host'], + )); + $client->setPublic(false); + + $clientId = uniqid('monolog.predis.client.', true); + $container->setDefinition($clientId, $client); + } + $definition->setArguments(array( + new Reference($clientId), + $handler['redis']['key_name'], + $handler['level'], + $handler['bubble'], + )); + break; case 'chromephp': $definition->setArguments(array( @@ -835,6 +872,8 @@ private function getHandlerClassByType($handlerType) 'mongo' => 'Monolog\Handler\MongoDBHandler', 'elasticsearch' => 'Monolog\Handler\ElasticSearchHandler', 'server_log' => 'Symfony\Bridge\Monolog\Handler\ServerLogHandler', + 'redis' => 'Monolog\Handler\RedisHandler', + 'predis' => 'Monolog\Handler\RedisHandler', ); if (!isset($typeToClassMapping[$handlerType])) { diff --git a/Resources/config/schema/monolog-1.0.xsd b/Resources/config/schema/monolog-1.0.xsd index 137df65e..cf0eac87 100644 --- a/Resources/config/schema/monolog-1.0.xsd +++ b/Resources/config/schema/monolog-1.0.xsd @@ -157,6 +157,20 @@ + + + + + + + + + + + + + + diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index a59c75d6..aa7a5b3c 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -362,6 +362,50 @@ public function testWithNestedHandler() $this->assertTrue($config['handlers']['foobar']['nested']); } + public function testWithRedisHandler() + { + $configs = array( + array( + 'handlers' => array( + 'redis' => array( + 'type' => 'redis', + 'redis' => array( + 'host' => '127.0.1.1', + 'password' => 'pa$$w0rd', + 'port' => 1234, + 'database' => 1, + 'key_name' => 'monolog_redis_test' + ) + ) + ) + ) + ); + $config = $this->process($configs); + + $this->assertEquals('127.0.1.1', $config['handlers']['redis']['redis']['host']); + $this->assertEquals('pa$$w0rd', $config['handlers']['redis']['redis']['password']); + $this->assertEquals(1234, $config['handlers']['redis']['redis']['port']); + $this->assertEquals(1, $config['handlers']['redis']['redis']['database']); + $this->assertEquals('monolog_redis_test', $config['handlers']['redis']['redis']['key_name']); + + $configs = array( + array( + 'handlers' => array( + 'redis' => array( + 'type' => 'predis', + 'redis' => array( + 'host' => '127.0.1.1', + 'key_name' => 'monolog_redis_test' + ) + ) + ) + ) + ); + $config = $this->process($configs); + + $this->assertEquals('127.0.1.1', $config['handlers']['redis']['redis']['host']); + $this->assertEquals('monolog_redis_test', $config['handlers']['redis']['redis']['key_name']); + } /** * Processes an array of configurations and returns a compiled version.