Skip to content

feat(span-first): add span v2 support for frames tracking#3447

Open
buenaflor wants to merge 34 commits intofeat/span-firstfrom
feat/span/frames-tracking-support
Open

feat(span-first): add span v2 support for frames tracking#3447
buenaflor wants to merge 34 commits intofeat/span-firstfrom
feat/span/frames-tracking-support

Conversation

@buenaflor
Copy link
Contributor

@buenaflor buenaflor commented Jan 14, 2026

📜 Description

Part of span-first

💡 Motivation and Context

Part of #3334

💚 How did you test it?

Manual, unit/widget test

📝 Checklist

  • I reviewed submitted code
  • I added tests to verify changes
  • No new PII added or SDK only sends newly added PII if sendDefaultPii is enabled
  • I updated the docs if needed
  • All tests passing
  • No breaking changes

🔮 Next steps

#skip-changelog

@buenaflor buenaflor changed the title [DRAFT] feat(span-first): add span v2 support for frames tracking feat(span-first): add span v2 support for frames tracking Feb 3, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Feb 3, 2026

Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against ced147d

/// Collects frames from [SentryDelayedFramesTracker], calculates the metrics
/// and attaches them to spans.
@internal
class SpanFrameMetricsCollectorV2 implements PerformanceContinuousCollectorV2 {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this class is mostly copied from the transaction version, just adapted to span v2

Copy link
Collaborator

Choose a reason for hiding this comment

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

Would it make sense to use the abstraction InstrumentationSpan instead, or did the logic also change for v2?

Copy link
Contributor Author

@buenaflor buenaflor Feb 3, 2026

Choose a reason for hiding this comment

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

Updated: I updated the impl to make the unified

@buenaflor buenaflor marked this pull request as ready for review February 3, 2026 12:10
@buenaflor buenaflor requested a review from denrase as a code owner February 3, 2026 12:10
/// Collects frames from [SentryDelayedFramesTracker], calculates the metrics
/// and attaches them to spans.
@internal
class SpanFrameMetricsCollectorV2 implements PerformanceContinuousCollectorV2 {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would it make sense to use the abstraction InstrumentationSpan instead, or did the logic also change for v2?

@override
Future<void> onSpanFinished(SentrySpanV2 span, DateTime endTimestamp) async {
return _tryCatch('onSpanFinished', () async {
if (span is NoOpSentrySpan) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same as above, probably also a good idea to check for the UnsetSpan and throw, if we do this elsewhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Rather than checking both let's check if (span is! RecordingSentrySpanV2)

final collector = SpanFrameMetricsCollectorV2(framesTracker,
resumeFrameTracking: () => widgetsBinding.resumeTrackingFrames(),
pauseFrameTracking: () => widgetsBinding.pauseTrackingFrames());
_collector = collector;
Copy link
Collaborator

Choose a reason for hiding this comment

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

We did implement a V2 perfomrce collector, but are not adding it to options, is this correct?

Copy link
Contributor Author

@buenaflor buenaflor Feb 3, 2026

Choose a reason for hiding this comment

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

it's a behaviour difference.

for transactions we add it to the options so we can manually trigger onSpanFinish and onSpanEnded via options.collector.onSpanFinished() but now that we use lifecycle callbacks we dont need to do that anymroe for spanv2 so we dont need to add it to the options

I'll refactor the static version to use lifeecycle callbacks as well

@buenaflor
Copy link
Contributor Author

Would it make sense to use the abstraction InstrumentationSpan instead, or did the logic also change for v2?

I checked and probably not, this specific integration requires lots of concrete specific usages, the abstraction wouldn't help here

}

@override
bool get finished => _endTimestamp != null;
Copy link
Contributor Author

@buenaflor buenaflor Feb 4, 2026

Choose a reason for hiding this comment

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

this change is necessary for the lifecycle callbacks to function correctly. we were triggering the callbacks before the endTimestamp was set (which means we never had access to the endTimestamp) but we could not trigger it after because then the span would be immutable to change in setData for example. so this check alone is not enough

}

@override
bool get isNoop => _span is! RecordingSentrySpanV2;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think this check suffices

Future<void> _tryCatch(String methodName, Future<void> Function() fn) async {
try {
return fn();
return await fn();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

await here otherwise errors won't be caught in the catch block

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants