Skip to content

Commit 7fbba52

Browse files
author
Luca Forstner
committed
Implement propagating sampling decision properly
1 parent 1646f0b commit 7fbba52

File tree

1 file changed

+37
-2
lines changed

1 file changed

+37
-2
lines changed

packages/core/src/utils-hoist/tracing.ts

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { PropagationContext, TraceparentData } from '../types-hoist';
1+
import type { DynamicSamplingContext, PropagationContext, TraceparentData } from '../types-hoist';
22

33
import { baggageHeaderToDynamicSamplingContext } from './baggage';
44
import { generateSpanId, generateTraceId } from './propagationContext';
@@ -68,7 +68,7 @@ export function propagationContextFromHeaders(
6868
parentSpanId,
6969
sampled: parentSampled,
7070
dsc: dynamicSamplingContext || {}, // If we have traceparent data but no DSC it means we are not head of trace and we must freeze it
71-
sampleRand: parseSampleRandFromDsc(dynamicSamplingContext?.sample_rand),
71+
sampleRand: getSampleRandFromTraceparentAndDsc(traceparentData, dynamicSamplingContext),
7272
};
7373
}
7474

@@ -101,3 +101,38 @@ export function parseSampleRandFromDsc(sampleRand: string | undefined): number {
101101
return Math.random();
102102
}
103103
}
104+
105+
function getSampleRandFromTraceparentAndDsc(
106+
traceparentData: TraceparentData | undefined,
107+
dsc: Partial<DynamicSamplingContext> | undefined,
108+
): number {
109+
const parsedSampleRand = parseSamplingDscNumber(dsc?.sample_rand);
110+
if (parsedSampleRand !== undefined) {
111+
return parsedSampleRand;
112+
}
113+
114+
const parsedSampleRate = parseSamplingDscNumber(dsc?.sample_rate);
115+
if (parsedSampleRate && traceparentData?.parentSampled !== undefined) {
116+
return traceparentData.parentSampled
117+
? // Returns a sample rand with positive sampling decision [0, sampleRate)
118+
Math.random() * parsedSampleRate
119+
: // Returns a sample rand with negative sampling decision [sampleRate, 1]
120+
parsedSampleRate + Math.random() * (1 - parsedSampleRate);
121+
} else {
122+
return Math.random();
123+
}
124+
}
125+
126+
function parseSamplingDscNumber(sampleRand: string | undefined): number | undefined {
127+
try {
128+
const parsed = Number(sampleRand); // Number(undefined) will return NaN and fail the next check
129+
if (isNaN(parsed) || parsed < 0 || parsed > 1) {
130+
// This is probably an invariant but returning undefined seems sensible.
131+
return undefined;
132+
} else {
133+
return parsed;
134+
}
135+
} catch {
136+
return undefined;
137+
}
138+
}

0 commit comments

Comments
 (0)