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

Screenshot Grouping #2754

Open
wants to merge 3 commits into
base: v9
Choose a base branch
from
Open
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
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
- Responses are attached to the `Hint` object, which can be read in `beforeSend`/`beforeSendTransaction` callbacks via `hint.response`.
- For now, only the `dio` integration is supported.
- Enable privacy masking for screenshots by default ([#2728](https://github.com/getsentry/sentry-dart/pull/2728))

- Screenshot Grouping ([#2754](https://github.com/getsentry/sentry-dart/pull/2754))
Copy link
Contributor

Choose a reason for hiding this comment

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

  • 🚫 The changelog entry seems to be part of an already released section ## 9.0.0.
    Consider moving the entry to the ## Unreleased section, please.

- Moved `SentryFlutterOptions.attachScreenshot` to `SentryFlutterOptions.screenshot.attach`
- Moved `SentryFlutterOptions.screenshotQuality` to `SentryFlutterOptions.screenshot.quality`
- Moved `SentryFlutterOptions.beforeCaptureScreenshot` to `SentryFlutterOptions.screenshot.beforeCapture`

### Enhancements

- Replay: improve Android native interop performance by using JNI ([#2670](https://github.com/getsentry/sentry-dart/pull/2670))
Expand Down
2 changes: 1 addition & 1 deletion flutter/example/integration_test/web_sdk_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ void main() {
await restoreFlutterOnErrorAfter(() async {
await SentryFlutter.init((options) {
options.dsn = fakeDsn;
options.attachScreenshot = true;
options.screenshot.attach = true;

confOptions = options;
}, appRunner: () async {
Expand Down
2 changes: 1 addition & 1 deletion flutter/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Future<void> setupSentry(
options.addIntegration(LoggingIntegration(minEventLevel: Level.INFO));
options.sendDefaultPii = true;
options.reportSilentFlutterErrors = true;
options.attachScreenshot = true;
options.screenshot.attach = true;
options.attachViewHierarchy = true;
// We can enable Sentry debug logging during development. This is likely
// going to log too much for your app, but can be useful when figuring out
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class ScreenshotEventProcessor implements EventProcessor {
late final Debouncer _debouncer;

ScreenshotEventProcessor(this._options) {
final targetResolution = _options.screenshotQuality.targetResolution();
final targetResolution = _options.screenshot.quality.targetResolution();
_recorder = ScreenshotRecorder(
ScreenshotRecorderConfig(
width: targetResolution,
Expand Down Expand Up @@ -50,7 +50,7 @@ class ScreenshotEventProcessor implements EventProcessor {
// skip capturing in case of debouncing (=too many frequent capture requests)
// the BeforeCaptureCallback may overrule the debouncing decision
final shouldDebounce = _debouncer.shouldDebounce();
final beforeCaptureScreenshot = _options.beforeCaptureScreenshot;
final beforeCaptureScreenshot = _options.screenshot.beforeCapture;

try {
FutureOr<bool>? result;
Expand Down
4 changes: 2 additions & 2 deletions flutter/lib/src/integrations/screenshot_integration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import '../event_processor/screenshot_event_processor.dart';
import '../sentry_flutter_options.dart';

/// Adds [ScreenshotEventProcessor] to options event processors if
/// [SentryFlutterOptions.attachScreenshot] is true
/// [SentryFlutterOptions.attach] is true
class ScreenshotIntegration implements Integration<SentryFlutterOptions> {
SentryFlutterOptions? _options;
ScreenshotEventProcessor? _screenshotEventProcessor;
Expand All @@ -18,7 +18,7 @@ class ScreenshotIntegration implements Integration<SentryFlutterOptions> {
);
return;
}
if (options.attachScreenshot) {
if (options.screenshot.attach) {
_options = options;
final screenshotEventProcessor = ScreenshotEventProcessor(options);
options.addEventProcessor(screenshotEventProcessor);
Expand Down
35 changes: 20 additions & 15 deletions flutter/lib/src/sentry_flutter_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -172,21 +172,8 @@ class SentryFlutterOptions extends SentryOptions {
/// Enable auto performance tracking by default.
bool enableAutoPerformanceTracing = true;

/// Automatically attaches a screenshot when capturing an error or exception.
///
/// Requires adding the [SentryWidget] to the widget tree.
/// Example:
/// runApp(SentryWidget(child: App()));
/// The [SentryWidget] has to be the root widget of the app.
bool attachScreenshot = false;

/// The quality of the attached screenshot
SentryScreenshotQuality screenshotQuality = SentryScreenshotQuality.high;

/// Sets a callback which is executed before capturing screenshots. Only
/// relevant if `attachScreenshot` is set to true. When false is returned
/// from the function, no screenshot will be attached.
BeforeCaptureCallback? beforeCaptureScreenshot;
/// Collection of screenshot options.
SentryFlutterScreenshotOptions screenshot = SentryFlutterScreenshotOptions();

/// Enable or disable automatic breadcrumbs for User interactions Using [Listener]
///
Expand Down Expand Up @@ -385,6 +372,24 @@ class _SentryFlutterExperimentalOptions {
final privacy = SentryPrivacyOptions();
}

class SentryFlutterScreenshotOptions {
/// Automatically attaches a screenshot when capturing an error or exception.
///
/// Requires adding the [SentryWidget] to the widget tree.
/// Example:
/// runApp(SentryWidget(child: App()));
/// The [SentryWidget] has to be the root widget of the app.
bool attach = false;

/// The quality of the attached screenshot
SentryScreenshotQuality quality = SentryScreenshotQuality.high;

/// Sets a callback which is executed before capturing screenshots. Only
/// relevant if `attach` is set to true. When false is returned from the
/// function, no screenshot will be attached.
BeforeCaptureCallback? beforeCapture;
}

/// A callback which can be used to suppress capturing of screenshots.
/// It's called in [ScreenshotEventProcessor] if screenshots are enabled.
/// This gives more fine-grained control over when capturing should be performed,
Expand Down
24 changes: 12 additions & 12 deletions flutter/test/event_processor/screenshot_event_processor_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -83,23 +83,23 @@ void main() {
testWidgets('does add screenshot in correct resolution for low',
(tester) async {
final height = SentryScreenshotQuality.low.targetResolution()!;
fixture.options.screenshotQuality = SentryScreenshotQuality.low;
fixture.options.screenshot.quality = SentryScreenshotQuality.low;
await _addScreenshotAttachment(tester, null,
added: true, isWeb: false, expectedMaxWidthOrHeight: height);
});

testWidgets('does add screenshot in correct resolution for medium',
(tester) async {
final height = SentryScreenshotQuality.medium.targetResolution()!;
fixture.options.screenshotQuality = SentryScreenshotQuality.medium;
fixture.options.screenshot.quality = SentryScreenshotQuality.medium;
await _addScreenshotAttachment(tester, null,
added: true, isWeb: false, expectedMaxWidthOrHeight: height);
});

testWidgets('does add screenshot in correct resolution for high',
(tester) async {
final widthOrHeight = SentryScreenshotQuality.high.targetResolution()!;
fixture.options.screenshotQuality = SentryScreenshotQuality.high;
fixture.options.screenshot.quality = SentryScreenshotQuality.high;
await _addScreenshotAttachment(tester, null,
added: true, isWeb: false, expectedMaxWidthOrHeight: widthOrHeight);
});
Expand Down Expand Up @@ -137,7 +137,7 @@ void main() {
group('beforeCaptureScreenshot', () {
testWidgets('does add screenshot if beforeCapture returns true',
(tester) async {
fixture.options.beforeCaptureScreenshot =
fixture.options.screenshot.beforeCapture =
(SentryEvent event, Hint hint, bool shouldDebounce) {
return true;
};
Expand All @@ -147,7 +147,7 @@ void main() {

testWidgets('does add screenshot if async beforeCapture returns true',
(tester) async {
fixture.options.beforeCaptureScreenshot =
fixture.options.screenshot.beforeCapture =
(SentryEvent event, Hint hint, bool shouldDebounce) async {
await Future<void>.delayed(Duration(milliseconds: 1));
return true;
Expand All @@ -158,7 +158,7 @@ void main() {

testWidgets('does not add screenshot if beforeCapture returns false',
(tester) async {
fixture.options.beforeCaptureScreenshot =
fixture.options.screenshot.beforeCapture =
(SentryEvent event, Hint hint, bool shouldDebounce) {
return false;
};
Expand All @@ -168,7 +168,7 @@ void main() {

testWidgets('does not add screenshot if async beforeCapture returns false',
(tester) async {
fixture.options.beforeCaptureScreenshot =
fixture.options.screenshot.beforeCapture =
(SentryEvent event, Hint hint, bool shouldDebounce) async {
await Future<void>.delayed(Duration(milliseconds: 1));
return false;
Expand All @@ -179,7 +179,7 @@ void main() {

testWidgets('does add screenshot if beforeCapture throws', (tester) async {
fixture.options.automatedTestMode = false;
fixture.options.beforeCaptureScreenshot =
fixture.options.screenshot.beforeCapture =
(SentryEvent event, Hint hint, bool shouldDebounce) {
throw Error();
};
Expand All @@ -190,7 +190,7 @@ void main() {
testWidgets('does add screenshot if async beforeCapture throws',
(tester) async {
fixture.options.automatedTestMode = false;
fixture.options.beforeCaptureScreenshot =
fixture.options.screenshot.beforeCapture =
(SentryEvent event, Hint hint, bool shouldDebounce) async {
await Future<void>.delayed(Duration(milliseconds: 1));
throw Error();
Expand All @@ -204,7 +204,7 @@ void main() {
await tester.runAsync(() async {
var shouldDebounceValues = <bool>[];

fixture.options.beforeCaptureScreenshot =
fixture.options.screenshot.beforeCapture =
(SentryEvent event, Hint hint, bool shouldDebounce) {
shouldDebounceValues.add(shouldDebounce);
return true;
Expand Down Expand Up @@ -241,7 +241,7 @@ void main() {
SentryEvent? beforeScreenshotEvent;
Hint? beforeScreenshotHint;

fixture.options.beforeCaptureScreenshot =
fixture.options.screenshot.beforeCapture =
(SentryEvent event, Hint hint, bool shouldDebounce) {
beforeScreenshotEvent = event;
beforeScreenshotHint = hint;
Expand Down Expand Up @@ -342,7 +342,7 @@ class Fixture {
SentryFlutterOptions options = defaultTestOptions();

Fixture() {
options.attachScreenshot = true;
options.screenshot.attach = true;
hub = Hub(options);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class Fixture {
final options = defaultTestOptions();

ScreenshotIntegration getSut({bool attachScreenshot = true}) {
options.attachScreenshot = attachScreenshot;
options.screenshot.attach = attachScreenshot;
return ScreenshotIntegration();
}
}
2 changes: 1 addition & 1 deletion min_version_test/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Future<void> setupSentry(AppRunner appRunner) async {
options.addIntegration(LoggingIntegration());
options.sendDefaultPii = true;
options.reportSilentFlutterErrors = true;
options.attachScreenshot = true;
options.screenshot.attach = true;
options.attachViewHierarchy = true;
// We can enable Sentry debug logging during development. This is likely
// going to log too much for your app, but can be useful when figuring out
Expand Down
Loading