From 32563c49b75636465c5fc69ebe94b01202c3b88b Mon Sep 17 00:00:00 2001 From: Avtandil Kikabidze Date: Sat, 7 Apr 2018 03:10:46 +0400 Subject: [PATCH] Add elastic search formatter --- .../Formatter/ElasticSearchFormatter.php | 87 +++++++++++++++++++ .../Formatter/ElasticSearchFormatterTest.php | 70 +++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 src/Monolog/Formatter/ElasticSearchFormatter.php create mode 100644 tests/Monolog/Formatter/ElasticSearchFormatterTest.php diff --git a/src/Monolog/Formatter/ElasticSearchFormatter.php b/src/Monolog/Formatter/ElasticSearchFormatter.php new file mode 100644 index 00000000..1ac9d2c7 --- /dev/null +++ b/src/Monolog/Formatter/ElasticSearchFormatter.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +/** + * Format a log message into an ElasticSearch record + * + * @author Avtandil Kikabidze + */ +class ElasticSearchFormatter extends NormalizerFormatter +{ + /** + * @var string ElasticSearch index name + */ + protected $index; + + /** + * @var string ElasticSearch record type + */ + protected $type; + + /** + * @param string $index ElasticSearch index name + * @param string $type ElasticSearch record type + */ + public function __construct($index, $type) + { + // ElasticSearch requires an ISO 8601 format date with optional millisecond precision. + parent::__construct('Y-m-d\TH:i:s.uP'); + + $this->index = $index; + $this->type = $type; + } + + /** + * {@inheritdoc} + */ + public function format(array $record) + { + $record = parent::format($record); + + return $this->getDocument($record); + } + + /** + * Getter index + * + * @return string + */ + public function getIndex(): string + { + return $this->index; + } + + /** + * Getter type + * + * @return string + */ + public function getType(): string + { + return $this->type; + } + + /** + * Convert a log message into an ElasticSearch record + * + * @param array $record Log message + * @return array + */ + protected function getDocument($record): array + { + $record['_index'] = $this->index; + $record['_type'] = $this->type; + + return $record; + } +} diff --git a/tests/Monolog/Formatter/ElasticSearchFormatterTest.php b/tests/Monolog/Formatter/ElasticSearchFormatterTest.php new file mode 100644 index 00000000..74a66bd6 --- /dev/null +++ b/tests/Monolog/Formatter/ElasticSearchFormatterTest.php @@ -0,0 +1,70 @@ + + * + * 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; + +class ElasticSearchFormatterTest extends \PHPUnit\Framework\TestCase +{ + /** + * @covers Monolog\Formatter\ElasticSearchFormatter::__construct + * @covers Monolog\Formatter\ElasticSearchFormatter::format + * @covers Monolog\Formatter\ElasticSearchFormatter::getDocument + */ + public function testFormat() + { + // Test log message + $msg = [ + 'level' => Logger::ERROR, + 'level_name' => 'ERROR', + 'channel' => 'meh', + 'context' => ['foo' => 7, 'bar', 'class' => new \stdClass], + 'datetime' => new \DateTimeImmutable("@0"), + 'extra' => [], + 'message' => 'log', + ]; + + // Expected values + $expected = $msg; + $expected['datetime'] = '1970-01-01T00:00:00.000000+00:00'; + $expected['context'] = [ + 'class' => ['stdClass' => []], + 'foo' => 7, + 0 => 'bar', + ]; + + // Format log message + $formatter = new ElasticSearchFormatter('my_index', 'doc_type'); + $doc = $formatter->format($msg); + $this->assertInternalType('array', $doc); + + // Record parameters + $this->assertEquals('my_index', $doc['_index']); + $this->assertEquals('doc_type', $doc['_type']); + + // Record data values + foreach (array_keys($expected) as $key) { + $this->assertEquals($expected[$key], $doc[$key]); + } + } + + /** + * @covers Monolog\Formatter\ElasticSearchFormatter::getIndex + * @covers Monolog\Formatter\ElasticSearchFormatter::getType + */ + public function testGetters() + { + $formatter = new ElasticaFormatter('my_index', 'doc_type'); + $this->assertEquals('my_index', $formatter->getIndex()); + $this->assertEquals('doc_type', $formatter->getType()); + } +}