From 87781ebcb43d2ccb5ba6422b43c2fa5bd9233651 Mon Sep 17 00:00:00 2001 From: Jeremy Kitchen Date: Mon, 11 Feb 2013 17:39:35 -0800 Subject: [PATCH 1/3] adds a redis handler This is useful when used in conjuction with the LogstashFormatter, but should also be useful for any formatter where $message["formatted"] is a string. --- src/Monolog/Handler/RedisHandler.php | 59 ++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/Monolog/Handler/RedisHandler.php diff --git a/src/Monolog/Handler/RedisHandler.php b/src/Monolog/Handler/RedisHandler.php new file mode 100644 index 00000000..a4b8380c --- /dev/null +++ b/src/Monolog/Handler/RedisHandler.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\Logger; +use Monolog\Formatter\LogstashFormatter; +use Predis\Client; + +/** + * Logs to a Redis key using rpush + * + * usage example: + * + * $log = new Logger('application'); + * $redis = new RedisHandler(new Predis\Client("tcp://localhost:6379"), "logs", "prod"); + * $log->pushHandler($redis); + * + * @author Thomas Tourlourat + */ +class RedisHandler extends AbstractProcessingHandler +{ + private $redisClient; + private $redisKey; + + # redis instance, key to use + public function __construct($redis, $key, $level = Logger::DEBUG, $bubble = true) + { + if (!($redis instanceof Client)) { + throw new \InvalidArgumentException('Predis\Client instance required'); + } + + $this->redisClient = $redis; + $this->redisKey = $key; + + parent::__construct($level, $bubble); + } + + protected function write(array $record) + { + $this->redisClient->rpush($this->redisKey, $record["formatted"]); + } + + /** + * {@inheritDoc} + */ + protected function getDefaultFormatter() + { + return new LogstashFormatter(); + } +} From e987508d062370b68fb3d3074c9a42e27393bc2c Mon Sep 17 00:00:00 2001 From: Jeremy Kitchen Date: Tue, 12 Feb 2013 13:28:14 -0800 Subject: [PATCH 2/3] \Redis support and LineFormatter as default per #161, this adds support for \Redis as well as switches the defaultFormatter out to use LineFormatter instead. --- src/Monolog/Handler/RedisHandler.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Monolog/Handler/RedisHandler.php b/src/Monolog/Handler/RedisHandler.php index a4b8380c..d916939c 100644 --- a/src/Monolog/Handler/RedisHandler.php +++ b/src/Monolog/Handler/RedisHandler.php @@ -12,8 +12,7 @@ namespace Monolog\Handler; use Monolog\Logger; -use Monolog\Formatter\LogstashFormatter; -use Predis\Client; +use Monolog\Formatter\LineFormatter; /** * Logs to a Redis key using rpush @@ -34,8 +33,8 @@ class RedisHandler extends AbstractProcessingHandler # redis instance, key to use public function __construct($redis, $key, $level = Logger::DEBUG, $bubble = true) { - if (!($redis instanceof Client)) { - throw new \InvalidArgumentException('Predis\Client instance required'); + if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) { + throw new \InvalidArgumentException('Predis\Client or Redis instance required'); } $this->redisClient = $redis; @@ -46,7 +45,11 @@ class RedisHandler extends AbstractProcessingHandler protected function write(array $record) { - $this->redisClient->rpush($this->redisKey, $record["formatted"]); + if ($this->redisClient instanceof \Predis\Client) { + $this->redisClient->rpush($this->redisKey, $record["formatted"]); + } else { + $this->redisClient->rPush($this->redisKey, $record["formatted"]); + } } /** @@ -54,6 +57,6 @@ class RedisHandler extends AbstractProcessingHandler */ protected function getDefaultFormatter() { - return new LogstashFormatter(); + return new LineFormatter(); } } From a463cdcf91570ec56b7c75669a5f856c03807ff2 Mon Sep 17 00:00:00 2001 From: Jeremy Kitchen Date: Tue, 12 Feb 2013 17:45:34 -0800 Subject: [PATCH 3/3] unit test for RedisHandler and README.md update * updated README.md to inform users of RedisHandler * added unit test for RedisHandler --- README.mdown | 1 + tests/Monolog/Handler/RedisHandlerTest.php | 71 ++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 tests/Monolog/Handler/RedisHandlerTest.php diff --git a/README.mdown b/README.mdown index 4489b4f7..694c7be6 100644 --- a/README.mdown +++ b/README.mdown @@ -126,6 +126,7 @@ Handlers - _DoctrineCouchDBHandler_: Logs records to a CouchDB server via the Doctrine CouchDB ODM. - _RavenHandler_: Logs records to a [Sentry](http://getsentry.com/) server using [raven](https://packagist.org/packages/raven/raven). +- _RedisHandlen_: Logs records to a [redis](http://redis.io) server. Wrappers / Special Handlers --------------------------- diff --git a/tests/Monolog/Handler/RedisHandlerTest.php b/tests/Monolog/Handler/RedisHandlerTest.php new file mode 100644 index 00000000..3629f8a2 --- /dev/null +++ b/tests/Monolog/Handler/RedisHandlerTest.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Handler; + +use Monolog\TestCase; +use Monolog\Logger; +use Monolog\Formatter\LineFormatter; + +class RedisHandlerTest extends TestCase +{ + /** + * @expectedException InvalidArgumentException + */ + public function testConstructorShouldThrowExceptionForInvalidRedis() + { + new RedisHandler(new \stdClass(), 'key'); + } + + public function testConstructorShouldWorkWithPredis() + { + $redis = $this->getMock('Predis\Client'); + $this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key')); + } + + public function testConstructorShouldWorkWithRedis() + { + $redis = $this->getMock('Redis'); + $this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key')); + } + + public function testPredisHandle() + { + $redis = $this->getMock('Predis\Client', array('rpush')); + + // Predis\Client uses rpush + $redis->expects($this->once()) + ->method('rpush') + ->with('key', 'test'); + + $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); + + $handler = new RedisHandler($redis, 'key'); + $handler->setFormatter(new LineFormatter("%message%")); + $handler->handle($record); + } + + public function testRedisHandle() + { + $redis = $this->getMock('Redis', array('rpush')); + + // Redis uses rPush + $redis->expects($this->once()) + ->method('rPush') + ->with('key', 'test'); + + $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34)); + + $handler = new RedisHandler($redis, 'key'); + $handler->setFormatter(new LineFormatter("%message%")); + $handler->handle($record); + } +}