Skip to content

Commit

Permalink
Add support for Fastify entry spans for Code Origin for Spans (#4449)
Browse files Browse the repository at this point in the history
This commit does two things:

- It lays the groundwork for an upcoming feature called "Code Origin for
  Spans".
- To showcase this feature, it adds limited support for just Fastify
  entry-spans.

To enable, set `DD_CODE_ORIGIN_FOR_SPANS_ENABLED=true`.
  • Loading branch information
watson authored Oct 14, 2024
1 parent bd4aff5 commit c085df1
Show file tree
Hide file tree
Showing 14 changed files with 511 additions and 37 deletions.
2 changes: 2 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
/packages/dd-trace/test/appsec/ @DataDog/asm-js

/integration-tests/debugger/ @DataDog/dd-trace-js @DataDog/debugger
/packages/datadog-code-origin/ @DataDog/dd-trace-js @DataDog/debugger
/packages/datadog-plugin-*/**/code_origin.* @DataDog/dd-trace-js @DataDog/debugger
/packages/dd-trace/src/debugger/ @DataDog/dd-trace-js @DataDog/debugger
/packages/dd-trace/test/debugger/ @DataDog/dd-trace-js @DataDog/debugger

Expand Down
38 changes: 38 additions & 0 deletions packages/datadog-code-origin/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use strict'

const { getUserLandFrames } = require('../dd-trace/src/plugins/util/stacktrace')

const limit = Number(process.env._DD_CODE_ORIGIN_MAX_USER_FRAMES) || 8

module.exports = {
entryTag,
exitTag
}

function entryTag (topOfStackFunc) {
return tag('entry', topOfStackFunc)
}

function exitTag (topOfStackFunc) {
return tag('exit', topOfStackFunc)
}

function tag (type, topOfStackFunc) {
const frames = getUserLandFrames(topOfStackFunc, limit)
const tags = {
'_dd.code_origin.type': type
}
for (let i = 0; i < frames.length; i++) {
const frame = frames[i]
tags[`_dd.code_origin.frames.${i}.file`] = frame.file
tags[`_dd.code_origin.frames.${i}.line`] = String(frame.line)
tags[`_dd.code_origin.frames.${i}.column`] = String(frame.column)
if (frame.method) {
tags[`_dd.code_origin.frames.${i}.method`] = frame.method
}
if (frame.type) {
tags[`_dd.code_origin.frames.${i}.type`] = frame.type
}
}
return tags
}
13 changes: 12 additions & 1 deletion packages/datadog-instrumentations/src/fastify.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const { addHook, channel, AsyncResource } = require('./helpers/instrument')

const errorChannel = channel('apm:fastify:middleware:error')
const handleChannel = channel('apm:fastify:request:handle')
const routeAddedChannel = channel('apm:fastify:route:added')

const parsingResources = new WeakMap()

Expand All @@ -16,6 +17,7 @@ function wrapFastify (fastify, hasParsingEvents) {

if (!app || typeof app.addHook !== 'function') return app

app.addHook('onRoute', onRoute)
app.addHook('onRequest', onRequest)
app.addHook('preHandler', preHandler)

Expand Down Expand Up @@ -86,8 +88,9 @@ function onRequest (request, reply, done) {

const req = getReq(request)
const res = getRes(reply)
const routeConfig = getRouteConfig(request)

handleChannel.publish({ req, res })
handleChannel.publish({ req, res, routeConfig })

return done()
}
Expand Down Expand Up @@ -142,6 +145,10 @@ function getRes (reply) {
return reply && (reply.raw || reply.res || reply)
}

function getRouteConfig (request) {
return request?.routeOptions?.config
}

function publishError (error, req) {
if (error) {
errorChannel.publish({ error, req })
Expand All @@ -150,6 +157,10 @@ function publishError (error, req) {
return error
}

function onRoute (routeOptions) {
routeAddedChannel.publish({ routeOptions, onRoute })
}

addHook({ name: 'fastify', versions: ['>=3'] }, fastify => {
const wrapped = shimmer.wrapFunction(fastify, fastify => wrapFastify(fastify, true))

Expand Down
2 changes: 1 addition & 1 deletion packages/datadog-instrumentations/src/mocha/common.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { addHook, channel } = require('../helpers/instrument')
const shimmer = require('../../../datadog-shimmer')
const { getCallSites } = require('../../../dd-trace/src/plugins/util/test')
const { getCallSites } = require('../../../dd-trace/src/plugins/util/stacktrace')
const { testToStartLine } = require('./utils')

const parameterizedTestCh = channel('ci:mocha:test:parameterize')
Expand Down
31 changes: 31 additions & 0 deletions packages/datadog-plugin-fastify/src/code_origin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use strict'

const { entryTag } = require('../../datadog-code-origin')
const Plugin = require('../../dd-trace/src/plugins/plugin')
const web = require('../../dd-trace/src/plugins/util/web')

const kCodeOriginForSpansTagsSym = Symbol('datadog.codeOriginForSpansTags')

class FastifyCodeOriginForSpansPlugin extends Plugin {
static get id () {
return 'fastify'
}

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

this.addSub('apm:fastify:request:handle', ({ req, routeConfig }) => {
const tags = routeConfig?.[kCodeOriginForSpansTagsSym]
if (!tags) return
const context = web.getContext(req)
context.span?.addTags(tags)
})

this.addSub('apm:fastify:route:added', ({ routeOptions, onRoute }) => {
if (!routeOptions.config) routeOptions.config = {}
routeOptions.config[kCodeOriginForSpansTagsSym] = entryTag(onRoute)
})
}
}

module.exports = FastifyCodeOriginForSpansPlugin
22 changes: 10 additions & 12 deletions packages/datadog-plugin-fastify/src/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
'use strict'

const RouterPlugin = require('../../datadog-plugin-router/src')
const FastifyTracingPlugin = require('./tracing')
const FastifyCodeOriginForSpansPlugin = require('./code_origin')
const CompositePlugin = require('../../dd-trace/src/plugins/composite')

class FastifyPlugin extends RouterPlugin {
static get id () {
return 'fastify'
}

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

this.addSub('apm:fastify:request:handle', ({ req }) => {
this.setFramework(req, 'fastify', this.config)
})
class FastifyPlugin extends CompositePlugin {
static get id () { return 'fastify' }
static get plugins () {
return {
tracing: FastifyTracingPlugin,
codeOriginForSpans: FastifyCodeOriginForSpansPlugin
}
}
}

Expand Down
19 changes: 19 additions & 0 deletions packages/datadog-plugin-fastify/src/tracing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict'

const RouterPlugin = require('../../datadog-plugin-router/src')

class FastifyTracingPlugin extends RouterPlugin {
static get id () {
return 'fastify'
}

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

this.addSub('apm:fastify:request:handle', ({ req }) => {
this.setFramework(req, 'fastify', this.config)
})
}
}

module.exports = FastifyTracingPlugin
Loading

0 comments on commit c085df1

Please sign in to comment.