Skip to content
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
469415c
bump to 9.5.0
buenaflor Mar 11, 2025
6c5f7f7
Update CHANGELOG
buenaflor Mar 11, 2025
b584a91
temp
buenaflor Mar 12, 2025
1dc4ffe
temp
buenaflor Mar 12, 2025
e6aa943
temp
buenaflor Mar 12, 2025
5a48913
add sessions to navigator observer
buenaflor Mar 12, 2025
d82c1c6
update
buenaflor Mar 12, 2025
f19e998
update
buenaflor Mar 13, 2025
079f78a
Merge branch 'main' into v9-feat/js-release-health
buenaflor Mar 13, 2025
e4b20e6
add web sessions
buenaflor Mar 13, 2025
b0f0733
update logs and improve adding web sessions code
buenaflor Mar 13, 2025
8b74f4d
add test for beforeSendEvent hook
buenaflor Mar 13, 2025
3296f90
clean up
buenaflor Mar 13, 2025
2348468
Delete flutter/lib/src/event_processor/session_event_processor.dart
buenaflor Mar 13, 2025
869e324
update test
buenaflor Mar 13, 2025
4f20bb9
add test for navigator observer
buenaflor Mar 13, 2025
5faab6d
update group name to web sessions
buenaflor Mar 13, 2025
8a658ef
update naming
buenaflor Mar 13, 2025
4426919
fix
buenaflor Mar 13, 2025
f8e91c2
naming
buenaflor Mar 13, 2025
186dd27
todo
buenaflor Mar 13, 2025
ce0b8c5
naming
buenaflor Mar 13, 2025
14f2f64
first test
buenaflor Mar 14, 2025
4338331
remove unnecessary code
buenaflor Mar 14, 2025
e1ceb32
update to internal and comments
buenaflor Mar 17, 2025
db0fa9b
make getSession nullable
buenaflor Mar 17, 2025
b4d0b7b
do we need this?
buenaflor Mar 17, 2025
fbc5721
update error count
buenaflor Mar 17, 2025
cf7bf9a
use tryCatchSync
buenaflor Mar 17, 2025
8ea8ffc
updateSession status and error can be non-null
buenaflor Mar 17, 2025
12f5bb0
update logger
buenaflor Mar 17, 2025
1417799
update tests
buenaflor Mar 17, 2025
e4dbbee
update test
buenaflor Mar 17, 2025
2416389
clean up
buenaflor Mar 17, 2025
b02d0bc
update
buenaflor Mar 17, 2025
affdb82
fix integration test
buenaflor Mar 17, 2025
4478d8f
cleanup
buenaflor Mar 17, 2025
64b13f8
fix async
buenaflor Mar 18, 2025
39b0584
update CHANGELOG
buenaflor Mar 18, 2025
55bff4a
Merge branch 'main' into v9-feat/js-release-health
buenaflor Mar 18, 2025
0bc50b0
fix internal usage
buenaflor Mar 18, 2025
9d0c67a
fix test
buenaflor Mar 18, 2025
7335da5
clean up web session updater
buenaflor Mar 18, 2025
d0ae7cf
update CHANGELOG
buenaflor Mar 18, 2025
8877646
Merge branch 'main' into v9-feat/js-release-health
buenaflor Mar 18, 2025
92a6c63
update dart comment
buenaflor Mar 18, 2025
bd464a5
Update session updater to check for navigator observer registration
buenaflor Mar 18, 2025
8e609fe
remove commented lines
buenaflor Mar 18, 2025
8396c74
update test structure
buenaflor Mar 18, 2025
082f904
no op tests for native_channel
buenaflor Mar 18, 2025
599dbee
update docs
buenaflor Mar 18, 2025
81bb504
refactor to use integration
buenaflor Mar 19, 2025
df79dec
update naming
buenaflor Mar 20, 2025
50d51e0
update docs
buenaflor Mar 20, 2025
8825e1f
use enable function
buenaflor Mar 20, 2025
c20aff6
update tests
buenaflor Mar 20, 2025
22b3550
update sentry_flutter_test
buenaflor Mar 20, 2025
a933ce1
fix integration test
buenaflor Mar 20, 2025
f9d8b56
fix tests
buenaflor Mar 20, 2025
7bbe0e7
Update flutter/lib/src/integrations/web_session_integration.dart
buenaflor Mar 21, 2025
25b6df3
Merge branch 'main' into v9-feat/js-release-health
buenaflor Mar 21, 2025
75b66b3
update _isEnabled
buenaflor Mar 21, 2025
4f19ef1
remove web check, web session integration is only added for web anyway
buenaflor Mar 21, 2025
97cf12e
implement beforeSendEventObserver
buenaflor Mar 21, 2025
dc195fa
remove unnecessary test
buenaflor Mar 21, 2025
13051e7
formatting
buenaflor Mar 21, 2025
9df9352
cleanup
buenaflor Mar 21, 2025
3b9e1bd
remove web_session_updater
buenaflor Mar 24, 2025
9a3700c
format
buenaflor Mar 24, 2025
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
- Cleanup platform mocking ([#2730](https://github.com/getsentry/sentry-dart/pull/2730))
- The `PlatformChecker` was renamed to `RuntimeChecker`
- Moved `PlatformChecker.platform` to `options.platform`
- Bump Javascript SDK from v8.42.0 to v9.5.0 ([#2784](https://github.com/getsentry/sentry-dart/pull/2784))
- [changelog](https://github.com/getsentry/sentry-javascript/blob/main/CHANGELOG.md#950)
- [diff](https://github.com/getsentry/sentry-javascript/compare/8.42.0...9.5.0)

## 9.0.0-alpha.1

Expand Down
7 changes: 4 additions & 3 deletions dart/lib/sentry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
/// A pure Dart client for Sentry.io crash reporting.
library;

// ignore: invalid_export_of_internal_element
export 'src/constants.dart';
export 'src/event_processor.dart';
export 'src/exception_cause.dart';
export 'src/exception_cause_extractor.dart';
Expand All @@ -18,12 +20,13 @@ export 'src/hub_adapter.dart';
export 'src/integration.dart';
export 'src/noop_isolate_error_integration.dart'
if (dart.library.io) 'src/isolate_error_integration.dart';
export 'src/observers.dart';
export 'src/performance_collector.dart';
export 'src/runtime_checker.dart';
export 'src/protocol.dart';
export 'src/protocol/sentry_feedback.dart';
export 'src/protocol/sentry_proxy.dart';
export 'src/run_zoned_guarded_integration.dart';
export 'src/runtime_checker.dart';
export 'src/scope.dart';
export 'src/scope_observer.dart';
export 'src/sentry.dart';
Expand All @@ -34,8 +37,6 @@ export 'src/sentry_envelope.dart';
export 'src/sentry_envelope_item.dart';
export 'src/sentry_options.dart';
// ignore: invalid_export_of_internal_element
export 'src/constants.dart';
// ignore: invalid_export_of_internal_element
export 'src/sentry_trace_origins.dart';
export 'src/span_data_convention.dart';
export 'src/spotlight.dart';
Expand Down
12 changes: 12 additions & 0 deletions dart/lib/src/observers.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'dart:async';

import '../sentry.dart';

// This file will contain observer definitions that are executed during
// specific points in the SDK such as as right before an event is sent.

/// Called right before an event is sent, after all processing is complete.
/// Should not modify the event at this point.
abstract class BeforeSendEventObserver {
FutureOr<void> onBeforeSendEvent(SentryEvent event, Hint hint);
}
25 changes: 25 additions & 0 deletions dart/lib/src/sentry_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@
return _emptySentryId;
}

// Event is fully processed and ready to be sent, emit beforeSendEvent observer
await _emitBeforeSendEventObserver(preparedEvent, hint);

var attachments = List<SentryAttachment>.from(scope?.attachments ?? []);
attachments.addAll(hint.attachments);
var screenshot = hint.screenshot;
Expand Down Expand Up @@ -563,4 +566,26 @@
}
return DataCategory.error;
}

FutureOr<void> _emitBeforeSendEventObserver(
SentryEvent event, Hint hint) async {
for (final callback in _options.beforeSendEventObservers) {
try {
final result = callback.onBeforeSendEvent(event, hint);
if (result is Future) {
await result;
}
} catch (exception, stackTrace) {
_options.logger(

Check warning on line 579 in dart/lib/src/sentry_client.dart

View check run for this annotation

Codecov / codecov/patch

dart/lib/src/sentry_client.dart#L579

Added line #L579 was not covered by tests
SentryLevel.error,
'Error while running beforeSendEvent callback',
exception: exception,
stackTrace: stackTrace,
);
if (_options.automatedTestMode) {

Check warning on line 585 in dart/lib/src/sentry_client.dart

View check run for this annotation

Codecov / codecov/patch

dart/lib/src/sentry_client.dart#L585

Added line #L585 was not covered by tests
rethrow;
}
}
}
}
}
11 changes: 11 additions & 0 deletions dart/lib/src/sentry_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,17 @@ class SentryOptions {
/// iOS only supports http proxies, while macOS also supports socks.
SentryProxy? proxy;

final List<BeforeSendEventObserver> _beforeSendEventObserver = [];

List<BeforeSendEventObserver> get beforeSendEventObservers =>
List.unmodifiable(_beforeSendEventObserver);

/// Adds an observer which is called right before an event is sent.
/// This should not be used to mutate the event.
void addBeforeSendEventObserver(BeforeSendEventObserver observer) {
_beforeSendEventObserver.add(observer);
}

SentryOptions({String? dsn, Platform? platform, RuntimeChecker? checker}) {
this.dsn = dsn;
if (platform != null) {
Expand Down
130 changes: 130 additions & 0 deletions dart/test/sentry_client_before_send_event_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import 'dart:async';
import 'dart:convert';

import 'package:sentry/sentry.dart';
import 'package:sentry/src/sentry_tracer.dart';
import 'package:test/test.dart';

import 'mocks/mock_transport.dart';
import 'test_utils.dart';

void main() {
group('SentryClient beforeSendEvent', () {
late Fixture fixture;

setUp(() {
fixture = Fixture();
});

test('beforeSendEvent is called with correct event and hint', () async {
final observer = _TestEventObserver();
fixture.options.addBeforeSendEventObserver(observer);

final client = fixture.getSut();
final hint = Hint();
final event = SentryEvent().copyWith(type: 'some random type');

await client.captureEvent(event, hint: hint);

expect(observer.inspectedEvent?.type, 'some random type');
expect(observer.inspectedHint, same(hint));
});

test('beforeSendEvent is called for transactions', () async {
final observer = _TestEventObserver();
fixture.options.addBeforeSendEventObserver(observer);

final client = fixture.getSut();
final hint = Hint();
final tracer = SentryTracer(
SentryTransactionContext('name', 'op'),
Sentry.currentHub,
);
final event = SentryTransaction(tracer);

await client.captureEvent(event, hint: hint);

expect(
(observer.inspectedEvent as SentryTransaction).tracer.name, 'name');
expect(
(observer.inspectedEvent as SentryTransaction)
.tracer
.context
.operation,
'op');
expect(observer.inspectedHint, same(hint));
});

test('beforeSendEvent is called after all other processors', () async {
final processingOrder = <String>[];

fixture.options.addEventProcessor(_TestEventProcessor(processingOrder));
fixture.options.beforeSend = (event, hint) {
processingOrder.add('beforeSend');
return event;
};

fixture.options
.addBeforeSendEventObserver(_TestOrderObserver(processingOrder));

final client = fixture.getSut();
final event = SentryEvent();

await client.captureEvent(event);

expect(
processingOrder, ['eventProcessor', 'beforeSend', 'beforeSendEvent']);
});
});
}

Future<SentryEvent> eventFromEnvelope(SentryEnvelope envelope) async {
final data = await envelope.items.first.dataFactory();
final utf8Data = utf8.decode(data);
final envelopeItemJson = jsonDecode(utf8Data);
return SentryEvent.fromJson(envelopeItemJson as Map<String, dynamic>);
}

class Fixture {
final options = defaultTestOptions();

SentryClient getSut() {
options.transport = MockTransport();

return SentryClient(options);
}
}

class _TestEventObserver implements BeforeSendEventObserver {
SentryEvent? inspectedEvent;
Hint? inspectedHint;

@override
FutureOr<void> onBeforeSendEvent(SentryEvent event, Hint hint) {
inspectedEvent = event;
inspectedHint = hint;
}
}

class _TestEventProcessor extends EventProcessor {
_TestEventProcessor(this._processingOrder);

final List<String> _processingOrder;

@override
FutureOr<SentryEvent?> apply(SentryEvent event, Hint hint) {
_processingOrder.add('eventProcessor');
return event;
}
}

class _TestOrderObserver extends BeforeSendEventObserver {
final List<String> _processingOrder;

_TestOrderObserver(this._processingOrder);

@override
FutureOr<void> onBeforeSendEvent(SentryEvent event, Hint hint) {
_processingOrder.add('beforeSendEvent');
}
}
26 changes: 26 additions & 0 deletions flutter/example/integration_test/web_sdk_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,32 @@
findsOneWidget,
);
});

testWidgets('sends the session update for error event', (tester) async {
await restoreFlutterOnErrorAfter(() async {
await SentryFlutter.init((options) {
options.dsn = fakeDsn;
}, appRunner: () async {
await tester.pumpWidget(
SentryWidget(child: const app.MyApp()),
);
});
});

final client = _getClient()!;
final completer = Completer<Map<dynamic, dynamic>>();

JSFunction beforeSendSessionCallback = ((JSObject session) {
final sessionDart = session.dartify() as Map<dynamic, dynamic>;
completer.complete(sessionDart);
}).toJS;

client.on('beforeSendSession'.toJS, beforeSendSessionCallback);

await Sentry.captureException(Exception('test'));

final session = await completer.future;

Check warning on line 182 in flutter/example/integration_test/web_sdk_test.dart

View workflow job for this annotation

GitHub Actions / analyze / analyze

The value of the local variable 'session' isn't used.

Try removing the variable or using it. See https://dart.dev/diagnostics/unused_local_variable to learn more about this problem.
});
});

group('disabled', () {
Expand Down
21 changes: 21 additions & 0 deletions flutter/lib/src/native/c/sentry_native.dart
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,27 @@ class SentryNative with SentryNativeSafeInvoker implements SentryNativeBinding {
_logNotSupported('capturing replay');
return SentryId.empty();
}

@override
FutureOr<void> startSession({bool ignoreDuration = false}) {
_logNotSupported('starting session');
}

@override
FutureOr<void> captureSession() {
_logNotSupported('capturing session');
}

@override
FutureOr<Map<dynamic, dynamic>?> getSession() {
_logNotSupported('getting session');
return null;
}

@override
FutureOr<void> updateSession({int? errors, String? status}) {
_logNotSupported('updating session');
}
}

extension on binding.sentry_value_u {
Expand Down
24 changes: 24 additions & 0 deletions flutter/lib/src/native/sentry_native_binding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,28 @@ abstract class SentryNativeBinding {
FutureOr<void> setReplayConfig(ReplayConfig config);

FutureOr<SentryId> captureReplay(bool isCrash);

/// Starts a new session.
///
/// Note: This is used on web platforms. Android and iOS handle sessions
/// automatically through their respective native SDKs.
/// Windows and Linux currently don't support sessions.
///
/// @param ignoreDurations If true, the session will ignore the configured session duration
FutureOr<void> startSession({bool ignoreDuration = false});

/// Gets the current active session.
///
/// Note: This is used on web platforms. Returns null on other platforms.
FutureOr<Map<dynamic, dynamic>?> getSession();

/// Updates the current session with the provided status and/or error count.
///
/// Note: This is primarily used on web platforms. No-op on other platforms.
FutureOr<void> updateSession({int? errors, String? status});

/// Sends the current session immediately.
///
/// Note: This is primarily used on web platforms. No-op on other platforms.
FutureOr<void> captureSession();
}
24 changes: 24 additions & 0 deletions flutter/lib/src/native/sentry_native_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
SentryNativeChannel(this.options)
: channel = SentrySafeMethodChannel(options);

void _logNotSupported(String operation) => options.logger(
SentryLevel.debug, 'SentryNativeChannel: $operation is not supported');

Check warning on line 33 in flutter/lib/src/native/sentry_native_channel.dart

View check run for this annotation

Codecov / codecov/patch

flutter/lib/src/native/sentry_native_channel.dart#L32-L33

Added lines #L32 - L33 were not covered by tests

@override
Future<void> init(Hub hub) async {
return channel.invokeMethod('initNativeSdk', <String, dynamic>{
Expand Down Expand Up @@ -246,4 +249,25 @@
channel.invokeMethod('captureReplay', {
'isCrash': isCrash,
}).then((value) => SentryId.fromId(value as String));

@override

Check warning on line 253 in flutter/lib/src/native/sentry_native_channel.dart

View check run for this annotation

Codecov / codecov/patch

flutter/lib/src/native/sentry_native_channel.dart#L253

Added line #L253 was not covered by tests
FutureOr<void> captureSession() {
_logNotSupported('capturing session');

Check warning on line 255 in flutter/lib/src/native/sentry_native_channel.dart

View check run for this annotation

Codecov / codecov/patch

flutter/lib/src/native/sentry_native_channel.dart#L255

Added line #L255 was not covered by tests
}

@override

Check warning on line 258 in flutter/lib/src/native/sentry_native_channel.dart

View check run for this annotation

Codecov / codecov/patch

flutter/lib/src/native/sentry_native_channel.dart#L258

Added line #L258 was not covered by tests
FutureOr<void> startSession({bool ignoreDuration = false}) {
_logNotSupported('starting session');

Check warning on line 260 in flutter/lib/src/native/sentry_native_channel.dart

View check run for this annotation

Codecov / codecov/patch

flutter/lib/src/native/sentry_native_channel.dart#L260

Added line #L260 was not covered by tests
}

@override

Check warning on line 263 in flutter/lib/src/native/sentry_native_channel.dart

View check run for this annotation

Codecov / codecov/patch

flutter/lib/src/native/sentry_native_channel.dart#L263

Added line #L263 was not covered by tests
FutureOr<Map<dynamic, dynamic>?> getSession() {
_logNotSupported('getting session');

Check warning on line 265 in flutter/lib/src/native/sentry_native_channel.dart

View check run for this annotation

Codecov / codecov/patch

flutter/lib/src/native/sentry_native_channel.dart#L265

Added line #L265 was not covered by tests
return null;
}

@override

Check warning on line 269 in flutter/lib/src/native/sentry_native_channel.dart

View check run for this annotation

Codecov / codecov/patch

flutter/lib/src/native/sentry_native_channel.dart#L269

Added line #L269 was not covered by tests
FutureOr<void> updateSession({int? errors, String? status}) {
_logNotSupported('updating session');

Check warning on line 271 in flutter/lib/src/native/sentry_native_channel.dart

View check run for this annotation

Codecov / codecov/patch

flutter/lib/src/native/sentry_native_channel.dart#L271

Added line #L271 was not covered by tests
}
}
Loading
Loading