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 transactions and ignore errors #1391 #2207

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
9c8955f
Add ignoreTransactions and ignoreErrors #1391
Aug 1, 2024
cb573bd
Merge branch 'main' of https://github.com/getsentry/sentry-dart into …
Aug 1, 2024
bf53140
chore: add changelog entry
Aug 1, 2024
8d4aa50
move methods from sentry_options to sentry_client and change to private
mar-hai Aug 1, 2024
42ba752
change discard reason to ignored
martinhaintz Aug 1, 2024
0295060
change iterable to list
mar-hai Aug 1, 2024
83c3e31
add event recorder to ignoredTransactions
mar-hai Aug 1, 2024
ef2e4d4
Merge branch 'feat/add-ignore-transactions-and-ignore-errors' of mart…
mar-hai Aug 1, 2024
8f61189
add tests for ignoreTransactions
mar-hai Aug 1, 2024
26991af
set ignoreErrors list to empty list a default
martinhaintz Aug 1, 2024
4ffe77b
change variables to final for ignoreTransaction
martinhaintz Aug 1, 2024
54837da
change var to final for ignoreErrors and adapt test
mar-hai Aug 1, 2024
3ccf1e6
Update CHANGELOG.md
martinhaintz Aug 1, 2024
76e1bd1
Add example for ignoreTransactions and ignoreErrors to changelog
martinhaintz Aug 1, 2024
1a629aa
fix: check for empty ignoreError and ignoreTransaction before handlin…
mar-hai Aug 6, 2024
e0d851e
Merge branch 'main' into feat/add-ignore-transactions-and-ignore-errors
martinhaintz Aug 6, 2024
3066ecf
moved ignoreTransactions and ignoreErrors back to unreleased area in …
martinhaintz Aug 6, 2024
02438c3
refactored implementation of ignoreErrors and ignoreTransactions and …
mar-hai Aug 6, 2024
6c00f8e
Merge branch 'main' into feat/add-ignore-transactions-and-ignore-errors
martinhaintz Aug 6, 2024
502f3d9
removed unnecessary backslash from tests
mar-hai Aug 6, 2024
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
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@
### Features

- Add support for span level measurements. ([#2214](https://github.com/getsentry/sentry-dart/pull/2214))
- Add `ignoreTransactions` and `ignoreErrors` to options ([#2207](https://github.com/getsentry/sentry-dart/pull/2207))
```dart
await SentryFlutter.init(
(options) {
options.dsn = 'https://[email protected]/0';
options.ignoreErrors = ["my-error", "^error-.*\$"];
options.ignoreTransactions = ["my-transaction", "^transaction-.*\$"];
...
},
appRunner: () => runApp(MyApp()),
);
```

## 8.6.0

Expand Down
46 changes: 46 additions & 0 deletions dart/lib/src/sentry_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ class SentryClient {
dynamic stackTrace,
Hint? hint,
}) async {
if (_isIgnoredError(event)) {
_options.logger(
SentryLevel.debug,
'Error was ignored as specified in the ignoredErrors options.',
);
_options.recorder
.recordLostEvent(DiscardReason.ignored, _getCategory(event));
return _emptySentryId;
}

if (_options.containsIgnoredExceptionForType(event.throwable)) {
_options.logger(
SentryLevel.debug,
Expand Down Expand Up @@ -180,6 +190,15 @@ class SentryClient {
return id ?? SentryId.empty();
}

bool _isIgnoredError(SentryEvent event) {
if (event.message == null || _options.ignoreErrors.isEmpty) {
return false;
}

var message = event.message!.formatted;
return _isMatchingRegexPattern(message, _options.ignoreErrors);
}

SentryEvent _prepareEvent(SentryEvent event, {dynamic stackTrace}) {
event = event.copyWith(
serverName: event.serverName ?? _options.serverName,
Expand Down Expand Up @@ -351,6 +370,17 @@ class SentryClient {
return _emptySentryId;
}

if (_isIgnoredTransaction(preparedTransaction)) {
_options.logger(
martinhaintz marked this conversation as resolved.
Show resolved Hide resolved
SentryLevel.debug,
'Transaction was ignored as specified in the ignoredTransactions options.',
);

_options.recorder.recordLostEvent(
DiscardReason.ignored, _getCategory(preparedTransaction));
return _emptySentryId;
}

preparedTransaction =
await _runBeforeSend(preparedTransaction, hint) as SentryTransaction?;

Expand Down Expand Up @@ -379,6 +409,15 @@ class SentryClient {
return id ?? SentryId.empty();
}

bool _isIgnoredTransaction(SentryTransaction transaction) {
if (_options.ignoreTransactions.isEmpty) {
return false;
}

var name = transaction.tracer.name;
return _isMatchingRegexPattern(name, _options.ignoreTransactions);
}

/// Reports the [envelope] to Sentry.io.
Future<SentryId?> captureEnvelope(SentryEnvelope envelope) {
return _attachClientReportsAndSend(envelope);
Expand Down Expand Up @@ -554,4 +593,11 @@ class SentryClient {
SentryId.empty(),
);
}

bool _isMatchingRegexPattern(String value, List<String> regexPattern,
{bool caseSensitive = false}) {
final combinedRegexPattern = regexPattern.join('|');
final regExp = RegExp(combinedRegexPattern, caseSensitive: caseSensitive);
return regExp.hasMatch(value);
}
}
8 changes: 8 additions & 0 deletions dart/lib/src/sentry_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ class SentryOptions {
/// sent. Events are picked randomly. Default is null (disabled)
double? sampleRate;

/// The ignoreErrors tells the SDK which errors should be not sent to the sentry server.
/// If an null or an empty list is used, the SDK will send all transactions.
List<String> ignoreErrors = [];

/// The ignoreTransactions tells the SDK which transactions should be not sent to the sentry server.
/// If null or an empty list is used, the SDK will send all transactions.
List<String> ignoreTransactions = [];

final List<String> _inAppExcludes = [];

/// A list of string prefixes of packages names that do not belong to the app, but rather third-party
Expand Down
124 changes: 124 additions & 0 deletions dart/test/sentry_client_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,130 @@ void main() {
});
});

group('SentryClient ignored errors', () {
late Fixture fixture;

setUp(() {
fixture = Fixture();
fixture.options.ignoreErrors = ["my-error", "^error-.*\$"];
});

martinhaintz marked this conversation as resolved.
Show resolved Hide resolved
test('drop event if error message fully matches ignoreErrors value',
() async {
final event = SentryEvent(message: SentryMessage("my-error"));

final client = fixture.getSut();
await client.captureEvent(event);

expect((fixture.transport).called(0), true);
});

test('drop event if error message partially matches ignoreErrors value',
() async {
final event = SentryEvent(message: SentryMessage("this is my-error-foo"));

final client = fixture.getSut();
await client.captureEvent(event);

expect((fixture.transport).called(0), true);
});

test(
'drop event if error message partially matches ignoreErrors regex value',
() async {
final event = SentryEvent(message: SentryMessage("error-test message"));

final client = fixture.getSut();
await client.captureEvent(event);

expect((fixture.transport).called(0), true);
});

test('send event if error message does not match ignoreErrors value',
() async {
final event = SentryEvent(message: SentryMessage("warning"));

final client = fixture.getSut();
await client.captureEvent(event);

expect((fixture.transport).called(1), true);
});

test('send event if no values are set for ignoreErrors', () async {
fixture.options.ignoreErrors = [];
final event = SentryEvent(message: SentryMessage("this is a test event"));

final client = fixture.getSut();
await client.captureEvent(event);

expect((fixture.transport).called(1), true);
});
});

group('SentryClient ignored transactions', () {
late Fixture fixture;

setUp(() {
fixture = Fixture();
fixture.options.ignoreTransactions = [
"my-transaction",
"^transaction-.*\$"
];
});

test('drop transaction if name fully matches ignoreTransaction value',
() async {
final client = fixture.getSut();
final fakeTransaction = fixture.fakeTransaction();
fakeTransaction.tracer.name = "my-transaction";
await client.captureTransaction(fakeTransaction);

expect((fixture.transport).called(0), true);
});

test('drop transaction if name partially matches ignoreTransaction value',
() async {
final client = fixture.getSut();
final fakeTransaction = fixture.fakeTransaction();
fakeTransaction.tracer.name = "this is a transaction-test";
await client.captureTransaction(fakeTransaction);

expect((fixture.transport).called(0), true);
});

test(
'drop transaction if name partially matches ignoreTransaction regex value',
() async {
final client = fixture.getSut();
final fakeTransaction = fixture.fakeTransaction();
fakeTransaction.tracer.name = "transaction-test message";
await client.captureTransaction(fakeTransaction);

expect((fixture.transport).called(0), true);
});

test('send transaction if name does not match ignoreTransaction value',
() async {
final client = fixture.getSut();
final fakeTransaction = fixture.fakeTransaction();
fakeTransaction.tracer.name = "capture";
await client.captureTransaction(fakeTransaction);

expect((fixture.transport).called(1), true);
});

test('send transaction if no values are set for ignoreTransaction',
() async {
fixture.options.ignoreTransactions = [];
final client = fixture.getSut();
final fakeTransaction = fixture.fakeTransaction();
fakeTransaction.tracer.name = "this is a test transaction";
await client.captureTransaction(fakeTransaction);

expect((fixture.transport).called(1), true);
});
});

group('SentryClient ignored exceptions', () {
late Fixture fixture;

Expand Down
Loading