From 869ca5963ffcef102aa20d387170fb9cdecc8a21 Mon Sep 17 00:00:00 2001 From: Dimitri Gritsajuk Date: Sun, 28 Oct 2018 15:43:09 +0100 Subject: [PATCH] [RavenHandler] Add environment and breadcrumbs support --- composer.json | 2 +- src/Monolog/Handler/RavenHandler.php | 45 ++++++++++++++++----- tests/Monolog/Handler/MockRavenClient.php | 2 +- tests/Monolog/Handler/RavenHandlerTest.php | 46 +++++++++++++++++++--- 4 files changed, 79 insertions(+), 16 deletions(-) diff --git a/composer.json b/composer.json index bd253ee6..0d1f4dbc 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ "require-dev": { "phpunit/phpunit": "^6.5", "graylog2/gelf-php": "^1.4.2", - "sentry/sentry": "^0.13", + "sentry/sentry": "^1.9", "ruflin/elastica": ">=0.90 <3.0", "doctrine/couchdb": "~1.0@dev", "aws/aws-sdk-php": "^2.4.9 || ^3.0", diff --git a/src/Monolog/Handler/RavenHandler.php b/src/Monolog/Handler/RavenHandler.php index 801e52c1..f6cf88a0 100644 --- a/src/Monolog/Handler/RavenHandler.php +++ b/src/Monolog/Handler/RavenHandler.php @@ -38,6 +38,11 @@ class RavenHandler extends AbstractProcessingHandler Logger::EMERGENCY => Raven_Client::FATAL, ]; + /** + * @var string the current application environment (staging|preprod|prod) + */ + private $environment; + /** * @var string should represent the current version of the calling * software. Can be any string (git commit, version number) @@ -109,17 +114,15 @@ class RavenHandler extends AbstractProcessingHandler * * @param FormatterInterface $formatter */ - public function setBatchFormatter(FormatterInterface $formatter) + public function setBatchFormatter(FormatterInterface $formatter): void { $this->batchFormatter = $formatter; } /** * Gets the formatter for the logs generated by handleBatch(). - * - * @return FormatterInterface */ - public function getBatchFormatter() + public function getBatchFormatter(): FormatterInterface { if (!$this->batchFormatter) { $this->batchFormatter = $this->getDefaultBatchFormatter(); @@ -177,6 +180,10 @@ class RavenHandler extends AbstractProcessingHandler $options['extra']['extra'] = $record['extra']; } + if (!empty($this->environment) && !isset($options['environment'])) { + $options['environment'] = $this->environment; + } + if (!empty($this->release) && !isset($options['release'])) { $options['release'] = $this->release; } @@ -190,7 +197,7 @@ class RavenHandler extends AbstractProcessingHandler // restore the user context if it was modified if (!is_bool($previousUserContext)) { - $this->ravenClient->user_context($previousUserContext); + $this->ravenClient->user_context($previousUserContext, false); } } @@ -207,7 +214,7 @@ class RavenHandler extends AbstractProcessingHandler * * @return FormatterInterface */ - protected function getDefaultBatchFormatter() + protected function getDefaultBatchFormatter(): FormatterInterface { return new LineFormatter(); } @@ -217,19 +224,39 @@ class RavenHandler extends AbstractProcessingHandler * * @return array */ - protected function getExtraParameters() + protected function getExtraParameters(): array { - return ['checksum', 'release', 'event_id']; + return ['checksum', 'release', 'environment', 'event_id']; } /** * @param string $value * @return self */ - public function setRelease($value) + public function setRelease($value): self { $this->release = $value; return $this; } + + public function setEnvironment($value): self + { + $this->environment = $value; + + return $this; + } + + /** + * @link https://docs.sentry.io/learn/breadcrumbs/ + */ + public function addBreadcrumb(array $crumb): void + { + $this->ravenClient->breadcrumbs->record($crumb); + } + + public function resetBreadcrumbs(): void + { + $this->ravenClient->breadcrumbs->reset(); + } } diff --git a/tests/Monolog/Handler/MockRavenClient.php b/tests/Monolog/Handler/MockRavenClient.php index d344d342..07434e49 100644 --- a/tests/Monolog/Handler/MockRavenClient.php +++ b/tests/Monolog/Handler/MockRavenClient.php @@ -15,7 +15,7 @@ use Raven_Client; class MockRavenClient extends Raven_Client { - public function capture($data, $stack, $vars = null) + public function capture($data, $stack = null, $vars = null) { $data = array_merge($this->get_user_data(), $data); $this->lastData = $data; diff --git a/tests/Monolog/Handler/RavenHandlerTest.php b/tests/Monolog/Handler/RavenHandlerTest.php index 082042f0..c80a5763 100644 --- a/tests/Monolog/Handler/RavenHandlerTest.php +++ b/tests/Monolog/Handler/RavenHandlerTest.php @@ -42,9 +42,7 @@ class RavenHandlerTest extends TestCase protected function getHandler($ravenClient) { - $handler = new RavenHandler($ravenClient); - - return $handler; + return new RavenHandler($ravenClient); } protected function getRavenClient() @@ -144,7 +142,7 @@ class RavenHandlerTest extends TestCase $this->assertSame('test_user_id', $ravenClient->context->user['id']); // handle with null context - $ravenClient->user_context(null); + $ravenClient->user_context(null, false); $handler->handle($recordWithContext); $this->assertEquals($user, $ravenClient->lastData['user']); @@ -165,7 +163,7 @@ class RavenHandlerTest extends TestCase $handler->handle($record); } - $this->assertEquals($record['message'], $ravenClient->lastData['message']); + $this->assertEquals('[test] ' . $record['message'], $ravenClient->lastData['message']); } public function testHandleBatch() @@ -256,6 +254,44 @@ class RavenHandlerTest extends TestCase $this->assertEquals($localRelease, $ravenClient->lastData['release']); } + public function testEnvironment() + { + $ravenClient = $this->getRavenClient(); + $handler = $this->getHandler($ravenClient); + $handler->setEnvironment('preprod'); + + $handler->handle($this->getRecord(Logger::INFO, 'Hello 👋 from PREPROD env')); + $this->assertEquals('preprod', $ravenClient->lastData['environment']); + + $handler->handle($this->getRecord(Logger::INFO, 'Hello 👋 from STAGING env', ['environment' => 'staging'])); + $this->assertEquals('staging', $ravenClient->lastData['environment']); + } + + public function testBreadcrumbs() + { + $ravenClient = $this->getRavenClient(); + $handler = $this->getHandler($ravenClient); + + $handler->addBreadcrumb($crumb1 = [ + 'level' => 'info', + 'category' => 'test', + 'message' => 'Step 1: user auth', + ]); + + $handler->addBreadcrumb($crumb2 = [ + 'level' => 'info', + 'category' => 'test', + 'message' => 'Step 2: prepare user redirect', + ]); + + $handler->handle($this->getRecord(Logger::ERROR, 'ERROR 💥')); + $this->assertArraySubset([$crumb1, $crumb2], $ravenClient->breadcrumbs->fetch()); + + $handler->resetBreadcrumbs(); + $handler->handle($this->getRecord(Logger::INFO, 'Hello!')); + $this->assertEmpty($ravenClient->breadcrumbs->fetch()); + } + private function methodThatThrowsAnException() { throw new \Exception('This is an exception');