Comparing version 0.1.5 to 0.1.6
@@ -1,1 +0,1 @@ | ||
module.exports = '0.1.5' | ||
module.exports = '0.1.6' |
{ | ||
"name": "dd-trace", | ||
"version": "0.1.5", | ||
"version": "0.1.6", | ||
"description": "Datadog APM tracing client for JavaScript (experimental)", | ||
@@ -42,2 +42,3 @@ "main": "index.js", | ||
"parent-module": "^0.1.0", | ||
"path-to-regexp": "^2.2.1", | ||
"performance-now": "^2.1.0", | ||
@@ -44,0 +45,0 @@ "read-pkg-up": "^3.0.0", |
@@ -37,4 +37,4 @@ 'use strict' | ||
if (config.plugins !== false) { | ||
loadIntegrations().forEach(integration => { | ||
this._plugins.has(integration) || this._plugins.set(integration) | ||
this._integrations.forEach(integration => { | ||
this._plugins.has(integration) || this._plugins.set(integration, {}) | ||
}) | ||
@@ -41,0 +41,0 @@ } |
@@ -8,10 +8,7 @@ 'use strict' | ||
const METHODS = require('methods').concat('use', 'route', 'param', 'all') | ||
const pathToRegExp = require('path-to-regexp') | ||
const OPERATION_NAME = 'express.request' | ||
function patch (express, tracer, config) { | ||
METHODS.forEach((method) => { | ||
shimmer.wrap(express.application, method, wrapper) | ||
}) | ||
function createWrapMethod (tracer, config) { | ||
function middleware (req, res, next) { | ||
@@ -34,5 +31,6 @@ const url = `${req.protocol}://${req.get('host')}${req.originalUrl}` | ||
const returned = res.end.apply(this, arguments) | ||
const paths = tracer._context.get('express.paths') | ||
if (req.route && req.route.path) { | ||
span.setTag('resource.name', req.route.path) | ||
if (paths) { | ||
span.setTag('resource.name', paths.join('')) | ||
} | ||
@@ -53,4 +51,4 @@ | ||
function wrapper (original) { | ||
return function () { | ||
return function wrapMethod (original) { | ||
return function methodWithTrace () { | ||
if (!this._datadog_trace_patched && !this._router) { | ||
@@ -65,8 +63,80 @@ this._datadog_trace_patched = true | ||
function unpatch (express) { | ||
METHODS.forEach((method) => { | ||
shimmer.unwrap(express.application, method) | ||
function createWrapProcessParams (tracer, config) { | ||
const context = tracer._context | ||
return function wrapProcessParams (processParams) { | ||
return function processParamsWithTrace (layer, called, req, res, done) { | ||
const matchers = layer._datadog_matchers | ||
let paths = context.get('express.paths') || [] | ||
if (matchers) { | ||
// Try to guess which path actually matched | ||
for (let i = 0; i < matchers.length; i++) { | ||
if (matchers[i].test(layer.path)) { | ||
paths = paths.concat(matchers[i].path) | ||
context.run(() => { | ||
context.set('express.paths', paths) | ||
layer.handle = context.bind(layer.handle) | ||
}) | ||
break | ||
} | ||
} | ||
} | ||
return processParams.apply(this, arguments) | ||
} | ||
} | ||
} | ||
function createWrapRouterMethod () { | ||
return function wrapRouterMethod (original) { | ||
return function methodWithTrace (fn) { | ||
const offset = this.stack.length | ||
const router = original.apply(this, arguments) | ||
const matchers = extractMatchers(fn) | ||
this.stack.slice(offset).forEach(layer => { | ||
layer._datadog_matchers = matchers | ||
}) | ||
return router | ||
} | ||
} | ||
} | ||
function extractMatchers (fn) { | ||
const arg = flatten([].concat(fn)) | ||
if (typeof arg[0] === 'function') { | ||
return [] | ||
} | ||
return arg.map(pattern => ({ | ||
path: pattern instanceof RegExp ? `(${pattern})` : pattern, | ||
test: path => pathToRegExp(pattern).test(path) | ||
})) | ||
} | ||
function flatten (arr) { | ||
return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(flatten(val)) : acc.concat(val), []) | ||
} | ||
function patch (express, tracer, config) { | ||
METHODS.forEach(method => { | ||
shimmer.wrap(express.application, method, createWrapMethod(tracer, config)) | ||
}) | ||
shimmer.wrap(express.Router, 'process_params', createWrapProcessParams(tracer, config)) | ||
shimmer.wrap(express.Router, 'use', createWrapRouterMethod(tracer, config)) | ||
shimmer.wrap(express.Router, 'route', createWrapRouterMethod(tracer, config)) | ||
} | ||
function unpatch (express) { | ||
METHODS.forEach(method => shimmer.unwrap(express.application, method)) | ||
shimmer.unwrap(express.Router, 'process_params') | ||
shimmer.unwrap(express.Router, 'use') | ||
shimmer.unwrap(express.Router, 'route') | ||
} | ||
module.exports = { | ||
@@ -73,0 +143,0 @@ name: 'express', |
@@ -120,3 +120,3 @@ 'use strict' | ||
expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer') | ||
expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer', {}) | ||
}) | ||
@@ -140,3 +140,3 @@ | ||
expect(plugins.other.patch).to.have.been.calledWith(other, 'tracer') | ||
expect(plugins.other.patch).to.have.been.calledWith(other, 'tracer', {}) | ||
}) | ||
@@ -151,3 +151,3 @@ }) | ||
expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer') | ||
expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer', {}) | ||
}) | ||
@@ -161,3 +161,3 @@ | ||
expect(integrations.express.patch).to.not.have.been.calledWith(express, 'tracer') | ||
expect(integrations.express.patch).to.not.have.been.calledWith(express, 'tracer', {}) | ||
}) | ||
@@ -171,3 +171,3 @@ | ||
expect(integrations.http.patch).to.have.been.called | ||
expect(integrations.http.patch).to.have.been.calledWith(http, 'tracer') | ||
expect(integrations.http.patch).to.have.been.calledWith(http, 'tracer', {}) | ||
}) | ||
@@ -181,4 +181,4 @@ | ||
expect(mysql).to.deep.equal({ foo: 'bar' }) | ||
expect(integrations.mysql[0].patch).to.have.been.calledWith(Connection, 'tracer') | ||
expect(integrations.mysql[1].patch).to.have.been.calledWith(Pool, 'tracer') | ||
expect(integrations.mysql[0].patch).to.have.been.calledWith(Connection, 'tracer', {}) | ||
expect(integrations.mysql[1].patch).to.have.been.calledWith(Pool, 'tracer', {}) | ||
}) | ||
@@ -208,3 +208,3 @@ }) | ||
expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer') | ||
expect(integrations.express.patch).to.have.been.calledWith(express, 'tracer', {}) | ||
}) | ||
@@ -219,4 +219,4 @@ }) | ||
expect(integrations.mysql[0].patch).to.have.been.calledWith(Connection, 'tracer') | ||
expect(integrations.mysql[1].patch).to.have.been.calledWith(Pool, 'tracer') | ||
expect(integrations.mysql[0].patch).to.have.been.calledWith(Connection, 'tracer', {}) | ||
expect(integrations.mysql[1].patch).to.have.been.calledWith(Pool, 'tracer', {}) | ||
}) | ||
@@ -230,3 +230,3 @@ | ||
expect(integrations.express.patch).to.not.have.been.calledWith(express, 'tracer') | ||
expect(integrations.express.patch).to.not.have.been.calledWith(express, 'tracer', {}) | ||
}) | ||
@@ -233,0 +233,0 @@ }) |
@@ -30,3 +30,3 @@ 'use strict' | ||
it('should do automatic instrumentation', done => { | ||
it('should do automatic instrumentation on app routes', done => { | ||
const app = express() | ||
@@ -59,12 +59,20 @@ | ||
it('should support custom routers', done => { | ||
it('should do automatic instrumentation on routers', done => { | ||
const app = express() | ||
const router = express.Router() | ||
app.use((req, res) => { | ||
router.get('/user/:id', (req, res) => { | ||
res.status(200).send() | ||
}) | ||
app.use('/app', router) | ||
getPort().then(port => { | ||
agent.use(traces => { | ||
expect(traces[0][0]).to.have.property('resource', 'express.request') | ||
expect(traces[0][0]).to.have.property('service', 'test') | ||
expect(traces[0][0]).to.have.property('type', 'web') | ||
expect(traces[0][0]).to.have.property('resource', '/app/user/:id') | ||
expect(traces[0][0].meta).to.have.property('span.kind', 'server') | ||
expect(traces[0][0].meta).to.have.property('http.url', `http://localhost:${port}/app/user/1`) | ||
expect(traces[0][0].meta).to.have.property('http.method', 'GET') | ||
expect(traces[0][0].meta).to.have.property('http.status_code', '200') | ||
@@ -77,3 +85,3 @@ | ||
axios | ||
.get(`http://localhost:${port}`) | ||
.get(`http://localhost:${port}/app/user/1`) | ||
.catch(done) | ||
@@ -84,2 +92,72 @@ }) | ||
it('should surround matchers based on regular expressions', done => { | ||
const app = express() | ||
const router = express.Router() | ||
router.get(/^\/user\/(\d)$/, (req, res) => { | ||
res.status(200).send() | ||
}) | ||
app.use('/app', router) | ||
getPort().then(port => { | ||
agent.use(traces => { | ||
expect(traces[0][0]).to.have.property('resource', '/app(/^\\/user\\/(\\d)$/)') | ||
done() | ||
}) | ||
appListener = app.listen(port, 'localhost', () => { | ||
axios | ||
.get(`http://localhost:${port}/app/user/1`) | ||
.catch(done) | ||
}) | ||
}) | ||
}) | ||
it('should support a nested array of paths on the router', done => { | ||
const app = express() | ||
const router = express.Router() | ||
router.get([['/user/:id'], '/users/:id'], (req, res) => { | ||
res.status(200).send() | ||
}) | ||
app.use('/app', router) | ||
getPort().then(port => { | ||
agent.use(traces => { | ||
expect(traces[0][0]).to.have.property('resource', '/app/user/:id') | ||
done() | ||
}) | ||
appListener = app.listen(port, 'localhost', () => { | ||
axios | ||
.get(`http://localhost:${port}/app/user/1`) | ||
.catch(done) | ||
}) | ||
}) | ||
}) | ||
it('should fallback to the default resource name if a path pattern could not be found', done => { | ||
const app = express() | ||
app.use((req, res, next) => res.status(200).send()) | ||
getPort().then(port => { | ||
agent.use(traces => { | ||
expect(traces[0][0]).to.have.property('resource', 'express.request') | ||
done() | ||
}) | ||
appListener = app.listen(port, 'localhost', () => { | ||
axios | ||
.get(`http://localhost:${port}/app`) | ||
.catch(done) | ||
}) | ||
}) | ||
}) | ||
it('should support context propagation', done => { | ||
@@ -86,0 +164,0 @@ const app = express() |
Sorry, the diff of this file is not supported yet
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
137230
3968
18
+ Addedpath-to-regexp@^2.2.1
+ Addedpath-to-regexp@2.4.0(transitive)