Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions packages/datadog-plugin-http/src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@ class HttpServerPlugin extends ServerPlugin {

constructor (...args) {
super(...args)
this._parentStore = undefined
this.addTraceSub('exit', message => this.exit(message))
}

start ({ req, res, abortController }) {
const store = storage('legacy').getStore()
let store = storage('legacy').getStore()
const span = web.startSpan(
this.tracer,
{
Expand All @@ -32,11 +31,31 @@ class HttpServerPlugin extends ServerPlugin {
span.setTag(COMPONENT, this.constructor.id)
span._integrationName = this.constructor.id

this._parentStore = store
this.enter(span, { ...store, req, res })

const context = web.getContext(req)

if (context) {
context.parentStore = store
}

if (incomingHttpRequestStart.hasSubscribers) {
const weakReq = new WeakRef(req)
const weakRes = new WeakRef(res)
store = Object.create(store ?? null)
Object.defineProperty(store, 'req', {
configurable: true,
enumerable: false,
get () { return weakReq.deref() }
})

Object.defineProperty(store, 'res', {
configurable: true,
enumerable: false,
get () { return weakRes.deref() }
})
}

this.enter(span, store)

if (!context.instrumented) {
context.res.writeHead = web.wrapWriteHead(context)
context.instrumented = true
Expand Down Expand Up @@ -64,9 +83,15 @@ class HttpServerPlugin extends ServerPlugin {
}

exit ({ req }) {
const span = this._parentStore && this._parentStore.span
this.enter(span, this._parentStore)
this._parentStore = undefined
const context = web.getContext(req)
const parentStore = context?.parentStore

const span = parentStore?.span
this.enter(span, parentStore)

if (context) {
context.parentStore = undefined
}
}

configure (config) {
Expand Down
47 changes: 28 additions & 19 deletions packages/datadog-plugin-router/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,50 +9,59 @@ const { COMPONENT } = require('../../dd-trace/src/constants')
class RouterPlugin extends WebPlugin {
static id = 'router'

#storeStacks = new WeakMap()
#contexts = new WeakMap()

constructor (...args) {
super(...args)

this._storeStack = []
this._contexts = new WeakMap()

this.addSub(`apm:${this.constructor.id}:middleware:enter`, ({ req, name, route }) => {
const childOf = this._getActive(req) || this._getStoreSpan()
const childOf = this.#getActive(req) || this.#getStoreSpan()

if (!childOf) return

const span = this._getMiddlewareSpan(name, childOf)
const context = this._createContext(req, route, childOf)
const span = this.#getMiddlewareSpan(name, childOf)
const context = this.#createContext(req, route, childOf)

if (childOf !== span) {
context.middleware.push(span)
}

const store = storage('legacy').getStore()
this._storeStack.push(store)
let storeStack = this.#storeStacks.get(req)
if (!storeStack) {
storeStack = []
this.#storeStacks.set(req, storeStack)
}
storeStack.push(store)
this.enter(span, store)

web.patch(req)
web.setRoute(req, context.route)
})

this.addSub(`apm:${this.constructor.id}:middleware:next`, ({ req }) => {
const context = this._contexts.get(req)
const context = this.#contexts.get(req)

if (!context) return

context.stack.pop()
})

this.addSub(`apm:${this.constructor.id}:middleware:finish`, ({ req }) => {
const context = this._contexts.get(req)
const context = this.#contexts.get(req)

if (!context || context.middleware.length === 0) return

context.middleware.pop().finish()
})

this.addSub(`apm:${this.constructor.id}:middleware:exit`, ({ req }) => {
const savedStore = this._storeStack.pop()
const storeStack = this.#storeStacks.get(req)
const savedStore = storeStack && storeStack.pop()
if (storeStack && storeStack.length === 0) {
this.#storeStacks.delete(req)
}
const span = savedStore && savedStore.span
this.enter(span, savedStore)
})
Expand All @@ -62,15 +71,15 @@ class RouterPlugin extends WebPlugin {

if (!this.config.middleware) return

const span = this._getActive(req)
const span = this.#getActive(req)

if (!span) return

span.setTag('error', error)
})

this.addSub('apm:http:server:request:finish', ({ req }) => {
const context = this._contexts.get(req)
const context = this.#contexts.get(req)

if (!context) return

Expand All @@ -82,22 +91,22 @@ class RouterPlugin extends WebPlugin {
})
}

_getActive (req) {
const context = this._contexts.get(req)
#getActive (req) {
const context = this.#contexts.get(req)

if (!context) return
if (context.middleware.length === 0) return context.span

return context.middleware.at(-1)
}

_getStoreSpan () {
#getStoreSpan () {
const store = storage('legacy').getStore()

return store && store.span
}

_getMiddlewareSpan (name, childOf) {
#getMiddlewareSpan (name, childOf) {
if (this.config.middleware === false) {
return childOf
}
Expand All @@ -116,8 +125,8 @@ class RouterPlugin extends WebPlugin {
return span
}

_createContext (req, route, span) {
let context = this._contexts.get(req)
#createContext (req, route, span) {
let context = this.#contexts.get(req)

if (!route || route === '/' || route === '*') {
route = ''
Expand All @@ -140,7 +149,7 @@ class RouterPlugin extends WebPlugin {
middleware: []
}

this._contexts.set(req, context)
this.#contexts.set(req, context)
}

return context
Expand Down
2 changes: 1 addition & 1 deletion packages/dd-trace/src/id.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,5 +243,5 @@ function writeUInt32BE (buffer, value, offset) {
* @returns {Identifier}
*/
module.exports = function createIdentifier (value, radix) {
return new Identifier(value, radix)
return new Identifier(value ?? '', radix)
}
9 changes: 7 additions & 2 deletions packages/dd-trace/src/plugins/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,13 @@ module.exports = class Plugin {

if (!store || !store.span) return

if (!store.span._spanContext._tags.error) {
store.span.setTag('error', error || 1)
/**
* @type {{ _spanContext: { _tags: Record<string, unknown> }, setTag: (key: string, value: unknown) => void }}
*/
const span = /** @type {typeof span} */ (store.span)

if (!span._spanContext._tags.error) {
span.setTag('error', error || 1)
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/dd-trace/src/plugins/util/web.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ function startSpanHelper (tracer, name, options, traceCtx, config = {}) {

const web = {
TYPE: WEB,
/** @type {TracingPlugin | null} */
plugin: null,

// Ensure the configuration has the correct structure and defaults.
Expand Down
Loading