FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix(core): [Callback Errors 6] Handle profilesSampler failures by adinauer · Pull Request #6164 · getsentry/sentry-java · GitHub

Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .java  (1) .kt  (1) .md  (1) All 3 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
1 change: 1 addition & 0 deletions CHANGELOG.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
- Drop telemetry and record `callback_error` when a customer event processor throws instead of continuing with a potentially partially processed item. SDK-owned processor failures are logged and processing continues without a `callback_error` client report.
- Drop breadcrumbs when `beforeBreadcrumb` throws instead of storing exception details on the breadcrumb.
- When `tracesSampler` throws, drop the transaction and record `callback_error` instead of inheriting the parent sampling decision or falling back to `tracesSampleRate` ([#6163](https://github.com/getsentry/sentry-java/pull/6163))
- When `profilesSampler` throws, disable profiling instead of falling back to `profilesSampleRate` or inheriting the parent's profiling decision. Trace sampling is unchanged ([#6164](https://github.com/getsentry/sentry-java/pull/6164))
- Disable URL caching when reading `META-INF/MANIFEST.MF` files during version detection so that the SDK no longer keeps jar file handles open for the life of the process ([#6124](https://github.com/getsentry/sentry-java/pull/6124)
- Keep the `EventListener` wrapped by `SentryOkHttpEventListener` per `Call` ([#6003](https://github.com/getsentry/sentry-java/pull/6003))

Expand Down
11 changes: 10 additions & 1 deletion sentry/src/main/java/io/sentry/TracesSampler.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,18 @@ public TracesSamplingDecision sample(final @NotNull SamplingContext samplingCont
}

Double profilesSampleRate = null;
boolean profilesSamplerFailed = false;
if (options.getProfilesSampler() != null) {
try {
profilesSampleRate = options.getProfilesSampler().sample(samplingContext);
} catch (Throwable t) {
profilesSamplerFailed = true;
options
.getLogger()
.log(SentryLevel.ERROR, "Error in the 'ProfilesSamplerCallback' callback.", t);
}
}
if (profilesSampleRate == null) {
if (profilesSampleRate == null && !profilesSamplerFailed) {
profilesSampleRate = options.getProfilesSampleRate();
}
Boolean profilesSampled = profilesSampleRate != null && sample(profilesSampleRate, sampleRand);
Expand Down Expand Up @@ -69,6 +71,13 @@ public TracesSamplingDecision sample(final @NotNull SamplingContext samplingCont
final TracesSamplingDecision parentSamplingDecision =
samplingContext.getTransactionContext().getParentSamplingDecision();
if (parentSamplingDecision != null) {
if (profilesSamplerFailed) {
return SampleRateUtils.backfilledSampleRand(
new TracesSamplingDecision(
parentSamplingDecision.getSampled(),
parentSamplingDecision.getSampleRate(),
parentSamplingDecision.getSampleRand()));
}
return SampleRateUtils.backfilledSampleRand(parentSamplingDecision);
}

Expand Down
92 changes: 83 additions & 9 deletions sentry/src/test/java/io/sentry/TracesSamplerTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ class TracesSamplerTest {

@Test
fun `when profilesSampler returns null and parentSampled is set sampler uses it as a sampling decision`() {
val sampler = fixture.getSut(tracesSampleRate = 1.0, profilesSamplerCallback = null)
val sampler = fixture.getSut(tracesSampleRate = 1.0, profilesSamplerCallback = { null })
val transactionContextParentSampled = TransactionContext("name", "op")
transactionContextParentSampled.setParentSampled(true, true)
val samplingDecision =
Expand Down Expand Up @@ -225,7 +225,7 @@ class TracesSamplerTest {
fixture.getSut(
tracesSampleRate = 1.0,
profilesSampleRate = 0.2,
profilesSamplerCallback = null,
profilesSamplerCallback = { null },
)
val samplingDecision =
sampler.sample(
Expand Down Expand Up @@ -358,18 +358,92 @@ class TracesSamplerTest {
}

@Test
fun `when a profilingRate and a ProfilesSamplerCallback is set but the callback throws an exception then profiling should still be enabled`() {
val exception = Exception("faulty ProfilesSamplerCallback")
fun `when profilesSampler throws then static profile rates are ignored`() {
for (profilesSampleRate in listOf(null, 0.0, 1.0)) {
val sampler =
fixture.getSut(
tracesSampleRate = 1.0,
profilesSampleRate = profilesSampleRate,
profilesSamplerCallback = {
throw IllegalStateException("faulty ProfilesSamplerCallback")
},
)
val decision =
sampler.sample(SamplingContext(TransactionContext("name", "op"), null, 0.0, null))

assertThat(decision.sampled).isTrue()
assertThat(decision.sampleRate).isEqualTo(1.0)
assertThat(decision.sampleRand).isEqualTo(0.0)
assertThat(decision.profileSampled).isFalse()
assertThat(decision.profileSampleRate).isNull()
}
}

@Test
fun `when profilesSampler throws then tracesSampler still determines trace sampling`() {
val sampler =
fixture.getSut(
tracesSampleRate = 1.0,
tracesSampleRate = 0.0,
profilesSampleRate = 1.0,
profilesSamplerCallback = { throw exception },
tracesSamplerCallback = { 0.5 },
profilesSamplerCallback = { throw IllegalStateException("faulty ProfilesSamplerCallback") },
)
val decision =
sampler.sample(SamplingContext(TransactionContext("name", "op"), null, 0.0, null))
assertTrue(decision.profileSampled)
assertEquals(0.0, decision.sampleRand)
sampler.sample(SamplingContext(TransactionContext("name", "op"), null, 0.1, null))

assertThat(decision.sampled).isTrue()
assertThat(decision.sampleRate).isEqualTo(0.5)
assertThat(decision.sampleRand).isEqualTo(0.1)
assertThat(decision.profileSampled).isFalse()
assertThat(decision.profileSampleRate).isNull()
}

@Test
fun `when profilesSampler throws then parent trace sampling is preserved without profiling`() {
val sampler =
fixture.getSut(
tracesSampleRate = 1.0,
profilesSampleRate = 1.0,
profilesSamplerCallback = { throw IllegalStateException("faulty ProfilesSamplerCallback") },
)
for (sampled in listOf(true, false)) {
val sampleRand = if (sampled) 0.1 else 0.9
val parentDecision = TracesSamplingDecision(sampled, 0.5, sampleRand, true, 1.0)
val transactionContext =
TransactionContext(SentryId(), SpanId(), SpanId(), parentDecision, null)

val decision = sampler.sample(SamplingContext(transactionContext, null, sampleRand, null))

assertThat(decision.sampled).isEqualTo(sampled)
assertThat(decision.sampleRate).isEqualTo(0.5)
assertThat(decision.sampleRand).isEqualTo(sampleRand)
assertThat(decision.profileSampled).isFalse()
assertThat(decision.profileSampleRate).isNull()
assertThat(parentDecision.profileSampled).isEqualTo(sampled)
assertThat(parentDecision.profileSampleRate).isEqualTo(1.0)
}
}

@Test
fun `when both samplers throw then tracing and profiling are disabled despite a sampled parent`() {
val sampler =
fixture.getSut(
tracesSampleRate = 0.0,
profilesSampleRate = 1.0,
tracesSamplerCallback = { throw IllegalStateException("faulty TracesSamplerCallback") },
profilesSamplerCallback = { throw IllegalStateException("faulty ProfilesSamplerCallback") },
)
val parentDecision = TracesSamplingDecision(true, 0.5, true, 1.0)
val transactionContext =
TransactionContext(SentryId(), SpanId(), SpanId(), parentDecision, null)

val decision = sampler.sample(SamplingContext(transactionContext, null, 0.9, null))

assertThat(decision.sampled).isFalse()
assertThat(decision.sampleRate).isNull()
assertThat(decision.sampleRand).isEqualTo(0.9)
assertThat(decision.profileSampled).isFalse()
assertThat(decision.profileSampleRate).isNull()
}

@Test
Expand Down
Loading

Back | FazBrowse Home | New Git URL