diff --git a/src/Client.php b/src/Client.php index 0fb96d986..76f0958fb 100644 --- a/src/Client.php +++ b/src/Client.php @@ -14,6 +14,8 @@ use Sentry\Transport\Result; use Sentry\Transport\TransportInterface; +use function count; + /** * Default implementation of the {@see ClientInterface} interface. */ @@ -468,10 +470,24 @@ private function addThrowableToEvent(Event $event, \Throwable $exception, EventH $exceptions[] = new ExceptionDataBag( $exception, $this->stacktraceBuilder->buildFromException($exception), + // @FIXME this sets the same mechanism on all exception $hint->mechanism ?? new ExceptionMechanism(ExceptionMechanism::TYPE_GENERIC, true, ['code' => $exception->getCode()]) ); } while ($exception = $exception->getPrevious()); + if (count($exceptions) > 1) { + foreach ($exceptions as $key => $value) { + if ($key === 0) { + $value->getMechanism()->setIsExceptionGroup(true); + } + if ($key > 0) { + $value->getMechanism()->setParentId(0); + } + + $value->getMechanism()->setExceptionId($key); + } + } + $event->setExceptions($exceptions); } } diff --git a/src/ExceptionMechanism.php b/src/ExceptionMechanism.php index fed2081b1..a42e21f2d 100644 --- a/src/ExceptionMechanism.php +++ b/src/ExceptionMechanism.php @@ -32,6 +32,12 @@ final class ExceptionMechanism */ private $data; + private $exceptionId; + + private $parentId; + + private $isExceptionGroup; + /** * Class constructor. * @@ -47,6 +53,9 @@ public function __construct(string $type, bool $handled, array $data = []) $this->type = $type; $this->handled = $handled; $this->data = $data; + $this->exceptionId = 0; + $this->parentId = null; + $this->isExceptionGroup = false; } /** @@ -89,4 +98,40 @@ public function setData(array $data): self return $this; } + + public function getExceptionId(): int + { + return $this->exceptionId; + } + + public function setExceptionId(int $exceptionId): self + { + $this->exceptionId = $exceptionId; + + return $this; + } + + public function getParentId(): ?int + { + return $this->parentId; + } + + public function setParentId(int $parentId): self + { + $this->parentId = $parentId; + + return $this; + } + + public function getIsExceptionGroup(): bool + { + return $this->isExceptionGroup; + } + + public function setIsExceptionGroup(bool $isExceptionGroup): self + { + $this->isExceptionGroup = $isExceptionGroup; + + return $this; + } } diff --git a/src/Serializer/EnvelopItems/EventItem.php b/src/Serializer/EnvelopItems/EventItem.php index dd37f70ff..5b4e24cdc 100644 --- a/src/Serializer/EnvelopItems/EventItem.php +++ b/src/Serializer/EnvelopItems/EventItem.php @@ -165,25 +165,34 @@ public static function toEnvelopeItem(Event $event): string */ protected static function serializeException(ExceptionDataBag $exception): array { - $exceptionMechanism = $exception->getMechanism(); - $exceptionStacktrace = $exception->getStacktrace(); $result = [ 'type' => $exception->getType(), 'value' => $exception->getValue(), ]; + $exceptionStacktrace = $exception->getStacktrace(); if ($exceptionStacktrace !== null) { $result['stacktrace'] = [ 'frames' => array_map([self::class, 'serializeStacktraceFrame'], $exceptionStacktrace->getFrames()), ]; } + $exceptionMechanism = $exception->getMechanism(); if ($exceptionMechanism !== null) { $result['mechanism'] = [ 'type' => $exceptionMechanism->getType(), 'handled' => $exceptionMechanism->isHandled(), + 'exception_id' => $exceptionMechanism->getExceptionId(), ]; + if ($exceptionMechanism->getIsExceptionGroup()) { + $result['mechanism']['is_exception_group'] = true; + } + + if ($exceptionMechanism->getParentId() !== null) { + $result['mechanism']['parent_id'] = $exceptionMechanism->getParentId(); + } + if ($exceptionMechanism->getData() !== []) { $result['mechanism']['data'] = $exceptionMechanism->getData(); }