Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to log to redis #292

Closed
wants to merge 44 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
00ed2f3
Add stream handler lock option
mRoca Dec 7, 2017
9f6f0b6
Allow setting "ident" parameter for SyslogUdpHandler, affects #266
dhirtzbruch May 5, 2018
86fd51e
Support environment option for raven client
Taluu Jun 12, 2018
a3790d9
add support for redis
Oct 15, 2018
7fdda67
Register processors for autoconfiguration
nicolas-grekas Nov 10, 2018
d24abd1
Merge branch 'master' of https://github.com/symfony/monolog-bundle
Jan 3, 2019
24291fb
Remove duplicate entry
B-Galati Jan 16, 2019
523768f
minor #293 Remove duplicate entry (B-Galati)
lyrixx Jan 31, 2019
cc9abf6
Expose configuration for the ConsoleHandler
lyrixx Feb 22, 2019
005aefb
feature #297 Expose configuration for the ConsoleHandler (lyrixx)
lyrixx Mar 12, 2019
981d74f
Fix typo in PhpDoc
jdreesen May 2, 2019
969e476
feature #285 Register processors for autoconfiguration (nicolas-grekas)
lyrixx May 16, 2019
962a2e1
minor #301 Fix typo in PhpDoc (jdreesen)
lyrixx May 16, 2019
366f692
Flush loggers on kernel.reset
dnna Sep 9, 2018
6684794
feature #279 Flush loggers on kernel.reset (dnna)
lyrixx May 16, 2019
a7c1046
Fixed CS and CHANGELOG
lyrixx May 16, 2019
f6c8593
Deprecrate "excluded_404s" option
geoffrey-brier Jul 26, 2018
d810fcc
feature #302 Deprecate "excluded_404s" option (geoffrey-brier)
lyrixx May 16, 2019
9f8e531
Fixed PHPUnit Warning
lyrixx May 16, 2019
c720aab
feature #270 Support environment option for raven client (Taluu)
lyrixx May 16, 2019
b97e237
feature #267 Allow setting "ident" parameter for SyslogUdpHandler, af…
lyrixx May 16, 2019
a6c3267
feature #303 Fixed PHPUnit Warning (lyrixx)
lyrixx May 16, 2019
036cd4b
feature #242 Add stream handler lock option (mRoca)
lyrixx May 16, 2019
2e0714e
add better explanation of wat an id is
May 28, 2019
100cfde
fix handler key not correct
May 28, 2019
a143416
add support for redis
Oct 15, 2018
f07d51b
add better explanation of wat an id is
May 28, 2019
9c992e1
fix handler key not correct
May 28, 2019
efc4265
Merge branch 'add-redis-config-support' of https://github.com/ruudvdd…
Jun 3, 2019
b43daff
fix exception messages when a certain redis class does not exist
Jun 3, 2019
7a1dcab
add changelog rule
Jun 3, 2019
56709bc
add enter between types
Jun 3, 2019
e2fc27d
change back type and fix configuration
Jun 3, 2019
5448621
add support for redis
Oct 15, 2018
4a01df8
add better explanation of wat an id is
May 28, 2019
eabdb9c
fix handler key not correct
May 28, 2019
ad6b37f
add support for redis
Oct 15, 2018
e23d1ff
add better explanation of wat an id is
May 28, 2019
d1ca48b
fix handler key not correct
May 28, 2019
2e09bfd
fix exception messages when a certain redis class does not exist
Jun 3, 2019
5d8ee96
add changelog rule
Jun 3, 2019
ec0dc0c
add enter between types
Jun 3, 2019
7a012af
change back type and fix configuration
Jun 3, 2019
dee6679
Merge branch 'add-redis-config-support' of https://github.com/ruudvdd…
Jun 3, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion .travis.yml
Expand Up @@ -24,9 +24,10 @@ matrix:
env: SYMFONY_VERSION="2.8.*"
- php: 5.6
env: SYMFONY_VERSION="3.4.*" DEPENDENCIES=dev
- php: 7.1
- php: 7.0
- php: 7.1
# There is a bug in PHPUnit 5.7
env: SYMFONY_PHPUNIT_VERSION=6.5
- php: 7.2
- php: 7.3
# Test against dev versions
Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG.md
@@ -1,8 +1,13 @@
## 3.3.2 (2018-12-29)
## 3.4.0 (xxxx-xx-xx)

* Deprecate "excluded_404s" option
* Flush loggers on `kernel.reset`
* Register processors (`ProcessorInterface`) for autoconfiguration (tag: `monolog.processor`)
* Expose configuration for the `ConsoleHandler`
* 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 configuration support for Redis

## 3.3.1 (2018-11-04)

Expand All @@ -14,6 +19,7 @@
* Added timeouts to the pushover, hipchat, slack handlers
* Dropped support for PHP 5.3, 5.4, and HHVM
* Added configuration for HttpCodeActivationStrategy
* Deprecated "excluded_404s" option for Symfony >= 3.4

## 3.2.0 (2018-03-05)

Expand Down
81 changes: 79 additions & 2 deletions DependencyInjection/Configuration.php
Expand Up @@ -31,11 +31,14 @@
* - path: string
* - [level]: level name or int value, defaults to DEBUG
* - [bubble]: bool, defaults to true
* - [file_permission]: int|null, defaults to null (0644)
* - [use_locking]: bool, defaults to false
*
* - console:
* - [verbosity_levels]: level => verbosity configuration
* - [level]: level name or int value, defaults to DEBUG
* - [bubble]: bool, defaults to true
* - [console_formater_options]: array
*
* - firephp:
* - [level]: level name or int value, defaults to DEBUG
Expand Down Expand Up @@ -85,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
Expand All @@ -110,7 +128,7 @@
* - [flush_on_overflow]: bool, defaults to false
*
* - deduplication:
* - handler: the wrapper handler's name
* - handler: the wrapped handler's name
* - [store]: The file/path where the deduplication log should be kept, defaults to %kernel.cache_dir%/monolog_dedup_*
* - [deduplication_level]: The minimum logging level for log records to be looked at for deduplication purposes, defaults to ERROR
* - [time]: The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through, defaults to 60
Expand Down Expand Up @@ -138,6 +156,7 @@
* - [logopts]: defaults to LOG_PID
* - [level]: level name or int value, defaults to DEBUG
* - [bubble]: bool, defaults to true
* - [ident]: string, defaults to
*
* - swift_mailer:
* - from_email: optional if email_prototype is given
Expand Down Expand Up @@ -359,9 +378,10 @@ public function getConfigTreeBuilder()
})
->end()
->end()
->booleanNode('use_locking')->defaultFalse()->end() // stream
->scalarNode('filename_format')->defaultValue('{filename}-{date}')->end() //rotating
->scalarNode('date_format')->defaultValue('Y-m-d')->end() //rotating
->scalarNode('ident')->defaultFalse()->end() // syslog
->scalarNode('ident')->defaultFalse()->end() // syslog and syslogudp
->scalarNode('logopts')->defaultValue(LOG_PID)->end() // syslog
->scalarNode('facility')->defaultValue('user')->end() // syslog
->scalarNode('max_files')->defaultValue(0)->end() // rotating
Expand Down Expand Up @@ -517,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()
Expand Down Expand Up @@ -560,6 +618,7 @@ public function getConfigTreeBuilder()
->scalarNode('client_id')->defaultNull()->end() // raven_handler
->scalarNode('auto_log_stacks')->defaultFalse()->end() // raven_handler
->scalarNode('release')->defaultNull()->end() // raven_handler
->scalarNode('environment')->defaultNull()->end() // raven_handler
->scalarNode('message_type')->defaultValue(0)->end() // error_log
->arrayNode('tags') // loggly
->beforeNormalization()
Expand All @@ -571,6 +630,16 @@ public function getConfigTreeBuilder()
->then(function ($v) { return array_filter(array_map('trim', $v)); })
->end()
->prototype('scalar')->end()
->end()
// console
->variableNode('console_formater_options')
->defaultValue([])
->validate()
->ifTrue(function ($v) {
return !is_array($v);
})
->thenInvalid('console_formater_options must an array.')
->end()
->end()
->arrayNode('verbosity_levels') // console
->beforeNormalization()
Expand Down Expand Up @@ -833,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']); })
Expand Down
79 changes: 77 additions & 2 deletions DependencyInjection/MonologExtension.php
Expand Up @@ -11,6 +11,13 @@

namespace Symfony\Bundle\MonologBundle\DependencyInjection;

use Monolog\Processor\ProcessorInterface;
use Monolog\ResettableInterface;
use Predis;
use Redis;
use Symfony\Bridge\Monolog\Handler\FingersCrossed\HttpCodeActivationStrategy;
use Symfony\Bridge\Monolog\Processor\TokenProcessor;
use Symfony\Bridge\Monolog\Processor\WebProcessor;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\ContainerBuilder;
Expand Down Expand Up @@ -108,6 +115,18 @@ public function load(array $configs, ContainerBuilder $container)
}

$container->setParameter('monolog.additional_channels', isset($config['channels']) ? $config['channels'] : array());

if (method_exists($container, 'registerForAutoconfiguration')) {
if (interface_exists(ProcessorInterface::class)) {
$container->registerForAutoconfiguration(ProcessorInterface::class)
->addTag('monolog.processor');
} else {
$container->registerForAutoconfiguration(WebProcessor::class)
->addTag('monolog.processor');
}
$container->registerForAutoconfiguration(TokenProcessor::class)
->addTag('monolog.processor');
}
}

/**
Expand Down Expand Up @@ -138,7 +157,8 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
return $handlerId;
}

$definition = new Definition($this->getHandlerClassByType($handler['type']));
$handlerClass = $this->getHandlerClassByType($handler['type']);
$definition = new Definition($handlerClass);

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

Expand Down Expand Up @@ -168,6 +188,7 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
$handler['level'],
$handler['bubble'],
$handler['file_permission'],
$handler['use_locking'],
));
break;

Expand All @@ -176,6 +197,7 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
null,
$handler['bubble'],
isset($handler['verbosity_levels']) ? $handler['verbosity_levels'] : array(),
$handler['console_formater_options']
));
$definition->addTag('kernel.event_subscriber');
break;
Expand Down Expand Up @@ -291,6 +313,43 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
$handler['bubble'],
));
break;
case 'redis':
case 'predis':
lyrixx marked this conversation as resolved.
Show resolved Hide resolved
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');
$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');
$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(
Expand Down Expand Up @@ -325,6 +384,9 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
if (isset($handler['activation_strategy'])) {
$activation = new Reference($handler['activation_strategy']);
} elseif (!empty($handler['excluded_404s'])) {
if (class_exists(HttpCodeActivationStrategy::class)) {
@trigger_error('The "excluded_404s" option is deprecated in MonologBundle since version 3.4.0, you should rely on the "excluded_http_codes" option instead.', E_USER_DEPRECATED);
}
$activationDef = new Definition('Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy', array(
new Reference('request_stack'),
$handler['excluded_404s'],
Expand Down Expand Up @@ -436,6 +498,9 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
$handler['level'],
$handler['bubble'],
));
if ($handler['ident']) {
$definition->addArgument($handler['ident']);
}
break;

case 'swift_mailer':
Expand Down Expand Up @@ -613,7 +678,10 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
} else {
$client = new Definition('Raven_Client', array(
$handler['dsn'],
array('auto_log_stacks' => $handler['auto_log_stacks'])
array(
'auto_log_stacks' => $handler['auto_log_stacks'],
'environment' => $handler['environment']
)
));
$client->setPublic(false);
$clientId = 'monolog.raven.client.'.sha1($handler['dsn']);
Expand Down Expand Up @@ -741,6 +809,11 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
if (!empty($handler['formatter'])) {
$definition->addMethodCall('setFormatter', array(new Reference($handler['formatter'])));
}

if (!in_array($handlerId, $this->nestedHandlers) && is_subclass_of($handlerClass, ResettableInterface::class)) {
$definition->addTag('kernel.reset', array('method' => 'reset'));
}

$container->setDefinition($handlerId, $definition);

return $handlerId;
Expand Down Expand Up @@ -801,6 +874,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])) {
Expand Down
15 changes: 15 additions & 0 deletions Resources/config/schema/monolog-1.0.xsd
Expand Up @@ -34,6 +34,7 @@
<xsd:attribute name="level" type="level" />
<xsd:attribute name="bubble" type="xsd:boolean" />
<xsd:attribute name="process-psr-3-messages" type="xsd:boolean" />
<xsd:attribute name="use_locking" type="xsd:boolean" />
<xsd:attribute name="app-name" type="xsd:string" />
<xsd:attribute name="path" type="xsd:string" />
<xsd:attribute name="id" type="xsd:string" />
Expand Down Expand Up @@ -156,6 +157,20 @@
<xsd:attribute name="collection" type="xsd:string" />
</xsd:complexType>

<xsd:complexType name="redis">
<xsd:attribute name="id" type="xsd:string" />
<xsd:attribute name="host" type="xsd:string" />
<xsd:attribute name="password" type="xsd:string" />
<xsd:attribute name="port" type="xsd:integer" />
<xsd:attribute name="database" type="xsd:integer" />
<xsd:attribute name="key_name" type="xsd:string" />
</xsd:complexType>

<xsd:complexType name="predis">
<xsd:attribute name="id" type="xsd:string" />
<xsd:attribute name="host" type="xsd:string" />
</xsd:complexType>

<xsd:complexType name="elasticsearch">
<xsd:attribute name="id" type="xsd:string" />
<xsd:attribute name="host" type="xsd:string" />
Expand Down
3 changes: 3 additions & 0 deletions Tests/DependencyInjection/Compiler/LoggerChannelPassTest.php
Expand Up @@ -140,6 +140,9 @@ public function testChannelsConfigurationOptionSupportsAppChannel()

$container->setParameter('monolog.additional_channels', array('app'));
$container->compile();

// the test ensures that the validation does not fail (i.e. it does not throw any exceptions)
$this->addToAssertionCount(1);
}

private function getContainer()
Expand Down