diff --git a/.gitattributes b/.gitattributes index a19ade077d..82afe757ba 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ CHANGELOG.md merge=union +* text=auto eol=lf diff --git a/CHANGELOG.md b/CHANGELOG.md index a81fb8e16d..c3fc27ce76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ### Features - Added [Flutter renderer](https://docs.flutter.dev/development/platform-integration/web/renderers) information to events ([#1035](https://github.com/getsentry/sentry-dart/pull/1035)) +- Added missing DSN field into the SentryEnvelopeHeader ([#1050](https://github.com/getsentry/sentry-dart/pull/1050)) ### Dependencies diff --git a/dart/lib/src/sentry_client.dart b/dart/lib/src/sentry_client.dart index b250badf7e..ec63372f7a 100644 --- a/dart/lib/src/sentry_client.dart +++ b/dart/lib/src/sentry_client.dart @@ -133,6 +133,7 @@ class SentryClient { final envelope = SentryEnvelope.fromEvent( preparedEvent, _options.sdk, + dsn: _options.dsn, traceContext: scope?.span?.traceContext(), attachments: scope?.attachments, ); @@ -318,6 +319,7 @@ class SentryClient { final envelope = SentryEnvelope.fromTransaction( preparedTransaction, _options.sdk, + dsn: _options.dsn, traceContext: traceContext, attachments: attachments, ); @@ -336,6 +338,7 @@ class SentryClient { final envelope = SentryEnvelope.fromUserFeedback( userFeedback, _options.sdk, + dsn: _options.dsn, ); return _attachClientReportsAndSend(envelope); } diff --git a/dart/lib/src/sentry_envelope.dart b/dart/lib/src/sentry_envelope.dart index f090e26ea3..eb62aeec47 100644 --- a/dart/lib/src/sentry_envelope.dart +++ b/dart/lib/src/sentry_envelope.dart @@ -24,6 +24,7 @@ class SentryEnvelope { factory SentryEnvelope.fromEvent( SentryEvent event, SdkVersion sdkVersion, { + String? dsn, SentryTraceContextHeader? traceContext, List? attachments, }) { @@ -31,6 +32,7 @@ class SentryEnvelope { SentryEnvelopeHeader( event.eventId, sdkVersion, + dsn: dsn, traceContext: traceContext, ), [ @@ -43,11 +45,16 @@ class SentryEnvelope { factory SentryEnvelope.fromUserFeedback( SentryUserFeedback feedback, - SdkVersion sdkVersion, - ) { + SdkVersion sdkVersion, { + String? dsn, + }) { return SentryEnvelope( // no need for [traceContext] - SentryEnvelopeHeader(feedback.eventId, sdkVersion), + SentryEnvelopeHeader( + feedback.eventId, + sdkVersion, + dsn: dsn, + ), [SentryEnvelopeItem.fromUserFeedback(feedback)], ); } @@ -56,6 +63,7 @@ class SentryEnvelope { factory SentryEnvelope.fromTransaction( SentryTransaction transaction, SdkVersion sdkVersion, { + String? dsn, SentryTraceContextHeader? traceContext, List? attachments, }) { @@ -63,6 +71,7 @@ class SentryEnvelope { SentryEnvelopeHeader( transaction.eventId, sdkVersion, + dsn: dsn, traceContext: traceContext, ), [ diff --git a/dart/lib/src/sentry_envelope_header.dart b/dart/lib/src/sentry_envelope_header.dart index 5fe941ab04..c6b2bb9ead 100644 --- a/dart/lib/src/sentry_envelope_header.dart +++ b/dart/lib/src/sentry_envelope_header.dart @@ -7,11 +7,13 @@ class SentryEnvelopeHeader { SentryEnvelopeHeader( this.eventId, this.sdkVersion, { + this.dsn, this.traceContext, }); SentryEnvelopeHeader.newEventId() : eventId = SentryId.newId(), sdkVersion = null, + dsn = null, traceContext = null; /// The identifier of encoded `SentryEvent`. @@ -22,6 +24,9 @@ class SentryEnvelopeHeader { final SentryTraceContextHeader? traceContext; + /// The `DSN` of the Sentry project. + final String? dsn; + /// Header encoded as JSON Map toJson() { final json = {}; @@ -41,6 +46,9 @@ class SentryEnvelopeHeader { json['trace'] = tempTraceContext.toJson(); } + if (dsn != null) { + json['dsn'] = dsn; + } return json; } } diff --git a/dart/test/mocks.dart b/dart/test/mocks.dart index cb36172d06..836dccc762 100644 --- a/dart/test/mocks.dart +++ b/dart/test/mocks.dart @@ -129,7 +129,10 @@ typedef EventProcessorFunction = FutureOr Function(SentryEvent event, {dynamic hint}); var fakeEnvelope = SentryEnvelope.fromEvent( - fakeEvent, SdkVersion(name: 'sdk1', version: '1.0.0')); + fakeEvent, + SdkVersion(name: 'sdk1', version: '1.0.0'), + dsn: fakeDsn, +); class MockRateLimiter implements RateLimiter { bool filterReturnsNull = false; diff --git a/dart/test/sentry_client_test.dart b/dart/test/sentry_client_test.dart index 5161fcb53b..2cc2d15e62 100644 --- a/dart/test/sentry_client_test.dart +++ b/dart/test/sentry_client_test.dart @@ -195,6 +195,16 @@ void main() { expect(capturedEvent.threads?.first.stacktrace, isNull); }); + + test('event envelope contains dsn', () async { + final client = fixture.getSut(); + final event = SentryEvent(); + await client.captureEvent(event); + + final capturedEnvelope = (fixture.transport).envelopes.first; + + expect(capturedEnvelope.header.dsn, fixture.options.dsn); + }); }); group('SentryClient captures exception', () { @@ -468,6 +478,16 @@ void main() { expect(id, SentryId.empty()); }); + + test('transaction envelope contains dsn', () async { + final client = fixture.getSut(); + final tr = SentryTransaction(fixture.tracer); + await client.captureTransaction(tr); + + final capturedEnvelope = (fixture.transport).envelopes.first; + + expect(capturedEnvelope.header.dsn, fixture.options.dsn); + }); }); group('SentryClient : apply scope to the captured event', () { @@ -1193,6 +1213,20 @@ void main() { expect(fixture.recorder.reason, DiscardReason.sampleRate); expect(fixture.recorder.category, DataCategory.error); }); + + test('user feedback envelope contains dsn', () async { + final client = fixture.getSut(); + final event = SentryEvent(); + final feedback = SentryUserFeedback( + eventId: event.eventId, + name: 'test', + ); + await client.captureUserFeedback(feedback); + + final capturedEnvelope = (fixture.transport).envelopes.first; + + expect(capturedEnvelope.header.dsn, fixture.options.dsn); + }); }); } diff --git a/dart/test/sentry_envelope_header_test.dart b/dart/test/sentry_envelope_header_test.dart index 912a7ef9e3..23b06a1c5c 100644 --- a/dart/test/sentry_envelope_header_test.dart +++ b/dart/test/sentry_envelope_header_test.dart @@ -2,6 +2,8 @@ import 'package:sentry/sentry.dart'; import 'package:sentry/src/sentry_envelope_header.dart'; import 'package:test/test.dart'; +import 'mocks.dart'; + void main() { group('SentryEnvelopeHeader', () { test('toJson empty', () { @@ -23,6 +25,7 @@ void main() { final sut = SentryEnvelopeHeader( eventId, sdkVersion, + dsn: fakeDsn, traceContext: context, ); final expextedSkd = sdkVersion.toJson(); @@ -30,6 +33,7 @@ void main() { 'event_id': eventId.toString(), 'sdk': expextedSkd, 'trace': context.toJson(), + 'dsn': fakeDsn, }; expect(sut.toJson(), expected); }); diff --git a/dart/test/sentry_envelope_test.dart b/dart/test/sentry_envelope_test.dart index c7c683995a..0b4aa4348f 100644 --- a/dart/test/sentry_envelope_test.dart +++ b/dart/test/sentry_envelope_test.dart @@ -9,6 +9,7 @@ import 'package:sentry/src/sentry_tracer.dart'; import 'package:sentry/src/utils.dart'; import 'package:test/test.dart'; +import 'mocks.dart'; import 'mocks/mock_hub.dart'; void main() { @@ -67,6 +68,7 @@ void main() { final sut = SentryEnvelope.fromEvent( sentryEvent, sdkVersion, + dsn: fakeDsn, traceContext: context, ); @@ -75,6 +77,7 @@ void main() { expect(sut.header.eventId, eventId); expect(sut.header.sdkVersion, sdkVersion); expect(sut.header.traceContext, context); + expect(sut.header.dsn, fakeDsn); expect(sut.items[0].header.contentType, expectedEnvelopeItem.header.contentType); expect(sut.items[0].header.type, expectedEnvelopeItem.header.type); @@ -105,6 +108,7 @@ void main() { final sut = SentryEnvelope.fromTransaction( tr, sdkVersion, + dsn: fakeDsn, traceContext: traceContext, ); @@ -113,6 +117,7 @@ void main() { expect(sut.header.eventId, tr.eventId); expect(sut.header.sdkVersion, sdkVersion); expect(sut.header.traceContext, traceContext); + expect(sut.header.dsn, fakeDsn); expect(sut.items[0].header.contentType, expectedEnvelopeItem.header.contentType); expect(sut.items[0].header.type, expectedEnvelopeItem.header.type); @@ -140,12 +145,14 @@ void main() { final sut = SentryEnvelope.fromEvent( sentryEvent, sdkVersion, + dsn: fakeDsn, attachments: [attachment], ); final expectedEnvelopeItem = SentryEnvelope.fromEvent( sentryEvent, sdkVersion, + dsn: fakeDsn, ); final sutEnvelopeData = []; @@ -171,6 +178,7 @@ void main() { name: 'test', version: '1', ), + dsn: fakeDsn, ); final _ = sut.envelopeStream(SentryOptions()).map((e) => e); diff --git a/dart/test/sentry_envelope_vm_test.dart b/dart/test/sentry_envelope_vm_test.dart index 33dce0515d..8e216bf226 100644 --- a/dart/test/sentry_envelope_vm_test.dart +++ b/dart/test/sentry_envelope_vm_test.dart @@ -1,4 +1,5 @@ @TestOn('vm') +import 'dart:convert'; import 'dart:io'; import 'package:sentry/sentry_io.dart'; @@ -6,6 +7,8 @@ import 'package:sentry/src/sentry_envelope_header.dart'; import 'package:sentry/src/sentry_envelope_item_header.dart'; import 'package:test/test.dart'; +import 'mocks.dart'; + void main() { group('SentryEnvelopeItem', () { test('item with binary payload', () async { @@ -50,248 +53,21 @@ void main() { final sdkVersion = SdkVersion(name: '', version: ''); final attachment = IoSentryAttachment.fromPath('this_path_does_not_exist.txt'); - final envelope = SentryEnvelope.fromEvent( event, sdkVersion, + dsn: fakeDsn, attachments: [attachment], ); final data = (await envelope.envelopeStream(SentryOptions()).toList()) .reduce((a, b) => a + b); - expect(data, envelopeBinaryData); + final file = File('test_resources/envelope-no-attachment.envelope'); + final jsonStr = await file.readAsString(); + final dataStr = utf8.decode(data); + + expect(dataStr, jsonStr); }); }); } - -final envelopeBinaryData = [ - 123, - 34, - 101, - 118, - 101, - 110, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 34, - 44, - 34, - 115, - 100, - 107, - 34, - 58, - 123, - 34, - 110, - 97, - 109, - 101, - 34, - 58, - 34, - 34, - 44, - 34, - 118, - 101, - 114, - 115, - 105, - 111, - 110, - 34, - 58, - 34, - 34, - 125, - 125, - 10, - 123, - 34, - 99, - 111, - 110, - 116, - 101, - 110, - 116, - 95, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 97, - 112, - 112, - 108, - 105, - 99, - 97, - 116, - 105, - 111, - 110, - 47, - 106, - 115, - 111, - 110, - 34, - 44, - 34, - 116, - 121, - 112, - 101, - 34, - 58, - 34, - 101, - 118, - 101, - 110, - 116, - 34, - 44, - 34, - 108, - 101, - 110, - 103, - 116, - 104, - 34, - 58, - 56, - 54, - 125, - 10, - 123, - 34, - 101, - 118, - 101, - 110, - 116, - 95, - 105, - 100, - 34, - 58, - 34, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 48, - 34, - 44, - 34, - 116, - 105, - 109, - 101, - 115, - 116, - 97, - 109, - 112, - 34, - 58, - 34, - 49, - 57, - 55, - 48, - 45, - 48, - 49, - 45, - 48, - 49, - 84, - 48, - 48, - 58, - 48, - 48, - 58, - 48, - 48, - 46, - 48, - 48, - 48, - 90, - 34, - 125 -]; diff --git a/dart/test/sentry_user_feedback_test.dart b/dart/test/sentry_user_feedback_test.dart index 132a564b97..ae1d4d8bff 100644 --- a/dart/test/sentry_user_feedback_test.dart +++ b/dart/test/sentry_user_feedback_test.dart @@ -77,6 +77,7 @@ void main() { final envelope = SentryEnvelope.fromUserFeedback( feedback, SdkVersion(name: 'a', version: 'b'), + dsn: fakeDsn, ); expect(envelope.items.length, 1); @@ -85,6 +86,7 @@ void main() { SentryItemType.userFeedback, ); expect(envelope.header.eventId.toString(), feedback.eventId.toString()); + expect(envelope.header.dsn, fakeDsn); }); }); diff --git a/dart/test/transport/http_transport_test.dart b/dart/test/transport/http_transport_test.dart index d6394c9c3f..876feb6f15 100644 --- a/dart/test/transport/http_transport_test.dart +++ b/dart/test/transport/http_transport_test.dart @@ -2,17 +2,16 @@ import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:http/testing.dart'; +import 'package:sentry/sentry.dart'; import 'package:sentry/src/client_reports/discard_reason.dart'; import 'package:sentry/src/sentry_envelope_header.dart'; import 'package:sentry/src/sentry_envelope_item_header.dart'; import 'package:sentry/src/sentry_item_type.dart'; +import 'package:sentry/src/sentry_tracer.dart'; import 'package:sentry/src/transport/data_category.dart'; +import 'package:sentry/src/transport/http_transport.dart'; import 'package:sentry/src/transport/rate_limiter.dart'; import 'package:test/test.dart'; -import 'package:sentry/src/sentry_tracer.dart'; - -import 'package:sentry/sentry.dart'; -import 'package:sentry/src/transport/http_transport.dart'; import '../mocks.dart'; import '../mocks/mock_client_report_recorder.dart'; @@ -70,8 +69,11 @@ void main() { final sut = fixture.getSut(httpMock, mockRateLimiter); final sentryEvent = SentryEvent(); - final envelope = - SentryEnvelope.fromEvent(sentryEvent, fixture.options.sdk); + final envelope = SentryEnvelope.fromEvent( + sentryEvent, + fixture.options.sdk, + dsn: fixture.options.dsn, + ); await sut.send(envelope); final envelopeData = []; @@ -94,8 +96,11 @@ void main() { final sut = fixture.getSut(httpMock, mockRateLimiter); final sentryEvent = SentryEvent(); - final envelope = - SentryEnvelope.fromEvent(sentryEvent, fixture.options.sdk); + final envelope = SentryEnvelope.fromEvent( + sentryEvent, + fixture.options.sdk, + dsn: fixture.options.dsn, + ); final eventId = await sut.send(envelope); expect(eventId, SentryId.empty()); @@ -118,8 +123,11 @@ void main() { final sut = fixture.getSut(httpMock, mockRateLimiter); final sentryEvent = SentryEvent(); - final envelope = - SentryEnvelope.fromEvent(sentryEvent, fixture.options.sdk); + final envelope = SentryEnvelope.fromEvent( + sentryEvent, + fixture.options.sdk, + dsn: fixture.options.dsn, + ); await sut.send(envelope); expect(mockRateLimiter.envelopeToFilter?.header.eventId, @@ -139,8 +147,11 @@ void main() { final sut = fixture.getSut(httpMock, mockRateLimiter); final sentryEvent = SentryEvent(); - final envelope = - SentryEnvelope.fromEvent(sentryEvent, fixture.options.sdk); + final envelope = SentryEnvelope.fromEvent( + sentryEvent, + fixture.options.sdk, + dsn: fixture.options.dsn, + ); await sut.send(envelope); expect(mockRateLimiter.errorCode, 200); @@ -164,8 +175,11 @@ void main() { final sut = fixture.getSut(httpMock, MockRateLimiter()); final sentryEvent = SentryEvent(); - final envelope = - SentryEnvelope.fromEvent(sentryEvent, fixture.options.sdk); + final envelope = SentryEnvelope.fromEvent( + sentryEvent, + fixture.options.sdk, + dsn: fixture.options.dsn, + ); await sut.send(envelope); expect(fixture.clientReportRecorder.reason, DiscardReason.networkError); @@ -179,8 +193,11 @@ void main() { final sut = fixture.getSut(httpMock, MockRateLimiter()); final sentryEvent = SentryEvent(); - final envelope = - SentryEnvelope.fromEvent(sentryEvent, fixture.options.sdk); + final envelope = SentryEnvelope.fromEvent( + sentryEvent, + fixture.options.sdk, + dsn: fixture.options.dsn, + ); await sut.send(envelope); expect(fixture.clientReportRecorder.reason, null); @@ -194,8 +211,11 @@ void main() { final sut = fixture.getSut(httpMock, MockRateLimiter()); final sentryEvent = SentryEvent(); - final envelope = - SentryEnvelope.fromEvent(sentryEvent, fixture.options.sdk); + final envelope = SentryEnvelope.fromEvent( + sentryEvent, + fixture.options.sdk, + dsn: fixture.options.dsn, + ); await sut.send(envelope); expect(fixture.clientReportRecorder.reason, DiscardReason.networkError); diff --git a/dart/test_resources/envelope-no-attachment.envelope b/dart/test_resources/envelope-no-attachment.envelope new file mode 100644 index 0000000000..0faac03efa --- /dev/null +++ b/dart/test_resources/envelope-no-attachment.envelope @@ -0,0 +1,3 @@ +{"event_id":"00000000000000000000000000000000","sdk":{"name":"","version":""},"dsn":"https://abc@def.ingest.sentry.io/1234567"} +{"content_type":"application/json","type":"event","length":86} +{"event_id":"00000000000000000000000000000000","timestamp":"1970-01-01T00:00:00.000Z"} \ No newline at end of file diff --git a/dio/test/mocks.dart b/dio/test/mocks.dart index b17a27e8b6..f12bc2c4aa 100644 --- a/dio/test/mocks.dart +++ b/dio/test/mocks.dart @@ -131,6 +131,7 @@ typedef EventProcessorFunction = FutureOr var fakeEnvelope = SentryEnvelope.fromEvent( fakeEvent, SdkVersion(name: 'sdk1', version: '1.0.0'), + dsn: fakeDsn, ); class MockRateLimiter implements RateLimiter { diff --git a/flutter/test/android_platform_exception_event_processor_test.dart b/flutter/test/android_platform_exception_event_processor_test.dart index 77a85724da..cbc375b837 100644 --- a/flutter/test/android_platform_exception_event_processor_test.dart +++ b/flutter/test/android_platform_exception_event_processor_test.dart @@ -7,7 +7,7 @@ import 'package:package_info_plus/package_info_plus.dart'; import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/src/event_processor/android_platform_exception_event_processor.dart'; -import 'integrations/native_app_start_integration_test.dart'; +import 'mocks.dart'; void main() { late Fixture fixture; diff --git a/flutter/test/file_system_transport_test.dart b/flutter/test/file_system_transport_test.dart index 6d066d53c7..a8c185fae3 100644 --- a/flutter/test/file_system_transport_test.dart +++ b/flutter/test/file_system_transport_test.dart @@ -10,6 +10,8 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:sentry/sentry.dart'; import 'package:sentry_flutter/src/file_system_transport.dart'; +import 'mocks.dart'; + void main() { const _channel = MethodChannel('sentry_flutter'); @@ -33,7 +35,11 @@ void main() { final sdkVersion = SdkVersion(name: 'fixture-sdkName', version: 'fixture-sdkVersion'); - final envelope = SentryEnvelope.fromEvent(event, sdkVersion); + final envelope = SentryEnvelope.fromEvent( + event, + sdkVersion, + dsn: fixture.options.dsn, + ); final sentryId = await transport.send(envelope); expect(sentryId, sentryId); @@ -49,7 +55,11 @@ void main() { final sdkVersion = SdkVersion(name: 'fixture-sdkName', version: 'fixture-sdkVersion'); - final envelope = SentryEnvelope.fromEvent(event, sdkVersion); + final envelope = SentryEnvelope.fromEvent( + event, + sdkVersion, + dsn: fixture.options.dsn, + ); final sentryId = await transport.send(envelope); expect(SentryId.empty(), sentryId); @@ -67,7 +77,11 @@ void main() { SentryEvent(message: SentryMessage('hi I am a special char ◤')); final sdkVersion = SdkVersion(name: 'fixture-sdkName', version: 'fixture-sdkVersion'); - final envelope = SentryEnvelope.fromEvent(event, sdkVersion); + final envelope = SentryEnvelope.fromEvent( + event, + sdkVersion, + dsn: fixture.options.dsn, + ); await transport.send(envelope); final envelopeList = arguments as List; @@ -100,7 +114,7 @@ void main() { } class Fixture { - final options = SentryOptions(dsn: ''); + final options = SentryOptions(dsn: fakeDsn); FileSystemTransport getSut(MethodChannel channel) { return FileSystemTransport(channel, options); diff --git a/flutter/test/integrations/native_app_start_integration_test.dart b/flutter/test/integrations/native_app_start_integration_test.dart index ef851af6ac..5bc5dbc4a7 100644 --- a/flutter/test/integrations/native_app_start_integration_test.dart +++ b/flutter/test/integrations/native_app_start_integration_test.dart @@ -10,8 +10,6 @@ import 'package:sentry/src/sentry_tracer.dart'; import '../mocks.dart'; import '../mocks.mocks.dart'; -const fakeDsn = 'https://abc@def.ingest.sentry.io/1234567'; - void main() { group('$NativeAppStartIntegration', () { late Fixture fixture;