@google-cloud/trace-agent
Advanced tools
Comparing version 2.6.1 to 2.7.0
@@ -19,3 +19,4 @@ "use strict"; | ||
const url_1 = require("url"); | ||
const SUPPORTED_VERSIONS = '8 - 16'; | ||
// Used when patching Hapi 17. | ||
const ORIGINAL = Symbol(); | ||
function getFirstHeader(req, key) { | ||
@@ -28,56 +29,54 @@ let headerValue = req.headers[key] || null; | ||
} | ||
function createMiddleware(api) { | ||
return function middleware(request, reply) { | ||
const req = request.raw.req; | ||
const res = request.raw.res; | ||
const originalEnd = res.end; | ||
const options = { | ||
name: req.url ? (url_1.parse(req.url).pathname || '') : '', | ||
url: req.url, | ||
traceContext: getFirstHeader(req, api.constants.TRACE_CONTEXT_HEADER_NAME), | ||
skipFrames: 3 | ||
function instrument(api, request, continueCb) { | ||
const req = request.raw.req; | ||
const res = request.raw.res; | ||
const originalEnd = res.end; | ||
const options = { | ||
name: req.url ? (url_1.parse(req.url).pathname || '') : '', | ||
url: req.url, | ||
traceContext: getFirstHeader(req, api.constants.TRACE_CONTEXT_HEADER_NAME), | ||
skipFrames: 4 | ||
}; | ||
return api.runInRootSpan(options, (root) => { | ||
// Set response trace context. | ||
const responseTraceContext = api.getResponseTraceContext(options.traceContext || null, api.isRealSpan(root)); | ||
if (responseTraceContext) { | ||
res.setHeader(api.constants.TRACE_CONTEXT_HEADER_NAME, responseTraceContext); | ||
} | ||
if (!api.isRealSpan(root)) { | ||
return continueCb(); | ||
} | ||
api.wrapEmitter(req); | ||
api.wrapEmitter(res); | ||
const url = `${req.headers['X-Forwarded-Proto'] || 'http'}://${req.headers.host}${req.url}`; | ||
// we use the path part of the url as the span name and add the full | ||
// url as a label | ||
// req.path would be more desirable but is not set at the time our | ||
// middleware runs. | ||
root.addLabel(api.labels.HTTP_METHOD_LABEL_KEY, req.method); | ||
root.addLabel(api.labels.HTTP_URL_LABEL_KEY, url); | ||
root.addLabel(api.labels.HTTP_SOURCE_IP, req.connection.remoteAddress); | ||
// wrap end | ||
res.end = function () { | ||
res.end = originalEnd; | ||
const returned = res.end.apply(this, arguments); | ||
if (request.route && request.route.path) { | ||
root.addLabel('hapi/request.route.path', request.route.path); | ||
} | ||
root.addLabel(api.labels.HTTP_RESPONSE_CODE_LABEL_KEY, res.statusCode); | ||
root.endSpan(); | ||
return returned; | ||
}; | ||
api.runInRootSpan(options, (root) => { | ||
// Set response trace context. | ||
const responseTraceContext = api.getResponseTraceContext(options.traceContext || null, api.isRealSpan(root)); | ||
if (responseTraceContext) { | ||
res.setHeader(api.constants.TRACE_CONTEXT_HEADER_NAME, responseTraceContext); | ||
} | ||
if (!api.isRealSpan(root)) { | ||
return reply.continue(); | ||
} | ||
api.wrapEmitter(req); | ||
api.wrapEmitter(res); | ||
const url = `${req.headers['X-Forwarded-Proto'] || 'http'}://${req.headers.host}${req.url}`; | ||
// we use the path part of the url as the span name and add the full | ||
// url as a label | ||
// req.path would be more desirable but is not set at the time our | ||
// middleware runs. | ||
root.addLabel(api.labels.HTTP_METHOD_LABEL_KEY, req.method); | ||
root.addLabel(api.labels.HTTP_URL_LABEL_KEY, url); | ||
root.addLabel(api.labels.HTTP_SOURCE_IP, req.connection.remoteAddress); | ||
// wrap end | ||
res.end = function () { | ||
res.end = originalEnd; | ||
const returned = res.end.apply(this, arguments); | ||
if (request.route && request.route.path) { | ||
root.addLabel('hapi/request.route.path', request.route.path); | ||
} | ||
root.addLabel(api.labels.HTTP_RESPONSE_CODE_LABEL_KEY, res.statusCode); | ||
root.endSpan(); | ||
return returned; | ||
}; | ||
// if the event is aborted, end the span (as res.end will not be called) | ||
req.once('aborted', () => { | ||
root.addLabel(api.labels.ERROR_DETAILS_NAME, 'aborted'); | ||
root.addLabel(api.labels.ERROR_DETAILS_MESSAGE, 'client aborted the request'); | ||
root.endSpan(); | ||
}); | ||
return reply.continue(); | ||
// if the event is aborted, end the span (as res.end will not be called) | ||
req.once('aborted', () => { | ||
root.addLabel(api.labels.ERROR_DETAILS_NAME, 'aborted'); | ||
root.addLabel(api.labels.ERROR_DETAILS_MESSAGE, 'client aborted the request'); | ||
root.endSpan(); | ||
}); | ||
}; | ||
return continueCb(); | ||
}); | ||
} | ||
const plugin = [{ | ||
file: '', | ||
versions: SUPPORTED_VERSIONS, | ||
const plugin = [ | ||
{ | ||
versions: '8 - 16', | ||
patch: (hapi, api) => { | ||
@@ -87,3 +86,5 @@ shimmer.wrap(hapi.Server.prototype, 'connection', (connection) => { | ||
const server = connection.apply(this, arguments); | ||
server.ext('onRequest', createMiddleware(api)); | ||
server.ext('onRequest', function handler(request, reply) { | ||
return instrument(api, request, () => reply.continue()); | ||
}); | ||
return server; | ||
@@ -96,4 +97,34 @@ }; | ||
} | ||
}]; | ||
}, | ||
/** | ||
* In Hapi 17, the work that is done on behalf of a request stems from | ||
* Request#_execute. We patch that function to ensure that context is | ||
* available in every handler. | ||
*/ | ||
{ | ||
versions: '17', | ||
file: 'lib/request.js', | ||
// Request is a class name. | ||
// tslint:disable-next-line:variable-name | ||
patch: (Request, api) => { | ||
// TODO(kjin): shimmer cannot wrap AsyncFunction objects. | ||
// Once shimmer introduces this functionality, change this code to use it. | ||
const origExecute = Request.prototype._execute; | ||
Request.prototype._execute = | ||
Object.assign(function _executeWrap() { | ||
return instrument(api, this, () => { | ||
return origExecute.apply(this, arguments); | ||
}); | ||
}, { [ORIGINAL]: origExecute }); | ||
}, | ||
// Request is a class name. | ||
// tslint:disable-next-line:variable-name | ||
unpatch: (Request) => { | ||
if (Request.prototype._execute[ORIGINAL]) { | ||
Request.prototype._execute = Request.prototype._execute[ORIGINAL]; | ||
} | ||
} | ||
} | ||
]; | ||
module.exports = plugin; | ||
//# sourceMappingURL=plugin-hapi.js.map |
{ | ||
"name": "@google-cloud/trace-agent", | ||
"version": "2.6.1", | ||
"version": "2.7.0", | ||
"description": "Node.js Support for StackDriver Trace", | ||
@@ -16,2 +16,3 @@ "main": "build/src/index.js", | ||
"check-install": "npm run script check-install", | ||
"get-plugin-types": "npm run script get-plugin-types", | ||
"coverage": "npm run script run-unit-tests-with-coverage report-coverage", | ||
@@ -23,5 +24,5 @@ "bump": "./bin/run-bump.sh", | ||
"compile-strict": "npm run script compile-auto-strict", | ||
"compile": "npm run script compile-auto compile-auto-strict", | ||
"compile": "npm run script get-plugin-types compile-auto compile-auto-strict", | ||
"fix": "gts fix", | ||
"prepare": "npm run script npm-clean compile-es2015 compile-es2015-strict", | ||
"prepare": "npm run script npm-clean get-plugin-types compile-es2015 compile-es2015-strict", | ||
"script": "ts-node -P ./scripts/tsconfig.json ./scripts", | ||
@@ -55,10 +56,6 @@ "license-check": "jsgl --local ." | ||
"@types/builtin-modules": "^2.0.0", | ||
"@types/connect": "^3.4.31", | ||
"@types/continuation-local-storage": "^3.2.1", | ||
"@types/express": "^4.11.0", | ||
"@types/extend": "^3.0.0", | ||
"@types/glob": "^5.0.32", | ||
"@types/hapi": "^16.1.12", | ||
"@types/is": "0.0.19", | ||
"@types/koa": "^2.0.43", | ||
"@types/methods": "^1.1.0", | ||
@@ -70,7 +67,5 @@ "@types/mocha": "^5.0.0", | ||
"@types/once": "^1.4.0", | ||
"@types/pg": "^7.4.5", | ||
"@types/pify": "^3.0.0", | ||
"@types/proxyquire": "^1.3.28", | ||
"@types/request": "^2.0.8", | ||
"@types/restify": "^5.0.7", | ||
"@types/semver": "^5.4.0", | ||
@@ -77,0 +72,0 @@ "@types/shimmer": "^1.0.1", |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
593182
41
4469