Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

trace level PoC #4994

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
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
11 changes: 8 additions & 3 deletions packages/datadog-plugin-router/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ class RouterPlugin extends WebPlugin {
context.middleware.push(span)
}

const store = storage.getStore()
this._storeStack.push(store)
this.enter(span, store)
if (span.constructor.name !== 'NoopSpan') {
const store = storage.getStore()
this._storeStack.push(store)
this.enter(span, store)
}

web.patch(req)
web.setRoute(req, context.route)
Expand Down Expand Up @@ -90,6 +92,9 @@ class RouterPlugin extends WebPlugin {
if (!context) return
if (context.middleware.length === 0) return context.span

// if the span is no-op then use the OG request span
if (context.middleware[context.middleware.length - 1].constructor.name === 'NoopSpan') return context.span

return context.middleware[context.middleware.length - 1]
}

Expand Down
4 changes: 4 additions & 0 deletions packages/dd-trace/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ class Config {
this._setValue(defaults, 'logInjection', false)
this._setValue(defaults, 'lookup', undefined)
this._setValue(defaults, 'inferredProxyServicesEnabled', false)
this._setValue(defaults, 'traceLevel', 'debug')
this._setValue(defaults, 'memcachedCommandEnabled', false)
this._setValue(defaults, 'openAiLogsEnabled', false)
this._setValue(defaults, 'openaiSpanCharLimit', 128)
Expand Down Expand Up @@ -688,6 +689,7 @@ class Config {
DD_TRACING_ENABLED,
DD_VERSION,
DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED,
DD_TRACE_LEVEL,
OTEL_METRICS_EXPORTER,
OTEL_PROPAGATORS,
OTEL_RESOURCE_ATTRIBUTES,
Expand Down Expand Up @@ -881,6 +883,7 @@ class Config {
this._setBoolean(env, 'tracing', DD_TRACING_ENABLED)
this._setString(env, 'version', DD_VERSION || tags.version)
this._setBoolean(env, 'inferredProxyServicesEnabled', DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED)
this._setString(env, 'traceLevel', DD_TRACE_LEVEL)
this._setString(env, 'aws.dynamoDb.tablePrimaryKeys', DD_AWS_SDK_DYNAMODB_TABLE_PRIMARY_KEYS)
}

Expand Down Expand Up @@ -996,6 +999,7 @@ class Config {
this._setBoolean(opts, 'traceId128BitLoggingEnabled', options.traceId128BitLoggingEnabled)
this._setString(opts, 'version', options.version || tags.version)
this._setBoolean(opts, 'inferredProxyServicesEnabled', options.inferredProxyServicesEnabled)
this._setString(opts, 'traceLevel', options.traceLevel)

// For LLMObs, we want the environment variable to take precedence over the options.
// This is reliant on environment config being set before options.
Expand Down
23 changes: 20 additions & 3 deletions packages/dd-trace/src/noop/span.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,24 @@

const NoopSpanContext = require('./span_context')
const id = require('../id')
const { performance } = require('perf_hooks')
const now = performance.now.bind(performance)
const dateNow = Date.now
const { storage } = require('../../../datadog-core') // TODO: noop storage?

class NoopSpan {
constructor (tracer, parent) {
constructor (tracer, parent, options) {
this._store = storage.getStore()
this._noopTracer = tracer
this._noopContext = this._createContext(parent)
this._noopContext = this._createContext(parent, options)
this._options = options
this._startTime = this._getTime()
}

_getTime () {
const startTime = dateNow() + now()

return startTime
}

context () { return this._noopContext }
Expand All @@ -27,10 +38,16 @@ class NoopSpan {
logEvent () {}
finish (finishTime) {}

_createContext (parent) {
_createContext (parent, options) {
const spanId = id()

if (parent) {
// necessary for trace level configuration. This pattern returns the first valid span context that is not a
// NoopSpanContext, aka the next parent span in the trace that will be kept.
if (options.keepParent) {
return parent.context()
}

return new NoopSpanContext({
noop: this,
traceId: parent._traceId,
Expand Down
48 changes: 47 additions & 1 deletion packages/dd-trace/src/opentracing/tracer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const os = require('os')
const Span = require('./span')
const NoopSpan = require('../noop/span')
const SpanProcessor = require('../span_processor')
const PrioritySampler = require('../priority_sampler')
const TextMapPropagator = require('./propagation/text_map')
Expand Down Expand Up @@ -57,6 +58,13 @@ class DatadogTracer {
'service.name': options?.tags?.service ? String(options.tags.service) : this._service
}

if (this._config.traceLevel !== 'debug') {
const traceLevelSpan = this._useTraceLevel(parent, options)
if (traceLevelSpan) {
return traceLevelSpan
}
}

// As per unified service tagging spec if a span is created with a service name different from the global
// service name it will not inherit the global version value
if (options?.tags?.service && options.tags.service !== this._service) {
Expand All @@ -81,7 +89,7 @@ class DatadogTracer {
}

inject (context, format, carrier) {
if (context instanceof Span) {
if (context instanceof Span || context instanceof NoopSpan) {
context = context.context()
}

Expand All @@ -105,13 +113,51 @@ class DatadogTracer {
return null
}
}

_useTraceLevel (parent, options) {
// service trace level indicates service exit / entry spans only
if (this._config.traceLevel === 'service') {
// if the parent is a SpanContext, this is a distributed trace and should create a child span
// if the parent is a Span or NoopSpan, this is from the same service
if (
parent instanceof Span || parent instanceof NoopSpan ||
options.childOf instanceof Span || options.childOf instanceof NoopSpan
) {
return new NoopSpan(this, parent, { keepParent: true })
}
} else if (this._config.traceLevel === 'span.kind') {
// span.kind trace level indicates eliminates repeated spans with the same span.kind
if (parent) {
if (
options?.tags && parent._tags && options?.tags['span.kind'] &&
parent._tags['span.kind'] === options.tags['span.kind']
) {
return new NoopSpan(this, parent, { keepParent: true })
}
}
} else if (this._config.traceLevel === 'integration') {
// integration trace level indicates eliminates repeated spans from the same integration
if (parent) {
if (options?.tags?.component && parent?._tags?.component === options?.tags?.component) {
return new NoopSpan(this, parent, { keepParent: true })
}
}
} else {
log.warn(`Received invalid Datadog Trace Level Configuration: ${this._config.traceLevel}`)
return null
}
}
}

function getContext (spanContext) {
if (spanContext instanceof Span) {
spanContext = spanContext.context()
}

if (spanContext instanceof NoopSpan) {
spanContext = spanContext.context()
}

if (!(spanContext instanceof SpanContext)) {
spanContext = null
}
Expand Down
2 changes: 1 addition & 1 deletion packages/dd-trace/src/plugins/tracing.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class TracingPlugin extends Plugin {
}

addError (error, span = this.activeSpan) {
if (span && !span._spanContext._tags.error) {
if (!span.context()._tags.error) {
// Errors may be wrapped in a context.
error = (error && error.error) || error
span.setTag('error', error || 1)
Expand Down
Loading