diff --git a/CHANGELOG.md b/CHANGELOG.md index 99eef6e809..9c1f5617b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,22 @@ - Sync `connectionTimeout` and `readTimeout` to Android ([#1397](https://github.com/getsentry/sentry-dart/pull/1397)) - Set User `name` and `geo` in native plugins ([#1393](https://github.com/getsentry/sentry-dart/pull/1393)) - Add processor count to device info ([#1402](https://github.com/getsentry/sentry-dart/pull/1402)) +- Add attachments to `Hint` ([#1404](https://github.com/getsentry/sentry-dart/pull/1404)) + +```dart +import 'dart:convert'; + +options.beforeSend = (event, {hint}) { + final text = 'This event should not be sent happen in prod. Investigate.'; + final textAttachment = SentryAttachment.fromIntList( + utf8.encode(text), + 'event_info.txt', + contentType: 'text/plain', + ); + hint?.attachments.add(textAttachment); + return event; +}; +``` ### Fixes diff --git a/dart/lib/src/hint.dart b/dart/lib/src/hint.dart index f88be70a65..87620d7ba1 100644 --- a/dart/lib/src/hint.dart +++ b/dart/lib/src/hint.dart @@ -20,15 +20,48 @@ import 'sentry_attachment/sentry_attachment.dart'; /// }; /// } /// ``` +/// +/// The [Hint] can also be used to add attachments to events. +/// +/// Example: +/// +/// ```dart +/// import 'dart:convert'; +/// +/// options.beforeSend = (event, {hint}) { +/// final text = 'This event should not be sent happen in prod. Investigate.'; +/// final textAttachment = SentryAttachment.fromIntList( +/// utf8.encode(text), +/// 'event_info.txt', +/// contentType: 'text/plain', +/// ); +/// hint?.attachments.add(textAttachment); +/// return event; +/// }; +/// ``` class Hint { final Map _internalStorage = {}; + final List attachments = []; + SentryAttachment? screenshot; SentryAttachment? viewHierarchy; Hint(); + factory Hint.withAttachment(SentryAttachment attachment) { + final hint = Hint(); + hint.attachments.add(attachment); + return hint; + } + + factory Hint.withAttachments(List attachments) { + final hint = Hint(); + hint.attachments.addAll(attachments); + return hint; + } + factory Hint.withMap(Map map) { final hint = Hint(); hint.addAll(map); diff --git a/dart/lib/src/sentry_client.dart b/dart/lib/src/sentry_client.dart index fef17b6eab..09f98e4d02 100644 --- a/dart/lib/src/sentry_client.dart +++ b/dart/lib/src/sentry_client.dart @@ -111,6 +111,7 @@ class SentryClient { preparedEvent = _eventWithoutBreadcrumbsIfNeeded(preparedEvent); var attachments = List.from(scope?.attachments ?? []); + attachments.addAll(hint.attachments); var screenshot = hint.screenshot; if (screenshot != null) { attachments.add(screenshot); diff --git a/dart/test/hint_test.dart b/dart/test/hint_test.dart index e0b686820f..d46a022405 100644 --- a/dart/test/hint_test.dart +++ b/dart/test/hint_test.dart @@ -1,7 +1,14 @@ import 'package:sentry/src/hint.dart'; +import 'package:sentry/src/sentry_attachment/sentry_attachment.dart'; import 'package:test/test.dart'; void main() { + late Fixture fixture; + + setUp(() { + fixture = Fixture(); + }); + test('Hint init with map', () { final hint = Hint.withMap({'fixture-key': 'fixture-value'}); expect("fixture-value", hint.get("fixture-key")); @@ -60,4 +67,25 @@ void main() { expect(hint.get("hint1"), null); expect(hint.get("hint2"), null); }); + + test('clear does not remove attachments, screenshot & viewHierarchy', () { + final attachment = SentryAttachment.fromIntList([], "fixture-fileName"); + + final sut = fixture.givenSut(); + sut.attachments.add(attachment); + sut.screenshot = attachment; + sut.viewHierarchy = attachment; + + sut.clear(); + + expect(sut.attachments.contains(attachment), true); + expect(sut.screenshot, attachment); + expect(sut.viewHierarchy, attachment); + }); +} + +class Fixture { + Hint givenSut() { + return Hint(); + } } diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index 1669e9049e..c055f3449f 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -1413,6 +1413,20 @@ void main() { expect(envelope.header.traceContext, isNotNull); }); + test('captureEvent adds attachments from hint', () async { + final attachment = SentryAttachment.fromIntList([], "fixture-fileName"); + final hint = Hint.withAttachment(attachment); + + final sut = fixture.getSut(); + await sut.captureEvent(fakeEvent, hint: hint); + + final capturedEnvelope = (fixture.transport).envelopes.first; + final attachmentItem = capturedEnvelope.items.firstWhereOrNull( + (element) => element.header.type == SentryItemType.attachment); + expect(attachmentItem?.header.attachmentType, + SentryAttachment.typeAttachmentDefault); + }); + test('captureEvent adds screenshot from hint', () async { final client = fixture.getSut(); final screenshot =