Comparing version 0.2.1-beta.1 to 0.2.1-beta.2
{ | ||
"name": "dd-trace", | ||
"version": "0.2.1-beta.1", | ||
"version": "0.2.1-beta.2", | ||
"description": "Datadog APM tracing client for JavaScript (experimental)", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -27,6 +27,5 @@ 'use strict' | ||
res.end = function () { | ||
res.end = originalEnd | ||
const returned = res.end.apply(this, arguments) | ||
const paths = tracer._context.get('express.paths') | ||
res.end = tracer.bind(function () { | ||
const returned = originalEnd.apply(this, arguments) | ||
const paths = tracer.currentSpan().context()._express_paths | ||
@@ -44,7 +43,7 @@ if (paths) { | ||
return returned | ||
} | ||
}) | ||
req._datadog_trace_patched = true | ||
return next() | ||
next() | ||
}) | ||
@@ -70,12 +69,12 @@ } | ||
const matchers = layer._datadog_matchers | ||
let paths = context.get('express.paths') || [] | ||
const span = context.get('current') | ||
if (matchers) { | ||
if (matchers && span) { | ||
const paths = span.context()._express_paths || [] | ||
// 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) | ||
span.context()._express_paths = paths.concat(matchers[i].path) | ||
context.set('express.paths', paths) | ||
break | ||
@@ -92,4 +91,2 @@ } | ||
function createWrapRouterMethod (tracer) { | ||
const context = tracer._context | ||
return function wrapRouterMethod (original) { | ||
@@ -102,10 +99,11 @@ return function methodWithTrace (fn) { | ||
this.stack.slice(offset).forEach(layer => { | ||
const handle = layer.handle_request | ||
const handleRequest = layer.handle_request | ||
const handleError = layer.handle_error | ||
layer.handle_request = (req, res, next) => { | ||
if (req._datadog_trace_patched) { | ||
next = context.bind(next) | ||
} | ||
return handleRequest.call(layer, req, res, wrapNext(tracer, layer, req, next)) | ||
} | ||
return handle.call(layer, req, res, next) | ||
layer.handle_error = (error, req, res, next) => { | ||
return handleError.call(layer, error, req, res, wrapNext(tracer, layer, req, next)) | ||
} | ||
@@ -121,2 +119,21 @@ | ||
function wrapNext (tracer, layer, req, next) { | ||
if (req._datadog_trace_patched) { | ||
const originalNext = next | ||
return tracer.bind(function () { | ||
const span = tracer.currentSpan() | ||
const paths = span && span.context()._express_paths | ||
if (paths && layer.path && !layer.regexp.fast_star) { | ||
paths.pop() | ||
} | ||
originalNext.apply(null, arguments) | ||
}) | ||
} | ||
return next | ||
} | ||
function extractMatchers (fn) { | ||
@@ -123,0 +140,0 @@ const arg = flatten([].concat(fn)) |
@@ -143,2 +143,34 @@ 'use strict' | ||
it('should only keep the last matching path of a middleware stack', done => { | ||
const app = express() | ||
const router = express.Router() | ||
router.use('/', (req, res, next) => next()) | ||
router.use('*', (req, res, next) => next()) | ||
router.use('/bar', (req, res, next) => next()) | ||
router.use('/bar', (req, res, next) => { | ||
res.status(200).send() | ||
}) | ||
app.use('/', (req, res, next) => next()) | ||
app.use('*', (req, res, next) => next()) | ||
app.use('/foo/bar', (req, res, next) => next()) | ||
app.use('/foo', router) | ||
getPort().then(port => { | ||
agent | ||
.use(traces => { | ||
expect(traces[0][0]).to.have.property('resource', '/foo/bar') | ||
}) | ||
.then(done) | ||
.catch(done) | ||
appListener = app.listen(port, 'localhost', () => { | ||
axios | ||
.get(`http://localhost:${port}/foo/bar`) | ||
.catch(done) | ||
}) | ||
}) | ||
}) | ||
it('should support asynchronous routers', done => { | ||
@@ -244,2 +276,28 @@ const app = express() | ||
it('should bind the response to the current context', done => { | ||
const app = express() | ||
context.run(() => { | ||
const send = context.bind(res => res.status(200).send()) | ||
app.get('/user', (req, res) => { | ||
send(res) | ||
}) | ||
}) | ||
getPort().then(port => { | ||
agent | ||
.use(traces => { | ||
expect(traces[0][0]).to.have.property('resource', '/user') | ||
}) | ||
.then(done) | ||
.catch(done) | ||
appListener = app.listen(port, 'localhost', () => { | ||
axios.get(`http://localhost:${port}/user`) | ||
.catch(done) | ||
}) | ||
}) | ||
}) | ||
it('should bind the next callback to the current context', done => { | ||
@@ -272,2 +330,33 @@ const app = express() | ||
it('should bind the next callback to the current context on error', done => { | ||
const app = express() | ||
app.use((req, res, next) => { | ||
next(new Error('boom')) | ||
}) | ||
app.use((e, req, res, next) => { | ||
context.run(() => { | ||
context.set('foo', 'bar') | ||
next() | ||
}) | ||
}) | ||
app.use((req, res, next) => { | ||
res.status(200).send(context.get('foo')) | ||
}) | ||
getPort().then(port => { | ||
appListener = app.listen(port, 'localhost', () => { | ||
axios.get(`http://localhost:${port}/user`) | ||
.then(res => { | ||
expect(res.status).to.equal(200) | ||
expect(res.data).to.be.empty | ||
done() | ||
}) | ||
.catch(done) | ||
}) | ||
}) | ||
}) | ||
it('should only include paths for routes that matched', done => { | ||
@@ -274,0 +363,0 @@ const app = express() |
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
205862
5819