Skip to content

Commit ed17f96

Browse files
authored
Merge branch 'main' into feat/cache-screenshots
2 parents 1cc345a + 73992eb commit ed17f96

38 files changed

+4038
-3790
lines changed

.github/workflows/flutter_test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ jobs:
8181

8282
- name: build apk
8383
working-directory: ./flutter/example/android
84-
run: flutter build apk --debug
84+
run: flutter build apk --debug --target-platform=android-x64
8585

8686
- name: launch android emulator & run android native test
8787
uses: reactivecircus/android-emulator-runner@62dbb605bba737720e10b196cb4220d374026a6d #[email protected]

.github/workflows/testflight.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- uses: actions/checkout@v4
1717
- uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1 # [email protected]
1818
- run: xcodes select 15.0.1
19-
- uses: ruby/setup-ruby@7bae1d00b5db9166f4f0fc47985a3a5702cb58f0 # pin@v1.197.0
19+
- uses: ruby/setup-ruby@7d3497fd78c07c0d84ebafa58d8dac60cd1f0763 # pin@v1.199.0
2020
with:
2121
ruby-version: '2.7.5'
2222
bundler-cache: true

CHANGELOG.md

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,59 @@
11
# Changelog
22

3-
## Unreleased
3+
## 8.10.1
4+
5+
### Fixes
6+
7+
- Android build error when compiling ([#2397](https://github.com/getsentry/sentry-dart/pull/2397))
8+
9+
## 8.10.0
410

511
### Features
612

13+
- Emit `transaction.data` inside `contexts.trace.data` ([#2284](https://github.com/getsentry/sentry-dart/pull/2284))
14+
- Blocking app starts span if "appLaunchedInForeground" is false. (Android only) ([#2291](https://github.com/getsentry/sentry-dart/pull/2291))
15+
- Replay: user-configurable masking (redaction) for widget classes and specific widget instances. ([#2324](https://github.com/getsentry/sentry-dart/pull/2324))
16+
Some examples of the configuration:
17+
18+
```dart
19+
await SentryFlutter.init(
20+
(options) {
21+
...
22+
options.experimental.replay.mask<IconButton>();
23+
options.experimental.replay.unmask<Image>();
24+
options.experimental.replay.maskCallback<Text>(
25+
(Element element, Text widget) =>
26+
(widget.data?.contains('secret') ?? false)
27+
? SentryMaskingDecision.mask
28+
: SentryMaskingDecision.continueProcessing);
29+
},
30+
appRunner: () => runApp(MyApp()),
31+
);
32+
```
33+
34+
Also, you can wrap any of your widgets with `SentryMask()` or `SentryUnmask()` widgets to mask/unmask them, respectively. For example:
35+
36+
```dart
37+
 SentryUnmask(Text('Not secret at all'));
38+
```
39+
40+
- Support `captureFeedback` ([#2230](https://github.com/getsentry/sentry-dart/pull/2230))
41+
- Deprecated `Sentry.captureUserFeedback`, use `captureFeedback` instead.
42+
- Deprecated `Hub.captureUserFeedback`, use `captureFeedback` instead.
43+
- Deprecated `SentryClient.captureUserFeedback`, use `captureFeedback` instead.
44+
- Deprecated `SentryUserFeedback`, use `SentryFeedback` instead.
45+
- Add `SentryFeedbackWidget` ([#2240](https://github.com/getsentry/sentry-dart/pull/2240))
46+
47+
```dart
48+
Navigator.push(
49+
context,
50+
MaterialPageRoute(
51+
builder: (context) => SentryFeedbackWidget(associatedEventId: id),
52+
fullscreenDialog: true,
53+
),
54+
);
55+
```
56+
757
- Add screenshot to `SentryFeedbackWidget` ([#2369](https://github.com/getsentry/sentry-dart/pull/2369))
858
- Use `SentryFlutter.captureScreenshot` to create a screenshot attachment
959
- Call `SentryFeedbackWidget` with this attachment to add it to the user feedback
@@ -29,11 +79,49 @@
2979

3080
### Enhancements
3181

82+
- Avoid sending too many empty client reports when Http Transport is used ([#2380](https://github.com/getsentry/sentry-dart/pull/2380))
3283
- Cache parsed DSN ([#2365](https://github.com/getsentry/sentry-dart/pull/2365))
3384
- Handle backpressure earlier in pipeline ([#2371](https://github.com/getsentry/sentry-dart/pull/2371))
3485
- Drops max un-awaited parallel tasks earlier, so event processors & callbacks are not executed for them.
3586
- Change by setting `SentryOptions.maxQueueSize`. Default is 30.
87+
- Use native spotlight integrations on Flutter Android, iOS, macOS ([#2285](https://github.com/getsentry/sentry-dart/pull/2285))
88+
- Improve app start integration ([#2266](https://github.com/getsentry/sentry-dart/pull/2266))
89+
- Fixes pendingTimer during tests ([#2103](https://github.com/getsentry/sentry-dart/issues/2103))
90+
- Fixes transaction slows app start ([#2233](https://github.com/getsentry/sentry-dart/issues/2233))
91+
- Only store slow and frozen frames for frame delay calculation ([#2337](https://github.com/getsentry/sentry-dart/pull/2337))
92+
- Add ReplayIntegration to the integrations list on events when replay is enabled. ([#2349](https://github.com/getsentry/sentry-dart/pull/2349))
93+
94+
### Fixes
95+
96+
- App lag with frame tracking enabled when span finishes after a long time ([#2311](https://github.com/getsentry/sentry-dart/pull/2311))
97+
- Only start frame tracking if we receive valid display refresh data ([#2307](https://github.com/getsentry/sentry-dart/pull/2307))
98+
- Rounding error used on frames.total and reject frame measurements if frames.total is less than frames.slow or frames.frozen ([#2308](https://github.com/getsentry/sentry-dart/pull/2308))
99+
- iOS replay integration when only `onErrorSampleRate` is specified ([#2306](https://github.com/getsentry/sentry-dart/pull/2306))
100+
- Fix TTID timing issue ([#2326](https://github.com/getsentry/sentry-dart/pull/2326))
101+
- TTFD fixes
102+
- Start missing TTFD for root screen transaction ([#2332](https://github.com/getsentry/sentry-dart/pull/2332))
103+
- Match TTFD to TTID end timespan if TTFD is unfinished when user navigates to another screen ([#2347](https://github.com/getsentry/sentry-dart/pull/2347))
104+
- TTFD measurements should only be added for successful TTFD spans ([#2348](https://github.com/getsentry/sentry-dart/pull/2348))
105+
- Error when calling `SentryFlutter.reportFullyDisplayed()` twice ([#2339](https://github.com/getsentry/sentry-dart/pull/2339))
106+
- Accessing invalid json fields from `fetchNativeAppStart` should return null ([#2340](https://github.com/getsentry/sentry-dart/pull/2340))
107+
108+
### Deprecate
109+
110+
- Metrics API ([#2312](https://github.com/getsentry/sentry-dart/pull/2312))
111+
- Learn more: https://sentry.zendesk.com/hc/en-us/articles/26369339769883-Metrics-Beta-Coming-to-an-End
36112

113+
### Dependencies
114+
115+
- Bump Native SDK from v0.7.10 to v0.7.12 ([#2390](https://github.com/getsentry/sentry-dart/pull/2390))
116+
- [changelog](https://github.com/getsentry/sentry-native/blob/master/CHANGELOG.md#0712)
117+
- [diff](https://github.com/getsentry/sentry-native/compare/0.7.10...0.7.12)
118+
- Bump Android SDK from v7.15.0 to v7.16.0 ([#2373](https://github.com/getsentry/sentry-dart/pull/2373))
119+
- [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#7160)
120+
- [diff](https://github.com/getsentry/sentry-java/compare/7.15.0...7.16.0)
121+
- Bump Cocoa SDK from v8.37.0 to v8.40.1 ([#2394](https://github.com/getsentry/sentry-dart/pull/2394))
122+
- [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#8401)
123+
- [diff](https://github.com/getsentry/sentry-cocoa/compare/8.37.0...8.40.1)
124+
37125
## 8.10.0-beta.2
38126

39127
### Fixes

dart/lib/src/sentry_client.dart

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import 'sentry_options.dart';
2020
import 'sentry_stack_trace_factory.dart';
2121
import 'sentry_trace_context_header.dart';
2222
import 'sentry_user_feedback.dart';
23+
import 'transport/client_report_transport.dart';
2324
import 'transport/data_category.dart';
2425
import 'transport/http_transport.dart';
2526
import 'transport/noop_transport.dart';
@@ -54,10 +55,17 @@ class SentryClient {
5455
if (options.sendClientReports) {
5556
options.recorder = ClientReportRecorder(options.clock);
5657
}
58+
RateLimiter? rateLimiter;
5759
if (options.transport is NoOpTransport) {
58-
final rateLimiter = RateLimiter(options);
60+
rateLimiter = RateLimiter(options);
5961
options.transport = HttpTransport(options, rateLimiter);
6062
}
63+
// rateLimiter is null if FileSystemTransport is active since Native SDKs take care of rate limiting
64+
options.transport = ClientReportTransport(
65+
rateLimiter,
66+
options,
67+
options.transport,
68+
);
6169
// TODO: Web might change soon to use the JS SDK so we can remove it here later on
6270
final enableFlutterSpotlight = (options.spotlight.enabled &&
6371
(options.platformChecker.isWeb ||
@@ -427,7 +435,7 @@ class SentryClient {
427435

428436
/// Reports the [envelope] to Sentry.io.
429437
Future<SentryId?> captureEnvelope(SentryEnvelope envelope) {
430-
return _attachClientReportsAndSend(envelope);
438+
return _options.transport.send(envelope);
431439
}
432440

433441
/// Reports the [userFeedback] to Sentry.io.
@@ -439,7 +447,7 @@ class SentryClient {
439447
_options.sdk,
440448
dsn: _options.dsn,
441449
);
442-
return _attachClientReportsAndSend(envelope);
450+
return _options.transport.send(envelope);
443451
}
444452

445453
/// Reports the [feedback] to Sentry.io.
@@ -469,7 +477,7 @@ class SentryClient {
469477
_options.sdk,
470478
dsn: _options.dsn,
471479
);
472-
final id = await _attachClientReportsAndSend(envelope);
480+
final id = await _options.transport.send(envelope);
473481
return id ?? SentryId.empty();
474482
}
475483

@@ -621,10 +629,4 @@ class SentryClient {
621629
}
622630
return DataCategory.error;
623631
}
624-
625-
Future<SentryId?> _attachClientReportsAndSend(SentryEnvelope envelope) {
626-
final clientReport = _options.recorder.flush();
627-
envelope.addClientReport(clientReport);
628-
return _options.transport.send(envelope);
629-
}
630632
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import 'package:meta/meta.dart';
2+
import '../../sentry.dart';
3+
import '../sentry_envelope_header.dart';
4+
import 'rate_limiter.dart';
5+
6+
/// Decorator that handles attaching of client reports in tandem with rate
7+
/// limiting. The rate limiter is optional.
8+
@internal
9+
class ClientReportTransport implements Transport {
10+
final RateLimiter? _rateLimiter;
11+
final SentryOptions _options;
12+
final Transport _transport;
13+
14+
ClientReportTransport(this._rateLimiter, this._options, this._transport);
15+
16+
@visibleForTesting
17+
get rateLimiter => _rateLimiter;
18+
19+
int _numberOfDroppedEnvelopes = 0;
20+
21+
@visibleForTesting
22+
get numberOfDroppedEvents => _numberOfDroppedEnvelopes;
23+
24+
@override
25+
Future<SentryId?> send(SentryEnvelope envelope) async {
26+
final rateLimiter = _rateLimiter;
27+
28+
SentryEnvelope? filteredEnvelope = envelope;
29+
if (rateLimiter != null) {
30+
filteredEnvelope = rateLimiter.filter(envelope);
31+
}
32+
if (filteredEnvelope == null) {
33+
_numberOfDroppedEnvelopes += 1;
34+
}
35+
if (_numberOfDroppedEnvelopes >= 10) {
36+
// Create new envelope that could only contain client reports
37+
filteredEnvelope = SentryEnvelope(
38+
SentryEnvelopeHeader(SentryId.newId(), _options.sdk),
39+
[],
40+
);
41+
}
42+
if (filteredEnvelope == null) {
43+
return SentryId.empty();
44+
}
45+
_numberOfDroppedEnvelopes = 0;
46+
47+
final clientReport = _options.recorder.flush();
48+
filteredEnvelope.addClientReport(clientReport);
49+
50+
if (filteredEnvelope.items.isNotEmpty) {
51+
return _transport.send(filteredEnvelope);
52+
} else {
53+
return SentryId.empty();
54+
}
55+
}
56+
}

dart/lib/src/transport/http_transport.dart

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,9 @@ class HttpTransport implements Transport {
3535

3636
@override
3737
Future<SentryId?> send(SentryEnvelope envelope) async {
38-
final filteredEnvelope = _rateLimiter.filter(envelope);
39-
if (filteredEnvelope == null) {
40-
return SentryId.empty();
41-
}
42-
filteredEnvelope.header.sentAt = _options.clock();
38+
envelope.header.sentAt = _options.clock();
4339

44-
final streamedRequest =
45-
await _requestHandler.createRequest(filteredEnvelope);
40+
final streamedRequest = await _requestHandler.createRequest(envelope);
4641

4742
final response = await _options.httpClient
4843
.send(streamedRequest)

dart/lib/src/version.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
library version;
1010

1111
/// The SDK version reported to Sentry.io in the submitted events.
12-
const String sdkVersion = '8.10.0-beta.2';
12+
const String sdkVersion = '8.10.1';
1313

1414
String sdkName(bool isWeb) => isWeb ? _browserSdkName : _ioSdkName;
1515

dart/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: sentry
2-
version: 8.10.0-beta.2
2+
version: 8.10.1
33
description: >
44
A crash reporting library for Dart that sends crash reports to Sentry.io.
55
This library supports Dart VM and Web. For Flutter consider sentry_flutter instead.

dart/test/exception_identifier_test.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ void main() {
126126

127127
group('Integration test', () {
128128
setUp(() {
129-
fixture.options.transport = MockTransport();
129+
fixture.options.transport = fixture.mockTransport;
130130
});
131131

132132
test(
@@ -139,7 +139,7 @@ void main() {
139139

140140
await client.captureException(ObfuscatedException());
141141

142-
final transport = fixture.options.transport as MockTransport;
142+
final transport = fixture.mockTransport;
143143
final capturedEnvelope = transport.envelopes.first;
144144
final capturedEvent = await eventFromEnvelope(capturedEnvelope);
145145

@@ -154,7 +154,7 @@ void main() {
154154

155155
await client.captureException(ObfuscatedException());
156156

157-
final transport = fixture.options.transport as MockTransport;
157+
final transport = fixture.mockTransport;
158158
final capturedEnvelope = transport.envelopes.first;
159159
final capturedEvent = await eventFromEnvelope(capturedEnvelope);
160160

@@ -165,6 +165,7 @@ void main() {
165165
}
166166

167167
class Fixture {
168+
final mockTransport = MockTransport();
168169
SentryOptions options = defaultTestOptions();
169170
}
170171

dart/test/mocks/mock_transport.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ class MockTransport implements Transport {
1616
return _calls;
1717
}
1818

19+
bool parseFromEnvelope = true;
20+
1921
bool called(int calls) {
2022
return _calls == calls;
2123
}
@@ -28,7 +30,9 @@ class MockTransport implements Transport {
2830
// failure causes. Instead, we log them and check on access to [calls].
2931
try {
3032
envelopes.add(envelope);
31-
await _eventFromEnvelope(envelope);
33+
if (parseFromEnvelope) {
34+
await _eventFromEnvelope(envelope);
35+
}
3236
} catch (e, stack) {
3337
_exceptions += '$e\n$stack\n\n';
3438
rethrow;

0 commit comments

Comments
 (0)