diff --git a/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php b/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php new file mode 100644 index 00000000..0cd287f5 --- /dev/null +++ b/src/Monolog/Formatter/GoogleCloudLoggingFormatter.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use DateTimeInterface; +use Monolog\LogRecord; + +/** + * Encodes message information into JSON in a format compatible with Cloud logging. + * + * @see https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry + * + * @author Luís Cobucci + */ +final class GoogleCloudLoggingFormatter extends JsonFormatter +{ + /** {@inheritdoc} **/ + public function format(array $record): string + { + // Re-key level for GCP logging + $record['severity'] = $record['level_name']; + $record['timestamp'] = $record['datetime']->format(DateTimeInterface::RFC3339_EXTENDED); + + // Remove keys that are not used by GCP + unset($record['level'], $record['level_name'], $record['datetime']); + + return parent::format($record); + } +} + diff --git a/tests/Monolog/Formatter/GoogleCloudLoggingFormatterTest.php b/tests/Monolog/Formatter/GoogleCloudLoggingFormatterTest.php new file mode 100644 index 00000000..27aea2ca --- /dev/null +++ b/tests/Monolog/Formatter/GoogleCloudLoggingFormatterTest.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Formatter; + +use DateTimeInterface; +use Monolog\Test\TestCase; +use function json_decode; + +class GoogleCloudLoggingFormatterTest extends TestCase +{ + /** + * @test + * + * @covers \Monolog\Formatter\JsonFormatter + * @covers \Monolog\Formatter\GoogleCloudLoggingFormatter::format + */ + public function formatProvidesRfc3339Timestamps(): void + { + $formatter = new GoogleCloudLoggingFormatter(); + $record = $this->getRecord(); + + $formatted_decoded = json_decode($formatter->format($record), true); + $this->assertArrayNotHasKey("datetime", $formatted_decoded); + $this->assertArrayHasKey("timestamp", $formatted_decoded); + $this->assertSame($record['datetime']->format(DateTimeInterface::RFC3339_EXTENDED), $formatted_decoded["timestamp"]); + } + + /** + * @test + * + * @covers \Monolog\Formatter\JsonFormatter + * @covers \Monolog\Formatter\GoogleCloudLoggingFormatter::format + */ + public function formatIntroducesLogSeverity(): void + { + $formatter = new GoogleCloudLoggingFormatter(); + $record = $this->getRecord(); + + $formatted_decoded = json_decode($formatter->format($record), true); + $this->assertArrayNotHasKey("level", $formatted_decoded); + $this->assertArrayNotHasKey("level_name", $formatted_decoded); + $this->assertArrayHasKey("severity", $formatted_decoded); + $this->assertSame($record['level_name'], $formatted_decoded["severity"]); + } +}