From cd1fa4fe3af6494b2f8248b8d20cbb1fe3537050 Mon Sep 17 00:00:00 2001 From: Christian Weiske Date: Tue, 7 May 2024 14:36:40 +0200 Subject: [PATCH] [FEATURE] Special handling for log records with "exception" keys TYPO3 scheduler catches exceptions of failed tasks and logs messages with the exception as "exception" data property. PHP Exception objects do not get serialized by json_encode() and thus never reach Sentry; all information about them is lost. If a log record contains an 'exception' data key, then the exception itself is logged to Sentry. The log message is kept as breadcrumb. Resolves: https://github.com/networkteam/sentry_client/issues/106 --- Classes/SentryLogWriter.php | 39 ++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/Classes/SentryLogWriter.php b/Classes/SentryLogWriter.php index d4cba83..f31ae63 100644 --- a/Classes/SentryLogWriter.php +++ b/Classes/SentryLogWriter.php @@ -5,6 +5,7 @@ use Networkteam\SentryClient\Service\ConfigurationService; use Networkteam\SentryClient\Service\SentryService; use Networkteam\SentryClient\Trait\IgnoreMessage; +use Sentry\Breadcrumb; use Sentry\Event; use Sentry\Stacktrace; use Sentry\State\Scope; @@ -36,6 +37,12 @@ public function writeLog(LogRecord $record) if (SentryService::isEnabled() && $this->shouldHandleLogMessage($record) ) { + $data = $record->getData(); + if (isset($data['exception']) && $data['exception'] instanceof \Throwable) { + $this->writeException($record); + return $this; + } + withScope(function (Scope $scope) use ($record): void { $scope->setExtra('component', $record->getComponent()); if ($record->getData()) { @@ -46,7 +53,7 @@ public function writeLog(LogRecord $record) $record->getMessage(), $record->getComponent() ]); - + $message = $record->getMessage(); if (method_exists($this, 'interpolate')) { $message = $this->interpolate($message, $record->getData()); @@ -59,6 +66,36 @@ public function writeLog(LogRecord $record) return $this; } + /** + * Report a log record with an 'exception' object in its data. + * + * Exception objects in Sentry data properties do not get serialized + * and thus get lost. + * To keep them and their stacktrace, we send it as exception to Sentry. + * The log message is kept as breadcrumb. + * + * TYPO3 scheduler logs such messages when tasks fail. + */ + protected function writeException(LogRecord $record): void + { + $data = $record->getData(); + $exception = $data['exception']; + unset($data['exception']); + + withScope(function (Scope $scope) use ($data, $exception, $record): void { + $scope->setExtra('component', $record->getComponent()); + $scope->setExtra('data', $data); + + $message = $record->getMessage(); + if (method_exists($this, 'interpolate')) { + $message = $this->interpolate($message, $record->getData()); + } + $scope->addBreadcrumb(new Breadcrumb('error', 'default', 'log message', $message, [])); + + Client::captureException($exception); + }); + } + protected function shouldHandleLogMessage(LogRecord $logRecord): bool { if ($this->shouldIgnoreMessage($logRecord->getMessage())) {