@@ -14,41 +14,31 @@ import com.datadog.android.trace.api.span.DatadogSpan
1414import com.datadog.android.trace.internal.net.SpanSamplingIdProvider
1515
1616/* *
17- * A [com.datadog.android.core.sampling.DeterministicSampler] using the TraceID of a Span to compute the sampling decision.
17+ * A [com.datadog.android.core.sampling.DeterministicSampler] using the TraceID of a Span to compute the sampling
18+ * decision.
1819 *
19- * The sampling threshold is automatically rebased against the RUM session sample rate when it is
20- * available so that the combined effective sampling probability reflects:
20+ * When a span carries a RUM session context (written by
21+ * [com.datadog.android.trace.internal.RumContextPropagator]), the sampling threshold is
22+ * automatically rebased against the RUM session sample rate so that the combined effective
23+ * sampling probability reflects:
2124 *
2225 * ```
23- * rebasedTraceSampleRate = sessionSampleRate * traceSampleRate / 100
26+ * effectiveRate = traceSampleRate * sessionSampleRate / 100
2427 * ```
2528 *
26- * Note: overriding [getSampleRate] is not a supported extension point for per-span sampling
27- * behavior.
29+ * Spans without a `session_sample_rate` tag are sampled at the raw trace sample rate.
2830 *
2931 * @param sampleRateProvider Provider for the trace sample rate. Called each time the sampling
3032 * decision needs to be made. Values must be in the range [0;100].
31- * @param sessionSampleRateProvider Provider for the RUM session sample rate used to rebase the
32- * trace sample rate. Defaults to 100 (no rebasing).
3333 */
3434// TODO RUM-13454 -> Make this class internal in V4 (RUM-15590)
35- open class DeterministicTraceSampler private constructor(
36- private val sampleRateProvider : () -> Float ,
37- private val sessionSampleRateProvider : () -> Float
35+ open class DeterministicTraceSampler (
36+ sampleRateProvider : () -> Float
3837) : DeterministicSampler<DatadogSpan>(
3938 SpanSamplingIdProvider : :provideId,
4039 sampleRateProvider
4140) {
4241
43- /* *
44- * Creates a new instance of [DeterministicTraceSampler] with the given sample rate provider.
45- *
46- * @param sampleRateProvider Provider for the sample rate value.
47- */
48- constructor (
49- sampleRateProvider: () -> Float
50- ) : this (sampleRateProvider, { DeterministicSampler .SAMPLE_ALL_RATE })
51-
5242 /* *
5343 * Creates a new instance of [DeterministicTraceSampler] with the given sample rate.
5444 *
@@ -67,77 +57,47 @@ open class DeterministicTraceSampler private constructor(
6757 @FloatRange(from = 0.0 , to = 100.0 ) sampleRate: Double
6858 ) : this (sampleRate.toFloat())
6959
70- /* *
71- * Internal constructor used by [com.datadog.android.trace.ApmNetworkInstrumentationConfiguration]
72- * to wire the RUM session sample rate provider at instrumentation setup time.
73- */
74- internal constructor (
75- @FloatRange(from = 0.0 , to = 100.0 ) sampleRate: Float ,
76- sessionSampleRateProvider: () -> Float
77- ) : this ({ sampleRate }, sessionSampleRateProvider)
78-
79- /* *
80- * Returns the effective sample rate, rebased against the RUM session sample rate when it is
81- * available:
82- *
83- * ```
84- * effectiveRate = traceSampleRate * sessionSampleRate / 100
85- * ```
86- *
87- * Falls back to the raw trace sample rate when no session sample rate is available
88- * (i.e. [sessionSampleRateProvider] returns 100).
89- */
90- override fun getSampleRate (): Float {
91- val traceSampleRate = super .getSampleRate()
92- val sessionSampleRate = sessionSampleRateProvider()
93- return if (sessionSampleRate >= 0f && sessionSampleRate < DeterministicSampler .SAMPLE_ALL_RATE ) {
94- val rebased = traceSampleRate * sessionSampleRate / DeterministicSampler .SAMPLE_ALL_RATE
95- rebased.coerceAtMost(DeterministicSampler .SAMPLE_ALL_RATE )
96- } else {
97- traceSampleRate
98- }
99- }
100-
10160 /* * @inheritDoc */
10261 // TODO RUM-13454 -> Remove the @Suppress when getSampleRate(DatadogSpan) is removed in V4 (RUM-15590)
10362 @Suppress(" DEPRECATION" )
10463 override fun sample (item : DatadogSpan ): Boolean =
10564 computeSamplingDecision(getSampleRate(item), SpanSamplingIdProvider .provideId(item))
10665
10766 /* *
108- * Returns the effective sample rate for [item], applying cross-product rebasing when a RUM
109- * session rate is available.
67+ * Returns the effective sample rate for [item], applying cross-product rebasing when the
68+ * span carries a `session_sample_rate` tag (written by
69+ * [com.datadog.android.trace.internal.RumContextPropagator]).
11070 *
111- * When this sampler was created via [ApmNetworkInstrumentationConfiguration] the session rate
112- * is read from the injected [sessionSampleRateProvider]. For samplers created via the public
113- * constructors (no provider) the rate is read from the `session_sample_rate` span tag written
114- * by [com.datadog.android.trace.internal.RumContextPropagator], providing compatibility with
115- * [com.datadog.android.okhttp.trace.TracingInterceptor] and related legacy integrations.
71+ * When no tag is present the raw trace sample rate is returned unchanged.
11672 */
11773 // TODO RUM-13454 -> Remove this in V4 when deprecating legacy paths (RUM-15590)
11874 @Deprecated(
119- " Use ApmNetworkInstrumentationConfiguration for session-aware sampling. Will be removed in v4." ,
75+ " Will be removed in v4." ,
12076 level = DeprecationLevel .WARNING
12177 )
12278 fun getSampleRate (item : DatadogSpan ): Float {
123- // Compatibility path for integrations creating this sampler via public constructors
124- // (no sessionSampleRateProvider). In that case the session sample rate is propagated on
125- // the span context as `session_sample_rate` and must be used for rebasing.
126- val providerRate = sessionSampleRateProvider()
127- val providerRateIsValid = providerRate >= 0f && providerRate < DeterministicSampler .SAMPLE_ALL_RATE
128- val sessionSampleRate = when {
129- providerRateIsValid -> providerRate
130- else -> (item.context().tags[LogAttributes .RUM_SESSION_SAMPLE_RATE ] as ? Number )?.toFloat()
131- }
79+ return resolveEffectiveSampleRate(item)
80+ }
13281
82+ // region private
83+
84+ private fun resolveEffectiveSampleRate (item : DatadogSpan ): Float {
85+ val traceSampleRate = super .getSampleRate()
86+ val sessionSampleRate = resolveSessionSampleRate(item)
13387 return if (sessionSampleRate != null &&
13488 sessionSampleRate >= 0f &&
13589 sessionSampleRate < DeterministicSampler .SAMPLE_ALL_RATE
13690 ) {
137- val rebased = super .getSampleRate() * sessionSampleRate / DeterministicSampler .SAMPLE_ALL_RATE
138- if (rebased > DeterministicSampler . SAMPLE_ALL_RATE ) DeterministicSampler .SAMPLE_ALL_RATE else rebased
91+ (traceSampleRate * sessionSampleRate / DeterministicSampler .SAMPLE_ALL_RATE )
92+ .coerceAtMost( DeterministicSampler .SAMPLE_ALL_RATE )
13993 } else {
140- super .getSampleRate()
94+ traceSampleRate
14195 }
14296 }
97+
98+ private fun resolveSessionSampleRate (item : DatadogSpan ): Float? {
99+ return (item.context().tags[LogAttributes .RUM_SESSION_SAMPLE_RATE ] as ? Number )?.toFloat()
100+ }
101+
102+ // endregion
143103}
0 commit comments