Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add ignore_exceptions & ignore_transactions #1503

Merged
merged 9 commits into from
Mar 23, 2023
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: 10 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,16 @@ parameters:
count: 1
path: src/Options.php

-
message: "#^Method Sentry\\\\Options\\:\\:getIgnoreExceptions\\(\\) should return array\\<string\\> but returns mixed\\.$#"
count: 1
path: src/Options.php

-
message: "#^Method Sentry\\\\Options\\:\\:getIgnoreTransactions\\(\\) should return array\\<string\\> but returns mixed\\.$#"
count: 1
path: src/Options.php

-
message: "#^Method Sentry\\\\Options\\:\\:getInAppExcludedPaths\\(\\) should return array\\<string\\> but returns mixed\\.$#"
count: 1
Expand Down
47 changes: 47 additions & 0 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,12 @@ private function prepareEvent(Event $event, ?EventHint $hint = null, ?Scope $sco
return null;
}

$event = $this->applyIgnoreOptions($event);

if (null === $event) {
return null;
}

if (null !== $scope) {
$beforeEventProcessors = $event;
$event = $scope->applyToEvent($event, $hint);
Expand Down Expand Up @@ -311,6 +317,47 @@ private function prepareEvent(Event $event, ?EventHint $hint = null, ?Scope $sco
return $event;
}

private function applyIgnoreOptions(Event $event): ?Event
{
if ($event->getType() === EventType::event()) {
$exceptions = $event->getExceptions();

if (empty($exceptions)) {
return $event;
}

foreach ($exceptions as $exception) {
if (\in_array($exception->getType(), $this->options->getIgnoreExceptions(), true)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

The only thing is that this works slight different from the now deprecated IgnoreErrorsIntegration because that uses is_a, not sure if intentional but it might be nice to say you want to ignore HttpException::class instead of [ClientHttpException::class, ServerHttpException::class, ...] on the other hand this is more "expected" and you can still make that logic work with before_send of course.

Just a little rambling, I have no hard feelings either way so fine with the current impl.

$this->logger->info(
'The event will be discarded because it matches an entry in "ignore_exceptions".',
['event' => $event]
);

return null;
}
}
}

if ($event->getType() === EventType::transaction()) {
$transactionName = $event->getTransaction();

if (null === $transactionName) {
return $event;
}

if (\in_array($transactionName, $this->options->getIgnoreTransactions(), true)) {
$this->logger->info(
'The event will be discarded because it matches a entry in "ignore_transactions".',
['event' => $event]
);

return null;
}
}

return $event;
}

private function applyBeforeSendCallback(Event $event, ?EventHint $hint): ?Event
{
if ($event->getType() === EventType::event()) {
Expand Down
2 changes: 2 additions & 0 deletions src/Integration/IgnoreErrorsIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
* This integration decides whether an event should not be captured according
* to a series of options that must match with its data.
*
* @deprecated since version 3.17, to be removed in 4.0. Use the `ignore_exceptions` option instead
*
* @author Stefano Arlandini <[email protected]>
*
* @psalm-type IntegrationOptions array{
Expand Down
48 changes: 48 additions & 0 deletions src/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,50 @@ public function setServerName(string $serverName): void
$this->options = $this->resolver->resolve($options);
}

/**
* Gets a list of exceptions to be ignored and not sent to Sentry.
*
* @return string[]
*/
public function getIgnoreExceptions(): array
{
return $this->options['ignore_exceptions'];
}

/**
* Sets a list of exceptions to be ignored and not sent to Sentry.
*
* @param string[] $ignoreErrors The list of exceptions to be ignored
*/
public function setIgnoreExceptions(array $ignoreErrors): void
{
$options = array_merge($this->options, ['ignore_exceptions' => $ignoreErrors]);

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

/**
* Gets a list of transaction names to be ignored and not sent to Sentry.
*
* @return string[]
*/
public function getIgnoreTransactions(): array
{
return $this->options['ignore_transactions'];
}

/**
* Sets a list of transaction names to be ignored and not sent to Sentry.
*
* @param string[] $ignoreTransaction The list of transaction names to be ignored
*/
public function setIgnoreTransactions(array $ignoreTransaction): void
{
$options = array_merge($this->options, ['ignore_transactions' => $ignoreTransaction]);

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

/**
* Gets a callback that will be invoked before an event is sent to the server.
* If `null` is returned it won't be sent.
Expand Down Expand Up @@ -872,6 +916,8 @@ private function configureOptions(OptionsResolver $resolver): void
'release' => $_SERVER['SENTRY_RELEASE'] ?? null,
'dsn' => $_SERVER['SENTRY_DSN'] ?? null,
'server_name' => gethostname(),
'ignore_exceptions' => [],
'ignore_transactions' => [],
'before_send' => static function (Event $event): Event {
return $event;
},
Expand Down Expand Up @@ -916,6 +962,8 @@ private function configureOptions(OptionsResolver $resolver): void
$resolver->setAllowedTypes('server_name', 'string');
$resolver->setAllowedTypes('before_send', ['callable']);
$resolver->setAllowedTypes('before_send_transaction', ['callable']);
$resolver->setAllowedTypes('ignore_exceptions', 'string[]');
$resolver->setAllowedTypes('ignore_transactions', 'string[]');
$resolver->setAllowedTypes('trace_propagation_targets', 'string[]');
$resolver->setAllowedTypes('tags', 'string[]');
$resolver->setAllowedTypes('error_types', ['null', 'int']);
Expand Down
47 changes: 47 additions & 0 deletions tests/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,53 @@ public function processEventDiscardsEventWhenItIsSampledDueToSampleRateOptionDat
];
}

public function testProcessEventDiscardsEventWhenIgnoreExceptionsMatches(): void
{
$exception = new \Exception('Some foo error');

/** @var LoggerInterface&MockObject $logger */
$logger = $this->createMock(LoggerInterface::class);
$logger->expects($this->once())
->method('info')
->with('The event will be discarded because it matches an entry in "ignore_exceptions".', $this->callback(static function (array $context): bool {
return isset($context['event']) && $context['event'] instanceof Event;
}));

$options = [
'ignore_exceptions' => [\Exception::class],
];

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

$client->captureException($exception);
}

public function testProcessEventDiscardsEventWhenIgnoreTransactionsMatches(): void
{
$event = Event::createTransaction();
$event->setTransaction('GET /foo');

/** @var LoggerInterface&MockObject $logger */
$logger = $this->createMock(LoggerInterface::class);
$logger->expects($this->once())
->method('info')
->with('The event will be discarded because it matches a entry in "ignore_transactions".', $this->callback(static function (array $context): bool {
return isset($context['event']) && $context['event'] instanceof Event;
}));

$options = [
'ignore_transactions' => ['GET /foo'],
];

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

$client->captureEvent($event);
}

public function testProcessEventDiscardsEventWhenBeforeSendCallbackReturnsNull(): void
{
/** @var LoggerInterface&MockObject $logger */
Expand Down
18 changes: 18 additions & 0 deletions tests/OptionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,24 @@ static function (): void {},
null,
];

yield [
'ignore_exceptions',
['foo', 'bar'],
'getIgnoreExceptions',
'setIgnoreExceptions',
null,
null,
];

yield [
'ignore_transactions',
['foo', 'bar'],
'getIgnoreTransactions',
'setIgnoreTransactions',
null,
null,
];

yield [
'before_send',
static function (): void {},
Expand Down