8000 [Monolog] Fixed ElasticsearchLogstashHandler with monolog 2+ · symfony/symfony@1f4ca61 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1f4ca61

Browse files
committed
[Monolog] Fixed ElasticsearchLogstashHandler with monolog 2+
1 parent 54b6eb1 commit 1f4ca61

File tree

4 files changed

+179
-5
lines changed

4 files changed

+179
-5
lines changed

src/Symfony/Bridge/Monolog/Handler/ElasticsearchLogstashHandler.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
*/
4040
class ElasticsearchLogstashHandler extends AbstractHandler
4141
{
42+
use ProcessableHandlerTrait;
43+
use FormattableHandlerTrait;
44+
4245
private $endpoint;
4346
private $index;
4447
private $client;
@@ -79,7 +82,13 @@ public function handleBatch(array $records): void
7982

8083
protected function getDefaultFormatter(): FormatterInterface
8184
{
82-
return new LogstashFormatter('application', null, null, 'ctxt_', LogstashFormatter::V1);
85+
// Monolog 1.X
86+
if (\defined(LogstashFormatter::class.'::V1')) {
87+
return new LogstashFormatter('application', null, null, 'ctxt_', LogstashFormatter::V1);
88+
}
89+
90+
// Monolog 2.X
91+
return new LogstashFormatter('application');
8392
}
8493

8594
private function sendToElasticsearch(array $records)
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
/*
13+
* This file is part of the Monolog package.
14+
*
15+
* (c) Jordi Boggiano <j.boggiano@seld.be>
16+
*
17+
* For the full copyright and license information, please view the LICENSE
18+
* file that was distributed with this source code.
19+
*/
20+
21+
namespace Symfony\Bridge\Monolog\Handler;
22+
23+
use Monolog\Formatter\FormatterInterface;
24+
use Monolog\Formatter\LineFormatter;
25+
26+
/**
27+
* Helper trait for implementing FormattableInterface.
28+
*
29+
* @author Jordi Boggiano <j.boggiano@seld.be>
30+
*
31+
* @internal
32+
*/
33+
trait FormattableHandlerTrait
34+
{
35+
/**
36+
* @var FormatterInterface
37+
*/
38+
protected $formatter;
39+
40+
/**
41+
* {@inheritdoc}
42+
*
43+
* @suppress PhanTypeMismatchReturn
44+
*/
45+
public function setFormatter(FormatterInterface $formatter): HandlerInterface
46+
{
47+
$this->formatter = $formatter;
48+
49+
return $this;
50+
}
51+
52+
/**
53+
* {@inheritdoc}
54+
*/
55+
public function getFormatter(): FormatterInterface
56+
{
57+
if (!$this->formatter) {
58+
$this->formatter = $this->getDefaultFormatter();
59+
}
60+
61+
return $this->formatter;
62+
}
63+
64+
/**
65+
* Gets the default formatter.
66+
*
67+
* Overwrite this if the LineFormatter is not a good default for your handler.
68+
*/
69+
protected function getDefaultFormatter(): FormatterInterface
70+
{
71+
return new LineFormatter();
72+
}
73+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Monolog\Handler;
13+
14+
use Monolog\ResettableInterface;
15+
16+
/**
17+
* Helper trait for implementing ProcessableInterface.
18+
*
19+
* @author Jordi Boggiano <j.boggiano@seld.be>
20+
*
21+
* @internal
22+
*/
23+
trait ProcessableHandlerTrait
24+
{
25+
/**
26+
* @var callable[]
27+
*/
28+
protected $processors = [];
29+
30+
/**
31+
* {@inheritdoc}
32+
*
33+
* @suppress PhanTypeMismatchReturn
34+
*/
35+
public function pushProcessor($callback): HandlerInterface
36+
{
37+
array_unshift($this->processors, $callback);
38+
39+
return $this;
40+
}
41+
42+
/**
43+
* {@inheritdoc}
44+
*/
45+
public function popProcessor(): callable
46+
{
47+
if (!$this->processors) {
48+
throw new \LogicException('You tried to pop from an empty processor stack.');
49+
}
50+
51+
return array_shift($this->processors);
52+
}
53+
54+
/**
55+
* Processes a record.
56+
*/
57+
protected function processRecord(array $record): array
58+
{
59+
foreach ($this->processors as $processor) {
60+
$record = $processor($record);
61+
}
62+
63+
return $record;
64+
}
65< D7AE span class="diff-text-marker">+
66+
protected function resetProcessors()
67+
{
68+
foreach ($this->processors as $processor) {
69+
if ($processor instanceof ResettableInterface) {
70+
$processor->reset();
71+
}
72+
}
73+
}
74+
}

src/Symfony/Bridge/Monolog/Tests/Handler/ElasticsearchLogstashHandlerTest.php

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,17 @@ public function testHandle()
2727
$responseFactory = function ($method, $url, $options) use (&$callCount) {
2828
$body = <<<EOBODY
2929
{"index":{"_index":"log","_type":"_doc"}}
30-
{"@timestamp":"2020-01-01T00:00:00.000000+01:00","@version":1,"host":"my hostname","message":"My info message","type":"application","channel":"app","level":"INFO"}
30+
{"@timestamp":"2020-01-01T00:00:00.000000+01:00","@version":1,"host":"my hostname","message":"My info message","type":"application","channel":"app","level":"INFO","monolog_level":200}
3131
3232
3333
EOBODY;
3434

35+
// Monolog 1X
36+
if (\defined(LogstashFormatter::class.'::V1')) {
37+
$body = str_replace(',"monolog_level":200', '', $body);
38+
$body = str_replace(',"monolog_level":300', '', $body);
39+
}
40+
3541
$this->assertSame('POST', $method);
3642
$this->assertSame('http://es:9200/_bulk', $url);
3743
$this->assertSame($body, $options['body']);
@@ -64,14 +70,20 @@ public function testBandleBatch()
6470
$responseFactory = function ($method, $url, $options) use (&$callCount) {
6571
$body = <<<EOBODY
6672
{"index":{"_index":"log","_type":"_doc"}}
67-
{"@timestamp":"2020-01-01T00:00:00.000000+01:00","@version":1,"host":"my hostname","message":"My info message","type":"application","channel":"app","level":"INFO"}
73+
{"@timestamp":"2020-01-01T00:00:00.000000+01:00","@version":1,"host":"my hostname","message":"My info message","type":"application","channel":"app","level":"INFO","monolog_level":200}
6874
6975
{"index":{"_index":"log","_type":"_doc"}}
70-
{"@timestamp":"2020-01-01T00:00:01.000000+01:00","@version":1,"host":"my hostname","message":"My second message","type":"application","channel":"php","level":"WARNING"}
76+
{"@timestamp":"2020-01-01T00:00:01.000000+01:00","@version":1,"host":"my hostname","message":"My second message","type":"application","channel":"php","level":"WARNING","monolog_level":300}
7177
7278
7379
EOBODY;
7480

81+
// Monolog 1X
82+
if (\defined(LogstashFormatter::class.'::V1')) {
83+
$body = str_replace(',"monolog_level":200', '', $body);
84+
$body = str_replace(',"monolog_level":300', '', $body);
85+
}
86+
7587
$this->assertSame('POST', $method);
7688
$this->assertSame('http://es:9200/_bulk', $url);
7789
$this->assertSame($body, $options['body']);
@@ -114,6 +126,12 @@ class ElasticsearchLogstashHandlerWithHardCodedHostname extends ElasticsearchLog
114126
{
115127
protected function getDefaultFormatter(): FormatterInterface
116128
{
117-
return new LogstashFormatter('application', 'my hostname', null, 'ctxt_', LogstashFormatter::V1);
129+
// Monolog 1.X
130+
if (\defined(LogstashFormatter::class.'::V1')) {
131+
return new LogstashFormatter('application', 'my hostname', null, 'ctxt_', LogstashFormatter::V1);
132+
}
133+
134+
// Monolog 2.X
135+
return new LogstashFormatter('application', 'my hostname');
118136
}
119137
}

0 commit comments

Comments
 (0)
0