Skip to content

Commit 3a3d303

Browse files
committed
replace stack trace lines
1 parent 60d41d3 commit 3a3d303

File tree

4 files changed

+66
-54
lines changed

4 files changed

+66
-54
lines changed

dart/lib/src/sentry_exception_factory.dart

+2-3
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,12 @@ class SentryExceptionFactory {
5858
}
5959
}
6060

61-
final throwableString = throwable.toString();
62-
61+
final stackTraceUtils = StackTraceUtils(throwable.toString());
6362
// if --obfuscate feature is enabled, 'type' won't be human readable.
6463
// https://flutter.dev/docs/deployment/obfuscate#caveat
6564
return SentryException(
6665
type: (throwable.runtimeType).toString(),
67-
value: throwableString.isStackTrace() ? null : throwableString,
66+
value: stackTraceUtils.removeStackStraceLines(),
6867
mechanism: mechanism,
6968
stackTrace: sentryStackTrace,
7069
throwable: throwable,
+18-17
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
import 'package:meta/meta.dart';
22

33
@internal
4-
extension StackTraceUtils on String {
5-
bool isStackTrace() {
6-
final frameNumberPrefix = RegExp(r'^#\d+', multiLine: true);
7-
final matchesFrameNumber = frameNumberPrefix.hasMatch(this);
4+
class StackTraceUtils {
5+
StackTraceUtils(this.input);
86

9-
final fileAndLineNumberSuffix =
10-
RegExp(r'.dart:\d+:\d+\)$', multiLine: true);
11-
final matchesFileAndLineNumber = fileAndLineNumberSuffix.hasMatch(this);
7+
final String input;
128

13-
final abs = RegExp(r'\s(abs)\s');
14-
final virt = RegExp(r'\s(virt)\s');
15-
final matchesAbsAndVirt = abs.hasMatch(this) & virt.hasMatch(this);
9+
late final _stackStackTrace =
10+
RegExp(r'^#\d+.*\.dart:\d+:\d+\)$', multiLine: true);
11+
late final _flutterStackTrace =
12+
RegExp(r'^flutter:\s#\d+.*\.dart:\d+:\d+\)$', multiLine: true);
13+
late final _obfuscatedStackTrace =
14+
RegExp(r'^#\d+.*\+0x\w+$', multiLine: true);
15+
late final _multipleNewlines = RegExp(r'\n+');
1616

17-
final hexSuffix = RegExp(r'\+0(x)\w+$', multiLine: true);
18-
final matchesHexSuffix = hexSuffix.hasMatch(this);
19-
20-
final isStackTrace = matchesFrameNumber & matchesFileAndLineNumber;
21-
final isObfuscatedStackTrace =
22-
matchesFrameNumber & (matchesAbsAndVirt || matchesHexSuffix);
23-
return isStackTrace || isObfuscatedStackTrace;
17+
String removeStackStraceLines() {
18+
return input
19+
.replaceAll(_stackStackTrace, '')
20+
.replaceAll(_flutterStackTrace, '')
21+
.replaceAll(_obfuscatedStackTrace, '')
22+
.replaceAll('<asynchronous suspension>', '')
23+
.replaceAll(_multipleNewlines, '\n')
24+
.trim();
2425
}
2526
}

dart/test/sentry_exception_factory_test.dart

+9-3
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,11 @@ void main() {
174174
final stackTraceError = StackTraceError();
175175
final sentryException =
176176
fixture.getSut().getSentryException(stackTraceError);
177-
expect(sentryException.value, isNull);
177+
final expected = '''
178+
StackTraceError()
179+
Some random description''';
180+
181+
expect(sentryException.value, expected);
178182
});
179183
}
180184

@@ -198,10 +202,12 @@ class StackTraceError extends Error {
198202
@override
199203
String toString() {
200204
return '''
205+
StackTraceError()
206+
Some random description
207+
201208
#0 baz (file:///pathto/test.dart:50:3)
202209
<asynchronous suspension>
203-
#1 bar (file:///pathto/test.dart:46:9)
204-
''';
210+
#1 bar (file:///pathto/test.dart:46:9)''';
205211
}
206212
}
207213

dart/test/utils/stack_trace_utils_test.dart

+37-31
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@ import 'package:sentry/src/utils/stack_trace_utils.dart';
22
import 'package:test/test.dart';
33

44
void main() {
5+
late Fixture fixture;
6+
7+
setUp(() {
8+
fixture = Fixture();
9+
});
10+
511
final dartStackTrace = '''
612
randomPrefix
713
#0 main (file:///Users/denis/Repos/other/dart-stacktrace/main.dart:2:20)
814
#1 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:296:19)
915
#2 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:189:12)
1016
randomSuffix
11-
''';
17+
''';
1218

1319
final flutterStackTrace = '''
1420
randomPrefix
@@ -22,53 +28,53 @@ flutter: #0 MainScaffold.build.<anonymous closure> (package:sentry_flutter_
2228
#7 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:469:20)
2329
#8 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:445:22)
2430
#9 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:331:11)
25-
#10 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:400:7)<…>
31+
#10 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:400:7)
2632
randomSuffix
27-
''';
33+
''';
2834

2935
final flutterObfuscatedStackTrace = '''
36+
randomPrefix
3037
#00 abs 00000075266c2fbf virt 0000000000697fbf _kDartIsolateSnapshotInstructions+0x37e63f
3138
#1 abs 000000752685211f virt 000000000082711f _kDartIsolateSnapshotInstructions+0x50d79f
3239
#2 abs 0000007526851cb3 virt 0000000000826cb3 _kDartIsolateSnapshotInstructions+0x50d333
3340
#3 abs 0000007526851c63 virt 0000000000826c63 _kDartIsolateSnapshotInstructions+0x50d2e3
3441
#4 abs 0000007526851bf3 virt 0000000000826bf3 _kDartIsolateSnapshotInstructions+0x50d273
35-
''';
36-
37-
test('dart stack trace detected', () {
38-
expect(dartStackTrace.isStackTrace(), isTrue);
39-
});
40-
41-
test('flutter stack trace detected', () {
42-
expect(flutterStackTrace.isStackTrace(), isTrue);
43-
});
42+
randomSuffix
43+
''';
4444

45-
test('flutter obfuscated stack trace detected', () {
46-
expect(flutterObfuscatedStackTrace.isStackTrace(), isTrue);
47-
});
45+
final stackTraceWithAsyncSuspension = '''
46+
randomPrefix
47+
#0 baz (file:///pathto/test.dart:50:3)
48+
<asynchronous suspension>
49+
#1 bar (file:///pathto/test.dart:46:9)
50+
randomSuffix
51+
''';
4852

49-
test('stack trace not detected with frame number only', () {
50-
expect('#0'.isStackTrace(), isFalse);
51-
});
53+
final cleanedUp = 'randomPrefix\nrandomSuffix';
5254

53-
test('stack trace not detected with file name and line number only', () {
54-
expect('foo.dart:9000:1)'.isStackTrace(), isFalse);
55+
test('removes dart stack trace', () {
56+
final sut = fixture.getSut(dartStackTrace);
57+
expect(sut.removeStackStraceLines(), cleanedUp);
5558
});
5659

57-
test('stack trace not detected abs only', () {
58-
expect(' abs '.isStackTrace(), isFalse);
60+
test('removes flutter stack trace', () {
61+
final sut = fixture.getSut(flutterStackTrace);
62+
expect(sut.removeStackStraceLines(), cleanedUp);
5963
});
6064

61-
test('stack trace not detected virt only', () {
62-
expect(' virt '.isStackTrace(), isFalse);
65+
test('removes flutter obfuscated stack trace', () {
66+
final sut = fixture.getSut(flutterObfuscatedStackTrace);
67+
expect(sut.removeStackStraceLines(), cleanedUp);
6368
});
6469

65-
test('stack trace not detected abs & virt only', () {
66-
expect(
67-
' abs 00000075266c2fbf virt 0000000000697fbf'.isStackTrace(), isFalse);
70+
test('removes stack trace with asynchronous suspension', () {
71+
final sut = fixture.getSut(stackTraceWithAsyncSuspension);
72+
expect(sut.removeStackStraceLines(), cleanedUp);
6873
});
74+
}
6975

70-
test('stack trace not detected hex suffix only', () {
71-
expect(
72-
'_kDartIsolateSnapshotInstructions+0x50d273'.isStackTrace(), isFalse);
73-
});
76+
class Fixture {
77+
StackTraceUtils getSut(String input) {
78+
return StackTraceUtils(input);
79+
}
7480
}

0 commit comments

Comments
 (0)