From 5eccd17dc5bad181ac6442100460b136f6b76894 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 20 Aug 2022 14:09:11 +0200 Subject: [PATCH 1/2] Add graylog2/gelf-php 2.x support, fixes #1747 --- composer.json | 2 +- phpstan.neon.dist | 3 ++ .../Formatter/GelfMessageFormatter.php | 45 ++++++++++++------- .../Formatter/GelfMessageFormatterTest.php | 35 +++++++++++---- tests/Monolog/Handler/GelfHandlerTest.php | 26 +++++++++-- 5 files changed, 84 insertions(+), 27 deletions(-) diff --git a/composer.json b/composer.json index ab775ad6..b9437d6d 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "aws/aws-sdk-php": "^2.4.9 || ^3.0", "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", - "graylog2/gelf-php": "^1.4.2", + "graylog2/gelf-php": "^1.4.2 || ^2@dev", "guzzlehttp/guzzle": "^7.4", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", diff --git a/phpstan.neon.dist b/phpstan.neon.dist index d368b288..eb126d4a 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -41,3 +41,6 @@ parameters: # legacy elasticsearch namespace failures - '# Elastic\\Elasticsearch\\#' + + # legacy GelfPHP 1.x failures + - '# Gelf\\Message::set(Facility|Line|File)\(#' diff --git a/src/Monolog/Formatter/GelfMessageFormatter.php b/src/Monolog/Formatter/GelfMessageFormatter.php index a1a79372..f5b60d04 100644 --- a/src/Monolog/Formatter/GelfMessageFormatter.php +++ b/src/Monolog/Formatter/GelfMessageFormatter.php @@ -47,6 +47,11 @@ class GelfMessageFormatter extends NormalizerFormatter */ protected $maxLength; + /** + * @var int + */ + private $gelfVersion = 2; + /** * Translates Monolog log levels to Graylog2 log priorities. * @@ -78,6 +83,10 @@ class GelfMessageFormatter extends NormalizerFormatter $this->extraPrefix = is_null($extraPrefix) ? '' : $extraPrefix; $this->contextPrefix = $contextPrefix; $this->maxLength = is_null($maxLength) ? self::DEFAULT_MAX_LENGTH : $maxLength; + + if (method_exists(Message::class, 'setFacility')) { + $this->gelfVersion = 1; + } } /** @@ -113,16 +122,20 @@ class GelfMessageFormatter extends NormalizerFormatter $message->setShortMessage(Utils::substr($record['message'], 0, $this->maxLength)); } - if (isset($record['channel'])) { - $message->setFacility($record['channel']); - } - if (isset($extra['line'])) { - $message->setLine($extra['line']); - unset($extra['line']); - } - if (isset($extra['file'])) { - $message->setFile($extra['file']); - unset($extra['file']); + if ($this->gelfVersion === 1) { + if (isset($record['channel'])) { + $message->setFacility($record['channel']); + } + if (isset($extra['line'])) { + $message->setLine($extra['line']); + unset($extra['line']); + } + if (isset($extra['file'])) { + $message->setFile($extra['file']); + unset($extra['file']); + } + } else { + $message->setAdditional('channel', $record['channel']); } foreach ($extra as $key => $val) { @@ -147,11 +160,13 @@ class GelfMessageFormatter extends NormalizerFormatter $message->setAdditional($this->contextPrefix . $key, $val); } - /** @phpstan-ignore-next-line */ - if (null === $message->getFile() && isset($context['exception']['file'])) { - if (preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) { - $message->setFile($matches[1]); - $message->setLine($matches[2]); + if ($this->gelfVersion === 1) { + /** @phpstan-ignore-next-line */ + if (null === $message->getFile() && isset($context['exception']['file'])) { + if (preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) { + $message->setFile($matches[1]); + $message->setLine($matches[2]); + } } } diff --git a/tests/Monolog/Formatter/GelfMessageFormatterTest.php b/tests/Monolog/Formatter/GelfMessageFormatterTest.php index 88eb9a4a..d5619e4f 100644 --- a/tests/Monolog/Formatter/GelfMessageFormatterTest.php +++ b/tests/Monolog/Formatter/GelfMessageFormatterTest.php @@ -11,6 +11,7 @@ namespace Monolog\Formatter; +use Gelf\Message; use Monolog\Logger; use PHPUnit\Framework\TestCase; @@ -44,9 +45,13 @@ class GelfMessageFormatterTest extends TestCase $this->assertInstanceOf('Gelf\Message', $message); $this->assertEquals(0, $message->getTimestamp()); $this->assertEquals('log', $message->getShortMessage()); - $this->assertEquals('meh', $message->getFacility()); - $this->assertEquals(null, $message->getLine()); - $this->assertEquals(null, $message->getFile()); + if (self::isGelfVersion1()) { + $this->assertEquals('meh', $message->getFacility()); + $this->assertEquals(null, $message->getLine()); + $this->assertEquals(null, $message->getFile()); + } else { + $this->assertEquals('meh', $message->getAdditional('channel')); + } $this->assertEquals($this->isLegacy() ? 3 : 'error', $message->getLevel()); $this->assertNotEmpty($message->getHost()); @@ -77,8 +82,13 @@ class GelfMessageFormatterTest extends TestCase $message = $formatter->format($record); $this->assertInstanceOf('Gelf\Message', $message); - $this->assertEquals('test', $message->getFile()); - $this->assertEquals(14, $message->getLine()); + if (self::isGelfVersion1()) { + $this->assertEquals('test', $message->getFile()); + $this->assertEquals(14, $message->getLine()); + } else { + $this->assertEquals('test', $message->getAdditional('file')); + $this->assertEquals(14, $message->getAdditional('line')); + } } /** @@ -144,7 +154,7 @@ class GelfMessageFormatterTest extends TestCase 'level' => Logger::ERROR, 'level_name' => 'ERROR', 'channel' => 'meh', - 'context' => ['from' => 'logger', 'exception' => [ + 'context' => ['exception' => [ 'class' => '\Exception', 'file' => '/some/file/in/dir.php:56', 'trace' => ['/some/file/1.php:23', '/some/file/2.php:3'], @@ -158,8 +168,12 @@ class GelfMessageFormatterTest extends TestCase $this->assertInstanceOf('Gelf\Message', $message); - $this->assertEquals("/some/file/in/dir.php", $message->getFile()); - $this->assertEquals("56", $message->getLine()); + if (self::isGelfVersion1()) { + $this->assertEquals("/some/file/in/dir.php", $message->getFile()); + $this->assertEquals("56", $message->getLine()); + } else { + $this->assertEquals(['channel' => 'meh', 'ctxt_exception' => '{"class":"\\\\Exception","file":"/some/file/in/dir.php:56","trace":["/some/file/1.php:23","/some/file/2.php:3"]}'], $message->getAllAdditionals()); + } } /** @@ -277,4 +291,9 @@ class GelfMessageFormatterTest extends TestCase { return interface_exists('\Gelf\IMessagePublisher'); } + + private static function isGelfVersion1() + { + return method_exists(Message::class, 'setFacility'); + } } diff --git a/tests/Monolog/Handler/GelfHandlerTest.php b/tests/Monolog/Handler/GelfHandlerTest.php index 6a23423d..7e0cd953 100644 --- a/tests/Monolog/Handler/GelfHandlerTest.php +++ b/tests/Monolog/Handler/GelfHandlerTest.php @@ -55,11 +55,16 @@ class GelfHandlerTest extends TestCase $expectedMessage = new Message(); $expectedMessage ->setLevel(7) - ->setFacility("test") ->setShortMessage($record['message']) ->setTimestamp($record['datetime']) ; + if (self::isGelfVersion1()) { + $expectedMessage->setFacility("test"); + } else { + $expectedMessage->setAdditional('channel', "test"); + } + $messagePublisher = $this->getMessagePublisher(); $messagePublisher->expects($this->once()) ->method('publish') @@ -76,11 +81,16 @@ class GelfHandlerTest extends TestCase $expectedMessage = new Message(); $expectedMessage ->setLevel(4) - ->setFacility("test") ->setShortMessage($record['message']) ->setTimestamp($record['datetime']) ; + if (self::isGelfVersion1()) { + $expectedMessage->setFacility("test"); + } else { + $expectedMessage->setAdditional('channel', "test"); + } + $messagePublisher = $this->getMessagePublisher(); $messagePublisher->expects($this->once()) ->method('publish') @@ -100,7 +110,6 @@ class GelfHandlerTest extends TestCase $expectedMessage = new Message(); $expectedMessage ->setLevel(4) - ->setFacility("test") ->setHost("mysystem") ->setShortMessage($record['message']) ->setTimestamp($record['datetime']) @@ -108,6 +117,12 @@ class GelfHandlerTest extends TestCase ->setAdditional("CTXfrom", 'logger') ; + if (self::isGelfVersion1()) { + $expectedMessage->setFacility("test"); + } else { + $expectedMessage->setAdditional('channel', "test"); + } + $messagePublisher = $this->getMessagePublisher(); $messagePublisher->expects($this->once()) ->method('publish') @@ -117,4 +132,9 @@ class GelfHandlerTest extends TestCase $handler->setFormatter(new GelfMessageFormatter('mysystem', 'EXT', 'CTX')); $handler->handle($record); } + + private static function isGelfVersion1() + { + return method_exists(Message::class, 'setFacility'); + } } From 6bf3b35b8065590e8c0dc34a5eb4d6aaca0157b8 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 20 Aug 2022 14:12:43 +0200 Subject: [PATCH 2/2] Deprecate FlowdockHandler and formatter as the service was shutdown, fixes #1748 --- doc/02-handlers-formatters-processors.md | 2 -- src/Monolog/Formatter/FlowdockFormatter.php | 1 + src/Monolog/Handler/FlowdockHandler.php | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/02-handlers-formatters-processors.md b/doc/02-handlers-formatters-processors.md index 305180ed..3985f291 100644 --- a/doc/02-handlers-formatters-processors.md +++ b/doc/02-handlers-formatters-processors.md @@ -31,7 +31,6 @@ [`mail()`](http://php.net/manual/en/function.mail.php) function. - [_SymfonyMailerHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/SymfonyMailerHandler.php): Sends emails using a [`symfony/mailer`](https://symfony.com/doc/current/mailer.html) instance. - [_PushoverHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/PushoverHandler.php): Sends mobile notifications via the [Pushover](https://www.pushover.net/) API. -- [_FlowdockHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/FlowdockHandler.php): Logs records to a [Flowdock](https://www.flowdock.com/) account. - [_SlackWebhookHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/SlackWebhookHandler.php): Logs records to a [Slack](https://www.slack.com/) account using Slack Webhooks. - [_SlackHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/SlackHandler.php): Logs records to a [Slack](https://www.slack.com/) account using the Slack API (complex setup). - [_SendGridHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/SendGridHandler.php): Sends emails via the SendGrid API. @@ -152,7 +151,6 @@ - [_ElasticaFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/ElasticaFormatter.php): Used to format log records into an Elastica\Document object, only useful for the ElasticaHandler. - [_ElasticsearchFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/ElasticsearchFormatter.php): Used to add index and type keys to log records, only useful for the ElasticsearchHandler. - [_LogglyFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/LogglyFormatter.php): Used to format log records into Loggly messages, only useful for the LogglyHandler. -- [_FlowdockFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/FlowdockFormatter.php): Used to format log records into Flowdock messages, only useful for the FlowdockHandler. - [_MongoDBFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/MongoDBFormatter.php): Converts \DateTime instances to \MongoDate and objects recursively to arrays, only useful with the MongoDBHandler. - [_LogmaticFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/LogmaticFormatter.php): Used to format log records to [Logmatic](http://logmatic.io/) messages, only useful for the LogmaticHandler. - [_FluentdFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/FluentdFormatter.php): Used to format log records to [Fluentd](https://www.fluentd.org/) logs, only useful with the SocketHandler. diff --git a/src/Monolog/Formatter/FlowdockFormatter.php b/src/Monolog/Formatter/FlowdockFormatter.php index 41b56b3c..867ae586 100644 --- a/src/Monolog/Formatter/FlowdockFormatter.php +++ b/src/Monolog/Formatter/FlowdockFormatter.php @@ -15,6 +15,7 @@ namespace Monolog\Formatter; * formats the record to be used in the FlowdockHandler * * @author Dominik Liebler + * @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4 */ class FlowdockFormatter implements FormatterInterface { diff --git a/src/Monolog/Handler/FlowdockHandler.php b/src/Monolog/Handler/FlowdockHandler.php index b837bdb6..5715d580 100644 --- a/src/Monolog/Handler/FlowdockHandler.php +++ b/src/Monolog/Handler/FlowdockHandler.php @@ -28,6 +28,7 @@ use Monolog\Formatter\FormatterInterface; * @see https://www.flowdock.com/api/push * * @phpstan-import-type FormattedRecord from AbstractProcessingHandler + * @deprecated Since 2.9.0 and 3.3.0, Flowdock was shutdown we will thus drop this handler in Monolog 4 */ class FlowdockHandler extends SocketHandler {