Skip to content

Commit 5873c88

Browse files
authored
feat: add injection metadata fields to telemetry forwarder (#6203)
1 parent c9df240 commit 5873c88

File tree

3 files changed

+120
-4
lines changed

3 files changed

+120
-4
lines changed

integration-tests/helpers/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,10 @@ function assertTelemetryPoints (pid, msgs, expectedTelemetryPoints) {
113113
runtime_name: 'nodejs',
114114
runtime_version: process.versions.node,
115115
tracer_version: require('../../package.json').version,
116-
pid: Number(pid)
116+
pid: Number(pid),
117+
result: 'unknown',
118+
result_reason: 'unknown',
119+
result_class: 'unknown'
117120
}
118121
}
119122
}

packages/dd-trace/src/guardrails/telemetry.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ var metadata = {
2222
runtime_name: 'nodejs',
2323
runtime_version: process.versions.node,
2424
tracer_version: tracerVersion,
25-
pid: process.pid
25+
pid: process.pid,
26+
result: 'unknown',
27+
result_reason: 'unknown',
28+
result_class: 'unknown'
2629
}
2730

2831
var seen = {}
@@ -64,14 +67,27 @@ function sendTelemetry (name, tags) {
6467
})
6568
proc.on('error', function () {
6669
log.error('Failed to spawn telemetry forwarder')
70+
metadata.result = 'error'
71+
metadata.result_class = 'internal_error'
72+
metadata.result_reason = 'Failed to spawn telemetry forwarder'
6773
})
6874
proc.on('exit', function (code) {
69-
if (code !== 0) {
75+
if (code === 0) {
76+
metadata.result = 'success'
77+
metadata.result_class = 'success'
78+
metadata.result_reason = 'Successfully configured ddtrace package'
79+
} else {
7080
log.error('Telemetry forwarder exited with code', code)
81+
metadata.result = 'error'
82+
metadata.result_class = 'internal_error'
83+
metadata.result_reason = 'Telemetry forwarder exited with code ' + code
7184
}
7285
})
7386
proc.stdin.on('error', function () {
7487
log.error('Failed to write telemetry data to telemetry forwarder')
88+
metadata.result = 'error'
89+
metadata.result_class = 'internal_error'
90+
metadata.result_reason = 'Failed to write telemetry data to telemetry forwarder'
7591
})
7692
proc.stdin.end(JSON.stringify({ metadata: metadata, points: points }))
7793
}

packages/dd-trace/test/guardrails/telemetry.spec.js

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
process.env.DD_INJECTION_ENABLED = 'true'
44

5+
const proxyquire = require('proxyquire')
6+
const { EventEmitter } = require('events')
57
const { telemetryForwarder, assertTelemetryPoints } = require('../../../../integration-tests/helpers')
68

79
describe('sendTelemetry', () => {
@@ -16,7 +18,7 @@ describe('sendTelemetry', () => {
1618

1719
beforeEach(() => {
1820
cleanup = telemetryForwarder()
19-
sendTelemetry = proxyquire('../src/guardrails/telemetry', {})
21+
sendTelemetry = proxyquire('../../src/guardrails/telemetry', {})
2022
})
2123

2224
it('should send telemetry', async () => {
@@ -68,4 +70,99 @@ describe('sendTelemetry', () => {
6870
assertTelemetryPoints(process.pid, msgs, ['abort.integration', '1'])
6971
})
7072
})
73+
74+
describe('Error scenarios and metadata', () => {
75+
let mockProc, telemetryModule, capturedStdinData
76+
77+
function createMockProcess () {
78+
const proc = new EventEmitter()
79+
proc.stdin = new EventEmitter()
80+
proc.stdin.end = (data) => {
81+
capturedStdinData = data
82+
}
83+
return proc
84+
}
85+
86+
function loadTelemetryModuleWithMockProc () {
87+
return proxyquire('../../src/guardrails/telemetry', {
88+
child_process: { spawn: () => mockProc }
89+
})
90+
}
91+
92+
function runTelemetry (eventType, value) {
93+
const originalStringify = JSON.stringify
94+
JSON.stringify = function (obj) {
95+
if (obj && obj.metadata && obj.points) {
96+
if (eventType === 'spawn-error') {
97+
mockProc.emit('error', new Error(value))
98+
} else if (eventType === 'exit') {
99+
mockProc.emit('exit', value)
100+
} else if (eventType === 'stdin-error') {
101+
mockProc.stdin.emit('error', new Error(value))
102+
}
103+
}
104+
return originalStringify.apply(this, arguments)
105+
}
106+
107+
try {
108+
telemetryModule([{ name: 'test', tags: [] }])
109+
} finally {
110+
JSON.stringify = originalStringify
111+
}
112+
}
113+
114+
function assertStdinMetadata (expected) {
115+
expect(capturedStdinData).to.exist
116+
const parsed = JSON.parse(capturedStdinData)
117+
expect(parsed.metadata.result).to.equal(expected.result)
118+
expect(parsed.metadata.result_class).to.equal(expected.result_class)
119+
expect(parsed.metadata.result_reason).to.equal(expected.result_reason)
120+
}
121+
122+
beforeEach(() => {
123+
mockProc = createMockProcess()
124+
capturedStdinData = null
125+
telemetryModule = loadTelemetryModuleWithMockProc()
126+
})
127+
128+
it('should set error metadata when telemetry forwarder fails to spawn', () => {
129+
runTelemetry('spawn-error', 'Spawn failed')
130+
131+
assertStdinMetadata({
132+
result: 'error',
133+
result_class: 'internal_error',
134+
result_reason: 'Failed to spawn telemetry forwarder'
135+
})
136+
})
137+
138+
it('should set error metadata when telemetry forwarder exits with non-zero code', () => {
139+
runTelemetry('exit', 1)
140+
141+
assertStdinMetadata({
142+
result: 'error',
143+
result_class: 'internal_error',
144+
result_reason: 'Telemetry forwarder exited with code 1'
145+
})
146+
})
147+
148+
it('should set error metadata when writing to telemetry forwarder fails', () => {
149+
runTelemetry('stdin-error', 'Write failed')
150+
151+
assertStdinMetadata({
152+
result: 'error',
153+
result_class: 'internal_error',
154+
result_reason: 'Failed to write telemetry data to telemetry forwarder'
155+
})
156+
})
157+
158+
it('should set success metadata when telemetry forwarder exits successfully', () => {
159+
runTelemetry('exit', 0)
160+
161+
assertStdinMetadata({
162+
result: 'success',
163+
result_class: 'success',
164+
result_reason: 'Successfully configured ddtrace package'
165+
})
166+
})
167+
})
71168
})

0 commit comments

Comments
 (0)