dd-trace
Version:
Datadog APM tracing client for JavaScript
118 lines (103 loc) • 3.67 kB
JavaScript
const Plugin = require('../../dd-trace/src/plugins/plugin')
const telemetryMetrics = require('../../dd-trace/src/telemetry/metrics')
const apiMetrics = telemetryMetrics.manager.namespace('tracers')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
// api ==> here
const objectMap = new WeakMap()
const injectionEnabledTag =
`injection_enabled:${getEnvironmentVariable('DD_INJECTION_ENABLED') ? 'yes' : 'no'}`
module.exports = class DdTraceApiPlugin extends Plugin {
static id = 'dd-trace-api'
constructor (...args) {
super(...args)
const tracer = this._tracer
this.addSub('datadog-api:v1:tracerinit', ({ proxy }) => {
const proxyVal = proxy()
objectMap.set(proxyVal, tracer)
objectMap.set(proxyVal.appsec, tracer.appsec)
objectMap.set(proxyVal.dogstatsd, tracer.dogstatsd)
})
const handleEvent = (name) => {
const counter = apiMetrics.count('public_api.called', [
`name:${name.replaceAll(':', '.')}`,
'api_version:v1',
injectionEnabledTag
])
// For v1, APIs are 1:1 with their internal equivalents, so we can just
// call the internal method directly. That's what we do here unless we
// want to override. As the API evolves, this may change.
this.addSub(`datadog-api:v1:${name}`, ({ self, args, ret, proxy, revProxy }) => {
counter.inc()
if (name.includes(':')) {
name = name.split(':').pop()
}
if (objectMap.has(self)) {
self = objectMap.get(self)
}
for (let i = 0; i < args.length; i++) {
if (objectMap.has(args[i])) {
args[i] = objectMap.get(args[i])
}
if (typeof args[i] === 'function') {
const orig = args[i]
args[i] = (...fnArgs) => {
for (let j = 0; j < fnArgs.length; j++) {
if (revProxy && revProxy[j]) {
const proxyVal = revProxy[j]()
objectMap.set(proxyVal, fnArgs[j])
fnArgs[j] = proxyVal
}
}
// TODO do we need to apply(this, ...) here?
return orig(...fnArgs)
}
}
}
try {
ret.value = self[name](...args)
if (proxy) {
const proxyVal = proxy()
objectMap.set(proxyVal, ret.value)
ret.value = proxyVal
}
} catch (e) {
ret.error = e
}
})
}
// handleEvent('configure')
handleEvent('startSpan')
handleEvent('wrap')
handleEvent('trace')
handleEvent('inject')
handleEvent('extract')
handleEvent('getRumData')
handleEvent('profilerStarted')
handleEvent('context:toTraceId')
handleEvent('context:toSpanId')
handleEvent('context:toTraceparent')
handleEvent('span:context')
handleEvent('span:setTag')
handleEvent('span:addTags')
handleEvent('span:finish')
handleEvent('span:addLink')
handleEvent('scope')
handleEvent('scope:activate')
handleEvent('scope:active')
handleEvent('scope:bind')
handleEvent('appsec:blockRequest')
handleEvent('appsec:isUserBlocked')
handleEvent('appsec:setUser')
handleEvent('appsec:trackCustomEvent')
handleEvent('appsec:trackUserLoginFailureEvent')
handleEvent('appsec:trackUserLoginSuccessEvent')
handleEvent('dogstatsd:decrement')
handleEvent('dogstatsd:distribution')
handleEvent('dogstatsd:flush')
handleEvent('dogstatsd:gauge')
handleEvent('dogstatsd:histogram')
handleEvent('dogstatsd:increment')
handleEvent('use')
}
}