Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

## Unreleased

- feat: Add `before_send_transaction` option (#1424)

## 3.11.0 (2022-10-25)

fix: Only include the transaction name to the DSC if it has good quality (#1410)
ref: Enable the ModulesIntegration by default (#1415)
ref: Expose the ExceptionMechanism through the event hint (#1416)
- fix: Only include the transaction name to the DSC if it has good quality (#1410)
- ref: Enable the ModulesIntegration by default (#1415)
- ref: Expose the ExceptionMechanism through the event hint (#1416)

## 3.10.0 (2022-10-19)

Expand All @@ -20,7 +22,7 @@ ref: Expose the ExceptionMechanism through the event hint (#1416)

## 3.9.0 (2022-10-05)

- feat: Add tracePropagationTargets option (#1396)
- feat: Add `trace_propagation_targets` option (#1396)
- feat: Expose a function to retrieve the URL of the CSP endpoint (#1378)
- feat: Add support for Dynamic Sampling (#1360)
- Add `segment` to `UserDataBag`
Expand Down
6 changes: 5 additions & 1 deletion phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ parameters:
count: 1
path: src/Options.php

-
message: "#^Method Sentry\\\\Options\\:\\:getBeforeSendTransactionCallback\\(\\) should return callable\\(Sentry\\\\Event, Sentry\\\\EventHint\\|null\\)\\: Sentry\\\\Event\\|null but returns mixed\\.$#"
count: 1
path: src/Options.php

-
message: "#^Method Sentry\\\\Options\\:\\:getClassSerializers\\(\\) should return array\\<string, callable\\(\\)\\: mixed\\> but returns mixed\\.$#"
count: 1
Expand Down Expand Up @@ -374,4 +379,3 @@ parameters:
message: "#^Method Sentry\\\\State\\\\HubInterface\\:\\:startTransaction\\(\\) invoked with 2 parameters, 1 required\\.$#"
count: 1
path: src/functions.php

47 changes: 39 additions & 8 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -288,28 +288,59 @@ private function prepareEvent(Event $event, ?EventHint $hint = null, ?Scope $sco
}

if (null !== $scope) {
$previousEvent = $event;
$beforeEventProcessors = $event;
$event = $scope->applyToEvent($event, $hint);

if (null === $event) {
$this->logger->info('The event will be discarded because one of the event processors returned "null".', ['event' => $previousEvent]);
$this->logger->info(
'The event will be discarded because one of the event processors returned "null".',
['event' => $beforeEventProcessors]
);

return null;
}
}

if (!$isTransaction) {
$previousEvent = $event;
$event = ($this->options->getBeforeSendCallback())($event, $hint);
$beforeSendCallback = $event;
$event = $this->applyBeforeSendCallback($event, $hint);

if (null === $event) {
$this->logger->info('The event will be discarded because the "before_send" callback returned "null".', ['event' => $previousEvent]);
}
if (null === $event) {
$this->logger->info(
sprintf(
'The event will be discarded because the "%s" callback returned "null".',
$this->getBeforeSendCallbackName($beforeSendCallback)
),
['event' => $beforeSendCallback]
);
}

return $event;
}

private function applyBeforeSendCallback(Event $event, ?EventHint $hint): ?Event
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

{
if ($event->getType() === EventType::event()) {
return ($this->options->getBeforeSendCallback())($event, $hint);
}

if ($event->getType() === EventType::transaction()) {
return ($this->options->getBeforeSendTransactionCallback())($event, $hint);
}

return $event;
}

private function getBeforeSendCallbackName(Event $event): string
{
$beforeSendCallbackName = 'before_send';

if ($event->getType() === EventType::transaction()) {
$beforeSendCallbackName = 'before_send_transaction';
}

return $beforeSendCallbackName;
}

/**
* Optionally adds a missing stacktrace to the Event if the client is configured to do so.
*
Expand Down
30 changes: 30 additions & 0 deletions src/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,32 @@ public function setBeforeSendCallback(callable $callback): void
$this->options = $this->resolver->resolve($options);
}

/**
* Gets a callback that will be invoked before an transaction is sent to the server.
* If `null` is returned it won't be sent.
*
* @psalm-return callable(Event, ?EventHint): ?Event
*/
public function getBeforeSendTransactionCallback(): callable
{
return $this->options['before_send_transaction'];
}

/**
* Sets a callable to be called to decide whether an transaction should
* be captured or not.
*
* @param callable $callback The callable
*
* @psalm-param callable(Event, ?EventHint): ?Event $callback
*/
public function setBeforeSendTransactionCallback(callable $callback): void
{
$options = array_merge($this->options, ['before_send_transaction' => $callback]);

$this->options = $this->resolver->resolve($options);
}

/**
* Gets an allow list of trace propagation targets.
*
Expand Down Expand Up @@ -801,6 +827,9 @@ private function configureOptions(OptionsResolver $resolver): void
'before_send' => static function (Event $event): Event {
return $event;
},
'before_send_transaction' => static function (Event $transaction): Event {
return $transaction;
},
'trace_propagation_targets' => [],
'tags' => [],
'error_types' => null,
Expand Down Expand Up @@ -836,6 +865,7 @@ private function configureOptions(OptionsResolver $resolver): void
$resolver->setAllowedTypes('dsn', ['null', 'string', 'bool', Dsn::class]);
$resolver->setAllowedTypes('server_name', 'string');
$resolver->setAllowedTypes('before_send', ['callable']);
$resolver->setAllowedTypes('before_send_transaction', ['callable']);
$resolver->setAllowedTypes('trace_propagation_targets', 'string[]');
$resolver->setAllowedTypes('tags', 'string[]');
$resolver->setAllowedTypes('error_types', ['null', 'int']);
Expand Down
58 changes: 57 additions & 1 deletion tests/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,39 @@ public function processEventChecksBeforeSendOptionDataProvider(): \Generator
];
}

/**
* @dataProvider processEventChecksBeforeSendTransactionOptionDataProvider
*/
public function testProcessEventChecksBeforeSendTransactionOption(Event $event, bool $expectedBeforeSendCall): void
{
$beforeSendTransactionCalled = false;
$options = [
'before_send_transaction' => static function () use (&$beforeSendTransactionCalled) {
$beforeSendTransactionCalled = true;

return null;
},
];

$client = ClientBuilder::create($options)->getClient();
$client->captureEvent($event);

$this->assertSame($expectedBeforeSendCall, $beforeSendTransactionCalled);
}

public function processEventChecksBeforeSendTransactionOptionDataProvider(): \Generator
{
yield [
Event::createEvent(),
false,
];

yield [
Event::createTransaction(),
true,
];
}

/**
* @dataProvider processEventDiscardsEventWhenItIsSampledDueToSampleRateOptionDataProvider
*/
Expand Down Expand Up @@ -574,7 +607,30 @@ public function testProcessEventDiscardsEventWhenBeforeSendCallbackReturnsNull()
->setLogger($logger)
->getClient();

$client->captureMessage('foo');
$client->captureEvent(Event::createEvent());
}

public function testProcessEventDiscardsEventWhenBeforeSendTransactionCallbackReturnsNull(): void
{
/** @var LoggerInterface&MockObject $logger */
$logger = $this->createMock(LoggerInterface::class);
$logger->expects($this->once())
->method('info')
->with('The event will be discarded because the "before_send_transaction" callback returned "null".', $this->callback(static function (array $context): bool {
return isset($context['event']) && $context['event'] instanceof Event;
}));

$options = [
'before_send_transaction' => static function () {
return null;
},
];

$client = ClientBuilder::create($options)
->setLogger($logger)
->getClient();

$client->captureEvent(Event::createTransaction());
}

public function testProcessEventDiscardsEventWhenEventProcessorReturnsNull(): void
Expand Down
9 changes: 9 additions & 0 deletions tests/OptionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,15 @@ static function (): void {},
null,
];

yield [
'before_send_transaction',
static function (): void {},
'getBeforeSendTransactionCallback',
'setBeforeSendTransactionCallback',
null,
null,
];

yield [
'trace_propagation_targets',
['www.example.com'],
Expand Down