From a5552dd34d9493cc18ba443d773de709842ebf8d Mon Sep 17 00:00:00 2001 From: fordnox Date: Sun, 15 Nov 2015 20:39:30 +0200 Subject: [PATCH 1/3] Add fluentd formatter. --- src/Monolog/Formatter/FluentdFormatter.php | 82 +++++++++++++++++++ .../Formatter/FluentdFormatterTest.php | 52 ++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 src/Monolog/Formatter/FluentdFormatter.php create mode 100644 tests/Monolog/Formatter/FluentdFormatterTest.php diff --git a/src/Monolog/Formatter/FluentdFormatter.php b/src/Monolog/Formatter/FluentdFormatter.php new file mode 100644 index 00000000..00c28dc5 --- /dev/null +++ b/src/Monolog/Formatter/FluentdFormatter.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +/** + * Class FluentdFormatter + * + * Serializes a log message to Fluetd unix socket protocol + * + * Fluentd config: + * + * + * type unix + * path /var/run/td-agent/td-agent.sock + * + * + * Monolog setup: + * + * $logger = new Monolog\Logger('fluent.tag'); + * $fluentHandler = new Monolog\Handler\SocketHandler('unix:///var/run/td-agent/td-agent.sock'); + * $fluentHandler->setFormatter(new Monolog\Formatter\FluentdFormatter()); + * $logger->pushHandler($fluentHandler); + * + * @author Andrius Putna + */ + +class FluentdFormatter implements FormatterInterface +{ + protected $levelTag = false; + + public function __construct($levelTag = false) + { + if (!function_exists('json_encode')) { + throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s FluentdUnixFormatter'); + } + + $this->levelTag = (bool)$levelTag; + } + + public function isUsingLevelsInTag() + { + return $this->levelTag; + } + + public function format(array $record) + { + $tag = $record['channel']; + if ($this->levelTag) { + $tag .= '.' . strtolower($record['level_name']); + } + + return '[' + . '"' . $tag . '"' + . ', ' + . $record['datetime']->getTimestamp() + . ', ' + . json_encode([ + 'message' => $record['message'], + 'level' => $record['level'], + 'level_name' => $record['level_name'], + 'extra' => $record['extra']]) + . ']'; + } + + public function formatBatch(array $records) + { + $message = ''; + foreach ($records as $record) { + $message .= $this->format($record); + } + return $message; + } +} diff --git a/tests/Monolog/Formatter/FluentdFormatterTest.php b/tests/Monolog/Formatter/FluentdFormatterTest.php new file mode 100644 index 00000000..5bba8d64 --- /dev/null +++ b/tests/Monolog/Formatter/FluentdFormatterTest.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use Monolog\Logger; +use Monolog\TestCase; + +class FluentdFormatterTest extends TestCase +{ + /** + * @covers Monolog\Formatter\FluentdFormatter::__construct + * @covers Monolog\Formatter\FluentdFormatter::isUsingLevelsInTag + */ + public function testConstruct() + { + $formatter = new FluentdFormatter(); + $this->assertEquals(false, $formatter->isUsingLevelsInTag()); + $formatter = new FluentdFormatter(false); + $this->assertEquals(false, $formatter->isUsingLevelsInTag()); + $formatter = new FluentdFormatter(true); + $this->assertEquals(true, $formatter->isUsingLevelsInTag()); + } + + /** + * @covers Monolog\Formatter\FluentdFormatter::format + */ + public function testFormat() + { + + $record = $this->getRecord(Logger::WARNING); + $record['datetime'] = new \DateTime("@0"); + + $formatter = new FluentdFormatter(); + $this->assertEquals( + '["test", 0, {"message":"test","level":300,"level_name":"WARNING","extra":[]}]', + $formatter->format($record)); + + $formatter = new FluentdFormatter(true); + $this->assertEquals( + '["test.warning", 0, {"message":"test","level":300,"level_name":"WARNING","extra":[]}]', + $formatter->format($record)); + } +} From 6abfc2276256a20bb57453c81a44fd3df13a35b9 Mon Sep 17 00:00:00 2001 From: fordnox Date: Sun, 15 Nov 2015 20:46:26 +0200 Subject: [PATCH 2/3] Fix Fluentd array notation to support older PHP versions --- src/Monolog/Formatter/FluentdFormatter.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Monolog/Formatter/FluentdFormatter.php b/src/Monolog/Formatter/FluentdFormatter.php index 00c28dc5..c3d5a8a8 100644 --- a/src/Monolog/Formatter/FluentdFormatter.php +++ b/src/Monolog/Formatter/FluentdFormatter.php @@ -14,7 +14,7 @@ namespace Monolog\Formatter; /** * Class FluentdFormatter * - * Serializes a log message to Fluetd unix socket protocol + * Serializes a log message to Fluentd unix socket protocol * * Fluentd config: * @@ -63,11 +63,11 @@ class FluentdFormatter implements FormatterInterface . ', ' . $record['datetime']->getTimestamp() . ', ' - . json_encode([ + . json_encode(array( 'message' => $record['message'], 'level' => $record['level'], 'level_name' => $record['level_name'], - 'extra' => $record['extra']]) + 'extra' => $record['extra'])) . ']'; } From 034e895a6dd682de4298960dd7c4218f5cc7e901 Mon Sep 17 00:00:00 2001 From: fordnox Date: Sun, 15 Nov 2015 21:23:25 +0200 Subject: [PATCH 3/3] Do not include message levels if it is already included in tag --- src/Monolog/Formatter/FluentdFormatter.php | 19 ++++++++++++++----- .../Formatter/FluentdFormatterTest.php | 14 +++++++++++--- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/Monolog/Formatter/FluentdFormatter.php b/src/Monolog/Formatter/FluentdFormatter.php index c3d5a8a8..7c58bbea 100644 --- a/src/Monolog/Formatter/FluentdFormatter.php +++ b/src/Monolog/Formatter/FluentdFormatter.php @@ -35,6 +35,9 @@ namespace Monolog\Formatter; class FluentdFormatter implements FormatterInterface { + /** + * @var bool $levelTag - should message level be a part of the fluentd tag + */ protected $levelTag = false; public function __construct($levelTag = false) @@ -58,16 +61,22 @@ class FluentdFormatter implements FormatterInterface $tag .= '.' . strtolower($record['level_name']); } + $message = array( + 'message' => $record['message'], + 'extra' => $record['extra'] + ); + + if (!$this->levelTag) { + $message['level'] = $record['level']; + $message['level_name'] = $record['level_name']; + } + return '[' . '"' . $tag . '"' . ', ' . $record['datetime']->getTimestamp() . ', ' - . json_encode(array( - 'message' => $record['message'], - 'level' => $record['level'], - 'level_name' => $record['level_name'], - 'extra' => $record['extra'])) + . json_encode($message) . ']'; } diff --git a/tests/Monolog/Formatter/FluentdFormatterTest.php b/tests/Monolog/Formatter/FluentdFormatterTest.php index 5bba8d64..8476f4c7 100644 --- a/tests/Monolog/Formatter/FluentdFormatterTest.php +++ b/tests/Monolog/Formatter/FluentdFormatterTest.php @@ -35,18 +35,26 @@ class FluentdFormatterTest extends TestCase */ public function testFormat() { - $record = $this->getRecord(Logger::WARNING); $record['datetime'] = new \DateTime("@0"); $formatter = new FluentdFormatter(); $this->assertEquals( - '["test", 0, {"message":"test","level":300,"level_name":"WARNING","extra":[]}]', + '["test", 0, {"message":"test","extra":[],"level":300,"level_name":"WARNING"}]', $formatter->format($record)); + } + + /** + * @covers Monolog\Formatter\FluentdFormatter::format + */ + public function testFormatWithTag() + { + $record = $this->getRecord(Logger::ERROR); + $record['datetime'] = new \DateTime("@0"); $formatter = new FluentdFormatter(true); $this->assertEquals( - '["test.warning", 0, {"message":"test","level":300,"level_name":"WARNING","extra":[]}]', + '["test.error", 0, {"message":"test","extra":[]}]', $formatter->format($record)); } }