From 4bef2a711c1ebb4e4630d5c3def9ce56c562ed8a Mon Sep 17 00:00:00 2001 From: Stefano Arlandini Date: Sun, 26 Feb 2017 23:28:32 +0100 Subject: [PATCH] Add a processor to remove all stacktraces from reported exceptions --- CHANGES | 1 + .../Processor/RemoveStacktraceProcessor.php | 39 +++++++ .../RemoveStacktraceProcessorTest.php | 103 ++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 lib/Raven/Processor/RemoveStacktraceProcessor.php create mode 100644 test/Raven/Tests/Processor/RemoveStacktraceProcessorTest.php diff --git a/CHANGES b/CHANGES index 1c568963e5..99b726a49f 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,7 @@ - Collect User.ip_address automatically (#419). - Added a processor to remove web cookies and another to remove HTTP body data for POST, PUT, PATCH and DELETE requests. They will be enabled by default in ``2.0`` (#405). - Added a processor to sanitize HTTP headers (e.g. the Authorization header) (#428). +- Added a processor to remove all stacktraces from reported exceptions (#429) 1.6.2 ----- diff --git a/lib/Raven/Processor/RemoveStacktraceProcessor.php b/lib/Raven/Processor/RemoveStacktraceProcessor.php new file mode 100644 index 0000000000..f7c407359d --- /dev/null +++ b/lib/Raven/Processor/RemoveStacktraceProcessor.php @@ -0,0 +1,39 @@ + + */ +class Raven_Processor_RemoveStacktraceProcessor extends Raven_Processor +{ + /** + * {@inheritdoc} + */ + public function process(&$data) + { + if (!isset($data['exception'], $data['exception']['values'])) { + return; + } + + foreach ($data['exception']['values'] as &$exception) { + if (!isset($exception['stacktrace'])) { + continue; + } + + foreach ($exception['stacktrace']['frames'] as &$frame) { + unset($frame['pre_context'], $frame['context_line'], $frame['post_context']); + } + } + } +} diff --git a/test/Raven/Tests/Processor/RemoveStacktraceProcessorTest.php b/test/Raven/Tests/Processor/RemoveStacktraceProcessorTest.php new file mode 100644 index 0000000000..62bf90935b --- /dev/null +++ b/test/Raven/Tests/Processor/RemoveStacktraceProcessorTest.php @@ -0,0 +1,103 @@ +client = $this->getMockBuilder('Raven_Client') + ->setMethods(array_diff($this->getClassMethods('Raven_Client'), array('captureException', 'capture', 'get_default_data', 'get_http_data', 'get_user_data', 'get_extra_data'))) + ->getMock(); + + $this->client->store_errors_for_bulk_send = true; + + $this->processor = new Raven_Processor_RemoveStacktraceProcessor($this->client); + } + + public function testProcess() + { + try { + throw new \Exception(); + } catch (\Exception $exception) { + $this->client->captureException($exception); + } + + $this->assertArrayHasKey('stacktrace', $this->client->_pending_events[0]['exception']['values'][0]); + + $this->processor->process($this->client->_pending_events[0]); + + $this->assertArrayNotHasKey('pre_context', $this->client->_pending_events[0]['exception']['values'][0]['stacktrace']['frames']); + $this->assertArrayNotHasKey('context_line', $this->client->_pending_events[0]['exception']['values'][0]['stacktrace']['frames']); + $this->assertArrayNotHasKey('post_context', $this->client->_pending_events[0]['exception']['values'][0]['stacktrace']['frames']); + } + + public function testProcessWithPreviousException() + { + try { + try { + throw new \Exception('foo'); + } catch (\Exception $exception) { + throw new \Exception('bar', 0, $exception); + } + } catch (\Exception $exception) { + $this->client->captureException($exception); + } + + foreach ($this->client->_pending_events[0]['exception']['values'] as $exceptionValue) { + foreach ($exceptionValue['stacktrace']['frames'] as $frame) { + $this->assertArrayHasKey('pre_context', $frame); + $this->assertArrayHasKey('context_line', $frame); + $this->assertArrayHasKey('post_context', $frame); + } + } + + $this->processor->process($this->client->_pending_events[0]); + + foreach ($this->client->_pending_events[0]['exception']['values'] as $exceptionValue) { + foreach ($exceptionValue['stacktrace']['frames'] as $frame) { + $this->assertArrayNotHasKey('pre_context', $frame); + $this->assertArrayNotHasKey('context_line', $frame); + $this->assertArrayNotHasKey('post_context', $frame); + } + } + } + + /** + * Gets all the public and abstracts methods of a given class. + * + * @param string $className The FCQN of the class + * + * @return array + */ + private function getClassMethods($className) + { + $class = new ReflectionClass($className); + $methods = array(); + + foreach ($class->getMethods() as $method) { + if ($method->isPublic() || $method->isAbstract()) { + $methods[] = $method->getName(); + } + } + + return $methods; + } +}