Skip to content

Turn async ID gathering off by default #5621

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

Merged
merged 3 commits into from
Apr 30, 2025
Merged
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
40 changes: 7 additions & 33 deletions integration-tests/profiler/profiler.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -351,10 +351,9 @@ describe('profiler', () => {
// 'local root span id's
// - samples with spans also must have a 'trace endpoint' label with values 'endpoint-0',
// 'endpoint-1', or 'endpoint-2'
// - every occurrence of a span must have the same root span, endpoint, and asyncId
// - every occurrence of a span must have the same root span and endpoint
const rootSpans = new Set()
const endpoints = new Set()
const asyncIds = new Set()
const spans = new Map()
const strings = profile.stringTable
const tsKey = strings.dedup('end_timestamp_ns')
Expand All @@ -364,13 +363,11 @@ describe('profiler', () => {
const threadNameKey = strings.dedup('thread name')
const threadIdKey = strings.dedup('thread id')
const osThreadIdKey = strings.dedup('os thread id')
const asyncIdKey = strings.dedup('async id')
const threadNameValue = strings.dedup('Main Event Loop')
const nonJSThreadNameValue = strings.dedup('Non-JS threads')

const asyncIdWorks = require('semifies')(process.versions.node, '>=22.10.0')
for (const sample of profile.sample) {
let ts, spanId, rootSpanId, endpoint, threadName, threadId, osThreadId, asyncId
let ts, spanId, rootSpanId, endpoint, threadName, threadId, osThreadId
for (const label of sample.label) {
switch (label.key) {
case tsKey: ts = label.num; break
Expand All @@ -380,12 +377,6 @@ describe('profiler', () => {
case threadNameKey: threadName = label.str; break
case threadIdKey: threadId = label.str; break
case osThreadIdKey: osThreadId = label.str; break
case asyncIdKey:
asyncId = label.num
if (asyncId === 0) {
asyncId = undefined
}
break
default: assert.fail(`Unexpected label key ${strings.dedup(label.key)} ${encoded}`)
}
}
Expand Down Expand Up @@ -419,27 +410,11 @@ describe('profiler', () => {
// 3 of them.
continue
}
const spanData = { rootSpanId, endpoint, asyncId }
// Record async ID so we can verify we encountered 9 different values.
// Async ID can be sporadically missing if sampling hits an intrinsified
// function.
if (asyncId !== undefined) {
asyncIds.add(asyncId)
}
const spanData = { rootSpanId, endpoint }
const existingSpanData = spans.get(spanId)
if (existingSpanData) {
// Span's root span, endpoint, and async ID must be consistent
// across samples.
assert.equal(existingSpanData.rootSpanId, rootSpanId, encoded)
assert.equal(existingSpanData.endpoint, endpoint, encoded)
if (asyncIdWorks) {
// Account for asyncID sporadically missing
if (existingSpanData.asyncId === undefined) {
existingSpanData.asyncId = asyncId
} else if (asyncId !== undefined) {
assert.equal(existingSpanData.asyncId, asyncId, encoded)
}
}
// Span's root span and endpoint must be consistent across samples
assert.deepEqual(spanData, existingSpanData, encoded)
} else {
// New span id, store span data
spans.set(spanId, spanData)
Expand All @@ -457,10 +432,9 @@ describe('profiler', () => {
}
}
}
// Need to have a total of 9 different spans, with 9 different async IDs,
// 3 different root spans, and 3 different endpoints.
// Need to have a total of 9 different spans, with 3 different root spans
// and 3 different endpoints.
assert.equal(spans.size, 9, encoded)
assert.equal(asyncIds.size, asyncIdWorks ? 9 : 0, encoded)
assert.equal(rootSpans.size, 3, encoded)
assert.equal(endpoints.size, 3, encoded)
})
Expand Down
6 changes: 0 additions & 6 deletions packages/dd-trace/src/profiling/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@ const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('../plugins/util/tags')
const { tagger } = require('./tagger')
const { isFalse, isTrue } = require('../util')
const { getAzureTagsFromMetadata, getAzureAppMetadata } = require('../azure_metadata')
const satisfies = require('semifies')

class Config {
constructor (options = {}) {
const {
DD_AGENT_HOST,
DD_ENV,
DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED, // used for testing
DD_PROFILING_ASYNC_ID_ENABLED,
DD_PROFILING_CODEHOTSPOTS_ENABLED,
DD_PROFILING_CPU_ENABLED,
DD_PROFILING_DEBUG_SOURCE_MAPS,
Expand Down Expand Up @@ -181,10 +179,6 @@ class Config {
this.timelineSamplingEnabled = isTrue(coalesce(options.timelineSamplingEnabled,
DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED, true))

// Async ID gathering only works reliably on Node >= 22.10.0
this.asyncIdEnabled = isTrue(coalesce(options.asyncIdEnabled,
DD_PROFILING_ASYNC_ID_ENABLED, this.timelineEnabled && satisfies(process.versions.node, '>=22.10.0')))

this.codeHotspotsEnabled = isTrue(coalesce(options.codeHotspotsEnabled,
DD_PROFILING_CODEHOTSPOTS_ENABLED,
DD_PROFILING_EXPERIMENTAL_CODEHOTSPOTS_ENABLED, samplingContextsAvailable))
Expand Down
20 changes: 8 additions & 12 deletions packages/dd-trace/src/profiling/profilers/wall.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,12 @@ function ensureChannelsActivated () {
class NativeWallProfiler {
constructor (options = {}) {
this.type = 'wall'
// Currently there's a crash sometimes on worker threads trying to collect async IDs so for the
// time being we'll constrain it to only the main thread.
this._asyncIdEnabled = !!options.asyncIdEnabled && require('worker_threads').isMainThread
this._samplingIntervalMicros = options.samplingInterval || 1e6 / 99 // 99hz
this._flushIntervalMillis = options.flushInterval || 60 * 1e3 // 60 seconds
this._codeHotspotsEnabled = !!options.codeHotspotsEnabled
this._cpuProfilingEnabled = !!options.cpuProfilingEnabled
this._endpointCollectionEnabled = !!options.endpointCollectionEnabled
this._flushIntervalMillis = options.flushInterval || 60 * 1e3 // 60 seconds
this._samplingIntervalMicros = options.samplingInterval || 1e6 / 99 // 99hz
this._timelineEnabled = !!options.timelineEnabled
this._v8ProfilerBugWorkaroundEnabled = !!options.v8ProfilerBugWorkaroundEnabled
this._cpuProfilingEnabled = !!options.cpuProfilingEnabled
// We need to capture span data into the sample context for either code hotspots
// or endpoint collection.
this._captureSpanData = this._codeHotspotsEnabled || this._endpointCollectionEnabled
Expand All @@ -88,6 +84,7 @@ class NativeWallProfiler {
// timestamps require the sample contexts feature in the pprof wall profiler), or
// cpu profiling is enabled.
this._withContexts = this._captureSpanData || this._timelineEnabled || this._cpuProfilingEnabled
this._v8ProfilerBugWorkaroundEnabled = !!options.v8ProfilerBugWorkaroundEnabled
this._mapper = undefined
this._pprof = undefined

Expand Down Expand Up @@ -128,14 +125,13 @@ class NativeWallProfiler {
}

this._pprof.time.start({
collectAsyncId: this._asyncIdEnabled,
collectCpuTime: this._cpuProfilingEnabled,
durationMillis: this._flushIntervalMillis,
intervalMicros: this._samplingIntervalMicros,
lineNumbers: false,
durationMillis: this._flushIntervalMillis,
sourceMapper: this._mapper,
withContexts: this._withContexts,
workaroundV8Bug: this._v8ProfilerBugWorkaroundEnabled
lineNumbers: false,
workaroundV8Bug: this._v8ProfilerBugWorkaroundEnabled,
collectCpuTime: this._cpuProfilingEnabled
})

if (this._withContexts) {
Expand Down
9 changes: 3 additions & 6 deletions packages/dd-trace/test/profiling/profilers/wall.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ describe('profilers/native/wall', () => {
withContexts: false,
lineNumbers: false,
workaroundV8Bug: false,
collectCpuTime: false,
collectAsyncId: false
collectCpuTime: false
})
})

Expand All @@ -78,8 +77,7 @@ describe('profilers/native/wall', () => {
withContexts: false,
lineNumbers: false,
workaroundV8Bug: false,
collectCpuTime: false,
collectAsyncId: false
collectCpuTime: false
})
})

Expand Down Expand Up @@ -175,8 +173,7 @@ describe('profilers/native/wall', () => {
withContexts: false,
lineNumbers: false,
workaroundV8Bug: false,
collectCpuTime: false,
collectAsyncId: false
collectCpuTime: false
})
})

Expand Down
Loading