Skip to content

Commit

Permalink
[pinpoint-apm#245] Fix Node Process UNDEFINED
Browse files Browse the repository at this point in the history
  • Loading branch information
feelform committed Dec 19, 2024
1 parent e8b6d72 commit 2184464
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 30 deletions.
4 changes: 1 addition & 3 deletions demo/express/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ router.get('/', async function(req, res, next) {
const json = await response.json()
console.log(json)

setTimeout(() => {
res.render('index', { title: 'Express' })
}, 1000)
res.render('index', { title: 'Express' })
})

router.get('/api', function(req, res, next) {
Expand Down
2 changes: 1 addition & 1 deletion lib/instrumentation/http/http-request-trace-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class HttpRequestTraceBuilder {
// record serviceType: traceContext.newTraceObject() Trace class constructor
// ServletRequestListener.java: createTrace(REQ request)
record(spanRecorder) {
spanRecorder.recordServiceType(ServiceType.node.getCode())
spanRecorder.recordServiceType(ServiceType.node)
spanRecorder.recordApi(defaultPredefinedMethodDescriptorRegistry.nodeServerMethodDescriptor)
spanRecorder.recordRpc(this.request.getUrlPathname())
spanRecorder.recordEndPoint(this.request.getHeader('host'))
Expand Down
61 changes: 40 additions & 21 deletions test/instrumentation/context/nested-async-trace.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,12 @@ const spanMessageStreamService = (call) => {
const spanOrSpanChunk = spanMessage.getSpan() ?? spanMessage.getSpanchunk()
const spanOrSpanChunks = agent.getSpanOrSpanChunks()
spanOrSpanChunks.push(spanOrSpanChunk)

if (agent.getTraces().length === ++dataStreamCount) {
spanMessageEndEventCallback?.()
}
})

call.on('end', () => {

})
}

Expand Down Expand Up @@ -146,7 +144,7 @@ test(`nested mysql async query with express`, async (t) => {
agent.callbackTraceClose(async (trace) => {
let actualBuilder = new MethodDescriptorBuilder(expected('get', 'app.get'))
.setClassName(expected('app', 'Function'))
.setLineNumber(119)
.setLineNumber(117)
.setFileName('nested-async-trace.test.js')
let actualMethodDescriptor = apiMetaService.cacheApiWithBuilder(actualBuilder)
let actualSpanEvent = trace.repository.dataSender.mockSpan.spanEventList.find(spanEvent => spanEvent.sequence === 0)
Expand All @@ -159,7 +157,7 @@ test(`nested mysql async query with express`, async (t) => {
t.equal(actualSpanEvent.serviceType, expressServiceType.getCode(), 'serviceType is express')

actualBuilder = new MethodDescriptorBuilder('createConnection')
.setLineNumber(120)
.setLineNumber(118)
.setFileName('nested-async-trace.test.js')
actualMethodDescriptor = apiMetaService.cacheApiWithBuilder(actualBuilder)
actualSpanEvent = trace.repository.dataSender.mockSpan.spanEventList.find(spanEvent => spanEvent.sequence === 1)
Expand All @@ -172,7 +170,7 @@ test(`nested mysql async query with express`, async (t) => {

actualBuilder = new MethodDescriptorBuilder('connect')
.setClassName('Connection')
.setLineNumber(129)
.setLineNumber(127)
.setFileName('nested-async-trace.test.js')
actualMethodDescriptor = apiMetaService.cacheApiWithBuilder(actualBuilder)
actualSpanEvent = trace.repository.dataSender.mockSpan.spanEventList.find(spanEvent => spanEvent.sequence === 2)
Expand All @@ -194,7 +192,7 @@ test(`nested mysql async query with express`, async (t) => {

actualBuilder = new MethodDescriptorBuilder('query')
.setClassName('Connection')
.setLineNumber(135)
.setLineNumber(133)
.setFileName('nested-async-trace.test.js')
actualMethodDescriptor = apiMetaService.cacheApiWithBuilder(actualBuilder)
actualSpanEvent = trace.spanBuilder.spanEventList.find(spanEvent => spanEvent.sequence === 3)
Expand All @@ -216,7 +214,7 @@ test(`nested mysql async query with express`, async (t) => {

actualBuilder = new MethodDescriptorBuilder('query')
.setClassName('Connection')
.setLineNumber(141)
.setLineNumber(139)
.setFileName('nested-async-trace.test.js')
actualMethodDescriptor = apiMetaService.cacheApiWithBuilder(actualBuilder)
actualSpanEvent = actualSpanChunk.spanEventList[1]
Expand Down Expand Up @@ -328,30 +326,43 @@ test(`nested mysql2 async query with express`, async (t) => {
timezone: '+09:00'
})

let callCount = 0
connection.query(`SELECT * FROM member`, async function (error, results) {
if (error) throw error
t.equal(results[0].id, 'a', 'SELECT member id')
t.equal(results[0].name, 'name1', 'SELECT member name')
t.equal(results[0].joined.getDate(), new Date('2023-01-18T00:00:00+09:00').getDate(), 'SELECT member joined')

connection.query(`SELECT * FROM member WHERE id = ?`, results[0].id, async function (error, results) {

callCount++
if (callCount == 2) {
setTimeout(() => {
res.send('ok get')
}, 1000)
}
})
})

const [rows] = await connection.promise().query(`SELECT * FROM member WHERE id = ?`, 'a')
const [rows] = await connection.promise()
.query(`SELECT * FROM member a WHERE a.id = ?`, 'a')
.then(([rows]) => {
callCount++
if (callCount == 2) {
setTimeout(() => {
res.send('ok get')
}, 1000)
}
return [rows]
})
t.equal(rows[0].id, 'a', 'id in SELECT query hooking')
t.equal(rows[0].name, 'name1', 'name in SELECT query hooking')
t.equal(rows[0].joined.toISOString().slice(0, 10), '2023-01-17', 'joined in SELECT query hooking')

setTimeout(() => {
res.send('ok get')
}, 1000)

agent.callbackTraceClose(async (trace) => {
t.equal(trace.spanBuilder.serviceType, ServiceType.node.getCode(), 'Span serviceType is node')
let actualBuilder = new MethodDescriptorBuilder(expected('get', 'app.get'))
.setClassName(expected('app', 'Function'))
.setLineNumber(321)
.setLineNumber(319)
.setFileName('nested-async-trace.test.js')
let actualMethodDescriptor = apiMetaService.cacheApiWithBuilder(actualBuilder)
let actualSpanEvent = trace.spanBuilder.spanEventList.find(spanEvent => spanEvent.sequence === 0)
Expand All @@ -364,7 +375,7 @@ test(`nested mysql2 async query with express`, async (t) => {
t.equal(actualSpanEvent.serviceType, expressServiceType.getCode(), 'serviceType is express')

actualBuilder = new MethodDescriptorBuilder('createConnection')
.setLineNumber(322)
.setLineNumber(320)
.setFileName('nested-async-trace.test.js')
actualMethodDescriptor = apiMetaService.cacheApiWithBuilder(actualBuilder)
actualSpanEvent = trace.spanBuilder.spanEventList.find(spanEvent => spanEvent.sequence === 1)
Expand All @@ -377,7 +388,7 @@ test(`nested mysql2 async query with express`, async (t) => {

actualBuilder = new MethodDescriptorBuilder('query')
.setClassName('Connection')
.setLineNumber(331)
.setLineNumber(330)
.setFileName('nested-async-trace.test.js')
actualMethodDescriptor = apiMetaService.cacheApiWithBuilder(actualBuilder)
actualSpanEvent = trace.spanBuilder.spanEventList.find(spanEvent => spanEvent.sequence === 2)
Expand All @@ -399,7 +410,7 @@ test(`nested mysql2 async query with express`, async (t) => {

actualBuilder = new MethodDescriptorBuilder('query')
.setClassName('Connection')
.setLineNumber(337)
.setLineNumber(336)
.setFileName('nested-async-trace.test.js')
actualMethodDescriptor = apiMetaService.cacheApiWithBuilder(actualBuilder)
actualSpanEvent = actualSpanChunk.spanEventList[1]
Expand Down Expand Up @@ -441,10 +452,12 @@ test(`nested mysql2 async query with express`, async (t) => {
t.equal(actualSpanChunk.spanEventList[0].sequence, 0, 'sequence is equal')
t.equal(actualSpanChunk.spanEventList[0].serviceType, ServiceType.async.getCode(), 'serviceType is mysql')

connection.end()
t.equal(agent.getSendedApiMetaInfos().length, 0, 'agent.getSendedApiMetaInfos() is empty')
t.end()
trace.repository.dataSender.close()
spanMessageEndEventCallback = async () => {
connection.end()
t.equal(agent.getSendedApiMetaInfos().length, 0, 'agent.getSendedApiMetaInfos() is empty')
t.end()
trace.repository.dataSender.close()
}
})
})

Expand All @@ -462,6 +475,12 @@ test(`nested mysql2 async query with express`, async (t) => {
sendedApiMetaInfos.splice(index, 1)
}

dataStreamCount = 0
agent.setContinueAsyncContextTraceObjectCallback(async (trace) => {
const parentTrace = agent.getTraceByAsyncId(trace.localAsyncId)
t.true(parentTrace !== undefined, 'parent trace is not undefined')
})

const server = app.listen(5006, async () => {
const result = await axios.get('http://localhost:5006/test1')
t.equal(result.status, 200, 'status is 200')
Expand Down
39 changes: 34 additions & 5 deletions test/support/agent-singleton-mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ const resetSendedApiMetaInfos = () => {
const getSendedApiMetaInfos = () => {
return sendedApiMetaInfos
}
const getTraceByAsyncId = (asyncId) => {
return getTraces().find(trace => {
const spanChunkSpanEvents = agent.dataSender.mockSpanChunks.flatMap(spanChunk => spanChunk.spanEventList)
const spanEvents = trace.callStack.stack.concat(trace.repository.buffer).concat(spanChunkSpanEvents)
const asyncSpanEvent = spanEvents.find(spanEvent => spanEvent.asyncId?.getAsyncId() === asyncId.getAsyncId())
return asyncSpanEvent
})
}

class MockAgent extends Agent {
startSchedule(agentId, agentStartTime) {
this.mockAgentId = agentId
Expand Down Expand Up @@ -105,25 +114,36 @@ class MockAgent extends Agent {
stringMetaService.init(dataSender)
apiMetaService.init(dataSender)

resetTraces()
resetSpanOrSpanChunks()
resetSendedApiMetaInfos()

resetTraces()
this.newTraceCallback = null
const getNewTraceCallback = () => {
return this.newTraceCallback
}
shimmer.wrap(this.traceContext, 'newTrace', function (origin) {
return function () {
const returned = origin.apply(this, arguments)
getNewTraceCallback()?.(returned)
getTraces().push(returned)
return returned
}
})

this.continueAsyncContextTraceObjectCallback = null
const getContinueAsyncContextTraceObjectCallback = () => {
return this.continueAsyncContextTraceObjectCallback
}
shimmer.wrap(this.traceContext, 'continueAsyncContextTraceObject', function (origin) {
return function () {
const returned = origin.apply(this, arguments)
getContinueAsyncContextTraceObjectCallback()?.(returned)
getTraces().push(returned)
return returned
}
})

resetSendedApiMetaInfos()
shimmer.wrap(apiMetaService, 'sendApiMetaInfo', function (origin) {
return function () {
const returned = origin.apply(this, arguments)
Expand Down Expand Up @@ -166,9 +186,6 @@ class MockAgent extends Agent {

completeTraceObject(trace) {
super.completeTraceObject(trace)
// if (!trace[closedTraceWrapped]) {
// this.traces.push(trace)
// }
}

getTraces() {
Expand All @@ -190,6 +207,18 @@ class MockAgent extends Agent {
getSendedApiMetaInfos() {
return getSendedApiMetaInfos()
}

setNewTraceCallback(callback) {
this.newTraceCallback = callback
}

setContinueAsyncContextTraceObjectCallback(callback) {
this.continueAsyncContextTraceObjectCallback = callback
}

getTraceByAsyncId(asyncId) {
return getTraceByAsyncId(asyncId)
}
}

const agent = new MockAgent(require('../pinpoint-config-test'))
Expand Down

0 comments on commit 2184464

Please sign in to comment.