Skip to content

Commit 1da91fe

Browse files
authored
test: add a test of trace-context propagation for HTTP/2 (#3453)
This is a follow-up to the just-added HTTP/2 trace-context fix. Refs: #3451
1 parent 37345ca commit 1da91fe

3 files changed

Lines changed: 70 additions & 41 deletions

File tree

CHANGELOG.asciidoc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ See <<esm>> for full details.
6969
7070
* Ensure `apm.setGlobalLabel(...)` does not throw an error when apm is inactive.
7171
({issues}3442[#3442])
72-
* Set the transaction parent for an incoming HTTP/2 request ({issues}1830[#1830])
72+
73+
* Set the trace-context for an incoming HTTP/2 request. Contributed by @paulish.
74+
({issues}1830[#1830])
7375
7476
[float]
7577
===== Chores

lib/instrumentation/modules/http2.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,10 @@ module.exports = function (http2, agent, { enabled }) {
6363

6464
const traceparent = headers.traceparent || headers['elastic-apm-traceparent']
6565
const tracestate = headers.tracestate
66-
const trans = agent.startTransaction(null, null, {
66+
const trans = agent.startTransaction(null, 'request', {
6767
childOf: traceparent,
6868
tracestate: tracestate
6969
})
70-
trans.type = 'request'
7170
// `trans.req` and `trans.res` are fake representations of Node.js's
7271
// core `http.IncomingMessage` and `http.ServerResponse` objects,
7372
// sufficient for `parsers.getContextFromRequest()` and

test/instrumentation/modules/http2.test.js

Lines changed: 66 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ var pem = require('https-pem')
2424
var test = require('tape')
2525

2626
var mockClient = require('../../_mock_http_client')
27-
var findObjInArray = require('../../_utils').findObjInArray
2827
const constants = require('../../../lib/constants')
2928

3029
if (semver.satisfies(process.version, '8.x')) {
@@ -339,45 +338,70 @@ isSecure.forEach(secure => {
339338
})
340339
})
341340

341+
// Scenario:
342+
// - create a manual transaction (expect transaction)
343+
// - http2 client "GET /" request (expect span, then HTTP/2 transaction)
344+
// - http2 client "GET /sub" request inside server handler (expect span,
345+
// then HTTP/2 transcation)
342346
test(`http2.request${secure ? ' secure' : ' '}`, t => {
343-
t.plan(39)
344-
345-
resetAgent(3, (data) => {
346-
t.strictEqual(data.transactions.length, 2)
347-
t.strictEqual(data.spans.length, 1)
348-
349-
var sub = data.transactions[0]
350-
assertPath(t, sub, secure, port, '/sub', '2.0')
351-
352-
var root = data.transactions[1]
353-
assertPath(t, root, secure, port, '/', '2.0')
354-
355-
var span = findObjInArray(data.spans, 'transaction_id', root.id)
356-
t.ok(span, 'root transaction should have span')
357-
t.strictEqual(span.type, 'external')
358-
t.strictEqual(span.subtype, 'http')
359-
t.strictEqual(span.action, 'GET')
360-
t.strictEqual(span.name, `GET http${secure ? 's' : ''}://localhost:${port}`)
361-
t.deepEqual(span.context.http, {
362-
method: 'GET',
363-
status_code: 200,
364-
url: `http${secure ? 's' : ''}://localhost:${port}/sub`
365-
}, 'span.context.http')
366-
t.deepEqual(span.context.destination, {
367-
service: {
368-
type: '',
369-
name: '',
370-
resource: `localhost:${port}`
371-
},
372-
address: 'localhost',
373-
port
374-
}, 'span.context.destination')
375-
t.deepEqual(span.context.service.target, {
376-
type: 'http',
377-
name: `localhost:${port}`
378-
}, 'span.context.service.target')
347+
resetAgent(5, (data) => {
348+
t.strictEqual(data.transactions.length, 3)
349+
t.strictEqual(data.spans.length, 2)
350+
const transactions = data.transactions.sort((a, b) => {
351+
return a.timestamp < b.timestamp ? -1 : 1
352+
})
353+
const spans = data.spans.sort((a, b) => {
354+
return a.timestamp < b.timestamp ? -1 : 1
355+
})
356+
357+
const transManual = transactions[0]
358+
t.equal(transManual.name, 'manual', 'transManual.name')
359+
360+
const expectedSpanContextFromPath = (urlPath) => {
361+
return {
362+
service: { target: { type: 'http', name: `localhost:${port}` } },
363+
destination: {
364+
address: 'localhost',
365+
port,
366+
service: { type: '', name: '', resource: `localhost:${port}` }
367+
},
368+
http: {
369+
method: 'GET',
370+
status_code: 200,
371+
url: `http${secure ? 's' : ''}://localhost:${port}${urlPath}`
372+
}
373+
}
374+
}
375+
let span = spans[0]
376+
t.strictEqual(span.name, `GET http${secure ? 's' : ''}://localhost:${port}`, 'span.name')
377+
t.strictEqual(span.type, 'external', 'span.type')
378+
t.strictEqual(span.subtype, 'http', 'span.subtype')
379+
t.strictEqual(span.action, 'GET', 'span.action')
380+
t.strictEqual(span.trace_id, transManual.trace_id, 'span.trace_id')
381+
t.strictEqual(span.parent_id, transManual.id, 'span.parent_id')
382+
t.deepEqual(span.context, expectedSpanContextFromPath('/'), 'span.context')
383+
384+
const transRoot = transactions[1]
385+
t.equal(transRoot.trace_id, transManual.trace_id, 'transRoot.trace_id')
386+
t.equal(transRoot.parent_id, span.id, 'transRoot.parent_id')
387+
assertPath(t, transRoot, secure, port, '/', '2.0')
388+
389+
span = spans[1]
390+
t.strictEqual(span.name, `GET http${secure ? 's' : ''}://localhost:${port}`, 'span.name')
391+
t.strictEqual(span.type, 'external', 'span.type')
392+
t.strictEqual(span.subtype, 'http', 'span.subtype')
393+
t.strictEqual(span.action, 'GET', 'span.action')
394+
t.strictEqual(span.trace_id, transRoot.trace_id, 'span.trace_id')
395+
t.strictEqual(span.parent_id, transRoot.id, 'span.parent_id')
396+
t.deepEqual(span.context, expectedSpanContextFromPath('/sub'), 'span.context')
397+
398+
const transSub = transactions[2]
399+
t.equal(transSub.trace_id, transRoot.trace_id, 'transSub.trace_id')
400+
t.equal(transSub.parent_id, span.id, 'transSub.parent_id')
401+
assertPath(t, transSub, secure, port, '/sub', '2.0')
379402

380403
server.close()
404+
t.end()
381405
})
382406

383407
var port
@@ -426,10 +450,14 @@ isSecure.forEach(secure => {
426450
client.on('error', onError)
427451
client.on('socketError', onError)
428452

453+
const transManual = agent.startTransaction('manual')
429454
var req = client.request({ ':path': '/' })
430455
assertResponse(t, req, 'foo')
431456
req.resume()
432-
req.on('end', () => client.destroy())
457+
req.on('end', () => {
458+
client.destroy()
459+
transManual.end()
460+
})
433461
req.end()
434462
})
435463
})

0 commit comments

Comments
 (0)