Skip to content

Conversation

@stefanosiano
Copy link
Member

📜 Description

performance data collection is now started only when the transaction is sampled

💡 Motivation and Context

We were running the performance collection even when the transaction was not sampled, so the data was lost.
Avoiding it will lower the overhead of performance data collection

💚 How did you test it?

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

🔮 Next steps

@stefanosiano stefanosiano marked this pull request as ready for review October 24, 2025 12:09
Comment on lines 94 to 96
if (compositePerformanceCollector != null && Boolean.TRUE.equals(isSampled())) {
compositePerformanceCollector.start(this);
}

Choose a reason for hiding this comment

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

Bug: compositePerformanceCollector fails to start for transactions with deferred sampling decisions that are later marked as sampled.
Severity: CRITICAL | Confidence: 0.98

🔍 Detailed Analysis

When a transaction is created with a deferred sampling decision (samplingDecision = null), the SentryTracer constructor evaluates Boolean.TRUE.equals(isSampled()). Since isSampled() returns null, this condition is false, preventing compositePerformanceCollector.start() from being called. If the transaction is later sampled via setSamplingDecision(new TracesSamplingDecision(true)), the performance collector remains unstarted, resulting in a loss of performance data for that transaction. Additionally, compositePerformanceCollector.stop() is unconditionally called during finish(), potentially on an uninitialized collector.

💡 Suggested Fix

Modify the SentryTracer constructor to start compositePerformanceCollector if isSampled() is null, or add logic within setSamplingDecision() to start the collector if it wasn't previously started and the transaction becomes sampled.

🤖 Prompt for AI Agent
Fix this bug. In sentry/src/main/java/io/sentry/SentryTracer.java at lines 94-96: When a
transaction is created with a deferred sampling decision (`samplingDecision = null`),
the `SentryTracer` constructor evaluates `Boolean.TRUE.equals(isSampled())`. Since
`isSampled()` returns `null`, this condition is `false`, preventing
`compositePerformanceCollector.start()` from being called. If the transaction is later
sampled via `setSamplingDecision(new TracesSamplingDecision(true))`, the performance
collector remains unstarted, resulting in a loss of performance data for that
transaction. Additionally, `compositePerformanceCollector.stop()` is unconditionally
called during `finish()`, potentially on an uninitialized collector.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Member Author

Choose a reason for hiding this comment

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

this is the only case why we didn't do it before
should we ignore it?

Copy link
Member

@romtsn romtsn Oct 28, 2025

Choose a reason for hiding this comment

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

hmm, yeah I think this is valid actually. Probably we can't simply just do that without a breaking change - but even then I think we'd have to discuss this. I'd imagine if we ever do tail-based sampling (and we probably will), setSamplingDecision will be useful for that. So maybe this PR has to be backlogged for now

Copy link
Member Author

Choose a reason for hiding this comment

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

got it
on the other side, if the sample rate is like 0.01, we'd run the performance collection 10k times more than needed 😅
Let's discuss it in the next sync

@github-actions
Copy link
Contributor

github-actions bot commented Oct 24, 2025

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 300.92 ms 342.73 ms 41.81 ms
Size 1.58 MiB 2.12 MiB 551.52 KiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
ee747ae 382.73 ms 435.41 ms 52.68 ms
96449e8 361.30 ms 423.39 ms 62.09 ms
ee747ae 374.71 ms 455.18 ms 80.47 ms
3699cd5 423.60 ms 495.52 ms 71.92 ms
b3d8889 371.84 ms 447.49 ms 75.65 ms
27d7cf8 369.82 ms 422.62 ms 52.80 ms
d364ace 411.72 ms 430.81 ms 19.10 ms
7314dbe 437.83 ms 505.64 ms 67.81 ms
ce0a49e 532.00 ms 609.96 ms 77.96 ms
3998a95 415.94 ms 478.54 ms 62.60 ms

App size

Revision Plain With Sentry Diff
ee747ae 1.58 MiB 2.10 MiB 530.95 KiB
96449e8 1.58 MiB 2.11 MiB 539.35 KiB
ee747ae 1.58 MiB 2.10 MiB 530.95 KiB
3699cd5 1.58 MiB 2.10 MiB 533.45 KiB
b3d8889 1.58 MiB 2.10 MiB 535.07 KiB
27d7cf8 1.58 MiB 2.12 MiB 549.42 KiB
d364ace 1.58 MiB 2.11 MiB 539.75 KiB
7314dbe 1.58 MiB 2.10 MiB 533.45 KiB
ce0a49e 1.58 MiB 2.10 MiB 532.94 KiB
3998a95 1.58 MiB 2.10 MiB 532.96 KiB

Previous results on branch: stefanosiano/enh/collect-performance-sampled-profile

Startup times

Revision Plain With Sentry Diff
a5d8753 343.00 ms 383.61 ms 40.61 ms
c4bc643 310.58 ms 365.24 ms 54.66 ms

App size

Revision Plain With Sentry Diff
a5d8753 1.58 MiB 2.12 MiB 549.44 KiB
c4bc643 1.58 MiB 2.12 MiB 549.44 KiB

cursor[bot]

This comment was marked as outdated.

Copy link
Member

@markushi markushi left a comment

Choose a reason for hiding this comment

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

LGTM!

@stefanosiano stefanosiano merged commit a1ddfed into main Oct 29, 2025
61 checks passed
@stefanosiano stefanosiano deleted the stefanosiano/enh/collect-performance-sampled-profile branch October 29, 2025 15:28
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.

4 participants