Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http.param #88

Merged
merged 16 commits into from
May 27, 2021
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog
All notable changes to Pinpoint Node.js agent will be documented in this file.

## [0.9.0-next.0] - 2021-05-27
### Added
- #87 HTTP param

## [0.8.2] - 2021-05-10
### Fixed
- #73 fix require.main undefined error by webpack and node -r pinpoint-node-agent
Expand Down
5 changes: 4 additions & 1 deletion lib/constant/annotation-key.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@

'use strict'

// https://github.com/pinpoint-apm/pinpoint/blob/b6a3f3e8aed8111264bedc77b110e0ffd5aa4852/commons/src/main/java/com/navercorp/pinpoint/common/trace/AnnotationKey.java#L144
const AnnotationKey = require('../context/annotation-key')
const AnnotationKeyProperty = require('./annotation').AnnotationKeyProperty

const DefaultAnnotationKey = {
API: new AnnotationKey(12, "API"),
API_METADATA: new AnnotationKey(13, "API-METADATA"),
HTTP_URL: new AnnotationKey(40, "http.url"),
HTTP_PARAM: new AnnotationKey(41, "http.param", AnnotationKeyProperty.VIEW_IN_RECORD_SET),
HTTP_STATUS_CODE: new AnnotationKey(46, "http.status.code")
}

const EventAnnotationKey= {
const EventAnnotationKey = {
MONGO_JSON_DATA: new AnnotationKey(150, "MONGO-JSON-Data")
}

Expand Down
13 changes: 8 additions & 5 deletions lib/instrumentation/http-shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ exports.instrumentRequest = function (agent, moduleName) {
if (trace && trace.canSampled()) {
recordRequest(trace.spanRecorder, requestData)
trace.spanRecorder.recordApi(GeneralMethodDescriptor.SERVER_REQUEST)
if (requestData && typeof requestData.searchParams === 'string') {
trace.spanRecorder.recordAttribute(DefaultAnnotationKey.HTTP_PARAM, requestData.searchParams)
}
}

endOfStream(res, function (err) {
Expand Down Expand Up @@ -104,13 +107,13 @@ exports.traceOutgoingRequest = function (agent, moduleName) {

// If request object has an asyncId, use request object's one
if (arguments && arguments[0] && AsyncIdAccessor.getAsyncId(arguments[0])) {
asyncId = AsyncIdAccessor.getAsyncId(arguments[0]);
asyncId = AsyncIdAccessor.getAsyncId(arguments[0])
} else {
spanEventRecorder = trace.traceBlockBegin();
spanEventRecorder = trace.traceBlockBegin()
spanEventRecorder.recordServiceType(ServiceTypeCode.ASYNC_HTTP_CLIENT_INTERNAL)
spanEventRecorder.recordApiDesc('http.request')
asyncId = spanEventRecorder.recordNextAsyncId()
trace.traceBlockEnd(spanEventRecorder);
trace.traceBlockEnd(spanEventRecorder)
}
const httpURL = req._headers.host + url.parse(req.path).pathname

Expand All @@ -131,7 +134,7 @@ exports.traceOutgoingRequest = function (agent, moduleName) {
return req

function onresponse(res) {
log.debug('intercepted http.ClientcRequest response event %o', {id: httpURL})
log.debug('intercepted http.ClientcRequest response event %o', { id: httpURL })
// Inspired by:
// https://github.com/nodejs/node/blob/9623ce572a02632b7596452e079bba066db3a429/lib/events.js#L258-L274
if (res.prependListener) {
Expand All @@ -151,7 +154,7 @@ exports.traceOutgoingRequest = function (agent, moduleName) {
}

function onEnd() {
log.debug('intercepted http.IncomingMessage end event %o', {id: httpURL})
log.debug('intercepted http.IncomingMessage end event %o', { id: httpURL })
if (asyncTrace) {
asyncEventRecorder.recordAttribute(DefaultAnnotationKey.HTTP_STATUS_CODE, this.statusCode)
asyncTrace.traceAsyncEnd(asyncEventRecorder)
Expand Down
2 changes: 1 addition & 1 deletion lib/instrumentation/module/express.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ module.exports = function (agent, version, express) {
apiMetaService.cacheApi(descriptor)
descMap[objectName + methodName] = descriptor
return descMap
}, {});
}, {})

function getMethodDescriptor(objectPath, methodName, httpMethod) {
const method = objectPath === 'route' ? httpMethod : methodName
Expand Down
31 changes: 21 additions & 10 deletions lib/instrumentation/request-header-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,25 @@ const TransactionId = require('../context/transaction-id')
const samplingFlag = require('../sampler/sampling-flag')

class RequestHeaderUtils {
static read (request) {
static read(request) {
if (!request) {
return null
}

let requestData = new RequestData()
const parsedUrl = url.parse(request.url)
requestData.rpcName = parsedUrl ? parsedUrl.pathname : ''

// https://nodejs.org/api/url.html#url_url_parse_urlstring_parsequerystring_slashesdenotehost
// url.parse throw error
try {
const parsedUrl = url.parse(request.url)
requestData.rpcName = parsedUrl ? parsedUrl.pathname : ''
const query = parsedUrl.query
if (query && query.length > 0) {
requestData.searchParams = query
}
} catch (error) {
log.error(error)
}
requestData.endPoint = this.getHeader(request, 'host')
const remoteAddress = this.getHeader(request, 'x-forwarded-for') || request.connection.remoteAddress
if (remoteAddress) {
Expand All @@ -35,19 +46,19 @@ class RequestHeaderUtils {
return requestData
}

static readPinpointHeader (request, requestData) {
static readPinpointHeader(request, requestData) {
requestData.transactionId = TransactionId.toTransactionId(this.getHeader(request, PinpointHeader.HTTP_TRACE_ID))
if (requestData.transactionId) {
const spanId = this.getHeader(request, PinpointHeader.HTTP_SPAN_ID);
const spanId = this.getHeader(request, PinpointHeader.HTTP_SPAN_ID)
if (spanId) {
requestData.spanId = spanId
}

const parentSpanId = this.getHeader(request, PinpointHeader.HTTP_PARENT_SPAN_ID);
const parentSpanId = this.getHeader(request, PinpointHeader.HTTP_PARENT_SPAN_ID)
if (parentSpanId) {
requestData.parentSpanId = parentSpanId
}

requestData.parentApplicationName = this.getHeader(request, PinpointHeader.HTTP_PARENT_APPLICATION_NAME)
requestData.parentApplicationType = Number(this.getHeader(request, PinpointHeader.HTTP_PARENT_APPLICATION_TYPE))
requestData.flags = Number(this.getHeader(request, PinpointHeader.HTTP_FLAGS))
Expand All @@ -58,7 +69,7 @@ class RequestHeaderUtils {
return requestData
}

static getHeader (request, name) {
static getHeader(request, name) {
if (request.getHeader) {
return request.getHeader(name.toLowerCase())
}
Expand All @@ -69,7 +80,7 @@ class RequestHeaderUtils {
this.setHeader(request, PinpointHeader.HTTP_SAMPLED, samplingFlag.samplingRateFalse())
}

static write (request, agent, nextSpanId, host) {
static write(request, agent, nextSpanId, host) {
if (!agent) {
return
}
Expand All @@ -88,7 +99,7 @@ class RequestHeaderUtils {
return request
}

static setHeader (request, name, value) {
static setHeader(request, name, value) {
if (request.setHeader) {
request.setHeader(name, value)
} else {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pinpoint-node-agent",
"version": "0.8.2",
"version": "0.9.0-next.0",
"main": "index.js",
"scripts": {
"test": "./node_modules/.bin/tape ./test/**/*.test.js",
Expand Down
4 changes: 2 additions & 2 deletions test/client/grpc-data-sender-client-side-stream.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ test('gRPC client side stream reconnect test', (t) => {
t.deepEqual(actuals.data, {}, 'actuals data')
t.false(actuals.ended, 'client side stream lives')

given.deadline = given.deadline - (5 * 60 * 1000 + 100)
given.deadline = given.deadline - (10 * 60 * 1000 + 100)
const fistDeadline = given.deadline
given.write({ order: 2 })
t.deepEqual(actuals.data, { order: 2 }, 'actuals data is order: 2')
Expand Down Expand Up @@ -512,7 +512,7 @@ test('stream deadline test', (t) => {
}
}
})
t.equal(given.grpcStreamDeadline, 5 * 60 * 1000, 'default dealine times')
t.equal(given.grpcStreamDeadline, 10 * 60 * 1000, 'default dealine times')

given.setDeadlineMinutes(6)
t.equal(given.grpcStreamDeadline, 6 * 60 * 1000, '6 minutes dealine times')
Expand Down
36 changes: 26 additions & 10 deletions test/instrumentation/module/express.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@
const test = require('tape')
const axios = require('axios')

const { log, fixture, util, enableDataSending } = require('../../test-helper')

const { log, util } = require('../../test-helper')
const agent = require('../../support/agent-singleton-mock')

const express = require('express')
const DefaultAnnotationKey = require('../../../lib/constant/annotation-key').DefaultAnnotationKey

const TEST_ENV = {
host: 'localhost',
Expand All @@ -25,22 +24,39 @@ test(`${testName1} Should record request in basic route`, function (t) {

const testName = testName1

t.plan(3)
t.plan(6)

const PATH = '/'+testName
const PATH = '/' + testName
const app = new express()

const stackString = `Error
at Function.route (/Users/feelform/workspace/pinpoint/pinpoint-node-agent/lib/instrumentation/module/express.js:64:13)
at Function.app.<computed> [as get] (/Users/feelform/workspace/pinpoint/pinpoint-node-agent/node_modules/express/lib/application.js:481:30)
at Test.<anonymous> (/Users/feelform/workspace/pinpoint/pinpoint-node-agent/test/instrumentation/module/express.test.js:33:7)
at Test.bound [as _cb] (/Users/feelform/workspace/pinpoint/pinpoint-node-agent/node_modules/tape/lib/test.js:80:32)
at Test.run (/Users/feelform/workspace/pinpoint/pinpoint-node-agent/node_modules/tape/lib/test.js:96:10)
at Test.bound [as run] (/Users/feelform/workspace/pinpoint/pinpoint-node-agent/node_modules/tape/lib/test.js:80:32)
at Immediate.next [as _onImmediate] (/Users/feelform/workspace/pinpoint/pinpoint-node-agent/node_modules/tape/lib/results.js:83:19)
at processImmediate (internal/timers.js:456:21)`

app.get(PATH, async (req, res) => {
Math.random()
await util.sleep(3000)
res.send('ok get')

const trace = agent.traceContext.currentTraceObject()
t.equal(trace.span.annotations[0].key, DefaultAnnotationKey.HTTP_PARAM.name, 'HTTP param key match')
t.equal(trace.span.annotations[0].value.stringValue, 'api=test&test1=test', 'HTTP param value match')
})
app.post(PATH, (req, res) => {
res.send('ok post')

const trace = agent.traceContext.currentTraceObject()
t.false(trace.span.annotations[0], 'HTTP param undefined case')
})

const server = app.listen(TEST_ENV.port, async function () {
const result1 = await axios.get(getServerUrl(PATH))
const result1 = await axios.get(getServerUrl(PATH) + '?api=test&test1=test')
t.ok(result1.status, 200)

const result2 = await axios.post(getServerUrl(PATH))
Expand All @@ -62,7 +78,7 @@ test(`[${testName2}] Should record request in express.Router`, function (t) {

t.plan(3)

const PATH = '/'+testName
const PATH = '/' + testName
const app = new express()

const router1 = express.Router()
Expand Down Expand Up @@ -103,7 +119,7 @@ test(`${testName3} Should record request taking more than 2 sec`, function (t) {

t.plan(2)

const PATH = '/'+testName
const PATH = '/' + testName
const app = new express()

app.get(PATH, async (req, res) => {
Expand Down Expand Up @@ -159,7 +175,7 @@ test(`${testName4} Should record internal error in express.test.js`, function (t
console.log('[app] error handler')
res.json({ message: error.message })
res.status = 500
});
})

const server = app.listen(TEST_ENV.port, async function () {
const result = await axios.get(getServerUrl(PATH))
Expand Down Expand Up @@ -216,7 +232,7 @@ test(`${testName5} Should record middleware`, function (t) {
const testName6 = 'express6'
test(`${testName6} Should record each http method`, function (t) {
agent.bindHttp()

const testName = testName6

t.plan(6)
Expand Down