Skip to content

Commit 8728790

Browse files
authored
feat(breadcrumbs): add flag to reset breadcrumbs between messages (#946)
1 parent 30772be commit 8728790

File tree

15 files changed

+209
-26
lines changed

15 files changed

+209
-26
lines changed

src/DependencyInjection/Configuration.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ private function addMessengerSection(ArrayNodeDefinition $rootNode): void
187187
->{interface_exists(MessageBusInterface::class) ? 'canBeDisabled' : 'canBeEnabled'}()
188188
->children()
189189
->booleanNode('capture_soft_fails')->defaultTrue()->end()
190+
->booleanNode('isolate_breadcrumbs_by_message')->defaultFalse()->end()
190191
->end()
191192
->end()
192193
->end();

src/DependencyInjection/SentryExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ private function registerMessengerListenerConfiguration(ContainerBuilder $contai
208208
return;
209209
}
210210

211-
$container->getDefinition(MessengerListener::class)->setArgument(1, $config['capture_soft_fails']);
211+
$container->getDefinition(MessengerListener::class)->setArgument(1, $config['capture_soft_fails'])->setArgument(2, $config['isolate_breadcrumbs_by_message']);
212212
}
213213

214214
/**

src/EventListener/MessengerListener.php

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Sentry\State\Scope;
1212
use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent;
1313
use Symfony\Component\Messenger\Event\WorkerMessageHandledEvent;
14+
use Symfony\Component\Messenger\Event\WorkerMessageReceivedEvent;
1415
use Symfony\Component\Messenger\Exception\DelayedMessageHandlingException;
1516
use Symfony\Component\Messenger\Exception\HandlerFailedException;
1617
use Symfony\Component\Messenger\Exception\WrappedExceptionsInterface;
@@ -30,15 +31,25 @@ final class MessengerListener
3031
private $captureSoftFails;
3132

3233
/**
33-
* @param HubInterface $hub The current hub
34-
* @param bool $captureSoftFails Whether to capture errors thrown
35-
* while processing a message that
36-
* will be retried
34+
* @var bool When this is enabled, a new scope is pushed on the stack when a message
35+
* is received and will pop it again after the message was finished (either success or fail).
36+
* This allows us to have breadcrumbs only for one message and no breadcrumb is leaked into
37+
* future messages.
3738
*/
38-
public function __construct(HubInterface $hub, bool $captureSoftFails = true)
39+
private $isolateBreadcrumbsByMessage;
40+
41+
/**
42+
* @param HubInterface $hub The current hub
43+
* @param bool $captureSoftFails Whether to capture errors thrown
44+
* while processing a message that
45+
* will be retried
46+
* @param bool $isolateBreadcrumbsByMessage Whether messages should have isolated breadcrumbs
47+
*/
48+
public function __construct(HubInterface $hub, bool $captureSoftFails = true, bool $isolateBreadcrumbsByMessage = false)
3949
{
4050
$this->hub = $hub;
4151
$this->captureSoftFails = $captureSoftFails;
52+
$this->isolateBreadcrumbsByMessage = $isolateBreadcrumbsByMessage;
4253
}
4354

4455
/**
@@ -48,28 +59,36 @@ public function __construct(HubInterface $hub, bool $captureSoftFails = true)
4859
*/
4960
public function handleWorkerMessageFailedEvent(WorkerMessageFailedEvent $event): void
5061
{
51-
if (!$this->captureSoftFails && $event->willRetry()) {
52-
return;
53-
}
62+
try {
63+
if (!$this->captureSoftFails && $event->willRetry()) {
64+
return;
65+
}
5466

55-
$this->hub->withScope(function (Scope $scope) use ($event): void {
56-
$envelope = $event->getEnvelope();
57-
$exception = $event->getThrowable();
67+
$this->hub->withScope(function (Scope $scope) use ($event): void {
68+
$envelope = $event->getEnvelope();
69+
$exception = $event->getThrowable();
5870

59-
$scope->setTag('messenger.receiver_name', $event->getReceiverName());
60-
$scope->setTag('messenger.message_class', \get_class($envelope->getMessage()));
71+
$scope->setTag('messenger.receiver_name', $event->getReceiverName());
72+
$scope->setTag('messenger.message_class', \get_class($envelope->getMessage()));
6173

62-
/** @var BusNameStamp|null $messageBusStamp */
63-
$messageBusStamp = $envelope->last(BusNameStamp::class);
74+
/** @var BusNameStamp|null $messageBusStamp */
75+
$messageBusStamp = $envelope->last(BusNameStamp::class);
6476

65-
if (null !== $messageBusStamp) {
66-
$scope->setTag('messenger.message_bus', $messageBusStamp->getBusName());
67-
}
77+
if (null !== $messageBusStamp) {
78+
$scope->setTag('messenger.message_bus', $messageBusStamp->getBusName());
79+
}
6880

69-
$this->captureException($exception, $event->willRetry());
70-
});
81+
$this->captureException($exception, $event->willRetry());
82+
});
7183

72-
$this->flushClient();
84+
$this->flushClient();
85+
} finally {
86+
// We always want to pop the scope at the end of this method to add the breadcrumbs
87+
// to any potential event that is produced.
88+
if ($this->isolateBreadcrumbsByMessage) {
89+
$this->hub->popScope();
90+
}
91+
}
7392
}
7493

7594
/**
@@ -82,6 +101,24 @@ public function handleWorkerMessageHandledEvent(WorkerMessageHandledEvent $event
82101
// Flush normally happens at shutdown... which only happens in the worker if it is run with a lifecycle limit
83102
// such as --time=X or --limit=Y. Flush immediately in a background worker.
84103
$this->flushClient();
104+
if ($this->isolateBreadcrumbsByMessage) {
105+
$this->hub->popScope();
106+
}
107+
}
108+
109+
/**
110+
* Method that will push a new scope on the hub to create message local breadcrumbs that will not
111+
* "leak" into future messages.
112+
*
113+
* @param WorkerMessageReceivedEvent $event
114+
*
115+
* @return void
116+
*/
117+
public function handleWorkerMessageReceivedEvent(WorkerMessageReceivedEvent $event): void
118+
{
119+
if ($this->isolateBreadcrumbsByMessage) {
120+
$this->hub->pushScope();
121+
}
85122
}
86123

87124
/**

src/Resources/config/schema/sentry-1.0.xsd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
<xsd:complexType name="messenger">
102102
<xsd:attribute name="enabled" type="xsd:boolean" />
103103
<xsd:attribute name="capture-soft-fails" type="xsd:boolean" />
104+
<xsd:attribute name="isolate-breadcrumbs-by-message" type="xsd:boolean" />
104105
</xsd:complexType>
105106

106107
<xsd:complexType name="tracing">

src/Resources/config/services.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676

7777
<tag name="kernel.event_listener" event="Symfony\Component\Messenger\Event\WorkerMessageFailedEvent" method="handleWorkerMessageFailedEvent" priority="50" />
7878
<tag name="kernel.event_listener" event="Symfony\Component\Messenger\Event\WorkerMessageHandledEvent" method="handleWorkerMessageHandledEvent" priority="50" />
79+
<tag name="kernel.event_listener" event="Symfony\Component\Messenger\Event\WorkerMessageReceivedEvent" method="handleWorkerMessageReceivedEvent" priority="50" />
7980
</service>
8081

8182
<service id="Sentry\SentryBundle\EventListener\LoginListener" class="Sentry\SentryBundle\EventListener\LoginListener">

tests/DependencyInjection/ConfigurationTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public function testProcessConfigurationWithDefaultConfiguration(): void
4242
'messenger' => [
4343
'enabled' => interface_exists(MessageBusInterface::class),
4444
'capture_soft_fails' => true,
45+
'isolate_breadcrumbs_by_message' => false,
4546
],
4647
'tracing' => [
4748
'enabled' => true,

tests/DependencyInjection/Fixtures/php/full.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
'messenger' => [
6161
'enabled' => true,
6262
'capture_soft_fails' => false,
63+
'isolate_breadcrumbs_by_message' => true,
6364
],
6465
'tracing' => [
6566
'dbal' => [

tests/DependencyInjection/Fixtures/xml/full.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
<sentry:ignore-exception>Symfony\Component\HttpKernel\Exception\BadRequestHttpException</sentry:ignore-exception>
5858
<sentry:ignore-transaction>GET tracing_ignored_transaction</sentry:ignore-transaction>
5959
</sentry:options>
60-
<sentry:messenger enabled="true" capture-soft-fails="false" />
60+
<sentry:messenger enabled="true" capture-soft-fails="false" isolate-breadcrumbs-by-message="true"/>
6161
<sentry:tracing>
6262
<sentry:dbal enabled="false">
6363
<sentry:connection>default</sentry:connection>

tests/DependencyInjection/Fixtures/yml/full.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ sentry:
5959
messenger:
6060
enabled: true
6161
capture_soft_fails: false
62+
isolate_breadcrumbs_by_message: true
6263
tracing:
6364
dbal:
6465
enabled: false

tests/DependencyInjection/SentryExtensionTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
use Symfony\Component\HttpKernel\KernelEvents;
4242
use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent;
4343
use Symfony\Component\Messenger\Event\WorkerMessageHandledEvent;
44+
use Symfony\Component\Messenger\Event\WorkerMessageReceivedEvent;
4445
use Symfony\Component\Messenger\MessageBusInterface;
4546

4647
abstract class SentryExtensionTest extends TestCase
@@ -138,10 +139,16 @@ public function testMessengerListener(): void
138139
'method' => 'handleWorkerMessageHandledEvent',
139140
'priority' => 50,
140141
],
142+
[
143+
'event' => WorkerMessageReceivedEvent::class,
144+
'method' => 'handleWorkerMessageReceivedEvent',
145+
'priority' => 50,
146+
],
141147
],
142148
], $definition->getTags());
143149

144150
$this->assertFalse($definition->getArgument(1));
151+
$this->assertTrue($definition->getArgument(2));
145152
}
146153

147154
public function testMessengerListenerIsRemovedWhenDisabled(): void

0 commit comments

Comments
 (0)