UNPKG

dd-trace

Version:

Datadog APM tracing client for JavaScript

173 lines (137 loc) 4.34 kB
'use strict' const web = require('../../dd-trace/src/plugins/util/web') function createWrapCallback (tracer, config) { config = web.normalizeConfig(config) return function wrapCallback (callback) { return function callbackWithTrace () { const handleRequest = callback.apply(this, arguments) if (typeof handleRequest !== 'function') return handleRequest return function handleRequestWithTrace (req, res) { web.instrument(tracer, config, req, res, 'koa.request') return handleRequest.apply(this, arguments) } } } } function createWrapCreateContext () { return function wrapCreateContext (createContext) { return function createContextWithTrace (req, res) { const ctx = createContext.apply(this, arguments) if (!ctx) return ctx web.patch(req) web.beforeEnd(req, () => { web.enterRoute(req, ctx.routePath) }) return ctx } } } function createWrapUse () { return function wrapUse (use) { return function useWithTrace () { const result = use.apply(this, arguments) if (!Array.isArray(this.middleware)) return result const fn = this.middleware.pop() this.middleware.push(wrapMiddleware(fn)) return result } } } function createWrapRegister (tracer, config) { return function wrapRegister (register) { return function registerWithTrace (path, methods, middleware, opts) { const route = register.apply(this, arguments) if (!Array.isArray(path) && route && Array.isArray(route.stack)) { wrapStack(route) } return route } } } function createWrapRouterUse (tracer, config) { return function wrapUse (use) { return function useWithTrace () { const router = use.apply(this, arguments) router.stack.forEach(wrapStack) return router } } } function wrapStack (layer) { layer.stack = layer.stack.map(middleware => { if (typeof middleware !== 'function') return middleware middleware = middleware._dd_original || middleware const wrappedMiddleware = wrapMiddleware(middleware) const handler = function (ctx, next) { if (!ctx || !web.active(ctx.req)) return middleware.apply(this, arguments) web.exitRoute(ctx.req) web.enterRoute(ctx.req, layer.path) return wrappedMiddleware.apply(this, arguments) } handler._dd_original = middleware return handler }) } function wrapMiddleware (fn) { if (typeof fn !== 'function') return fn return function (ctx, next) { if (!ctx) return fn.apply(this, arguments) return web.wrapMiddleware(ctx.req, fn, 'koa.middleware', () => { try { const result = fn.apply(this, arguments) if (result && typeof result.then === 'function') { result.then( () => web.finish(ctx.req), err => web.finish(ctx.req, err) ) } else { web.finish(ctx.req) } return result } catch (e) { web.finish(ctx.req, e) throw e } }) } } module.exports = [ { name: 'koa', versions: ['>=2'], patch (Koa, tracer, config) { this.wrap(Koa.prototype, 'callback', createWrapCallback(tracer, config)) this.wrap(Koa.prototype, 'createContext', createWrapCreateContext(tracer, config)) this.wrap(Koa.prototype, 'use', createWrapUse(tracer, config)) }, unpatch (Koa) { this.unwrap(Koa.prototype, 'callback') this.unwrap(Koa.prototype, 'createContext') this.unwrap(Koa.prototype, 'use') } }, { name: '@koa/router', versions: ['>=8'], patch (Router, tracer, config) { this.wrap(Router.prototype, 'register', createWrapRegister(tracer, config)) this.wrap(Router.prototype, 'use', createWrapRouterUse(tracer, config)) }, unpatch (Router) { this.unwrap(Router.prototype, 'register') this.unwrap(Router.prototype, 'use') } }, { name: 'koa-router', versions: ['>=7'], patch (Router, tracer, config) { this.wrap(Router.prototype, 'register', createWrapRegister(tracer, config)) this.wrap(Router.prototype, 'use', createWrapRouterUse(tracer, config)) }, unpatch (Router) { this.unwrap(Router.prototype, 'register') this.unwrap(Router.prototype, 'use') } } ]