Skip to content

Commit 037a29f

Browse files
committed
wip: sync cross agent tests
1 parent 891b54f commit 037a29f

File tree

12 files changed

+650
-139
lines changed

12 files changed

+650
-139
lines changed

lib/config/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,8 +1257,8 @@ function setTraceIDRatioSampler({ key, value, config, paths }) {
12571257
}
12581258
logger.trace('Setting %s environment variable', envVar)
12591259
} else {
1260-
logger.error('Not setting %s environment variable. Setting sampler root to default.', envVar)
1261-
config.distributed_tracing.sampler.root = 'default'
1260+
logger.error('Not setting %s environment variable. Setting sampler %s to default.', envVar, key)
1261+
config.distributed_tracing.sampler[key] = 'default'
12621262
}
12631263
}
12641264
}

lib/samplers/adaptive-sampler.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ class AdaptiveSampler {
3333
}
3434
}
3535

36+
toString() {
37+
return 'AdaptiveSampler'
38+
}
39+
3640
get sampled() {
3741
return this._sampled
3842
}

lib/transaction/index.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,20 +1065,26 @@ function decideSamplingFromW3cData({ transaction, traceparent, tracestate }) {
10651065
* @param {Transaction} params.transaction The transaction to update.
10661066
* @param {Tracestate} params.tracestate A tracestate object with embedded New Relic intrinsics.
10671067
* @param {object} params.sampler The sampler to use, AdaptiveSampler or TraceIdRatioBasedSampler.
1068-
* @param {string} params.samplerType A string describing the sampler being used
1069-
* ('default', 'always_on', 'always_off').
1068+
* @param {string|object} params.samplerType A string describing the sampler being used
1069+
* ('default', 'always_on', 'always_off'), or an object if 'trace_id_ratio_based'.
10701070
*/
10711071
function applySamplingStrategy({ transaction, tracestate, sampler, samplerType }) {
10721072
if (sampler?.toString() === 'TraceIdRatioBasedSampler') {
10731073
transaction.sampled = sampler.shouldSample(transaction.traceId)
1074-
// Force calc priority because transaction.sampled likely changed
1074+
// Force calc priority because transaction.sampled likekly has changed
10751075
transaction._calculatePriority(sampler)
10761076
return
10771077
}
10781078

10791079
// TODO: Make these their own samplers?
10801080
switch (samplerType) {
10811081
case 'default': {
1082+
// This case is if we're coming from the deprecated newrelic header logic
1083+
// where we don't want to override the sampled and priority values
1084+
if (!tracestate) {
1085+
return
1086+
}
1087+
10821088
transaction.sampled = tracestate?.intrinsics ? tracestate.isSampled : null
10831089
transaction.priority = tracestate?.intrinsics ? tracestate.priority : null
10841090
break
@@ -1196,8 +1202,20 @@ const _dtDefineAttrsFromTraceData = function _dtDefineAttrsFromTraceData(data, t
11961202
this.traceId = data.tr
11971203

11981204
if (data.pr) {
1205+
// TODO: We need to consider the sampler before blindly accepting this value.
11991206
this.priority = data.pr
12001207
this.sampled = data.sa != null ? data.sa : this.sampled
1208+
// we don't have traceparent or tracestate, but this will update
1209+
// sampling decision based on our samplers
1210+
const {
1211+
remote_parent_sampled: parentSampled,
1212+
remote_parent_not_sampled: parentNotSampled
1213+
} = this.agent.config.distributed_tracing.sampler
1214+
if (data?.sa) {
1215+
applySamplingStrategy({ transaction: this, sampler: this.agent.remoteParentSampledSampler, samplerType: parentSampled })
1216+
} else {
1217+
applySamplingStrategy({ transaction: this, sampler: this.agent.remoteParentNotSampledSampler, samplerType: parentNotSampled })
1218+
}
12011219
}
12021220

12031221
if (data.tx) {

test/integration/distributed-tracing/trace-context-cross-agent.test.js

Lines changed: 82 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const recordSupportability = require('../../../lib/agent').prototype.recordSuppo
1818

1919
const getDescendantValue = function (object, descendants) {
2020
const arrayDescendants = descendants.split('.')
21-
const noop = () => {}
21+
const noop = () => { }
2222
while (arrayDescendants.length && (object = object[arrayDescendants.shift()])) {
2323
noop()
2424
}
@@ -268,7 +268,7 @@ async function runTestCase(testCase, parentTest) {
268268
testExpectedFixtureKeys(testCase, [
269269
'account_id',
270270
'expected_metrics',
271-
'force_sampled_true',
271+
'force_adaptive_sampled_true',
272272
'inbound_headers',
273273
'intrinsics',
274274
'outbound_payloads',
@@ -279,7 +279,13 @@ async function runTestCase(testCase, parentTest) {
279279
'trusted_account_key',
280280
'web_transaction',
281281
'comment',
282-
'transaction_events_enabled'
282+
'transaction_events_enabled',
283+
// Sampling
284+
'remote_parent_sampled',
285+
'remote_parent_not_sampled',
286+
'root',
287+
'ratio',
288+
'expected_priority_between'
283289
])
284290

285291
if (testCase.outbound_payloads) {
@@ -325,21 +331,64 @@ async function runTestCase(testCase, parentTest) {
325331
})
326332

327333
await parentTest.test('trace context: ' + testCase.test_name, (t, end) => {
328-
const agent = helper.instrumentMockedAgent({})
334+
// Sampling config has to be given on agent initialization
335+
const initConfig = {
336+
distributed_tracing: {
337+
enabled: true,
338+
sampler: {
339+
root: {},
340+
remote_parent_sampled: {},
341+
remote_parent_not_sampled: {}
342+
}
343+
}
344+
}
345+
initConfig.distributed_tracing.sampler.remote_parent_sampled = testCase.remote_parent_sampled ?? 'default'
346+
initConfig.distributed_tracing.sampler.remote_parent_not_sampled = testCase.remote_parent_not_sampled ?? 'default'
347+
initConfig.distributed_tracing.sampler.root = testCase.root ?? 'default'
348+
if (testCase.ratio) {
349+
// The ratio to use for all of the trace ID ratio samplers defined in the test.
350+
// For testing purposes we are not defining different ratios for each trace ID ratio sampler instance.
351+
if (initConfig.distributed_tracing.sampler.root === 'trace_id_ratio_based') {
352+
initConfig.distributed_tracing.sampler.root = {
353+
trace_id_ratio_based: {
354+
ratio: testCase.ratio
355+
}
356+
}
357+
}
358+
if (initConfig.distributed_tracing.sampler.remote_parent_sampled === 'trace_id_ratio_based') {
359+
initConfig.distributed_tracing.sampler.remote_parent_sampled = {
360+
trace_id_ratio_based: {
361+
ratio: testCase.ratio
362+
}
363+
}
364+
}
365+
if (initConfig.distributed_tracing.sampler.remote_parent_not_sampled === 'trace_id_ratio_based') {
366+
initConfig.distributed_tracing.sampler.remote_parent_not_sampled = {
367+
trace_id_ratio_based: {
368+
ratio: testCase.ratio
369+
}
370+
}
371+
}
372+
}
373+
const agent = helper.instrumentMockedAgent(initConfig)
329374
agent.recordSupportability = recordSupportability
330375
agent.config.trusted_account_key = testCase.trusted_account_key
331376
agent.config.account_id = testCase.account_id
332377
agent.config.primary_application_id = 4657
333378
agent.config.span_events.enabled = testCase.span_events_enabled
334-
agent.config.transaction_events.enabled = testCase.transaction_events_enabled
335-
agent.config.distributed_tracing.enabled = true
379+
// Some new tests should have this set to true, but they are undefined instead
380+
if (testCase.transaction_events_enabled !== undefined) {
381+
agent.config.transaction_events.enabled = testCase.transaction_events_enabled
382+
} else agent.config.transaction_events.enabled = true
383+
336384
t.after(() => helper.unloadAgent(agent))
337385

338386
const agentApi = new API(agent)
339387

340388
const transactionType = testCase.web_transaction ? TYPES.WEB : TYPES.BG
341389

342390
helper.runInTransaction(agent, transactionType, function (transaction) {
391+
console.debug(testCase.test_name)
343392
transaction.baseSegment = transaction.trace.add('MyBaseSegment', (segment) => {
344393
recorder(
345394
transaction,
@@ -354,13 +403,7 @@ async function runTestCase(testCase, parentTest) {
354403
agentApi.noticeError(new Error('should error'))
355404
}
356405

357-
// monkey patch this transaction object
358-
// to force sampled to be true.
359-
if (testCase.force_sampled_true) {
360-
transaction.agent.transactionSampler.shouldSample = function stubShouldSample() {
361-
return true
362-
}
363-
}
406+
forceAdaptiveSamplers(agent, testCase.force_adaptive_sampled_true)
364407

365408
for (const inboundHeader of testCase.inbound_headers.values()) {
366409
transaction.acceptDistributedTraceHeaders(testCase.transport_type, inboundHeader)
@@ -406,6 +449,16 @@ async function runTestCase(testCase, parentTest) {
406449
transaction.trace.root.touch()
407450
transaction.end()
408451

452+
// check `expected_priority_between`
453+
if (testCase.expected_priority_between) {
454+
const [minPriority, maxPriority] = testCase.expected_priority_between
455+
const actualPriority = transaction.priority
456+
assert.ok(
457+
actualPriority >= minPriority && actualPriority <= maxPriority,
458+
`Expected transaction.priority (${actualPriority}) to be between ${minPriority} and ${maxPriority}`
459+
)
460+
}
461+
409462
// These tests assume setting a transport type even when there are not valid
410463
// trace headers. This is slightly inconsistent with the spec. Given DT
411464
// (NR format) does not include transport when there is no trace AND the
@@ -446,3 +499,19 @@ async function runTestCase(testCase, parentTest) {
446499
end()
447500
})
448501
}
502+
503+
function forceAdaptiveSamplers(agent, forceAdaptiveSampled) {
504+
if (forceAdaptiveSampled === undefined || forceAdaptiveSampled === null) return
505+
// "Whether to force a transaction to be sampled or not when the adaptive sampler is used"
506+
// implies this affects all samplers that are adaptive samplers
507+
const samplers = [agent.transactionSampler, agent.remoteParentSampledSampler, agent.remoteParentNotSampledSampler]
508+
for (const sampler of samplers) {
509+
if (sampler?.toString() === 'AdaptiveSampler') {
510+
// monkey patch this transaction object
511+
// to force sampled to the given value.
512+
sampler.shouldSample = function stubShouldSample() {
513+
return forceAdaptiveSampled
514+
}
515+
}
516+
}
517+
}

test/lib/cross_agent_tests/distributed_tracing/README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ the agent under test. Here's what the various fields in each test case mean:
1414
| `account_id` | The account id the agent would receive on connect. |
1515
| `web_transaction` | Whether the transaction that's tested is a web transaction or not. |
1616
| `raises_exception` | Whether to simulate an exception happening within the transaction or not, resulting in a transaction error event. |
17-
| `force_sampled_true` | Whether to force a transaction to be sampled or not. |
17+
| `root` | The sampler to use for transactions at the root of a trace. |
18+
| `remote_parent_sampled` | The sampler to use for transactions with a remote parent. |
19+
| `remote_parent_not_sampled` | The sampler to use for transactions with a remote parent that is not sampled. |
20+
| `expected_priority_between` | The inclusive range of the expected priority value on the generated transaction event. |
21+
| `force_adaptive_sampled_true` | Whether to force a transaction to be sampled or not when the adaptive sampler is used. |
22+
| `ratio` | The ratio to use for all of the trace ID ratio samplers defined in the test. For testing purposes we are not defining different ratios for each trace ID ratio sampler instance. If that is necessary, we will need a different way to configure the ratios. |
1823
| `transport_type` | The transport type for the inbound request. |
1924
| `inbound_headers` | The headers you should mock coming into the agent. |
2025
| `outbound_payloads` | The exact/expected/unexpected values for outbound `w3c` headers. |
@@ -23,6 +28,14 @@ the agent under test. Here's what the various fields in each test case mean:
2328
| `span_events_enabled` | Whether span events are enabled in the agent or not. |
2429
| `transaction_events_enabled` | Whether transaction events are enabled in the agent or not. |
2530

31+
The samplers that can referenced in the `root`, `remote_parent_sampled`, and `remote_parent_not_sampled` fields are:
32+
33+
- `default`: Use the adaptive sampler.
34+
- `adaptive`: Use the adaptive sampler.
35+
- `trace_id_ratio_based`: Use the trace ID ratio sampler.
36+
- `always_on`: Use the always on sampler.
37+
- `always_off`: Use the always off sampler.
38+
2639
The `outbound_payloads` and `intrinsics` field can have nested values, for example:
2740
```javascript
2841
...

test/lib/cross_agent_tests/distributed_tracing/distributed_tracing.json

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -796,78 +796,6 @@
796796
["Supportability/DistributedTrace/CreatePayload/Success", 2]
797797
]
798798
},
799-
{
800-
"test_name": "payload_from_trusted_partnership_account",
801-
"trusted_account_key": "44",
802-
"account_id": "11",
803-
"web_transaction": true,
804-
"raises_exception": false,
805-
"force_sampled_true": false,
806-
"span_events_enabled": true,
807-
"major_version": 0,
808-
"minor_version": 1,
809-
"transport_type": "HTTP",
810-
"inbound_payloads": [
811-
{
812-
"v": [0, 1],
813-
"d": {
814-
"ac": "33",
815-
"ap": "2827902",
816-
"tx": "e8b91a159289ff74",
817-
"pr": 0.123456,
818-
"sa": false,
819-
"ti": 1518469636035,
820-
"tr": "d6b4ba0c3a712ca",
821-
"tk": "44",
822-
"ty": "App"
823-
}
824-
}
825-
],
826-
"outbound_payloads": [
827-
{
828-
"exact": {
829-
"v": [0, 1],
830-
"d.ac": "11",
831-
"d.pr": 0.123456,
832-
"d.sa": false,
833-
"d.tr": "d6b4ba0c3a712ca",
834-
"d.tk": "44",
835-
"d.ty": "App"
836-
},
837-
"expected": ["d.ap", "d.tx", "d.ti"],
838-
"unexpected": ["d.id"]
839-
}
840-
],
841-
"intrinsics": {
842-
"target_events": ["Transaction"],
843-
"common":{
844-
"exact": {
845-
"parent.type": "App",
846-
"parent.app": "2827902",
847-
"parent.account": "33",
848-
"parent.transportType": "HTTP",
849-
"traceId": "d6b4ba0c3a712ca",
850-
"priority": 0.123456,
851-
"sampled": false
852-
},
853-
"expected": ["parent.transportDuration", "guid"],
854-
"unexpected": ["grandparentId", "cross_process_id", "nr.tripId", "nr.pathHash", "nr.referringPathHash", "nr.guid", "nr.referringTransactionGuid", "nr.alternatePathHashes"]
855-
},
856-
"Transaction": {
857-
"exact": {
858-
"parentId": "e8b91a159289ff74"
859-
}
860-
}
861-
},
862-
"expected_metrics": [
863-
["DurationByCaller/App/33/2827902/HTTP/all", 1],
864-
["DurationByCaller/App/33/2827902/HTTP/allWeb", 1],
865-
["TransportDuration/App/33/2827902/HTTP/all", 1],
866-
["TransportDuration/App/33/2827902/HTTP/allWeb", 1],
867-
["Supportability/DistributedTrace/AcceptPayload/Success", 1],
868-
["Supportability/DistributedTrace/CreatePayload/Success", 1]
869-
]
870-
},
871799
{
872800
"test_name": "payload_has_larger_minor_version",
873801
"trusted_account_key": "33",

0 commit comments

Comments
 (0)