Skip to content

Commit af29d09

Browse files
Merge branch 'add-partial-essential-granularity' of github.com:svetlanabrennan/node-newrelic into add-partial-essential-granularity
2 parents affbbda + caa9e05 commit af29d09

File tree

2 files changed

+118
-220
lines changed

2 files changed

+118
-220
lines changed

lib/spans/span-event.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ class SpanEvent {
171171
* @param {boolean} params.entryPoint whether the span is an entry point
172172
* @param {string} params.partialGranularityMode mode of partial trace ('reduced', 'essential', 'compact')
173173
* @param {boolean} params.isPartialTrace whether the trace is a partial trace
174-
* @returns {object} attributes, customAttributes and/or dropSpan
174+
* @returns {object} filtered attributes and custom attributes
175175
*/
176176
static filterPartialTraceAttributes({ segment, spanContext, entryPoint, partialGranularityMode, isPartialTrace }) {
177177
const attributes = segment.attributes.get(DESTINATIONS.SPAN_EVENT)

test/unit/spans/partial-granularity-spans.test.js

Lines changed: 117 additions & 219 deletions
Original file line numberDiff line numberDiff line change
@@ -9,244 +9,142 @@ const test = require('node:test')
99
const helper = require('#testlib/agent_helper.js')
1010
const SpanEvent = require('#agentlib/spans/span-event.js')
1111

12-
test('Partial Granularity Spans - reduced mode', async (t) => {
13-
test.beforeEach((ctx) => {
14-
const agent = helper.instrumentMockedAgent({
15-
distributed_tracing: {
12+
test.beforeEach((ctx) => {
13+
const agent = helper.instrumentMockedAgent({
14+
distributed_tracing: {
15+
enabled: true,
16+
full_granularity: {
17+
enabled: false
18+
},
19+
partial_granularity: {
1620
enabled: true,
17-
full_granularity: {
18-
enabled: false
19-
},
20-
partial_granularity: {
21-
enabled: true,
22-
type: 'reduced'
23-
}
21+
type: 'reduced'
2422
}
25-
})
26-
ctx.nr = { agent }
27-
})
28-
29-
test.afterEach((ctx) => {
30-
helper.unloadAgent(ctx.nr.agent)
31-
})
32-
33-
test('should include entry span', (t, end) => {
34-
const { agent } = t.nr
35-
helper.runInTransaction(agent, (transaction) => {
36-
transaction.isPartialTrace = true
37-
const segment = transaction.trace.add('entrySpan')
38-
transaction.baseSegment = segment
39-
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'reduced' })
40-
assert.ok(span)
41-
assert.equal(span.intrinsics['nr.entryPoint'], true)
42-
assert.equal(span.intrinsics['nr.pg'], true)
43-
assert.equal(span.intrinsics.parentId, null)
44-
end()
45-
})
46-
})
47-
48-
test('should include Llm span', (t, end) => {
49-
const { agent } = t.nr
50-
helper.runInTransaction(agent, (transaction) => {
51-
transaction.isPartialTrace = true
52-
const segment = transaction.trace.add('Llm/foobar')
53-
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'reduced' })
54-
assert.ok(span)
55-
end()
56-
})
57-
})
58-
59-
test('should include exit span that has entity relationship attrs', (t, end) => {
60-
const { agent } = t.nr
61-
helper.runInTransaction(agent, (transaction) => {
62-
transaction.isPartialTrace = true
63-
const segment = transaction.trace.add('Datastore/operation/Redis/SET')
64-
segment.addAttribute('host', 'redis-service')
65-
segment.addAttribute('port_path_or_id', 6379)
66-
segment.addAttribute('foo', 'bar')
67-
const spanContext = segment.getSpanContext()
68-
spanContext.addCustomAttribute('custom', 'test')
69-
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'reduced' })
70-
assert.ok(span)
71-
const [instrinsics, customAttrs, agentAttrs] = span.toJSON()
72-
assert.equal(instrinsics['name'], 'Datastore/operation/Redis/SET')
73-
assert.equal(instrinsics['span.kind'], 'client')
74-
assert.deepEqual(customAttrs, {
75-
custom: 'test'
76-
})
77-
assert.equal(span.intrinsics['nr.entryPoint'], null)
78-
assert.equal(span.intrinsics['nr.pg'], null)
79-
assert.equal(agentAttrs['peer.address'], 'redis-service:6379')
80-
assert.equal(agentAttrs['peer.hostname'], 'redis-service')
81-
assert.equal(agentAttrs['server.address'], 'redis-service')
82-
assert.equal(agentAttrs['server.port'], '6379')
83-
assert.equal(agentAttrs.foo, 'bar')
84-
end()
85-
})
86-
})
87-
88-
test('should not include exit span that does not have entity relationship attrs', (t, end) => {
89-
const { agent } = t.nr
90-
helper.runInTransaction(agent, (transaction) => {
91-
transaction.isPartialTrace = true
92-
const segment = transaction.trace.add('Datastore/operation/Redis/SET')
93-
segment.addAttribute('foo', 'bar')
94-
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'reduced' })
95-
assert.ok(!span)
96-
end()
97-
})
98-
})
99-
100-
test('should not include in process span', (t, end) => {
101-
const { agent } = t.nr
102-
helper.runInTransaction(agent, (transaction) => {
103-
transaction.isPartialTrace = true
104-
const segment = transaction.trace.add('test-segment')
105-
segment.addAttribute('foo', 'bar')
106-
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'reduced' })
107-
assert.ok(!span)
108-
end()
109-
})
110-
})
111-
112-
test('should include exit span that does not have entity relationship attrs when not part of partialTrace', (t, end) => {
113-
const { agent } = t.nr
114-
helper.runInTransaction(agent, (transaction) => {
115-
transaction.isPartialTrace = false
116-
const segment = transaction.trace.add('Datastore/operation/Redis/SET')
117-
segment.addAttribute('foo', 'bar')
118-
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'reduced' })
119-
assert.ok(span)
120-
const [instrinsics, , agentAttrs] = span.toJSON()
121-
assert.equal(instrinsics['name'], 'Datastore/operation/Redis/SET')
122-
assert.equal(instrinsics['span.kind'], 'client')
123-
assert.equal(span.intrinsics['nr.entryPoint'], null)
124-
assert.equal(span.intrinsics['nr.pg'], null)
125-
assert.equal(agentAttrs.foo, 'bar')
126-
end()
127-
})
23+
}
12824
})
25+
ctx.nr = { agent }
26+
})
12927

130-
test('should include in process span when not part of partialTrace', (t, end) => {
131-
const { agent } = t.nr
132-
helper.runInTransaction(agent, (transaction) => {
133-
transaction.isPartialTrace = false
134-
const segment = transaction.trace.add('test-segment')
135-
const spanContext = segment.getSpanContext()
136-
spanContext.addCustomAttribute('custom', 'test')
137-
segment.addAttribute('foo', 'bar')
138-
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'reduced' })
139-
assert.ok(span)
140-
const [instrinsics, customAttrs, agentAttrs] = span.toJSON()
141-
assert.equal(instrinsics['name'], 'test-segment')
142-
assert.equal(instrinsics['span.kind'], 'internal')
143-
assert.deepEqual(customAttrs, {
144-
custom: 'test'
145-
})
146-
assert.equal(span.intrinsics['nr.entryPoint'], null)
147-
assert.equal(span.intrinsics['nr.pg'], null)
148-
assert.equal(agentAttrs.foo, 'bar')
149-
end()
150-
})
151-
})
28+
test.afterEach((ctx) => {
29+
helper.unloadAgent(ctx.nr.agent)
15230
})
15331

154-
test('Partial Granularity Spans - essential mode', async (t) => {
155-
t.beforeEach((ctx) => {
156-
const agent = helper.instrumentMockedAgent({
157-
distributed_tracing: {
158-
enabled: true,
159-
partial_granularity: {
160-
enabled: true,
161-
type: 'essential'
162-
}
163-
}
164-
})
165-
ctx.nr = { agent }
32+
test('should include entry span', (t, end) => {
33+
const { agent } = t.nr
34+
helper.runInTransaction(agent, (transaction) => {
35+
transaction.isPartialTrace = true
36+
const segment = transaction.trace.add('entrySpan')
37+
transaction.baseSegment = segment
38+
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'reduced' })
39+
assert.ok(span)
40+
assert.equal(span.intrinsics['nr.entryPoint'], true)
41+
assert.equal(span.intrinsics['nr.pg'], true)
42+
assert.equal(span.intrinsics.parentId, null)
43+
end()
16644
})
45+
})
16746

168-
t.afterEach((ctx) => {
169-
helper.unloadAgent(ctx.nr.agent)
47+
test('should include Llm span', (t, end) => {
48+
const { agent } = t.nr
49+
helper.runInTransaction(agent, (transaction) => {
50+
transaction.isPartialTrace = true
51+
const segment = transaction.trace.add('Llm/foobar')
52+
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'reduced' })
53+
assert.ok(span)
54+
end()
17055
})
56+
})
17157

172-
await t.test('should include entry span', (t, end) => {
173-
const { agent } = t.nr
174-
helper.runInTransaction(agent, (transaction) => {
175-
transaction.isPartialTrace = true
176-
const segment = transaction.trace.add('entrySpan')
177-
transaction.baseSegment = segment
178-
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'essential' })
179-
assert.ok(span)
180-
assert.equal(span.intrinsics['nr.entryPoint'], true)
181-
assert.equal(span.intrinsics['nr.pg'], true)
182-
assert.equal(span.intrinsics.parentId, null)
183-
end()
58+
test('should include exit span that has entity relationship attrs', (t, end) => {
59+
const { agent } = t.nr
60+
helper.runInTransaction(agent, (transaction) => {
61+
transaction.isPartialTrace = true
62+
const segment = transaction.trace.add('Datastore/operation/Redis/SET')
63+
segment.addAttribute('host', 'redis-service')
64+
segment.addAttribute('port_path_or_id', 6379)
65+
segment.addAttribute('foo', 'bar')
66+
const spanContext = segment.getSpanContext()
67+
spanContext.addCustomAttribute('custom', 'test')
68+
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'reduced' })
69+
assert.ok(span)
70+
const [instrinsics, customAttrs, agentAttrs] = span.toJSON()
71+
assert.equal(instrinsics['name'], 'Datastore/operation/Redis/SET')
72+
assert.equal(instrinsics['span.kind'], 'client')
73+
assert.deepEqual(customAttrs, {
74+
custom: 'test'
18475
})
76+
assert.equal(span.intrinsics['nr.entryPoint'], null)
77+
assert.equal(span.intrinsics['nr.pg'], null)
78+
assert.equal(agentAttrs['peer.address'], 'redis-service:6379')
79+
assert.equal(agentAttrs['peer.hostname'], 'redis-service')
80+
assert.equal(agentAttrs['server.address'], 'redis-service')
81+
assert.equal(agentAttrs['server.port'], '6379')
82+
assert.equal(agentAttrs.foo, 'bar')
83+
end()
18584
})
85+
})
18686

187-
await t.test('should include Llm span', (t, end) => {
188-
const { agent } = t.nr
189-
helper.runInTransaction(agent, (transaction) => {
190-
transaction.isPartialTrace = true
191-
const segment = transaction.trace.add('Llm/foobar')
192-
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'essential' })
193-
assert.ok(span)
194-
end()
195-
})
87+
test('should not include exit span that does not have entity relationship attrs', (t, end) => {
88+
const { agent } = t.nr
89+
helper.runInTransaction(agent, (transaction) => {
90+
transaction.isPartialTrace = true
91+
const segment = transaction.trace.add('Datastore/operation/Redis/SET')
92+
segment.addAttribute('foo', 'bar')
93+
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'reduced' })
94+
assert.ok(!span)
95+
end()
19696
})
97+
})
19798

198-
await t.test('should include exit span with entity relationship and error attrs but no custom attrs', (t, end) => {
199-
const { agent } = t.nr
200-
helper.runInTransaction(agent, (transaction) => {
201-
transaction.isPartialTrace = true
202-
const segment = transaction.trace.add('Datastore/operation/Redis/SET')
203-
segment.addAttribute('host', 'redis-service')
204-
segment.addAttribute('port_path_or_id', 6379)
205-
segment.addAttribute('foo', 'bar')
206-
segment.addAttribute('error.message', 'something went wrong')
207-
segment.addAttribute('error.class', 'Error')
208-
const spanContext = segment.getSpanContext()
209-
spanContext.addCustomAttribute('custom', 'test')
210-
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'essential' })
211-
assert.ok(span)
212-
const [instrinsics, customAttrs, agentAttrs] = span.toJSON()
213-
assert.equal(instrinsics['name'], 'Datastore/operation/Redis/SET')
214-
assert.equal(instrinsics['span.kind'], 'client')
215-
assert.deepEqual(customAttrs, {}) // should drop custom attributes
216-
assert.equal(span.intrinsics['nr.entryPoint'], null)
217-
assert.equal(span.intrinsics['nr.pg'], null)
218-
assert.equal(agentAttrs['peer.address'], 'redis-service:6379')
219-
assert.equal(agentAttrs['peer.hostname'], 'redis-service')
220-
assert.equal(agentAttrs['server.address'], 'redis-service')
221-
assert.equal(agentAttrs['server.port'], '6379')
222-
assert.equal(agentAttrs.foo, undefined) // should drop non entity relationship agent attributes
223-
assert.equal(agentAttrs['error.message'], 'something went wrong') // keep error attributes if they exist
224-
assert.equal(agentAttrs['error.class'], 'Error') // keep error attributes if they exist
225-
end()
226-
})
99+
test('should not include in process span', (t, end) => {
100+
const { agent } = t.nr
101+
helper.runInTransaction(agent, (transaction) => {
102+
transaction.isPartialTrace = true
103+
const segment = transaction.trace.add('test-segment')
104+
segment.addAttribute('foo', 'bar')
105+
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'reduced' })
106+
assert.ok(!span)
107+
end()
227108
})
109+
})
228110

229-
await t.test('should not include exit span that does not have entity relationship attrs', (t, end) => {
230-
const { agent } = t.nr
231-
helper.runInTransaction(agent, (transaction) => {
232-
transaction.isPartialTrace = true
233-
const segment = transaction.trace.add('Datastore/operation/Redis/SET')
234-
segment.addAttribute('foo', 'bar')
235-
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'essential' })
236-
assert.ok(!span)
237-
end()
238-
})
111+
test('should include exit span that does not have entity relationship attrs when not part of partialTrace', (t, end) => {
112+
const { agent } = t.nr
113+
helper.runInTransaction(agent, (transaction) => {
114+
transaction.isPartialTrace = false
115+
const segment = transaction.trace.add('Datastore/operation/Redis/SET')
116+
segment.addAttribute('foo', 'bar')
117+
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'reduced' })
118+
assert.ok(span)
119+
const [instrinsics, , agentAttrs] = span.toJSON()
120+
assert.equal(instrinsics['name'], 'Datastore/operation/Redis/SET')
121+
assert.equal(instrinsics['span.kind'], 'client')
122+
assert.equal(span.intrinsics['nr.entryPoint'], null)
123+
assert.equal(span.intrinsics['nr.pg'], null)
124+
assert.equal(agentAttrs.foo, 'bar')
125+
end()
239126
})
127+
})
240128

241-
await t.test('should not include in process span', (t, end) => {
242-
const { agent } = t.nr
243-
helper.runInTransaction(agent, (transaction) => {
244-
transaction.isPartialTrace = true
245-
const segment = transaction.trace.add('test-segment')
246-
segment.addAttribute('foo', 'bar')
247-
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'essential' })
248-
assert.ok(!span)
249-
end()
129+
test('should include in process span when not part of partialTrace', (t, end) => {
130+
const { agent } = t.nr
131+
helper.runInTransaction(agent, (transaction) => {
132+
transaction.isPartialTrace = false
133+
const segment = transaction.trace.add('test-segment')
134+
const spanContext = segment.getSpanContext()
135+
spanContext.addCustomAttribute('custom', 'test')
136+
segment.addAttribute('foo', 'bar')
137+
const span = SpanEvent.fromSegment({ segment, transaction, inProcessSpans: true, partialGranularityMode: 'reduced' })
138+
assert.ok(span)
139+
const [instrinsics, customAttrs, agentAttrs] = span.toJSON()
140+
assert.equal(instrinsics['name'], 'test-segment')
141+
assert.equal(instrinsics['span.kind'], 'internal')
142+
assert.deepEqual(customAttrs, {
143+
custom: 'test'
250144
})
145+
assert.equal(span.intrinsics['nr.entryPoint'], null)
146+
assert.equal(span.intrinsics['nr.pg'], null)
147+
assert.equal(agentAttrs.foo, 'bar')
148+
end()
251149
})
252150
})

0 commit comments

Comments
 (0)