Skip to content

Conversation

@amychisholm03
Copy link
Contributor

@amychisholm03 amychisholm03 commented Nov 12, 2025

Description

Currently, the agent only has one real sampler, the AdaptiveSampler. This PR adds a second sampler type that is akin to OpenTelemetry's TraceIdRatioBasedSampler and proper classes for the other sampling decisions, always_on and always_off. For the later two sampling decisions, we only applied them if a valid tracestate and traceparent were present. Unfortunately, we still have to account for the deprecated-header or no-header case, which this PR fixes by better encapsulating sampling logic.

There is now a Sampler interface which exposes applySamplingDecision(transaction) which will update priority and sampled on the transaction with respect to the sampler's decision. Previously, this logic was scattered around Transaction (lib/transaction/index.js). This has been reduced to a refactored Transaction.prototype._calculatePriority() and a new applySamplerStrategy(transaction, tracestate, sampler), which is just Sampler.applySamplingDecision with a bit more logic.

There are (currently, core tracing will add more) three ways a customer could use ratio-based sampling. There are defined in our config as distributed_tracing.sampler.*. Under all of these, you would enable ratio-based-sampling by defining trace_id_ratio_based.ratio.

  • root: This is the main sampler for traces originating from the current service.
  • remote_parent_sampled: The sampler for when the upstream service has sampled the trace.
  • remote_parent_not_sampled: The sampler for when the upstream service has not sampled the trace.

Therefore, this PR adds two samplers stored on the agent to better encapsulate the above logic: agent.remoteParentSampledSampler and agent.remoteParentNotSampledSampler. The root sampler kept the current name of agent.transactionSampler. There is a lot of complexity around this, namely the possibly of > 1 AdaptiveSamplers who may or may not share state. This is out of scope for this PR and will be solved by #3519.

How to Test

Cross-agent tests are re-synced! The new tests uncovered some missing pieces with our sampling logic, outside of ratio-based sampling, which this PR solves.

npm run unit
npm run integration

Related Issues

Closes #3387 and closes #3480

@amychisholm03 amychisholm03 marked this pull request as draft November 12, 2025 15:34
@amychisholm03 amychisholm03 changed the title feat: Trace feat: TraceIdRatioBasedSampler Nov 12, 2025
@codecov
Copy link

codecov bot commented Nov 12, 2025

Codecov Report

❌ Patch coverage is 98.46154% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.65%. Comparing base (45667a0) to head (f2b2208).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
lib/samplers/ratio-based-sampler.js 97.59% 2 Missing ⚠️
lib/samplers/sampler.js 90.47% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3501      +/-   ##
==========================================
- Coverage   97.77%   97.65%   -0.13%     
==========================================
  Files         421      426       +5     
  Lines       55763    55923     +160     
  Branches        1        1              
==========================================
+ Hits        54524    54609      +85     
- Misses       1239     1314      +75     
Flag Coverage Δ
integration-tests-cjs-20.x 74.02% <96.53%> (+0.10%) ⬆️
integration-tests-cjs-22.x 74.06% <96.53%> (+0.10%) ⬆️
integration-tests-cjs-24.x 74.81% <96.53%> (+0.10%) ⬆️
integration-tests-esm-20.x 52.61% <60.00%> (+0.08%) ⬆️
integration-tests-esm-22.x 52.66% <60.00%> (+0.08%) ⬆️
integration-tests-esm-24.x 53.86% <60.00%> (+0.08%) ⬆️
unit-tests-20.x 88.74% <90.76%> (+0.01%) ⬆️
unit-tests-22.x 88.77% <90.76%> (+0.01%) ⬆️
unit-tests-24.x 88.78% <90.76%> (+0.01%) ⬆️
versioned-tests-20.x 81.00% <71.15%> (-0.34%) ⬇️
versioned-tests-22.x 81.00% <71.15%> (-0.35%) ⬇️
versioned-tests-24.x 80.94% <71.15%> (-0.34%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@amychisholm03 amychisholm03 force-pushed the NR-3387/ratio-based-sampler branch 7 times, most recently from bcd7c51 to 1e32477 Compare November 13, 2025 23:51
@amychisholm03 amychisholm03 force-pushed the NR-3387/ratio-based-sampler branch 2 times, most recently from 2c085a1 to 037a29f Compare November 17, 2025 18:05
@amychisholm03 amychisholm03 force-pushed the NR-3387/ratio-based-sampler branch from 531c86e to 0356e15 Compare November 17, 2025 19:53
@amychisholm03 amychisholm03 changed the title feat: TraceIdRatioBasedSampler feat: TraceIdRatioBasedSampler and other sampling fixes Nov 18, 2025
@amychisholm03 amychisholm03 force-pushed the NR-3387/ratio-based-sampler branch from 6f881da to d2d44ae Compare November 18, 2025 02:26
@amychisholm03 amychisholm03 force-pushed the NR-3387/ratio-based-sampler branch from 88dfa7a to f2b2208 Compare November 18, 2025 02:27
@amychisholm03 amychisholm03 marked this pull request as ready for review November 18, 2025 02:32
@bizob2828 bizob2828 self-assigned this Nov 18, 2025
Copy link
Member

@bizob2828 bizob2828 left a comment

Choose a reason for hiding this comment

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

I haven't fully reviewed but I have some concerns with our approach, especially when you layer on partial granularity/full granularity tracing

* @returns {Sampler} A Sampler e.g. AdaptiveSampler or TraceIdRatioBasedSampler
*/
function determineSampler({ agent, config, sampler = 'root' }) {
const samplerDefinition = config?.distributed_tracing?.sampler?.[sampler]
Copy link
Member

Choose a reason for hiding this comment

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

Feels like there has to be a better way to do this. This will not work for core tracing. Will we have to instantiate even more samplers?

* in respect to this sampler's decision.
* @param {Transaction} transaction the transaction to update
*/
applySamplingDecision(transaction) {
Copy link
Member

Choose a reason for hiding this comment

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

I'm unclear here. We've conflated a sampler with a sampler. Meaning previous samplers like adaptive sampler were called with shouldSample

transaction.sampled = tracestate?.intrinsics ? tracestate.isSampled : null
transaction.priority = tracestate?.intrinsics ? tracestate.priority : null
function applySamplingStrategy({ transaction, tracestate = null, sampler }) {
if (sampler?.toString() !== 'AdaptiveSampler') {
Copy link
Member

Choose a reason for hiding this comment

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

shouldn't all the sampling logic be encapsulated within the samplers? Having this hang off adaptive sampler feels wrong

applySamplingDecision(transaction) {
if (!transaction) return
// eslint-disable-next-line sonarjs/pseudo-random
const initPriority = Math.random()
Copy link
Member

Choose a reason for hiding this comment

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

This is the sample logic as the adaptive, it's just that it calls its shouldSample method. Feels like this should be in the default Sampler class

}

// Is it TraceIdRatioBased?
const ratioBasedSampler = samplerDefinition?.trace_id_ratio_based
Copy link
Member

Choose a reason for hiding this comment

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

this logic should live in the config. we shouldn't have to check if it's a valid ratio here.

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

Labels

None yet

Projects

Status: Needs PR Review

Development

Successfully merging this pull request may close these issues.

Resync Cross agent tests Add ratio based sampler

2 participants