Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ class ReplayTelemetryIntegration implements Integration<SentryFlutterOptions> {
if (attributes != null) {
event.span.setAttributes(attributes);
}

final span = event.span;
if (identical(span, span.segmentSpan)) {
return _native?.registerSegmentName(span.name);
}
Comment thread
buenaflor marked this conversation as resolved.
Comment thread
buenaflor marked this conversation as resolved.
};

_onGenerateNewTrace = (OnGenerateNewTrace event) async {
Expand Down
5 changes: 5 additions & 0 deletions packages/flutter/lib/src/native/c/sentry_native.dart
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,11 @@ class SentryNative with SentryNativeSafeInvoker implements SentryNativeBinding {
FutureOr<void> registerTraceId(SentryId traceId) {
// No-op. Replay trace ID registration is currently Android-only.
}

@override
FutureOr<void> registerSegmentName(String segmentName) {
// No-op. Replay segment name registration is currently Android-only.
}
}

extension SentryValueExtension on binding.sentry_value_u {
Expand Down
16 changes: 16 additions & 0 deletions packages/flutter/lib/src/native/java/sentry_native_java.dart
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,22 @@ class SentryNativeJava extends SentryNativeChannel {
});
});
}

@override
void registerSegmentName(String segmentName) {
if (segmentName.isEmpty) {
return;
}

tryCatchSync('registerSegmentName', () {
using((arena) {
final jSegmentName = segmentName.toJString()..releasedBy(arena);
_nativeReplay ??=
native.SentryFlutterPlugin.privateSentryGetReplayIntegration();
_nativeReplay?.registerSegmentName(jSegmentName);
});
});
}
}

// Direct JNI conversion is fine for primitives. Use the Map/List conversion
Expand Down
3 changes: 3 additions & 0 deletions packages/flutter/lib/src/native/sentry_native_binding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,7 @@ abstract class SentryNativeBinding {

/// Registers the active Dart trace ID with native replay.
FutureOr<void> registerTraceId(SentryId traceId);

/// Registers a segment name with native replay for the current replay segment.
FutureOr<void> registerSegmentName(String segmentName);
}
5 changes: 5 additions & 0 deletions packages/flutter/lib/src/native/sentry_native_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -445,4 +445,9 @@ class SentryNativeChannel
FutureOr<void> registerTraceId(SentryId traceId) {
// No-op. Replay trace ID registration is currently Android-only.
}

@override
FutureOr<void> registerSegmentName(String segmentName) {
// No-op. Replay segment name registration is currently Android-only.
}
}
5 changes: 5 additions & 0 deletions packages/flutter/lib/src/web/sentry_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,11 @@ class SentryWeb with SentryNativeSafeInvoker implements SentryNativeBinding {
// No-op. Replay trace ID registration is currently Android-only.
}

@override
FutureOr<void> registerSegmentName(String segmentName) {
// No-op. Replay segment name registration is currently Android-only.
}

@override
int? startProfiler(SentryId traceId) {
_logNotSupported('start profiler');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,31 @@ void main() {

verifyNever(fixture.nativeBinding.registerTraceId(any));
});

test('registers segment name with native replay', () async {
fixture.options.replay.sessionSampleRate = 0.5;

await fixture.getSut().call(fixture.hub, fixture.options);
clearInteractions(fixture.nativeBinding);
final span = fixture.createTestSpan(name: 'CheckoutScreen');
await fixture.options.lifecycleRegistry
.dispatchCallback(OnProcessSpan(span));

verify(fixture.nativeBinding.registerSegmentName('CheckoutScreen'))
.called(1);
});

test('does not register segment name for child spans', () async {
fixture.options.replay.sessionSampleRate = 0.5;

await fixture.getSut().call(fixture.hub, fixture.options);
clearInteractions(fixture.nativeBinding);
final span = fixture.createChildTestSpan();
await fixture.options.lifecycleRegistry
.dispatchCallback(OnProcessSpan(span));

verifyNever(fixture.nativeBinding.registerSegmentName(any));
});
});

group('in session mode', () {
Expand Down Expand Up @@ -346,6 +371,21 @@ void main() {

verifyNever(fixture.nativeBinding.registerTraceId(any));
});

test('does not register segment name with native replay', () async {
fixture.options.replay.sessionSampleRate = 0.5;

final sut = fixture.getSut();
await sut.call(fixture.hub, fixture.options);
await sut.close();
clearInteractions(fixture.nativeBinding);

final span = fixture.createTestSpan(name: 'CheckoutScreen');
await fixture.options.lifecycleRegistry
.dispatchCallback(OnProcessSpan(span));

verifyNever(fixture.nativeBinding.registerSegmentName(any));
});
});
});
}
Expand All @@ -370,6 +410,7 @@ class Fixture {
});
when(nativeBinding.replayId).thenReturn(null);
when(nativeBinding.registerTraceId(any)).thenReturn(null);
when(nativeBinding.registerSegmentName(any)).thenReturn(null);
}

SentryLog createTestLog() => SentryLog(
Expand All @@ -388,8 +429,9 @@ class Fixture {
attributes: <String, SentryAttribute>{},
);

RecordingSentrySpanV2 createTestSpan() => RecordingSentrySpanV2.root(
name: 'test-span',
RecordingSentrySpanV2 createTestSpan({String name = 'test-span'}) =>
RecordingSentrySpanV2.root(
name: name,
traceId: SentryId.newId(),
onSpanEnd: (_) async {},
clock: options.clock,
Expand Down
7 changes: 7 additions & 0 deletions packages/flutter/test/mocks.mocks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2103,6 +2103,13 @@ class MockSentryNativeBinding extends _i1.Mock
#registerTraceId,
[traceId],
)) as _i12.FutureOr<void>);

@override
_i12.FutureOr<void> registerSegmentName(String? segmentName) =>
(super.noSuchMethod(Invocation.method(
#registerSegmentName,
[segmentName],
)) as _i12.FutureOr<void>);
}

/// A class which mocks [SentryDelayedFramesTracker].
Expand Down
Loading