Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions lib/transaction/trace/partial-trace.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,23 +185,26 @@ class PartialTrace {
}

/**
* Checks if span was the retained exit span for a given entity and it has other spans that talked to the same
* entity. It will then sort all timestamps for spans that got dropped and calculate the `nr.durations` and assign
* `nr.ids` for all dropped spans to same entity. It will also reparent the span links from dropped spans to the retained exit span.
* Checks if span had a parentId, if so it will reparent to entry span.
* If span was the retained exit span for a given entity and it has other spans that talked to the same entity, it will:
* sort all timestamps for spans that got dropped and calculate the `nr.durations`
* assign `nr.ids` for all dropped spans to same entity.
* reparent the span links from dropped spans to the retained exit span.
*
* @param {SpanEvent} span to check if it has to calculate `nr.durations` and `nr.ids`
*/
applyCompaction(span) {
if (span.parentId) {
logger.debug(`Partial trace is compact, reparenting span ${span.id} from parent ${span.parentId} to entry span ${this.transaction.baseSegment.name}${this.transaction.baseSegment.id}`)
span.addIntrinsicAttribute('parentId', this.transaction.baseSegment.id)
}
const sameEntitySpans = this.compactSpanGroups[span.id]

if (!sameEntitySpans) {
logger.trace('Partial trace is compact, but not an exit span, not assigning `nr.ids` nor `nr.durations` to span %s', span.intrinsics.name)
return
}

logger.trace('Partial trace is compact, and an exit span, updating parentId(%s) to span %s', this.transaction.baseSegment.id, span.intrinsics.name)
span.addIntrinsicAttribute('parentId', this.transaction.baseSegment.id)

if (sameEntitySpans?.length < 2) {
logger.trace('Partial trace is compact, but no exit spans were dropped, not assigning `nr.ids` nor `nr.durations` to span %s', span.intrinsics.name)
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function findSpan({ spans, name }) {
function assertParentId({ parent, spans, span }) {
if (parent) {
const parentSpan = findSpan({ spans, name: parent })
assert.equal(span.parentId, parentSpan.id, `span ${span.intrinsics.name} should have parent ${parent}, got ${parentSpan.intrinsics.name}`)
assert.equal(span.parentId, parentSpan.id, `span ${span.intrinsics.name} should have parent ${parent}(${span.parentId}), got ${parentSpan.intrinsics.name}(${parentSpan.id})`)
} else {
assert.equal(span.parentId, parent)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,20 +65,27 @@
}
},
{
"name": "Llm/SOMETHING/function",
"timestamp": 1766435411000,
"name": "inprocess-2",
"timestamp": 1766435410020,
"duration_millis": 200,
"agent_attrs": {
"http.url": "myllm"
},
"children": [
{
"name": "External/D",
"timestamp": 1766435411100,
"duration_millis": 250,
"name": "Llm/SOMETHING/function",
"timestamp": 1766435411000,
"duration_millis": 200,
"agent_attrs": {
"http.url": "serviceD"
}
"http.url": "myllm"
},
"children": [
{
"name": "External/D",
"timestamp": 1766435411100,
"duration_millis": 250,
"agent_attrs": {
"http.url": "serviceD"
}
}
]
}
]
}
Expand Down
12 changes: 7 additions & 5 deletions test/unit/transaction/trace/partial-trace.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,15 @@ describe('applyCompaction', () => {
transaction.baseSegment = { id: 100 }
const now = Date.now()
const span1 = {
parentId: 99,
id: 1,
intrinsics: { timestamp: now, duration: 5 },
addIntrinsicAttribute: sinon.spy()
}
const span2 = { id: 2, intrinsics: { timestamp: now, duration: 5 } } // duration is 5
const span3 = { id: 3, intrinsics: { timestamp: now, duration: 7 } } // duration is 7
const span4 = { id: 4, intrinsics: { timestamp: now + 5000, duration: 3 } } // duration is 8
const span5 = { id: 5, intrinsics: { timestamp: now + 10000, duration: 10 } } // duration is 18
const span2 = { parentId: 1, id: 2, intrinsics: { timestamp: now, duration: 5 } } // duration is 5
const span3 = { parentId: 1, id: 3, intrinsics: { timestamp: now, duration: 7 } } // duration is 7
const span4 = { parentId: 1, id: 4, intrinsics: { timestamp: now + 5000, duration: 3 } } // duration is 8
const span5 = { parentId: 1, id: 5, intrinsics: { timestamp: now + 10000, duration: 10 } } // duration is 18
partialTrace.compactSpanGroups[1] = [span1, span5, span3, span4, span2]
partialTrace.applyCompaction(span1)
assert.ok(!transaction.metrics.unscoped['Supportability/Nodejs/PartialGranularity/NrIds/Dropped'])
Expand All @@ -184,7 +185,7 @@ describe('applyCompaction', () => {
const { partialTrace, transaction } = t.nr
transaction.baseSegment = { id: 100 }
const now = Date.now()
const span1 = { id: 0, intrinsics: { timestamp: now, duration: 5 }, addIntrinsicAttribute: sinon.spy() }
const span1 = { parentId: 99, id: 0, intrinsics: { timestamp: now, duration: 5 }, addIntrinsicAttribute: sinon.spy() }
partialTrace.compactSpanGroups[0] = []
const nrIds = []
for (let i = 1; i <= 100; i++) {
Expand All @@ -211,6 +212,7 @@ describe('applyCompaction', () => {
transaction.baseSegment = { id: 100 }
const now = Date.now()
const span1 = {
parentId: 99,
id: 1,
intrinsics: { timestamp: now, duration: 5 },
addIntrinsicAttribute: sinon.spy()
Expand Down
Loading