Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

dd-trace

Package Overview
Dependencies
Maintainers
1
Versions
676
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dd-trace - npm Package Compare versions

Comparing version
5.82.0
to
5.83.0
+221
packages/dd-trace/src/config/defaults.js
'use strict'
const pkg = require('../pkg')
const { GRPC_CLIENT_ERROR_STATUSES, GRPC_SERVER_ERROR_STATUSES } = require('../constants')
const { getEnvironmentVariable: getEnv } = require('./helper')
// eslint-disable-next-line @stylistic/max-len
const qsRegex = String.raw`(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:(?:\s|%20)*(?:=|%3D)[^&]+|(?:"|%22)(?:\s|%20)*(?::|%3A)(?:\s|%20)*(?:"|%22)(?:%2[^2]|%[^2]|[^"%])+(?:"|%22))|bearer(?:\s|%20)+[a-z0-9\._\-]+|token(?::|%3A)[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L](?:[\w=-]|%3D)+\.ey[I-L](?:[\w=-]|%3D)+(?:\.(?:[\w.+\/=-]|%3D|%2F|%2B)+)?|[\-]{5}BEGIN(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY[\-]{5}[^\-]+[\-]{5}END(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY|ssh-rsa(?:\s|%20)*(?:[a-z0-9\/\.+]|%2F|%5C|%2B){100,}`
// eslint-disable-next-line @stylistic/max-len
const defaultWafObfuscatorKeyRegex = String.raw`(?i)pass|pw(?:or)?d|secret|(?:api|private|public|access)[_-]?key|token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)|bearer|authorization|jsessionid|phpsessid|asp\.net[_-]sessionid|sid|jwt`
// eslint-disable-next-line @stylistic/max-len
const defaultWafObfuscatorValueRegex = String.raw`(?i)(?:p(?:ass)?w(?:or)?d|pass(?:[_-]?phrase)?|secret(?:[_-]?key)?|(?:(?:api|private|public|access)[_-]?)key(?:[_-]?id)?|(?:(?:auth|access|id|refresh)[_-]?)?token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?|jsessionid|phpsessid|asp\.net(?:[_-]|-)sessionid|sid|jwt)(?:\s*=([^;&]+)|"\s*:\s*("[^"]+"|\d+))|bearer\s+([a-z0-9\._\-]+)|token\s*:\s*([a-z0-9]{13})|gh[opsu]_([0-9a-zA-Z]{36})|ey[I-L][\w=-]+\.(ey[I-L][\w=-]+(?:\.[\w.+\/=-]+)?)|[\-]{5}BEGIN[a-z\s]+PRIVATE\sKEY[\-]{5}([^\-]+)[\-]{5}END[a-z\s]+PRIVATE\sKEY|ssh-rsa\s*([a-z0-9\/\.+]{100,})`
const service = getEnv('AWS_LAMBDA_FUNCTION_NAME') ||
getEnv('FUNCTION_NAME') || // Google Cloud Function Name set by deprecated runtimes
getEnv('K_SERVICE') || // Google Cloud Function Name set by newer runtimes
getEnv('WEBSITE_SITE_NAME') || // set by Azure Functions
pkg.name ||
'node'
module.exports = {
apiKey: undefined,
appKey: undefined,
apmTracingEnabled: true,
'appsec.apiSecurity.enabled': true,
'appsec.apiSecurity.sampleDelay': 30,
'appsec.apiSecurity.endpointCollectionEnabled': true,
'appsec.apiSecurity.endpointCollectionMessageLimit': 300,
'appsec.blockedTemplateGraphql': undefined,
'appsec.blockedTemplateHtml': undefined,
'appsec.blockedTemplateJson': undefined,
'appsec.enabled': undefined,
'appsec.eventTracking.mode': 'identification',
// TODO appsec.extendedHeadersCollection is deprecated, to delete in a major
'appsec.extendedHeadersCollection.enabled': false,
'appsec.extendedHeadersCollection.redaction': true,
'appsec.extendedHeadersCollection.maxHeaders': 50,
'appsec.obfuscatorKeyRegex': defaultWafObfuscatorKeyRegex,
'appsec.obfuscatorValueRegex': defaultWafObfuscatorValueRegex,
'appsec.rasp.enabled': true,
// TODO Deprecated, to delete in a major
'appsec.rasp.bodyCollection': false,
'appsec.rateLimit': 100,
'appsec.rules': undefined,
'appsec.sca.enabled': null,
'appsec.stackTrace.enabled': true,
'appsec.stackTrace.maxDepth': 32,
'appsec.stackTrace.maxStackTraces': 2,
'appsec.wafTimeout': 5e3, // µs
baggageMaxBytes: 8192,
baggageMaxItems: 64,
baggageTagKeys: 'user.id,session.id,account.id',
clientIpEnabled: false,
clientIpHeader: null,
'cloudPayloadTagging.requestsEnabled': false,
'cloudPayloadTagging.responsesEnabled': false,
'cloudPayloadTagging.maxDepth': 10,
'cloudPayloadTagging.rules': [],
'crashtracking.enabled': true,
'codeOriginForSpans.enabled': true,
'codeOriginForSpans.experimental.exit_spans.enabled': false,
dbmPropagationMode: 'disabled',
'dogstatsd.hostname': '127.0.0.1',
'dogstatsd.port': '8125',
dsmEnabled: false,
'dynamicInstrumentation.captureTimeoutMs': 15,
'dynamicInstrumentation.enabled': false,
'dynamicInstrumentation.probeFile': undefined,
'dynamicInstrumentation.redactedIdentifiers': [],
'dynamicInstrumentation.redactionExcludedIdentifiers': [],
'dynamicInstrumentation.uploadIntervalSeconds': 1,
env: undefined,
'experimental.aiguard.enabled': false,
'experimental.aiguard.endpoint': undefined,
'experimental.aiguard.maxMessagesLength': 16,
'experimental.aiguard.maxContentSize': 512 * 1024,
'experimental.aiguard.timeout': 10_000, // ms
'experimental.enableGetRumData': false,
'experimental.exporter': undefined,
'experimental.flaggingProvider.enabled': false,
'experimental.flaggingProvider.initializationTimeoutMs': 30_000,
flushInterval: 2000,
flushMinSpans: 1000,
gitMetadataEnabled: true,
graphqlErrorExtensions: [],
'grpc.client.error.statuses': GRPC_CLIENT_ERROR_STATUSES,
'grpc.server.error.statuses': GRPC_SERVER_ERROR_STATUSES,
headerTags: [],
'heapSnapshot.count': 0,
'heapSnapshot.destination': '',
'heapSnapshot.interval': 3600,
hostname: '127.0.0.1',
'iast.dbRowsToTaint': 1,
'iast.deduplicationEnabled': true,
'iast.enabled': false,
'iast.maxConcurrentRequests': 2,
'iast.maxContextOperations': 2,
'iast.redactionEnabled': true,
'iast.redactionNamePattern': null,
'iast.redactionValuePattern': null,
'iast.requestSampling': 30,
'iast.securityControlsConfiguration': null,
'iast.telemetryVerbosity': 'INFORMATION',
'iast.stackTrace.enabled': true,
injectionEnabled: [],
'installSignature.id': null,
'installSignature.time': null,
'installSignature.type': null,
instrumentationSource: 'manual',
injectForce: null,
isAzureFunction: false,
isCiVisibility: false,
isEarlyFlakeDetectionEnabled: false,
isFlakyTestRetriesEnabled: false,
flakyTestRetriesCount: 5,
isGCPFunction: false,
isGCPPubSubPushSubscriptionEnabled: true,
isGitUploadEnabled: false,
isIntelligentTestRunnerEnabled: false,
isManualApiEnabled: false,
'langchain.spanCharLimit': 128,
'langchain.spanPromptCompletionSampleRate': 1,
'llmobs.agentlessEnabled': undefined,
'llmobs.enabled': false,
'llmobs.mlApp': undefined,
ciVisibilityTestSessionName: '',
ciVisAgentlessLogSubmissionEnabled: false,
legacyBaggageEnabled: true,
isTestDynamicInstrumentationEnabled: false,
isServiceUserProvided: false,
testManagementAttemptToFixRetries: 20,
isTestManagementEnabled: false,
isImpactedTestsEnabled: false,
logInjection: true,
otelLogsEnabled: false,
otelUrl: undefined,
otelLogsUrl: undefined, // Will be computed using agent host
otelHeaders: undefined,
otelLogsHeaders: '',
otelProtocol: 'http/protobuf',
otelLogsProtocol: 'http/protobuf',
otelLogsTimeout: 10_000,
otelTimeout: 10_000,
otelBatchTimeout: 5000,
otelMaxExportBatchSize: 512,
otelMaxQueueSize: 2048,
otelMetricsEnabled: false,
otelMetricsUrl: undefined, // Will be computed using agent host
otelMetricsHeaders: '',
otelMetricsProtocol: 'http/protobuf',
otelMetricsTimeout: 10_000,
otelMetricsExportTimeout: 7500,
otelMetricsExportInterval: 10_000,
otelMetricsTemporalityPreference: 'DELTA', // DELTA, CUMULATIVE, or LOWMEMORY
lookup: undefined,
inferredProxyServicesEnabled: false,
memcachedCommandEnabled: false,
middlewareTracingEnabled: true,
openAiLogsEnabled: false,
'openai.spanCharLimit': 128,
peerServiceMapping: {},
plugins: true,
port: '8126',
'profiling.enabled': undefined,
'propagateProcessTags.enabled': undefined,
'profiling.exporters': 'agent',
'profiling.sourceMap': true,
'profiling.longLivedThreshold': undefined,
protocolVersion: '0.4',
queryStringObfuscation: qsRegex,
'remoteConfig.enabled': true,
'remoteConfig.pollInterval': 5, // seconds
reportHostname: false,
resourceRenamingEnabled: false,
'runtimeMetrics.enabled': false,
'runtimeMetrics.eventLoop': true,
'runtimeMetrics.gc': true,
runtimeMetricsRuntimeId: false,
sampleRate: undefined,
'sampler.rateLimit': 100,
'sampler.rules': [],
'sampler.spanSamplingRules': [],
scope: undefined,
service,
serviceMapping: {},
site: 'datadoghq.com',
spanAttributeSchema: 'v0',
spanComputePeerService: false,
spanLeakDebug: 0,
spanRemoveIntegrationFromService: false,
startupLogs: false,
'stats.enabled': false,
tags: {},
tagsHeaderMaxLength: 512,
'telemetry.debug': false,
'telemetry.dependencyCollection': true,
'telemetry.enabled': true,
'telemetry.heartbeatInterval': 60_000,
'telemetry.logCollection': true,
'telemetry.metrics': true,
traceEnabled: true,
traceId128BitGenerationEnabled: true,
traceId128BitLoggingEnabled: true,
tracePropagationExtractFirst: false,
tracePropagationBehaviorExtract: 'continue',
'tracePropagationStyle.inject': ['datadog', 'tracecontext', 'baggage'],
'tracePropagationStyle.extract': ['datadog', 'tracecontext', 'baggage'],
'tracePropagationStyle.otelPropagators': false,
traceWebsocketMessagesEnabled: true,
traceWebsocketMessagesInheritSampling: true,
traceWebsocketMessagesSeparateTraces: true,
tracing: true,
url: undefined,
version: pkg.version,
instrumentation_config_id: undefined,
'vertexai.spanCharLimit': 128,
'vertexai.spanPromptCompletionSampleRate': 1,
'trace.aws.addSpanPointers': true,
'trace.dynamoDb.tablePrimaryKeys': undefined,
'trace.nativeSpanEvents': false
}
'use strict'
const fs = require('fs')
const path = require('path')
const gitPropertiesCommitSHARegex = /git\.commit\.sha=([a-f\d]{40})/
const gitPropertiesRepositoryUrlRegex = /git\.repository_url=([\w\d:@/.-]+)/
const repositoryUrlRegex = /^([\w\d:@/.-]+)$/
const remoteOriginRegex = /^\[remote\s+"origin"\]/i
const gitHeadRefRegex = /ref:\s+(refs\/[A-Za-z0-9._/-]+)/
const commitSHARegex = /^[0-9a-f]{40}$/
function removeUserSensitiveInfo (repositoryUrl) {
try {
// repository URLs can contain username and password, so we want to filter those out
const parsedUrl = new URL(repositoryUrl)
if (parsedUrl.username || parsedUrl.password) {
return `${parsedUrl.origin}${parsedUrl.pathname}`
}
return repositoryUrl
} catch {
// if protocol isn't https, no password will be used
return repositoryUrl
}
}
function getGitMetadataFromGitProperties (gitPropertiesString) {
if (!gitPropertiesString) {
return {}
}
const commitSHAMatch = gitPropertiesString.match(gitPropertiesCommitSHARegex)
const repositoryUrlMatch = gitPropertiesString.match(gitPropertiesRepositoryUrlRegex)
const repositoryUrl = repositoryUrlMatch ? repositoryUrlMatch[1] : undefined
return {
commitSHA: commitSHAMatch ? commitSHAMatch[1] : undefined,
repositoryUrl: removeUserSensitiveInfo(repositoryUrl)
}
}
function getRemoteOriginURL (gitConfigContent) {
if (!gitConfigContent) {
return
}
const lines = gitConfigContent.split('\n')
let index = 0
// find the remote origin section
for (; index < lines.length; index++) {
const line = lines[index]
if (line[0] !== '[') continue // fast path
if (remoteOriginRegex.test(line)) break
}
// find the url key/value in the [remote "origin"] section
index++
for (; index < lines.length; index++) {
const line = lines[index]
if (line[0] === '[') return // abort, section didn't contain a url
const splitAt = line.indexOf('=')
if (splitAt === -1) continue
const key = line.slice(0, splitAt).trim().toLowerCase()
if (key !== 'url') continue
const repositoryUrlValue = line.slice(splitAt + 1).trim()
const repositoryUrlMatch = repositoryUrlValue.match(repositoryUrlRegex)
if (!repositoryUrlMatch) continue
return removeUserSensitiveInfo(repositoryUrlMatch[0])
}
}
function getGitHeadRef (gitHeadContent) {
if (!gitHeadContent) {
return
}
// Extract the ref after 'ref: '
const gitRefMatch = gitHeadContent.match(gitHeadRefRegex)
return gitRefMatch?.[1]
}
function resolveGitHeadSHA (DD_GIT_FOLDER_PATH) {
const gitHeadPath = path.join(DD_GIT_FOLDER_PATH, 'HEAD')
try {
const gitHeadContent = fs.readFileSync(gitHeadPath, 'utf8')
if (!gitHeadContent) {
return
}
const headContent = gitHeadContent.trim()
// Handle detached head case
if (commitSHARegex.test(headContent)) {
return headContent
}
// Handle ref case - extract the ref and read the SHA from the ref file
const gitHeadRef = getGitHeadRef(headContent)
if (!gitHeadRef) {
return
}
const gitHeadRefPath = path.join(DD_GIT_FOLDER_PATH, gitHeadRef)
const gitHeadRefContent = fs.readFileSync(gitHeadRefPath, 'utf8')
if (gitHeadRefContent) {
const headRefContent = gitHeadRefContent.trim()
if (commitSHARegex.test(headRefContent)) {
return headRefContent
}
}
} catch {}
}
module.exports = {
getGitMetadataFromGitProperties,
removeUserSensitiveInfo,
getGitHeadRef,
getRemoteOriginURL,
resolveGitHeadSHA,
}
'use strict'
/* eslint-disable eslint-rules/eslint-process-env */
const { deprecate } = require('util')
const { supportedConfigurations, aliases, deprecations } = require('./supported-configurations.json')
/**
* Types for environment variable handling.
*
* @typedef {keyof typeof supportedConfigurations} SupportedEnvKey
* @typedef {Partial<typeof process.env> & Partial<Record<SupportedEnvKey, string|undefined>>} TracerEnv
*/
const aliasToCanonical = {}
for (const canonical of Object.keys(aliases)) {
for (const alias of aliases[canonical]) {
if (aliasToCanonical[alias]) {
throw new Error(`The alias ${alias} is already used for ${aliasToCanonical[alias]}.`)
}
aliasToCanonical[alias] = canonical
}
}
const deprecationMethods = {}
for (const deprecation of Object.keys(deprecations)) {
deprecationMethods[deprecation] = deprecate(
() => {},
`The environment variable ${deprecation} is deprecated.` +
(aliasToCanonical[deprecation]
? ` Please use ${aliasToCanonical[deprecation]} instead.`
: ` ${deprecations[deprecation]}`),
`DATADOG_${deprecation}`
)
}
let localStableConfig
let fleetStableConfig
let stableConfigWarnings
let stableConfigLoaded = false
function loadStableConfig () {
stableConfigLoaded = true
// Lazy require to avoid circular dependency at module load time.
const { isInServerlessEnvironment } = require('../serverless')
if (isInServerlessEnvironment()) {
// Stable config is not supported in serverless environments.
return
}
const StableConfig = require('./stable')
const instance = new StableConfig()
localStableConfig = instance.localEntries
fleetStableConfig = instance.fleetEntries
stableConfigWarnings = instance.warnings
}
function getValueFromSource (name, source) {
const value = source[name]
if (value === undefined && aliases[name]) {
for (const alias of aliases[name]) {
if (source[alias] !== undefined) {
return source[alias]
}
}
}
return value
}
function validateAccess (name) {
if ((name.startsWith('DD_') || name.startsWith('OTEL_') || aliasToCanonical[name]) &&
!supportedConfigurations[name]) {
throw new Error(`Missing ${name} env/configuration in "supported-configurations.json" file.`)
}
}
module.exports = {
/**
* Expose raw stable config maps and warnings for consumers that need
* per-source access (e.g. telemetry in Config).
*
* @returns {{ localStableConfig: object, fleetStableConfig: object, stableConfigWarnings: string[] }}
*/
getStableConfigSources () {
if (!stableConfigLoaded) {
loadStableConfig()
}
return {
localStableConfig,
fleetStableConfig,
stableConfigWarnings,
}
},
/**
* Returns the environment variables that are supported by the tracer
* (including all non-Datadog/OTEL specific environment variables).
*
* This should only be called once in config.js to avoid copying the object frequently.
*
* @returns {TracerEnv} The environment variables
*/
getEnvironmentVariables () {
const configs = {}
for (const [key, value] of Object.entries(process.env)) {
// TODO(BridgeAR): Handle telemetry reporting for aliases.
if (key.startsWith('DD_') || key.startsWith('OTEL_') || aliasToCanonical[key]) {
if (supportedConfigurations[key]) {
configs[key] = value
} else if (aliasToCanonical[key] && configs[aliasToCanonical[key]] === undefined) {
// The alias should only be used if the actual configuration is not set
// In case that more than a single alias exist, use the one defined first in our own order
for (const alias of aliases[aliasToCanonical[key]]) {
if (process.env[alias] !== undefined) {
configs[aliasToCanonical[key]] = value
break
}
}
// TODO(BridgeAR) Implement logging. It would have to use a timeout to
// lazily log the message after all loading being done otherwise.
// debug(
// `Missing configuration ${env} in supported-configurations file. The environment variable is ignored.`
// )
}
deprecationMethods[key]?.()
} else {
configs[key] = value
}
}
return configs
},
getEnvironmentVariable (name) {
validateAccess(name)
return getValueFromSource(name, process.env)
},
/**
* Returns the value stored at the given name, assumed to be in environment variable format,
* from the supported env sources (process.env, local stable config, fleet stable config).
* Falls back to aliases if the canonical name is not set.
*
* @param {string} name Environment variable name
* @returns {string|undefined}
* @throws {Error} if the configuration is not supported
*/
getValueFromEnvSources (name) {
validateAccess(name)
if (!stableConfigLoaded) {
loadStableConfig()
}
if (fleetStableConfig !== undefined) {
const fromFleet = getValueFromSource(name, fleetStableConfig)
if (fromFleet !== undefined) {
return fromFleet
}
}
const fromEnv = getValueFromSource(name, process.env)
if (fromEnv !== undefined) {
return fromEnv
}
if (localStableConfig !== undefined) {
return getValueFromSource(name, localStableConfig)
}
},
}

Sorry, the diff of this file is too big to display

'use strict'
const os = require('os')
const fs = require('fs')
const { getEnvironmentVariable } = require('./helper')
class StableConfig {
constructor () {
this.warnings = [] // Logger hasn't been initialized yet, so we can't use log.warn
this.localEntries = {}
this.fleetEntries = {}
this.wasm_loaded = false
const { localConfigPath, fleetConfigPath } = this.#getStableConfigPaths()
const localConfig = this.#readConfigFromPath(localConfigPath)
const fleetConfig = this.#readConfigFromPath(fleetConfigPath)
if (!localConfig && !fleetConfig) {
// Bail out early if files are empty or we can't read them to avoid unnecessary library loading
return
}
// Note: we don't enforce loading because there may be cases where the library is not available and we
// want to avoid breaking the application. In those cases, we will not have the file-based configuration.
let libdatadog
try {
libdatadog = require('@datadog/libdatadog')
this.wasm_loaded = true
} catch {
this.warnings.push('Can\'t load libdatadog library')
return
}
const libconfig = libdatadog.maybeLoad('library_config')
if (libconfig === undefined) {
this.warnings.push('Can\'t load library_config library')
return
}
try {
const configurator = new libconfig.JsConfigurator()
// Intentionally pass through the raw environment variables for reporting.
// eslint-disable-next-line eslint-rules/eslint-process-env
configurator.set_envp(Object.entries(process.env).map(([key, value]) => `${key}=${value}`))
configurator.set_args(process.argv)
configurator.get_configuration(localConfig, fleetConfig).forEach((entry) => {
if (entry.source === 'local_stable_config') {
this.localEntries[entry.name] = entry.value
} else if (entry.source === 'fleet_stable_config') {
this.fleetEntries[entry.name] = entry.value
}
})
} catch (e) {
this.warnings.push(`Error parsing configuration from file: ${e.message}`)
}
}
#readConfigFromPath (path) {
try {
return fs.readFileSync(path, 'utf8')
} catch (err) {
if (err.code !== 'ENOENT') {
this.warnings.push(`Error reading config file at ${path}. ${err.code}: ${err.message}`)
}
return '' // Always return a string for configurator.get_configuration()
}
}
#getStableConfigPaths () {
// TODO(BridgeAR): Remove these environment variables once we have a proper way to test the stable config.
// Allow overriding the paths for testing
let localConfigPath = getEnvironmentVariable('DD_TEST_LOCAL_CONFIG_PATH')
let fleetConfigPath = getEnvironmentVariable('DD_TEST_FLEET_CONFIG_PATH')
switch (os.platform()) {
case 'darwin':
localConfigPath ??= '/opt/datadog-agent/etc/application_monitoring.yaml'
fleetConfigPath ??= '/opt/datadog-agent/etc/managed/datadog-agent/stable/application_monitoring.yaml'
break
case 'win32':
localConfigPath ??= String.raw`C:\ProgramData\Datadog\application_monitoring.yaml`
fleetConfigPath ??= String.raw`C:\ProgramData\Datadog\managed\datadog-agent\stable\application_monitoring.yaml`
break
default:
// Linux and other platforms as fallback
localConfigPath ??= '/etc/datadog-agent/application_monitoring.yaml'
fleetConfigPath ??= '/etc/datadog-agent/managed/datadog-agent/stable/application_monitoring.yaml'
}
return { localConfigPath, fleetConfigPath }
}
}
module.exports = StableConfig
{
"supportedConfigurations": {
"DD_AAS_DOTNET_EXTENSION_VERSION": ["A"],
"DD_ACTION_EXECUTION_ID": ["A"],
"DD_AGENT_HOST": ["A"],
"DD_AGENTLESS_LOG_SUBMISSION_ENABLED": ["A"],
"DD_AGENTLESS_LOG_SUBMISSION_URL": ["A"],
"DD_AI_GUARD_ENABLED": ["A"],
"DD_AI_GUARD_ENDPOINT": ["A"],
"DD_AI_GUARD_MAX_CONTENT_SIZE": ["A"],
"DD_AI_GUARD_MAX_MESSAGES_LENGTH": ["A"],
"DD_AI_GUARD_TIMEOUT": ["A"],
"DD_API_KEY": ["A"],
"DD_API_SECURITY_ENABLED": ["A"],
"DD_API_SECURITY_SAMPLE_DELAY": ["A"],
"DD_API_SECURITY_ENDPOINT_COLLECTION_ENABLED": ["A"],
"DD_API_SECURITY_ENDPOINT_COLLECTION_MESSAGE_LIMIT": ["A"],
"DD_APM_FLUSH_DEADLINE_MILLISECONDS": ["A"],
"DD_APM_TRACING_ENABLED": ["A"],
"DD_APP_KEY": ["A"],
"DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE": ["A"],
"DD_APPSEC_COLLECT_ALL_HEADERS": ["A"],
"DD_APPSEC_ENABLED": ["A"],
"DD_APPSEC_GRAPHQL_BLOCKED_TEMPLATE_JSON": ["A"],
"DD_APPSEC_HEADER_COLLECTION_REDACTION_ENABLED": ["A"],
"DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML": ["A"],
"DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON": ["A"],
"DD_APPSEC_MAX_COLLECTED_HEADERS": ["A"],
"DD_APPSEC_MAX_STACK_TRACE_DEPTH": ["A"],
"DD_APPSEC_MAX_STACK_TRACES": ["A"],
"DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP": ["A"],
"DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP": ["A"],
"DD_APPSEC_RASP_COLLECT_REQUEST_BODY": ["A"],
"DD_APPSEC_RASP_ENABLED": ["A"],
"DD_APPSEC_RULES": ["A"],
"DD_APPSEC_SCA_ENABLED": ["A"],
"DD_APPSEC_STACK_TRACE_ENABLED": ["A"],
"DD_APPSEC_TRACE_RATE_LIMIT": ["A"],
"DD_APPSEC_WAF_TIMEOUT": ["A"],
"DD_AZURE_RESOURCE_GROUP": ["A"],
"DD_CIVISIBILITY_AGENTLESS_ENABLED": ["A"],
"DD_CIVISIBILITY_AGENTLESS_URL": ["A"],
"DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER": ["A"],
"DD_CIVISIBILITY_DANGEROUSLY_FORCE_COVERAGE": ["A"],
"DD_CIVISIBILITY_DANGEROUSLY_FORCE_TEST_SKIPPING": ["A"],
"DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED": ["A"],
"DD_CIVISIBILITY_ENABLED": ["A"],
"DD_CIVISIBILITY_FLAKY_RETRY_COUNT": ["A"],
"DD_CIVISIBILITY_FLAKY_RETRY_ENABLED": ["A"],
"DD_CIVISIBILITY_GIT_UNSHALLOW_ENABLED": ["A"],
"DD_CIVISIBILITY_GIT_UPLOAD_ENABLED": ["A"],
"DD_CIVISIBILITY_IMPACTED_TESTS_DETECTION_ENABLED": ["A"],
"DD_CIVISIBILITY_ITR_ENABLED": ["A"],
"DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS": ["A"],
"DD_CIVISIBILITY_MANUAL_API_ENABLED": ["A"],
"DD_CIVISIBILITY_TEST_COMMAND": ["A"],
"DD_CIVISIBILITY_TEST_MODULE_ID": ["A"],
"DD_CIVISIBILITY_TEST_SESSION_ID": ["A"],
"DD_CODE_ORIGIN_FOR_SPANS_ENABLED": ["A"],
"DD_CODE_ORIGIN_FOR_SPANS_EXPERIMENTAL_EXIT_SPANS_ENABLED": ["A"],
"DD_CRASHTRACKING_ENABLED": ["A"],
"DD_CUSTOM_TRACE_ID": ["A"],
"DD_DATA_STREAMS_ENABLED": ["A"],
"DD_DBM_PROPAGATION_MODE": ["A"],
"DD_DOGSTATSD_HOST": ["A"],
"DD_DOGSTATSD_PORT": ["A"],
"DD_DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT_MS": ["A"],
"DD_DYNAMIC_INSTRUMENTATION_ENABLED": ["A"],
"DD_DYNAMIC_INSTRUMENTATION_PROBE_FILE": ["A"],
"DD_DYNAMIC_INSTRUMENTATION_REDACTED_IDENTIFIERS": ["A"],
"DD_DYNAMIC_INSTRUMENTATION_REDACTION_EXCLUDED_IDENTIFIERS": ["A"],
"DD_DYNAMIC_INSTRUMENTATION_UPLOAD_INTERVAL_SECONDS": ["A"],
"DD_ENV": ["A"],
"DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED": ["A"],
"DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED": ["A"],
"DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED": ["A"],
"DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_ENABLED": ["A"],
"DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_DIR": ["A"],
"DD_EXTERNAL_ENV": ["A"],
"DD_FLAGGING_PROVIDER_ENABLED": ["A"],
"DD_GIT_BRANCH": ["A"],
"DD_GIT_COMMIT_AUTHOR_DATE": ["A"],
"DD_GIT_COMMIT_AUTHOR_EMAIL": ["A"],
"DD_GIT_COMMIT_AUTHOR_NAME": ["A"],
"DD_GIT_COMMIT_COMMITTER_DATE": ["A"],
"DD_GIT_COMMIT_COMMITTER_EMAIL": ["A"],
"DD_GIT_COMMIT_COMMITTER_NAME": ["A"],
"DD_GIT_COMMIT_MESSAGE": ["A"],
"DD_GIT_COMMIT_SHA": ["A"],
"DD_GIT_PROPERTIES_FILE": ["A"],
"DD_GIT_FOLDER_PATH": ["A"],
"DD_GIT_REPOSITORY_URL": ["A"],
"DD_GIT_TAG": ["A"],
"DD_GIT_PULL_REQUEST_BASE_BRANCH": ["A"],
"DD_GIT_PULL_REQUEST_BASE_BRANCH_SHA": ["A"],
"DD_GIT_COMMIT_HEAD_SHA": ["A"],
"DD_GRPC_CLIENT_ERROR_STATUSES": ["A"],
"DD_GRPC_SERVER_ERROR_STATUSES": ["A"],
"DD_HEAP_SNAPSHOT_COUNT": ["A"],
"DD_HEAP_SNAPSHOT_INTERVAL": ["A"],
"DD_HEAP_SNAPSHOT_DESTINATION": ["A"],
"DD_IAST_DB_ROWS_TO_TAINT": ["A"],
"DD_IAST_DEDUPLICATION_ENABLED": ["A"],
"DD_IAST_ENABLED": ["A"],
"DD_IAST_MAX_CONCURRENT_REQUESTS": ["A"],
"DD_IAST_MAX_CONTEXT_OPERATIONS": ["A"],
"DD_IAST_REDACTION_ENABLED": ["A"],
"DD_IAST_REDACTION_NAME_PATTERN": ["A"],
"DD_IAST_REDACTION_VALUE_PATTERN": ["A"],
"DD_IAST_REQUEST_SAMPLING": ["A"],
"DD_IAST_SECURITY_CONTROLS_CONFIGURATION": ["A"],
"DD_IAST_STACK_TRACE_ENABLED": ["A"],
"DD_IAST_TELEMETRY_VERBOSITY": ["A"],
"DD_INJECT_FORCE": ["A"],
"DD_INJECTION_ENABLED": ["A"],
"DD_ENABLE_NX_SERVICE_NAME": ["A"],
"DD_INSTRUMENTATION_CONFIG_ID": ["A"],
"DD_INSTRUMENTATION_INSTALL_ID": ["A"],
"DD_INSTRUMENTATION_INSTALL_TIME": ["A"],
"DD_INSTRUMENTATION_INSTALL_TYPE": ["A"],
"DD_INSTRUMENTATION_TELEMETRY_ENABLED": ["A"],
"DD_INTERNAL_PROFILING_LONG_LIVED_THRESHOLD": ["A"],
"DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED": ["A"],
"DD_LAMBDA_HANDLER": ["A"],
"DD_LANGCHAIN_SPAN_CHAR_LIMIT": ["A"],
"DD_LANGCHAIN_SPAN_PROMPT_COMPLETION_SAMPLE_RATE": ["A"],
"DD_LLMOBS_AGENTLESS_ENABLED": ["A"],
"DD_LLMOBS_ENABLED": ["A"],
"DD_LLMOBS_ML_APP": ["A"],
"DD_LOG_LEVEL": ["A"],
"DD_LOGS_INJECTION": ["A"],
"DD_LOGS_OTEL_ENABLED": ["A"],
"DD_METRICS_OTEL_ENABLED": ["A"],
"DD_MINI_AGENT_PATH": ["A"],
"DD_OPENAI_LOGS_ENABLED": ["A"],
"DD_OPENAI_SPAN_CHAR_LIMIT": ["A"],
"DD_PIPELINE_EXECUTION_ID": ["A"],
"DD_PLAYWRIGHT_WORKER": ["A"],
"DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED": ["A"],
"DD_PROFILING_CODEHOTSPOTS_ENABLED": ["A"],
"DD_PROFILING_CPU_ENABLED": ["A"],
"DD_PROFILING_DEBUG_SOURCE_MAPS": ["A"],
"DD_PROFILING_DEBUG_UPLOAD_COMPRESSION": ["A"],
"DD_PROFILING_ENABLED": ["A"],
"DD_PROFILING_ENDPOINT_COLLECTION_ENABLED": ["A"],
"DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES": ["A"],
"DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE": ["A"],
"DD_PROFILING_EXPERIMENTAL_OOM_MAX_HEAP_EXTENSION_COUNT": ["A"],
"DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED": ["A"],
"DD_PROFILING_EXPORTERS": ["A"],
"DD_PROFILING_HEAP_ENABLED": ["A"],
"DD_PROFILING_HEAP_SAMPLING_INTERVAL": ["A"],
"DD_PROFILING_PPROF_PREFIX": ["A"],
"DD_PROFILING_PROFILERS": ["A"],
"DD_PROFILING_SOURCE_MAP": ["A"],
"DD_PROFILING_TIMELINE_ENABLED": ["A"],
"DD_PROFILING_UPLOAD_PERIOD": ["A"],
"DD_PROFILING_UPLOAD_TIMEOUT": ["A"],
"DD_PROFILING_V8_PROFILER_BUG_WORKAROUND": ["A"],
"DD_PROFILING_WALLTIME_ENABLED": ["A"],
"DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS": ["A"],
"DD_REMOTE_CONFIGURATION_ENABLED": ["A"],
"DD_RUNTIME_METRICS_ENABLED": ["A"],
"DD_RUNTIME_METRICS_EVENT_LOOP_ENABLED": ["A"],
"DD_RUNTIME_METRICS_GC_ENABLED": ["A"],
"DD_RUNTIME_METRICS_FLUSH_INTERVAL": ["A"],
"DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED": ["A"],
"DD_TRACE_GCP_PUBSUB_PUSH_ENABLED": ["A"],
"DD_SERVICE_MAPPING": ["A"],
"DD_SERVICE": ["A"],
"DD_SITE": ["A"],
"DD_SPAN_SAMPLING_RULES_FILE": ["A"],
"DD_SPAN_SAMPLING_RULES": ["A"],
"DD_TAGS": ["A"],
"DD_TELEMETRY_DEBUG": ["A"],
"DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED": ["A"],
"DD_TELEMETRY_FORWARDER_PATH": ["A"],
"DD_TELEMETRY_HEARTBEAT_INTERVAL": ["A"],
"DD_TELEMETRY_LOG_COLLECTION_ENABLED": ["A"],
"DD_TELEMETRY_METRICS_ENABLED": ["A"],
"DD_TEST_FAILED_TEST_REPLAY_ENABLED": ["A"],
"DD_TEST_FLEET_CONFIG_PATH": ["A"],
"DD_TEST_LOCAL_CONFIG_PATH": ["A"],
"DD_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES": ["A"],
"DD_TEST_MANAGEMENT_ENABLED": ["A"],
"DD_TEST_SESSION_NAME": ["A"],
"DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED": ["A"],
"DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED": ["A"],
"DD_TRACE_AEROSPIKE_ENABLED": ["A"],
"DD_TRACE_AI_ENABLED": ["A"],
"DD_TRACE_ANTHROPIC_ENABLED": ["A"],
"DD_TRACE_AGENT_PORT": ["A"],
"DD_TRACE_AGENT_PROTOCOL_VERSION": ["A"],
"DD_TRACE_AGENT_URL": ["A"],
"DD_TRACE_AMQP10_ENABLED": ["A"],
"DD_TRACE_AMQPLIB_ENABLED": ["A"],
"DD_TRACE_APOLLO_ENABLED": ["A"],
"DD_TRACE_APOLLO_GATEWAY_ENABLED": ["A"],
"DD_TRACE_APOLLO_SERVER_CORE_ENABLED": ["A"],
"DD_TRACE_APOLLO_SERVER_ENABLED": ["A"],
"DD_TRACE_APOLLO_SERVER_EXPRESS_ENABLED": ["A"],
"DD_TRACE_APOLLO_SERVER_FASTIFY_ENABLED": ["A"],
"DD_TRACE_APOLLO_SUBGRAPH_ENABLED": ["A"],
"DD_TRACE_AVSC_ENABLED": ["A"],
"DD_TRACE_AWS_ADD_SPAN_POINTERS": ["A"],
"DD_TRACE_AWS_SDK_AWS_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_AWS_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_BEDROCKRUNTIME_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_BEDROCKRUNTIME_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_CLOUDWATCHLOGS_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_CLOUDWATCHLOGS_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_DYNAMODB_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_DYNAMODB_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_EVENTBRIDGE_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_EVENTBRIDGE_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_KINESIS_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_KINESIS_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_LAMBDA_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_LAMBDA_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_NODE_HTTP_HANDLER_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_REDSHIFT_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_REDSHIFT_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_S3_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_S3_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SFN_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SFN_CLIENT_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SFN_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SMITHY_CLIENT_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SNS_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SNS_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SQS_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SQS_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_STATES_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_STATES_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_STEPFUNCTIONS_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_STEPFUNCTIONS_ENABLED": ["A"],
"DD_TRACE_AXIOS_ENABLED": ["A"],
"DD_TRACE_AZURE_EVENT_HUBS_ENABLED": ["A"],
"DD_TRACE_AZURE_EVENTHUBS_BATCH_LINKS_ENABLED": ["A"],
"DD_TRACE_AZURE_FUNCTIONS_ENABLED": ["A"],
"DD_TRACE_AZURE_SERVICE_BUS_ENABLED": ["A"],
"DD_TRACE_AZURE_SERVICEBUS_BATCH_LINKS_ENABLED": ["A"],
"DD_TRACE_BAGGAGE_MAX_BYTES": ["A"],
"DD_TRACE_BAGGAGE_MAX_ITEMS": ["A"],
"DD_TRACE_BAGGAGE_TAG_KEYS": ["A"],
"DD_TRACE_BEAUTIFUL_LOGS": ["A"],
"DD_TRACE_BLUEBIRD_ENABLED": ["A"],
"DD_TRACE_BULLMQ_ENABLED": ["A"],
"DD_TRACE_BODY_PARSER_ENABLED": ["A"],
"DD_TRACE_BSON_ENABLED": ["A"],
"DD_TRACE_BUNYAN_ENABLED": ["A"],
"DD_TRACE_CASSANDRA_DRIVER_ENABLED": ["A"],
"DD_TRACE_CHILD_PROCESS_ENABLED": ["A"],
"DD_TRACE_CLIENT_IP_ENABLED": ["A"],
"DD_TRACE_CLIENT_IP_HEADER": ["A"],
"DD_TRACE_CLOUD_PAYLOAD_TAGGING_MAX_DEPTH": ["A"],
"DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING": ["A"],
"DD_TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING": ["A"],
"DD_TRACE_COLLECTIONS_ENABLED": ["A"],
"DD_TRACE_COMMONPLUGIN_ENABLED": ["A"],
"DD_TRACE_CONFLUENTINC_KAFKA_JAVASCRIPT_ENABLED": ["A"],
"DD_TRACE_CONNECT_ENABLED": ["A"],
"DD_TRACE_COOKIE_ENABLED": ["A"],
"DD_TRACE_COOKIE_PARSER_ENABLED": ["A"],
"DD_TRACE_COUCHBASE_ENABLED": ["A"],
"DD_TRACE_CRYPTO_ENABLED": ["A"],
"DD_TRACE_CUCUMBER_CUCUMBER_ENABLED": ["A"],
"DD_TRACE_CUCUMBER_ENABLED": ["A"],
"DD_TRACE_CYPRESS_ENABLED": ["A"],
"DD_TRACE_DD_TRACE_API_ENABLED": ["A"],
"DD_TRACE_DEBUG": ["A"],
"DD_TRACE_DISABLED_INSTRUMENTATIONS": ["A"],
"DD_TRACE_DISABLED_PLUGINS": ["A"],
"DD_TRACE_DNS_ENABLED": ["A"],
"DD_TRACE_DYNAMODB_TABLE_PRIMARY_KEYS": ["A"],
"DD_TRACE_ELASTIC_ELASTICSEARCH_ENABLED": ["A"],
"DD_TRACE_ELASTIC_TRANSPORT_ENABLED": ["A"],
"DD_TRACE_ELASTICSEARCH_ENABLED": ["A"],
"DD_TRACE_ENABLED": ["A"],
"DD_TRACE_ENCODING_DEBUG": ["A"],
"DD_TRACE_EXPERIMENTAL_B3_ENABLED": ["A"],
"DD_TRACE_EXPERIMENTAL_EXPORTER": ["A"],
"DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED": ["A"],
"DD_TRACE_EXPERIMENTAL_SPAN_COUNTS": ["A"],
"DD_TRACE_EXPERIMENTAL_STATE_TRACKING": ["A"],
"DD_TRACE_EXPRESS_ENABLED": ["A"],
"DD_TRACE_EXPRESS_MONGO_SANITIZE_ENABLED": ["A"],
"DD_TRACE_EXPRESS_SESSION_ENABLED": ["A"],
"DD_TRACE_FASTIFY_ENABLED": ["A"],
"DD_TRACE_FETCH_ENABLED": ["A"],
"DD_TRACE_FIND_MY_WAY_ENABLED": ["A"],
"DD_TRACE_FLUSH_INTERVAL": ["A"],
"DD_TRACE_FS_ENABLED": ["A"],
"DD_TRACE_GENERIC_POOL_ENABLED": ["A"],
"DD_TRACE_GIT_METADATA_ENABLED": ["A"],
"DD_TRACE_GLOBAL_TAGS": ["A"],
"DD_TRACE_GOOGLE_CLOUD_PUBSUB_ENABLED": ["A"],
"DD_TRACE_GOOGLE_CLOUD_VERTEXAI_ENABLED": ["A"],
"DD_TRACE_GOOGLE_GAX_ENABLED": ["A"],
"DD_TRACE_GOOGLE_GENAI_ENABLED": ["A"],
"DD_TRACE_GRAPHQL_ENABLED": ["A"],
"DD_TRACE_GRAPHQL_ERROR_EXTENSIONS": ["A"],
"DD_TRACE_GRAPHQL_TAG_ENABLED": ["A"],
"DD_TRACE_GRAPHQL_TOOLS_ENABLED": ["A"],
"DD_TRACE_GRAPHQL_TOOLS_EXECUTOR_ENABLED": ["A"],
"DD_TRACE_GRAPHQL_YOGA_ENABLED": ["A"],
"DD_TRACE_GRPC_ENABLED": ["A"],
"DD_TRACE_GRPC_GRPC_JS_ENABLED": ["A"],
"DD_TRACE_GRPC_PROTO_LOADER_ENABLED": ["A"],
"DD_TRACE_HANDLEBARS_ENABLED": ["A"],
"DD_TRACE_HAPI_BOOM_ENABLED": ["A"],
"DD_TRACE_HAPI_ENABLED": ["A"],
"DD_TRACE_HAPI_HAPI_ENABLED": ["A"],
"DD_TRACE_HEADER_TAGS": ["A"],
"DD_TRACE_HONO_ENABLED": ["A"],
"DD_TRACE_HTTP_ENABLED": ["A"],
"DD_TRACE_HTTP2_ENABLED": ["A"],
"DD_TRACE_HTTPS_ENABLED": ["A"],
"DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED": ["A"],
"DD_TRACE_IOREDIS_ENABLED": ["A"],
"DD_TRACE_IOVALKEY_ENABLED": ["A"],
"DD_TRACE_JEST_CIRCUS_ENABLED": ["A"],
"DD_TRACE_JEST_CONFIG_ENABLED": ["A"],
"DD_TRACE_JEST_CORE_ENABLED": ["A"],
"DD_TRACE_JEST_ENABLED": ["A"],
"DD_TRACE_JEST_ENVIRONMENT_JSDOM_ENABLED": ["A"],
"DD_TRACE_JEST_ENVIRONMENT_NODE_ENABLED": ["A"],
"DD_TRACE_JEST_GLOBALS_ENABLED": ["A"],
"DD_TRACE_JEST_REPORTERS_ENABLED": ["A"],
"DD_TRACE_JEST_RUNTIME_ENABLED": ["A"],
"DD_TRACE_JEST_TEST_SEQUENCER_ENABLED": ["A"],
"DD_TRACE_JEST_TRANSFORM_ENABLED": ["A"],
"DD_TRACE_JEST_WORKER_ENABLED": ["A"],
"DD_TRACE_KAFKAJS_ENABLED": ["A"],
"DD_TRACE_KNEX_ENABLED": ["A"],
"DD_TRACE_KOA_ENABLED": ["A"],
"DD_TRACE_KOA_ROUTE_ENABLED": ["A"],
"DD_TRACE_KOA_ROUTER_ENABLED": ["A"],
"DD_TRACE_KOA_WEBSOCKET_ENABLED": ["A"],
"DD_TRACE_LANGCHAIN_ANTHROPIC_ENABLED": ["A"],
"DD_TRACE_LANGCHAIN_COHERE_ENABLED": ["A"],
"DD_TRACE_LANGCHAIN_CORE_ENABLED": ["A"],
"DD_TRACE_LANGCHAIN_ENABLED": ["A"],
"DD_TRACE_LANGCHAIN_GOOGLE_GENAI_ENABLED": ["A"],
"DD_TRACE_LANGCHAIN_OPENAI_ENABLED": ["A"],
"DD_TRACE_LDAPJS_ENABLED": ["A"],
"DD_TRACE_LDAPJS_PROMISE_ENABLED": ["A"],
"DD_TRACE_LEGACY_BAGGAGE_ENABLED": ["A"],
"DD_TRACE_LIMITD_CLIENT_ENABLED": ["A"],
"DD_TRACE_LODASH_ENABLED": ["A"],
"DD_TRACE_LOG_LEVEL": ["A"],
"DD_TRACE_LOOPBACK_ENABLED": ["A"],
"DD_TRACE_MARIADB_ENABLED": ["A"],
"DD_TRACE_MEMCACHED_COMMAND_ENABLED": ["A"],
"DD_TRACE_MEMCACHED_ENABLED": ["A"],
"DD_TRACE_MICROGATEWAY_CORE_ENABLED": ["A"],
"DD_TRACE_MIDDIE_ENABLED": ["A"],
"DD_TRACE_MIDDLEWARE_TRACING_ENABLED": ["A"],
"DD_TRACE_MOCHA_EACH_ENABLED": ["A"],
"DD_TRACE_MOCHA_ENABLED": ["A"],
"DD_TRACE_MOLECULER_ENABLED": ["A"],
"DD_TRACE_MONGODB_CORE_ENABLED": ["A"],
"DD_TRACE_MONGODB_ENABLED": ["A"],
"DD_TRACE_MONGODB_HEARTBEAT_ENABLED": ["A"],
"DD_TRACE_MONGOOSE_ENABLED": ["A"],
"DD_TRACE_MQUERY_ENABLED": ["A"],
"DD_TRACE_MULTER_ENABLED": ["A"],
"DD_TRACE_MYSQL_ENABLED": ["A"],
"DD_TRACE_MYSQL2_ENABLED": ["A"],
"DD_TRACE_NATIVE_SPAN_EVENTS": ["A"],
"DD_TRACE_NET_ENABLED": ["A"],
"DD_TRACE_NEXT_ENABLED": ["A"],
"DD_TRACE_NODE_CHILD_PROCESS_ENABLED": ["A"],
"DD_TRACE_NODE_REDIS_CLIENT_ENABLED": ["A"],
"DD_TRACE_NODE_SERIALIZE_ENABLED": ["A"],
"DD_TRACE_NYC_ENABLED": ["A"],
"DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP": ["A"],
"DD_TRACE_OPENAI_ENABLED": ["A"],
"DD_TRACE_OPENSEARCH_ENABLED": ["A"],
"DD_TRACE_OPENSEARCH_PROJECT_OPENSEARCH_ENABLED": ["A"],
"DD_TRACE_OPENTELEMETRY_SDK_TRACE_NODE_ENABLED": ["A"],
"DD_TRACE_ORACLEDB_ENABLED": ["A"],
"DD_TRACE_OTEL_ENABLED": ["A"],
"DD_TRACE_PARTIAL_FLUSH_MIN_SPANS": ["A"],
"DD_TRACE_PASSPORT_ENABLED": ["A"],
"DD_TRACE_PASSPORT_HTTP_ENABLED": ["A"],
"DD_TRACE_PASSPORT_LOCAL_ENABLED": ["A"],
"DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED": ["A"],
"DD_TRACE_PEER_SERVICE_MAPPING": ["A"],
"DD_TRACE_PG_CURSOR_ENABLED": ["A"],
"DD_TRACE_PG_ENABLED": ["A"],
"DD_TRACE_PG_NATIVE_ENABLED": ["A"],
"DD_TRACE_PG_QUERY_STREAM_ENABLED": ["A"],
"DD_TRACE_PINO_ENABLED": ["A"],
"DD_TRACE_PINO_PRETTY_ENABLED": ["A"],
"DD_TRACE_PLAYWRIGHT_CORE_ENABLED": ["A"],
"DD_TRACE_PLAYWRIGHT_ENABLED": ["A"],
"DD_TRACE_PLAYWRIGHT_TEST_ENABLED": ["A"],
"DD_TRACE_PRISMA_ENABLED": ["A"],
"DD_TRACE_PROCESS_ENABLED": ["A"],
"DD_TRACE_PROMISE_ENABLED": ["A"],
"DD_TRACE_PROMISE_JS_ENABLED": ["A"],
"DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT": ["A"],
"DD_TRACE_PROPAGATION_EXTRACT_FIRST": ["A"],
"DD_TRACE_PROPAGATION_STYLE_EXTRACT": ["A"],
"DD_TRACE_PROPAGATION_STYLE_INJECT": ["A"],
"DD_TRACE_PROPAGATION_STYLE": ["A"],
"DD_TRACE_PROTOBUFJS_ENABLED": ["A"],
"DD_TRACE_PUG_ENABLED": ["A"],
"DD_TRACE_Q_ENABLED": ["A"],
"DD_TRACE_RATE_LIMIT": ["A"],
"DD_TRACE_REACT_DOM_ENABLED": ["A"],
"DD_TRACE_REACT_ENABLED": ["A"],
"DD_TRACE_REDIS_CLIENT_ENABLED": ["A"],
"DD_TRACE_REDIS_ENABLED": ["A"],
"DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED": ["A"],
"DD_TRACE_REPORT_HOSTNAME": ["A"],
"DD_TRACE_REQUEST_ENABLED": ["A"],
"DD_TRACE_RESOURCE_RENAMING_ENABLED": ["A"],
"DD_TRACE_RESTIFY_ENABLED": ["A"],
"DD_TRACE_RHEA_ENABLED": ["A"],
"DD_TRACE_ROUTER_ENABLED": ["A"],
"DD_TRACE_SAMPLE_RATE": ["A"],
"DD_TRACE_SAMPLING_RULES": ["A"],
"DD_TRACE_SCOPE": ["A"],
"DD_TRACE_SELENIUM_ENABLED": ["A"],
"DD_TRACE_SELENIUM_WEBDRIVER_ENABLED": ["A"],
"DD_TRACE_SEQUELIZE_ENABLED": ["A"],
"DD_TRACE_SHAREDB_ENABLED": ["A"],
"DD_TRACE_SMITHY_SMITHY_CLIENT_ENABLED": ["A"],
"DD_TRACE_SPAN_ATTRIBUTE_SCHEMA": ["A"],
"DD_TRACE_SPAN_LEAK_DEBUG": ["A"],
"DD_TRACE_SQLITE3_ENABLED": ["A"],
"DD_TRACE_STARTUP_LOGS": ["A"],
"DD_TRACE_STATS_COMPUTATION_ENABLED": ["A"],
"DD_TRACE_SUFFIXPLUGIN_ENABLED": ["A"],
"DD_TRACE_TAGS": ["A"],
"DD_TRACE_TEDIOUS_ENABLED": ["A"],
"DD_TRACE_UNDICI_ENABLED": ["A"],
"DD_TRACE_URL_ENABLED": ["A"],
"DD_TRACE_VITEST_ENABLED": ["A"],
"DD_TRACE_VITEST_RUNNER_ENABLED": ["A"],
"DD_TRACE_VM_ENABLED": ["A"],
"DD_TRACE_WEBSOCKET_MESSAGES_ENABLED":["A"],
"DD_TRACE_WEBSOCKET_MESSAGES_INHERIT_SAMPLING": ["A"],
"DD_TRACE_WEBSOCKET_MESSAGES_SEPARATE_TRACES":["A"],
"DD_TRACE_WHEN_ENABLED": ["A"],
"DD_TRACE_WINSTON_ENABLED": ["A"],
"DD_TRACE_WORKERPOOL_ENABLED": ["A"],
"DD_TRACE_WS_ENABLED": ["A"],
"DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH": ["A"],
"DD_TRACING_ENABLED": ["A"],
"DD_VERSION": ["A"],
"DD_VERTEXAI_SPAN_CHAR_LIMIT": ["A"],
"DD_VERTEXAI_SPAN_PROMPT_COMPLETION_SAMPLE_RATE": ["A"],
"DD_VITEST_WORKER": ["A"],
"OTEL_LOG_LEVEL": ["A"],
"OTEL_LOGS_EXPORTER": ["A"],
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": ["A"],
"OTEL_EXPORTER_OTLP_LOGS_HEADERS": ["A"],
"OTEL_EXPORTER_OTLP_LOGS_PROTOCOL": ["A"],
"OTEL_EXPORTER_OTLP_LOGS_TIMEOUT": ["A"],
"OTEL_EXPORTER_OTLP_ENDPOINT": ["A"],
"OTEL_EXPORTER_OTLP_HEADERS": ["A"],
"OTEL_EXPORTER_OTLP_PROTOCOL": ["A"],
"OTEL_EXPORTER_OTLP_TIMEOUT": ["A"],
"OTEL_BSP_SCHEDULE_DELAY": ["A"],
"OTEL_BSP_MAX_EXPORT_BATCH_SIZE": ["A"],
"OTEL_BSP_MAX_QUEUE_SIZE": ["A"],
"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": ["A"],
"OTEL_EXPORTER_OTLP_METRICS_HEADERS": ["A"],
"OTEL_EXPORTER_OTLP_METRICS_PROTOCOL": ["A"],
"OTEL_EXPORTER_OTLP_METRICS_TIMEOUT": ["A"],
"OTEL_METRIC_EXPORT_INTERVAL": ["A"],
"OTEL_METRIC_EXPORT_TIMEOUT": ["A"],
"OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE": ["A"],
"OTEL_METRICS_EXPORTER": ["A"],
"OTEL_PROPAGATORS": ["A"],
"OTEL_RESOURCE_ATTRIBUTES": ["A"],
"OTEL_SDK_DISABLED": ["A"],
"OTEL_SERVICE_NAME": ["A"],
"OTEL_TRACES_EXPORTER": ["A"],
"OTEL_TRACES_SAMPLER_ARG": ["A"],
"OTEL_TRACES_SAMPLER": ["A"]
},
"aliases": {
"DD_AGENT_HOST": ["DD_TRACE_AGENT_HOSTNAME"],
"DD_API_KEY": ["DATADOG_API_KEY"],
"DD_API_SECURITY_ENABLED": ["DD_EXPERIMENTAL_API_SECURITY_ENABLED"],
"DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE": ["DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING"],
"DD_DOGSTATSD_HOST": ["DD_DOGSTATSD_HOSTNAME"],
"DD_INSTRUMENTATION_TELEMETRY_ENABLED": ["DD_TRACE_TELEMETRY_ENABLED"],
"DD_PROFILING_CODEHOTSPOTS_ENABLED": ["DD_PROFILING_EXPERIMENTAL_CODEHOTSPOTS_ENABLED"],
"DD_PROFILING_CPU_ENABLED": ["DD_PROFILING_EXPERIMENTAL_CPU_ENABLED"],
"DD_PROFILING_ENABLED": ["DD_EXPERIMENTAL_PROFILING_ENABLED"],
"DD_PROFILING_ENDPOINT_COLLECTION_ENABLED": ["DD_PROFILING_EXPERIMENTAL_ENDPOINT_COLLECTION_ENABLED"],
"DD_PROFILING_TIMELINE_ENABLED": ["DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED"],
"DD_REMOTE_CONFIGURATION_ENABLED": ["DD_REMOTE_CONFIG_ENABLED" ],
"DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED": ["DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED"],
"DD_SERVICE": ["DD_SERVICE_NAME"],
"DD_TRACE_AGENT_URL": ["DD_TRACE_URL"]
},
"deprecations": {
"DD_PROFILING_EXPERIMENTAL_ENDPOINT_COLLECTION_ENABLED": "DD_PROFILING_ENDPOINT_COLLECTION_ENABLED",
"DD_PROFILING_EXPERIMENTAL_CPU_ENABLED": "DD_PROFILING_CPU_ENABLED",
"DD_EXPERIMENTAL_PROFILING_ENABLED": "DD_PROFILING_ENABLED",
"DD_PROFILING_EXPERIMENTAL_CODEHOTSPOTS_ENABLED": "DD_PROFILING_CODEHOTSPOTS_ENABLED",
"DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED": "DD_PROFILING_TIMELINE_ENABLED",
"DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED": "DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED"
}
}
+6
-6

@@ -7,3 +7,3 @@ 'use strict'

const log = require('../packages/dd-trace/src/log')
const { getEnvironmentVariable } = require('../packages/dd-trace/src/config-helper')
const { getEnvironmentVariable, getValueFromEnvSources } = require('../packages/dd-trace/src/config/helper')

@@ -31,5 +31,5 @@ const PACKAGE_MANAGERS = ['npm', 'yarn', 'pnpm']

if (getEnvironmentVariable('MOCHA_WORKER_ID')) return 'mocha'
if (getEnvironmentVariable('DD_PLAYWRIGHT_WORKER')) return 'playwright'
if (getValueFromEnvSources('DD_PLAYWRIGHT_WORKER')) return 'playwright'
if (getEnvironmentVariable('TINYPOOL_WORKER_ID')) return 'vitest'
if (getEnvironmentVariable('DD_VITEST_WORKER')) return 'vitest'
if (getValueFromEnvSources('DD_VITEST_WORKER')) return 'vitest'
return null

@@ -48,4 +48,4 @@ }

let shouldInit = !isFalse(getEnvironmentVariable('DD_CIVISIBILITY_ENABLED'))
const isAgentlessEnabled = isTrue(getEnvironmentVariable('DD_CIVISIBILITY_AGENTLESS_ENABLED'))
let shouldInit = !isFalse(getValueFromEnvSources('DD_CIVISIBILITY_ENABLED'))
const isAgentlessEnabled = isTrue(getValueFromEnvSources('DD_CIVISIBILITY_AGENTLESS_ENABLED'))

@@ -64,3 +64,3 @@ if (!isTestWorker && isPackageManager()) {

if (isAgentlessEnabled) {
if (getEnvironmentVariable('DD_API_KEY')) {
if (getValueFromEnvSources('DD_API_KEY')) {
baseOptions.experimental = {

@@ -67,0 +67,0 @@ exporter: 'datadog'

@@ -10,3 +10,2 @@ "component","origin","license","copyright"

"@datadog/sketches-js","https://github.com/DataDog/sketches-js","['Apache-2.0']","['DataDog']"
"@datadog/source-map","npm:@datadog/source-map","[]","[]"
"@datadog/wasm-js-rewriter","https://github.com/DataDog/dd-wasm-js-rewriter","['Apache-2.0']","['Datadog Inc.']"

@@ -13,0 +12,0 @@ "@isaacs/ttlcache","https://github.com/isaacs/ttlcache","['BlueOak-1.0.0']","['Isaac Z. Schlueter']"

import * as iitm from 'import-in-the-middle/hook.mjs'
import regexpEscapeModule from './vendor/dist/escape-string-regexp/index.js'
import hooks from './packages/datadog-instrumentations/src/helpers/hooks.js'
import configHelper from './packages/dd-trace/src/config-helper.js'
import configHelper from './packages/dd-trace/src/config/helper.js'
import * as rewriterLoader from './packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs'

@@ -6,0 +6,0 @@ import { isRelativeRequire } from './packages/datadog-instrumentations/src/helpers/shared-utils.js'

{
"name": "dd-trace",
"version": "5.82.0",
"version": "5.83.0",
"description": "Datadog APM tracing client for JavaScript",

@@ -21,57 +21,60 @@ "main": "index.js",

"services": "node ./scripts/install_plugin_modules && node packages/dd-trace/test/setup/services",
"test": "SERVICES=* yarn services && mocha --expose-gc 'packages/dd-trace/test/setup/node.js' 'packages/*/test/**/*.spec.js'",
"test:aiguard": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/dd-trace/test/aiguard/**/*.spec.js\"",
"test": "echo '\nError: The root \"npm test\" command is intentionally disabled.\n\nInstead, run specific test suites:\n - npm run test:trace:core\n - npm run test:appsec\n - etc.\n\nOr run individual test files:\n npx mocha path/to/test.spec.js\n\nSee CONTRIBUTING.md (Testing section) for more details.\n' && exit 1",
"test:aiguard": "mocha packages/dd-trace/test/aiguard/**/*.spec.js",
"test:aiguard:ci": "nyc --no-clean --include \"packages/dd-trace/src/aiguard/**/*.js\" -- npm run test:aiguard",
"test:appsec": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" --exclude \"packages/dd-trace/test/appsec/**/*.plugin.spec.js\" \"packages/dd-trace/test/appsec/**/*.spec.js\"",
"test:appsec": "mocha --exclude \"packages/dd-trace/test/appsec/**/*.plugin.spec.js\" \"packages/dd-trace/test/appsec/**/*.spec.js\"",
"test:appsec:ci": "nyc --no-clean --include \"packages/dd-trace/src/appsec/**/*.js\" --exclude \"packages/dd-trace/test/appsec/**/*.plugin.spec.js\" -- npm run test:appsec",
"test:appsec:plugins": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/dd-trace/test/appsec/**/*.@($(echo $PLUGINS)).plugin.spec.js\"",
"test:appsec:plugins": "mocha \"packages/dd-trace/test/appsec/**/*.@(${PLUGINS}).plugin.spec.js\"",
"test:appsec:plugins:ci": "yarn services && nyc --no-clean --include \"packages/dd-trace/src/appsec/**/*.js\" -- npm run test:appsec:plugins",
"test:debugger": "mocha -r 'packages/dd-trace/test/setup/mocha.js' 'packages/dd-trace/test/debugger/**/*.spec.js'",
"test:debugger:ci": "nyc --no-clean --include 'packages/dd-trace/src/debugger/**/*.js' -- npm run test:debugger",
"test:debugger": "mocha packages/dd-trace/test/debugger/**/*.spec.js",
"test:debugger:ci": "nyc --no-clean --include \"packages/dd-trace/src/debugger/**/*.js\" -- npm run test:debugger",
"test:eslint-rules": "node eslint-rules/*.test.mjs",
"test:trace:core": "node scripts/mocha-parallel-files.js --expose-gc --timeout 30000 --require packages/dd-trace/test/setup/mocha.js -- \"packages/dd-trace/test/*.spec.js\" \"packages/dd-trace/test/{ci-visibility,config,datastreams,encode,exporters,opentelemetry,opentracing,plugins,remote_config,service-naming,standalone,telemetry,external-logger}/**/*.spec.js\"",
"test:trace:core": "node scripts/mocha-parallel-files.js --expose-gc --timeout 30000 -- \"packages/dd-trace/test/*.spec.js\" \"packages/dd-trace/test/{ci-visibility,config,crashtracking,datastreams,encode,exporters,msgpack,opentelemetry,opentracing,payload-tagging,plugins,remote_config,service-naming,standalone,telemetry,external-logger}/**/*.spec.js\"",
"test:trace:core:ci": "nyc --no-clean --include \"packages/dd-trace/src/**/*.js\" -- npm run test:trace:core",
"test:trace:guardrails": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/dd-trace/test/guardrails/**/*.spec.js\"",
"test:trace:guardrails": "mocha packages/dd-trace/test/guardrails/**/*.spec.js",
"test:trace:guardrails:ci": "nyc --no-clean --include \"packages/dd-trace/src/guardrails/**/*.js\" -- npm run test:trace:guardrails",
"test:esbuild": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/datadog-esbuild/test/**/*.spec.js\"",
"test:esbuild": "mocha packages/datadog-esbuild/test/**/*.spec.js",
"test:esbuild:ci": "nyc --no-clean --include \"packages/datadog-esbuild/test/**/*.js\" -- npm run test:esbuild",
"test:instrumentations": "mocha -r 'packages/dd-trace/test/setup/mocha.js' \"packages/datadog-instrumentations/test/@($(echo $PLUGINS)).spec.js\"",
"test:instrumentations:ci": "yarn services && nyc --no-clean --include \"packages/datadog-instrumentations/src/@($(echo $PLUGINS)).js\" --include \"packages/datadog-instrumentations/src/@($(echo $PLUGINS))/**/*.js\" -- npm run test:instrumentations",
"test:instrumentations:misc": "mocha -r 'packages/dd-trace/test/setup/mocha.js' 'packages/datadog-instrumentations/test/*/**/*.spec.js'",
"test:instrumentations:misc:ci": "nyc --no-clean --include 'packages/datadog-instrumentations/src/**/*.js' -- npm run test:instrumentations:misc",
"test:core": "node scripts/mocha-parallel-files.js --expose-gc --timeout 30000 -- \"packages/datadog-core/test/**/*.spec.js\"",
"test:instrumentations": "mocha \"packages/datadog-instrumentations/test/@(${PLUGINS}).spec.js\"",
"test:instrumentations:ci": "yarn services && nyc --no-clean --include \"packages/datadog-instrumentations/src/@(${PLUGINS}).js\" --include \"packages/datadog-instrumentations/src/@(${PLUGINS})/**/*.js\" -- npm run test:instrumentations",
"test:instrumentations:misc": "mocha packages/datadog-instrumentations/test/*/**/*.spec.js",
"test:instrumentations:misc:ci": "nyc --no-clean --include \"packages/datadog-instrumentations/src/**/*.js\" -- npm run test:instrumentations:misc",
"test:core": "node scripts/mocha-parallel-files.js --expose-gc --timeout 30000 -- packages/datadog-core/test/**/*.spec.js",
"test:core:ci": "nyc --no-clean --include \"packages/datadog-core/src/**/*.js\" -- npm run test:core",
"test:lambda": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/dd-trace/test/lambda/**/*.spec.js\"",
"test:code-origin": "mocha packages/datadog-code-origin/test/**/*.spec.js",
"test:code-origin:ci": "nyc --no-clean --include \"packages/datadog-code-origin/**/*.js\" -- npm run test:code-origin",
"test:lambda": "mocha packages/dd-trace/test/lambda/**/*.spec.js",
"test:lambda:ci": "nyc --no-clean --include \"packages/dd-trace/src/lambda/**/*.js\" -- npm run test:lambda",
"test:llmobs:sdk": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" --exclude \"packages/dd-trace/test/llmobs/plugins/**/*.spec.js\" \"packages/dd-trace/test/llmobs/**/*.spec.js\" ",
"test:llmobs:sdk": "mocha --exclude \"packages/dd-trace/test/llmobs/plugins/**/*.spec.js\" \"packages/dd-trace/test/llmobs/**/*.spec.js\"",
"test:llmobs:sdk:ci": "nyc --no-clean --include \"packages/dd-trace/src/llmobs/**/*.js\" -- npm run test:llmobs:sdk",
"test:llmobs:plugins": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/dd-trace/test/llmobs/plugins/@($(echo $PLUGINS))/*.spec.js\"",
"test:llmobs:plugins": "mocha \"packages/dd-trace/test/llmobs/plugins/@(${PLUGINS})/*.spec.js\"",
"test:llmobs:plugins:ci": "yarn services && nyc --no-clean --include \"packages/dd-trace/src/llmobs/**/*.js\" -- npm run test:llmobs:plugins",
"test:openfeature": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/dd-trace/test/openfeature/*.spec.js\"",
"test:openfeature": "mocha packages/dd-trace/test/openfeature/**/*.spec.js",
"test:openfeature:ci": "nyc --no-clean --include \"packages/dd-trace/src/openfeature/**/*.js\" -- npm run test:openfeature",
"test:plugins": "mocha --expose-gc -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/datadog-plugin-@($(echo $PLUGINS))/test/**/@($(echo ${SPEC:-'*'}))*.spec.js\"",
"test:plugins:ci": "yarn services && nyc --no-clean --include \"packages/datadog-plugin-@($(echo $PLUGINS))/src/**/*.js\" -- npm run test:plugins",
"test:plugins:ci:flaky": "yarn services && nyc --no-clean --include \"packages/datadog-plugin-@($(echo $PLUGINS))/src/**/*.js\" -- npm run test:plugins -- --bail --retries 2",
"test:plugins": "node --expose-gc ./node_modules/mocha/bin/mocha.js \"packages/datadog-plugin-@(${PLUGINS})/test/**/${SPEC:-*}*.spec.js\"",
"test:plugins:ci": "yarn services && nyc --no-clean --include \"packages/datadog-plugin-@(${PLUGINS})/src/**/*.js\" -- npm run test:plugins",
"test:plugins:ci:flaky": "yarn services && nyc --no-clean --include \"packages/datadog-plugin-@(${PLUGINS})/src/**/*.js\" -- npm run test:plugins -- --bail --retries 2",
"test:plugins:upstream": "node ./packages/dd-trace/test/plugins/suite.js",
"test:profiler": "node scripts/mocha-parallel-files.js --expose-gc --timeout 30000 --require packages/dd-trace/test/setup/mocha.js -- \"packages/dd-trace/test/profiling/**/*.spec.js\"",
"test:profiler": "node scripts/mocha-parallel-files.js --expose-gc --timeout 30000 -- packages/dd-trace/test/profiling/**/*.spec.js",
"test:profiler:ci": "nyc --no-clean --include \"packages/dd-trace/src/profiling/**/*.js\" -- npm run test:profiler",
"test:integration": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/*.spec.js\"",
"test:integration:aiguard": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/aiguard/*.spec.js\"",
"test:integration:appsec": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/appsec/*.spec.js\"",
"test:integration:cucumber": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/cucumber/*.spec.js\"",
"test:integration:cypress": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/cypress/*.spec.js\"",
"test:integration:debugger": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/debugger/*.spec.js\"",
"test:integration:esbuild": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/esbuild/*.spec.js\"",
"test:integration:openfeature": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/openfeature/*.spec.js\"",
"test:integration:jest": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/jest/*.spec.js\"",
"test:integration:mocha": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/mocha/*.spec.js\"",
"test:integration:playwright": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/playwright/*.spec.js\"",
"test:integration:selenium": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/selenium/*.spec.js\"",
"test:integration:vitest": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/vitest/*.spec.js\"",
"test:integration:testopt": "mocha --timeout 120000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/ci-visibility/*.spec.js\"",
"test:integration:profiler": "mocha --timeout 180000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/profiler/*.spec.js\"",
"test:integration:plugins": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/datadog-plugin-@($(echo $PLUGINS))/test/integration-test/**/*.spec.js\"",
"test:unit:plugins": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/datadog-instrumentations/test/@($(echo $PLUGINS)).spec.js\" \"packages/datadog-plugin-@($(echo $PLUGINS))/test/**/*.spec.js\" --exclude \"packages/datadog-plugin-@($(echo $PLUGINS))/test/integration-test/**/*.spec.js\"",
"test:shimmer": "mocha 'packages/datadog-shimmer/test/**/*.spec.js'",
"test:shimmer:ci": "nyc --no-clean --include 'packages/datadog-shimmer/src/**/*.js' -- npm run test:shimmer"
"test:integration": "mocha --timeout 60000 \"integration-tests/*.spec.js\"",
"test:integration:aiguard": "mocha --timeout 60000 \"integration-tests/aiguard/*.spec.js\"",
"test:integration:appsec": "mocha --timeout 60000 \"integration-tests/appsec/*.spec.js\"",
"test:integration:cucumber": "mocha --timeout 60000 \"integration-tests/cucumber/*.spec.js\"",
"test:integration:cypress": "mocha --timeout 60000 \"integration-tests/cypress/*.spec.js\"",
"test:integration:debugger": "mocha --timeout 60000 \"integration-tests/debugger/*.spec.js\"",
"test:integration:esbuild": "mocha --timeout 60000 \"integration-tests/esbuild/*.spec.js\"",
"test:integration:openfeature": "mocha --timeout 60000 \"integration-tests/openfeature/*.spec.js\"",
"test:integration:jest": "mocha --timeout 60000 \"integration-tests/jest/*.spec.js\"",
"test:integration:mocha": "mocha --timeout 60000 \"integration-tests/mocha/*.spec.js\"",
"test:integration:playwright": "mocha --timeout 60000 \"integration-tests/playwright/*.spec.js\"",
"test:integration:selenium": "mocha --timeout 60000 \"integration-tests/selenium/*.spec.js\"",
"test:integration:vitest": "mocha --timeout 60000 \"integration-tests/vitest/*.spec.js\"",
"test:integration:testopt": "mocha --timeout 120000 \"integration-tests/ci-visibility/*.spec.js\"",
"test:integration:profiler": "mocha --timeout 180000 \"integration-tests/profiler/*.spec.js\"",
"test:integration:plugins": "mocha \"packages/datadog-plugin-@($(echo $PLUGINS))/test/integration-test/**/*.spec.js\"",
"test:unit:plugins": "mocha \"packages/datadog-instrumentations/test/@($(echo $PLUGINS)).spec.js\" \"packages/datadog-plugin-@($(echo $PLUGINS))/test/**/*.spec.js\" --exclude \"packages/datadog-plugin-@($(echo $PLUGINS))/test/integration-test/**/*.spec.js\"",
"test:shimmer": "mocha \"packages/datadog-shimmer/test/**/*.spec.js\"",
"test:shimmer:ci": "nyc --no-clean --include \"packages/datadog-shimmer/src/**/*.js\" -- npm run test:shimmer",
"verify-exercised-tests": "node scripts/verify-exercised-tests.js"
},

@@ -131,3 +134,3 @@ "repository": {

"dc-polyfill": "^0.1.10",
"import-in-the-middle": "2.0.0"
"import-in-the-middle": "2.0.3"
},

@@ -140,3 +143,3 @@ "optionalDependencies": {

"@datadog/openfeature-node-server": "^0.2.0",
"@datadog/pprof": "5.13.1",
"@datadog/pprof": "5.13.2",
"@datadog/wasm-js-rewriter": "5.0.1",

@@ -147,9 +150,9 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0",

"devDependencies": {
"@babel/helpers": "^7.28.4",
"@babel/helpers": "^7.28.6",
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.39.0",
"@msgpack/msgpack": "^3.1.2",
"@eslint/js": "^9.39.2",
"@msgpack/msgpack": "^3.1.3",
"@openfeature/core": "^1.8.1",
"@openfeature/server-sdk": "~1.20.0",
"@stylistic/eslint-plugin": "^5.5.0",
"@stylistic/eslint-plugin": "^5.7.0",
"@types/mocha": "^10.0.10",

@@ -160,10 +163,10 @@ "@types/node": "^18.19.106",

"benchmark": "^2.1.4",
"body-parser": "^2.2.0",
"bun": "1.3.3",
"eslint": "^9.39.0",
"eslint-plugin-cypress": "^5.2.0",
"body-parser": "^2.2.2",
"bun": "1.3.6",
"eslint": "^9.39.2",
"eslint-plugin-cypress": "^5.2.1",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jsdoc": "^61.1.12",
"eslint-plugin-jsdoc": "^62.0.0",
"eslint-plugin-mocha": "^11.2.0",
"eslint-plugin-n": "^17.23.1",
"eslint-plugin-n": "^17.23.2",
"eslint-plugin-promise": "^7.2.1",

@@ -173,3 +176,3 @@ "eslint-plugin-unicorn": "^62.0.0",

"glob": "^10.4.5",
"globals": "^16.3.0",
"globals": "^17.0.0",
"graphql": "*",

@@ -176,0 +179,0 @@ "jszip": "^3.10.1",

@@ -13,8 +13,8 @@ 'use strict'

*
* @typedef {Record<string, unknown>} Store
* @template T
* @typedef {Record<string, T>} Store
*/
class DatadogStorage extends AsyncLocalStorage {
/**
*
* @param {Store} [store]
* @param {Store<unknown>} [store]
* @override

@@ -39,3 +39,3 @@ */

*
* @returns {Store}
* @returns {Store<unknown>}
*/

@@ -53,3 +53,3 @@ getHandle () {

* @param {object} [handle]
* @returns {Store | undefined}
* @returns {Store<unknown> | undefined}
* @override

@@ -74,3 +74,3 @@ */

* @template TArgs = unknown[]
* @param {Store} store
* @param {Store<unknown>} store
* @param {() => R} fn

@@ -94,3 +94,3 @@ * @param {...TArgs} args

* This is the map from handles to real stores, used in the class above.
* @type {WeakMap<WeakKey, Store|undefined>}
* @type {WeakMap<WeakKey, Store<unknown>|undefined>}
*/

@@ -97,0 +97,0 @@ const stores = new WeakMap()

@@ -100,2 +100,8 @@ 'use strict'

module.exports.setup = function (build) {
if (build.initialOptions.minify && !build.initialOptions.keepNames) {
throw new Error(
'Using --minify without --keep-names will break some dd-trace behavior. Refusing to bundle.'
)
}
if (DD_IAST_ENABLED) {

@@ -102,0 +108,0 @@ const iastRewriter = require('../dd-trace/src/appsec/iast/taint-tracking/rewriter')

@@ -44,5 +44,11 @@ 'use strict'

const tracers = new WeakSet()
function wrapTracer (tracer) {
if (Object.hasOwn(tracer, Symbol.for('_dd.wrapped'))) return
if (tracers.has(tracer)) {
return
}
tracers.add(tracer)
shimmer.wrap(tracer, 'startActiveSpan', function (startActiveSpan) {

@@ -94,4 +100,2 @@ return function () {

})
Object.defineProperty(tracer, Symbol.for('_dd.wrapped'), { value: true })
}

@@ -98,0 +102,0 @@

@@ -217,3 +217,3 @@ 'use strict'

childProcess.on('close', (code = 0) => {
childProcess.once('close', (code = 0) => {
if (!errorExecuted && code !== 0) {

@@ -220,0 +220,0 @@ childProcessChannel.error.publish(context)

@@ -6,3 +6,3 @@ 'use strict'

const log = require('../../dd-trace/src/log')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getEnvironmentVariable } = require('../../dd-trace/src/config/helper')
const {

@@ -9,0 +9,0 @@ getCoveredFilenamesFromCoverage,

@@ -9,3 +9,3 @@ 'use strict'

const ddGlobal = globalThis[Symbol.for('dd-trace')] ??= {}
const ddGlobal = globalThis[Symbol.for('dd-trace')]

@@ -12,0 +12,0 @@ /** cached objects */

'use strict'
// Use a global symbol to prevent stealthy-require to interfere.
// TODO: Use the symbol from dd-trace instead and remove this file.
const sym = Symbol.for('_ddtrace_instrumentations')
globalThis[sym] ??= {}
global[sym] = global[sym] || {}
module.exports = global[sym]
module.exports = globalThis[sym]

@@ -10,3 +10,3 @@ 'use strict'

const { isInServerlessEnvironment } = require('../../../dd-trace/src/serverless')
const { getEnvironmentVariables } = require('../../../dd-trace/src/config-helper')
const { getValueFromEnvSources } = require('../../../dd-trace/src/config/helper')
const checkRequireCache = require('./check-require-cache')

@@ -17,9 +17,5 @@ const Hook = require('./hook')

const envs = getEnvironmentVariables()
const DD_TRACE_DISABLED_INSTRUMENTATIONS = getValueFromEnvSources('DD_TRACE_DISABLED_INSTRUMENTATIONS') || ''
const DD_TRACE_DEBUG = getValueFromEnvSources('DD_TRACE_DEBUG') || ''
const {
DD_TRACE_DISABLED_INSTRUMENTATIONS = '',
DD_TRACE_DEBUG = ''
} = envs
const hooks = require('./hooks')

@@ -26,0 +22,0 @@ const instrumentations = require('./instrumentations')

@@ -38,3 +38,3 @@ 'use strict'

const log = require('../../../../dd-trace/src/log')
const { getEnvironmentVariable } = require('../../../../dd-trace/src/config-helper')
const { getEnvironmentVariable } = require('../../../../dd-trace/src/config/helper')
const transforms = require('./transforms')

@@ -41,0 +41,0 @@ const { generate, parse, traverse } = require('./compiler')

@@ -104,4 +104,4 @@ 'use strict'

ctx.res = res
res.on('end', finish)
res.on(errorMonitor, finish)
res.once('end', finish)
res.once(errorMonitor, finish)
break

@@ -108,0 +108,0 @@ }

@@ -96,2 +96,4 @@ 'use strict'

const BREAKPOINT_HIT_GRACE_PERIOD_MS = 200
const ATR_RETRY_SUPPRESSION_FLAG = '_ddDisableAtrRetry'
const atrSuppressedErrors = new Map()

@@ -382,3 +384,6 @@ // based on https://github.com/facebook/jest/blob/main/packages/jest-circus/src/formatNodeAssertErrors.ts#L41

if (this.isEarlyFlakeDetectionEnabled && (isNewTest || isModified)) {
const willRunEfd = this.isEarlyFlakeDetectionEnabled && (isNewTest || isModified)
event.test[ATR_RETRY_SUPPRESSION_FLAG] = Boolean(isAttemptToFix || willRunEfd)
if (!isAttemptToFix && willRunEfd) {
numEfdRetry = retriedTestsToNumAttempts.get(testName)

@@ -439,15 +444,18 @@ retriedTestsToNumAttempts.set(testName, numEfdRetry + 1)

const isSkipped = event.mode === 'todo' || event.mode === 'skip'
if (this.isTestManagementTestsEnabled) {
const isAttemptToFix = this.testManagementTestsForThisSuite?.attemptToFix?.includes(testFullName)
if (isAttemptToFix && !isSkipped && !retriedTestsToNumAttempts.has(testFullName)) {
retriedTestsToNumAttempts.set(testFullName, 0)
testsToBeRetried.add(testFullName)
this.retryTest({
jestEvent: event,
retryCount: testManagementAttemptToFixRetries,
retryType: 'Test Management (Attempt to Fix)'
})
}
const isAttemptToFix = this.isTestManagementTestsEnabled &&
this.testManagementTestsForThisSuite?.attemptToFix?.includes(testFullName)
if (
isAttemptToFix &&
!isSkipped &&
!retriedTestsToNumAttempts.has(testFullName)
) {
retriedTestsToNumAttempts.set(testFullName, 0)
testsToBeRetried.add(testFullName)
this.retryTest({
jestEvent: event,
retryCount: testManagementAttemptToFixRetries,
retryType: 'Test Management (Attempt to Fix)'
})
}
if (this.isImpactedTestsEnabled) {
if (!isAttemptToFix && this.isImpactedTestsEnabled) {
const testStartLine = getTestLineStart(event.asyncError, this.testSuite)

@@ -472,3 +480,3 @@ const testEndLine = getTestEndLine(event.fn, testStartLine)

}
if (this.isKnownTestsEnabled) {
if (!isAttemptToFix && this.isKnownTestsEnabled) {
const isNew = !this.knownTestsForThisSuite.includes(testFullName)

@@ -495,2 +503,9 @@ if (isNew && !isSkipped && !retriedTestsToNumAttempts.has(testFullName)) {

event.test.fn = originalTestFns.get(event.test)
// If ATR retry is being suppressed for this test (due to EFD or Attempt to Fix taking precedence)
// and the test has errors for this attempt, store the errors temporarily and clear them
// so Jest won't treat this attempt as failed (the real status will be reported after retries).
if (event.test?.[ATR_RETRY_SUPPRESSION_FLAG] && event.test.errors?.length) {
atrSuppressedErrors.set(event.test, event.test.errors)
event.test.errors = []
}

@@ -589,2 +604,8 @@ let attemptToFixPassed = false

}
if (event.name === 'run_finish') {
for (const [test, errors] of atrSuppressedErrors) {
test.errors = errors
}
atrSuppressedErrors.clear()
}
if (event.name === 'test_skip' || event.name === 'test_todo') {

@@ -591,0 +612,0 @@ const testName = getJestTestName(event.test, this.getShouldStripSeedFromTestName())

@@ -93,3 +93,4 @@ 'use strict'

const path = layer && layer.path
const route = typeof path === 'string' && !path.endsWith('(.*)') && !path.endsWith('([^/]*)') && path
const route = typeof path === 'string' && !path.endsWith('(.*)') && !path.endsWith('([^/]*)') &&
!path.includes('(?:') && path

@@ -96,0 +97,0 @@ enterChannel.publish({ req, name, route })

@@ -65,4 +65,4 @@ 'use strict'

if (res.on && typeof res.on === 'function') {
res.on('finish', onFinish)
res.on('close', onFinish)
res.once('finish', onFinish)
res.once('close', onFinish)
}

@@ -69,0 +69,0 @@

'use strict'
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getEnvironmentVariable } = require('../../dd-trace/src/config/helper')

@@ -5,0 +5,0 @@ if (getEnvironmentVariable('MOCHA_WORKER_ID')) {

@@ -8,3 +8,3 @@ 'use strict'

const log = require('../../../dd-trace/src/log')
const { getEnvironmentVariable } = require('../../../dd-trace/src/config-helper')
const { getEnvironmentVariable } = require('../../../dd-trace/src/config/helper')
const {

@@ -286,3 +286,3 @@ getTestSuitePath,

testManagementTestsCh.runStores(ctx, () => {})
} if (config.isImpactedTestsEnabled) {
} else if (config.isImpactedTestsEnabled) {
ctx.onDone = onReceivedImpactedTests

@@ -289,0 +289,0 @@ modifiedFilesCh.runStores(ctx, () => {})

@@ -70,3 +70,3 @@ 'use strict'

// We flush when the worker ends with its test file (a mocha instance in a worker runs a single test file)
this.on('end', () => {
this.once('end', () => {
workerFinishCh.publish()

@@ -73,0 +73,0 @@ })

@@ -42,3 +42,3 @@ 'use strict'

} else {
res.on('end', () => finishCh.publish(ctx))
res.once('end', () => finishCh.publish(ctx))
}

@@ -45,0 +45,0 @@

@@ -144,7 +144,7 @@ 'use strict'

} else {
this.on(errorMonitor, error => {
this.once(errorMonitor, error => {
ctx.error = error
errorCh.publish(ctx)
})
this.on('end', () => finishCh.publish(ctx))
this.once('end', () => finishCh.publish(ctx))
}

@@ -151,0 +151,0 @@

@@ -104,3 +104,3 @@ 'use strict'

function setupListeners (socket, protocol, ctx, finishCh, errorCh) {
const events = ['connect', errorMonitor, 'close', 'timeout']
const events = [errorMonitor, 'close', 'timeout']

@@ -113,19 +113,28 @@ const wrapListener = function (error) {

finishCh.runStores(ctx, () => {})
cleanupOtherListeners()
}
const localListener = function () {
const localListener = function (error) {
ctx.socket = socket
connectionCh.publish(ctx)
if (error) {
ctx.error = error
errorCh.publish(ctx)
}
finishCh.runStores(ctx, () => {})
cleanupOtherListeners()
}
const cleanupListener = function () {
const cleanupOtherListeners = function () {
socket.removeListener('connect', localListener)
events.forEach(event => {
socket.removeListener(event, wrapListener)
socket.removeListener(event, cleanupListener)
})
}
// TODO: Identify why the connect listener should remove the other listeners.
if (protocol === 'tcp') {
socket.once('connect', localListener)
} else {
events.push('connect')
}

@@ -135,4 +144,3 @@

socket.once(event, wrapListener)
socket.once(event, cleanupListener)
})
}
'use strict'
const shimmer = require('../../datadog-shimmer')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getEnvironmentVariable } = require('../../dd-trace/src/config/helper')
const { addHook, channel } = require('./helpers/instrument')

@@ -6,0 +6,0 @@

@@ -5,8 +5,8 @@ 'use strict'

const tracer = require('../../dd-trace')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')
const { addHook } = require('./helpers/instrument')
const otelSdkEnabled = getEnvironmentVariable('DD_TRACE_OTEL_ENABLED') ||
getEnvironmentVariable('OTEL_SDK_DISABLED')
? !getEnvironmentVariable('OTEL_SDK_DISABLED')
const otelSdkEnabled = getValueFromEnvSources('DD_TRACE_OTEL_ENABLED') ||
getValueFromEnvSources('OTEL_SDK_DISABLED')
? !getValueFromEnvSources('OTEL_SDK_DISABLED')
: undefined

@@ -13,0 +13,0 @@

@@ -115,5 +115,7 @@ 'use strict'

const retval = query.apply(this, arguments)
const queryQueue = this.queryQueue || this._queryQueue
const activeQuery = this.activeQuery || this._activeQuery
const deperecated = Object.hasOwn(this, '_activeQuery')
const queryQueue = deperecated ? this._queryQueue : this.queryQueue
const activeQuery = deperecated ? this._activeQuery : this.activeQuery
const newQuery = queryQueue.at(-1) || activeQuery

@@ -120,0 +122,0 @@

@@ -14,4 +14,4 @@ 'use strict'

const {
getEnvironmentVariable
} = require('../../dd-trace/src/config-helper')
getValueFromEnvSources
} = require('../../dd-trace/src/config/helper')
const { DD_MAJOR } = require('../../../version')

@@ -45,3 +45,3 @@ const { addHook, channel } = require('./helpers/instrument')

const RUM_FLUSH_WAIT_TIME = Number(getEnvironmentVariable('DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS')) || 1000
const RUM_FLUSH_WAIT_TIME = Number(getValueFromEnvSources('DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS')) || 1000

@@ -48,0 +48,0 @@ let applyRepeatEachIndex = null

'use strict'
const shimmer = require('../../datadog-shimmer')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')
const { addHook, channel } = require('./helpers/instrument')

@@ -20,3 +20,3 @@

const DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS =
Number(getEnvironmentVariable('DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS')) || 500
Number(getValueFromEnvSources('DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS')) || 500
const DD_CIVISIBILITY_TEST_EXECUTION_ID_COOKIE_NAME = 'datadog-ci-visibility-test-execution-id'

@@ -23,0 +23,0 @@

@@ -6,2 +6,3 @@ 'use strict'

const shimmer = require('../../datadog-shimmer')
const satisfies = require('../../../vendor/dist/semifies')
const {

@@ -14,7 +15,17 @@ addHook

// Undici 5.0.x has a bug where fetch doesn't preserve AggregateError in the error cause chain
// Use native DC only for versions where error handling works correctly
const NATIVE_DC_VERSION = '>=4.7.0 <5.0.0 || >=5.1.0'
addHook({
name: 'undici',
versions: ['^4.4.1', '5', '>=6.0.0']
}, undici => {
}, (undici, version) => {
// For versions with working native DC, let the plugin subscribe directly
if (satisfies(version, NATIVE_DC_VERSION)) {
return undici
}
// For older versions or those with buggy error handling, wrap fetch
return shimmer.wrap(undici, 'fetch', createWrapFetch(undici.Request, ch))
})

@@ -8,3 +8,3 @@ 'use strict'

const { tagsFromRequest, tagsFromResponse } = require('../../dd-trace/src/payload-tagging')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')

@@ -194,3 +194,3 @@ class BaseAwsSdkPlugin extends ClientPlugin {

const serviceId = this.serviceIdentifier.toUpperCase()
const envVarValue = getEnvironmentVariable(`DD_TRACE_AWS_SDK_${serviceId}_ENABLED`)
const envVarValue = getValueFromEnvSources(`DD_TRACE_AWS_SDK_${serviceId}_ENABLED`)
return envVarValue ? isTrue(envVarValue) : true

@@ -278,5 +278,5 @@ }

specificConfig.batchPropagationEnabled ??
getEnvironmentVariable(`DD_TRACE_AWS_SDK_${serviceId}_BATCH_PROPAGATION_ENABLED`) ??
getValueFromEnvSources(`DD_TRACE_AWS_SDK_${serviceId}_BATCH_PROPAGATION_ENABLED`) ??
config.batchPropagationEnabled ??
getEnvironmentVariable('DD_TRACE_AWS_SDK_BATCH_PROPAGATION_ENABLED')
getValueFromEnvSources('DD_TRACE_AWS_SDK_BATCH_PROPAGATION_ENABLED')
)

@@ -283,0 +283,0 @@

'use strict'
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')
const ProducerPlugin = require('../../dd-trace/src/plugins/producer')

@@ -92,3 +92,3 @@

function batchLinksAreEnabled () {
const eh = getEnvironmentVariable('DD_TRACE_AZURE_EVENTHUBS_BATCH_LINKS_ENABLED')
const eh = getValueFromEnvSources('DD_TRACE_AZURE_EVENTHUBS_BATCH_LINKS_ENABLED')
return eh !== 'false'

@@ -95,0 +95,0 @@ }

'use strict'
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')
const ProducerPlugin = require('../../dd-trace/src/plugins/producer')

@@ -93,3 +93,3 @@ const spanContexts = new WeakMap()

function batchLinksAreEnabled () {
const sb = getEnvironmentVariable('DD_TRACE_AZURE_SERVICEBUS_BATCH_LINKS_ENABLED')
const sb = getValueFromEnvSources('DD_TRACE_AZURE_SERVICEBUS_BATCH_LINKS_ENABLED')
return sb !== 'false'

@@ -96,0 +96,0 @@ }

@@ -5,3 +5,3 @@ 'use strict'

const { storage } = require('../../datadog-core')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getEnvironmentVariable, getValueFromEnvSources } = require('../../dd-trace/src/config/helper')

@@ -116,3 +116,3 @@ const {

provider: this.ciProviderName,
autoInjected: !!getEnvironmentVariable('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
autoInjected: !!getValueFromEnvSources('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
})

@@ -119,0 +119,0 @@

@@ -54,3 +54,3 @@ 'use strict'

const { ORIGIN_KEY, COMPONENT } = require('../../dd-trace/src/constants')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')
const { appClosing: appClosingTelemetry } = require('../../dd-trace/src/telemetry')

@@ -648,3 +648,3 @@ const log = require('../../dd-trace/src/log')

provider: this.ciProviderName,
autoInjected: !!getEnvironmentVariable('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
autoInjected: !!getValueFromEnvSources('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
})

@@ -651,0 +651,0 @@

@@ -6,3 +6,3 @@ 'use strict'

const apiMetrics = telemetryMetrics.manager.namespace('tracers')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')

@@ -13,3 +13,3 @@ // api ==> here

const injectionEnabledTag =
`injection_enabled:${getEnvironmentVariable('DD_INJECTION_ENABLED') ? 'yes' : 'no'}`
`injection_enabled:${getValueFromEnvSources('DD_INJECTION_ENABLED') ? 'yes' : 'no'}`

@@ -16,0 +16,0 @@ module.exports = class DdTraceApiPlugin extends Plugin {

'use strict'
const dc = require('dc-polyfill')
const { entryTags } = require('../../datadog-code-origin')

@@ -15,25 +17,29 @@ const Plugin = require('../../dd-trace/src/plugins/plugin')

this.addSub('apm:express:middleware:enter', ({ req, layer }) => {
// Middleware/request handling: apply pre-computed tags to spans
const handleMiddlewareEnter = ({ req, layer }) => {
const tags = layerTags.get(layer)
if (!tags) return
web.getContext(req)?.span?.addTags(tags)
})
}
this.addSub('apm:express:route:added', ({ topOfStackFunc, layer }) => {
this.addSub('apm:express:middleware:enter', handleMiddlewareEnter)
this.addSub('apm:router:middleware:enter', handleMiddlewareEnter)
// Route added handling: compute and cache tags
const handleRouteAdded = ({ topOfStackFunc, layer }) => {
if (!layer) return
if (layerTags.has(layer)) return
layerTags.set(layer, entryTags(topOfStackFunc))
})
}
this.addSub('apm:router:middleware:enter', ({ req, layer }) => {
const tags = layerTags.get(layer)
if (!tags) return
web.getContext(req)?.span?.addTags(tags)
})
this.addSub('apm:router:route:added', ({ topOfStackFunc, layer }) => {
if (!layer) return
if (layerTags.has(layer)) return
layerTags.set(layer, entryTags(topOfStackFunc))
})
if (this._tracerConfig.remoteConfig?.enabled) {
// When RC is enabled, use manual subscriptions (always pre-compute)
// This allows tags to be computed even when CO is disabled, so runtime enabling works
dc.channel('apm:express:route:added').subscribe(handleRouteAdded)
dc.channel('apm:router:route:added').subscribe(handleRouteAdded)
} else {
// When RC is disabled, use addSub (only computes when CO is enabled)
this.addSub('apm:express:route:added', handleRouteAdded)
this.addSub('apm:router:route:added', handleRouteAdded)
}
}

@@ -40,0 +46,0 @@ }

'use strict'
const dc = require('dc-polyfill')
const { entryTags } = require('../../datadog-code-origin')

@@ -21,6 +23,10 @@ const Plugin = require('../../dd-trace/src/plugins/plugin')

this.addSub('apm:fastify:route:added', ({ routeOptions, onRoute }) => {
if (!routeOptions.config) routeOptions.config = {}
routeOptions.config[kCodeOriginForSpansTagsSym] = entryTags(onRoute)
})
if (this._tracerConfig.remoteConfig?.enabled) {
// When RC is enabled, use manual subscription (always pre-computes)
// This allows tags to be computed even when CO is disabled, so runtime enabling works
dc.channel('apm:fastify:route:added').subscribe(handleRouteAdded)
} else {
// When RC is disabled, use addSub (only computes when CO is enabled)
this.addSub('apm:fastify:route:added', handleRouteAdded)
}
}

@@ -30,1 +36,8 @@ }

module.exports = FastifyCodeOriginForSpansPlugin
// Route added handling: compute and cache tags
function handleRouteAdded ({ routeOptions, onRoute }) {
if (!routeOptions.config) routeOptions.config = {}
if (routeOptions.config[kCodeOriginForSpansTagsSym]) return
routeOptions.config[kCodeOriginForSpansTagsSym] = entryTags(onRoute)
}

@@ -5,3 +5,3 @@ 'use strict'

const { storage } = require('../../datadog-core')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getEnvironmentVariable, getValueFromEnvSources } = require('../../dd-trace/src/config/helper')

@@ -165,3 +165,3 @@ const {

provider: this.ciProviderName,
autoInjected: !!getEnvironmentVariable('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
autoInjected: !!getValueFromEnvSources('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
})

@@ -168,0 +168,0 @@

@@ -5,3 +5,3 @@ 'use strict'

const { storage } = require('../../datadog-core')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')

@@ -410,3 +410,3 @@ const {

provider: this.ciProviderName,
autoInjected: !!getEnvironmentVariable('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
autoInjected: !!getValueFromEnvSources('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
})

@@ -413,0 +413,0 @@ }

@@ -5,3 +5,3 @@ 'use strict'

const DatabasePlugin = require('../../dd-trace/src/plugins/database')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')

@@ -24,3 +24,3 @@ class MongodbCorePlugin extends DatabasePlugin {

const heartbeatFromEnv = getEnvironmentVariable('DD_TRACE_MONGODB_HEARTBEAT_ENABLED')
const heartbeatFromEnv = getValueFromEnvSources('DD_TRACE_MONGODB_HEARTBEAT_ENABLED')

@@ -27,0 +27,0 @@ this.config.heartbeatEnabled = config.heartbeatEnabled ??

@@ -6,3 +6,3 @@ 'use strict'

const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')

@@ -110,3 +110,3 @@ const {

provider: this.ciProviderName,
autoInjected: !!getEnvironmentVariable('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
autoInjected: !!getValueFromEnvSources('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
})

@@ -398,3 +398,3 @@ appClosingTelemetry()

finishAllTraceSpans(span)
if (getEnvironmentVariable('DD_PLAYWRIGHT_WORKER')) {
if (getValueFromEnvSources('DD_PLAYWRIGHT_WORKER')) {
this.tracer._exporter.flush(onDone)

@@ -401,0 +401,0 @@ }

'use strict'
const FetchPlugin = require('../../datadog-plugin-fetch/src/index.js')
const HttpClientPlugin = require('../../datadog-plugin-http/src/client')
const { storage } = require('../../datadog-core')
const tags = require('../../../ext/tags')
const formats = require('../../../ext/formats')
const HTTP_HEADERS = formats.HTTP_HEADERS
const log = require('../../dd-trace/src/log')
const { CLIENT_PORT_KEY } = require('../../dd-trace/src/constants')
class UndiciPlugin extends FetchPlugin {
const {
HTTP_STATUS_CODE,
HTTP_REQUEST_HEADERS,
HTTP_RESPONSE_HEADERS,
} = tags
// WeakMap to store span context for native undici request objects
const requestContexts = new WeakMap()
class UndiciPlugin extends HttpClientPlugin {
static id = 'undici'
static prefix = 'tracing:apm:undici:fetch'
constructor (...args) {
super(...args)
// Subscribe to native undici diagnostic channels for undici >= 4.7.0
// These channels fire for ALL undici requests (fetch, request, stream, etc.)
this.addSub('undici:request:create', this.#onNativeRequestCreate.bind(this))
this.addSub('undici:request:headers', this.#onNativeRequestHeaders.bind(this))
this.addSub('undici:request:trailers', this.#onNativeRequestTrailers.bind(this))
this.addSub('undici:request:error', this.#onNativeRequestError.bind(this))
}
// ===========================================
// Native undici diagnostic channel handlers
// These fire for undici >= 4.7.0 for ALL request types (fetch, request, stream, etc.)
// ===========================================
#onNativeRequestCreate ({ request }) {
if (!request) return
const store = storage('legacy').getStore()
const { origin = '', path = '/' } = request
const method = request.method?.toUpperCase() ?? 'GET'
// Parse origin to extract protocol, hostname, port
let protocol = 'http:'
let hostname = 'localhost'
let port = ''
try {
const url = new URL(origin)
protocol = url.protocol
hostname = url.hostname
port = url.port
} catch {
// If origin is not a valid URL, use defaults
}
const host = port ? `${hostname}:${port}` : hostname
const pathname = path.split(/[?#]/)[0]
const uri = `${protocol}//${host}${pathname}`
const allowed = this.config.filter(uri)
const childOf = store && allowed ? store.span : null
const span = this.startSpan(this.operationName(), {
childOf,
meta: {
'span.kind': 'client',
'http.method': method,
'http.url': uri,
'out.host': hostname
},
metrics: {
[CLIENT_PORT_KEY]: port ? Number.parseInt(port, 10) : undefined
},
service: this.serviceName({ pluginConfig: this.config, sessionDetails: { host: hostname, port } }),
resource: method,
type: 'http'
}, false)
// Disable recording if not allowed
if (!allowed) {
span._spanContext._trace.record = false
}
// Capture request headers if configured
if (request.headers && this.config.headers) {
addConfiguredHeaders(span, request.headers, this.config.headers, HTTP_REQUEST_HEADERS)
}
// Inject trace headers if propagation is allowed
if (this.config.propagationFilter(uri)) {
const headers = {}
this.tracer.inject(span, HTTP_HEADERS, headers)
// Use addHeader if available (undici provides this on the request object)
if (typeof request.addHeader === 'function') {
for (const [name, value] of Object.entries(headers)) {
request.addHeader(name, value)
}
}
}
// Store span context for request for later retrieval
requestContexts.set(request, {
span,
store,
uri
})
// Enter the span context
storage('legacy').enterWith({ ...store, span })
}
#onNativeRequestHeaders ({ request, response }) {
const ctx = requestContexts.get(request)
if (!ctx) return
const { span } = ctx
const statusCode = response?.statusCode
if (statusCode) {
span.setTag(HTTP_STATUS_CODE, statusCode)
if (!this.config.validateStatus(statusCode)) {
span.setTag('error', 1)
}
}
// Add response headers if configured
if (response?.headers && this.config.headers) {
addConfiguredHeaders(span, response.headers, this.config.headers, HTTP_RESPONSE_HEADERS)
}
}
#onNativeRequestTrailers ({ request }) {
const ctx = requestContexts.get(request)
if (!ctx) return
const { span, store } = ctx
// Call the request hook if configured
this.config.hooks.request(span, null, null)
// Finish the span
span.finish()
// Clean up
requestContexts.delete(request)
// Restore parent store
if (store) {
storage('legacy').enterWith(store)
}
}
#onNativeRequestError ({ request, error }) {
const ctx = requestContexts.get(request)
if (!ctx) return
const { span, store } = ctx
// Don't record AbortError as an error - it's user-initiated cancellation
if (error && error.name !== 'AbortError') {
span.setTag('error', error)
}
// Call the request hook if configured
this.config.hooks.request(span, null, null)
// Finish the span
span.finish()
// Clean up
requestContexts.delete(request)
// Restore parent store
if (store) {
storage('legacy').enterWith(store)
}
}
// ===========================================
// Fetch-based tracing channel handlers
// These handle fetch() for undici < 4.7.0 (before native DC was added)
// ===========================================
bindStart (ctx) {
const req = ctx.req
const options = new URL(req.url)
options.headers = Object.fromEntries(req.headers.entries())
options.method = req.method
ctx.args = { options }
const store = super.bindStart(ctx)
// Inject trace headers back into the request
for (const name of Object.keys(options.headers)) {
if (!req.headers.has(name)) {
req.headers.set(name, options.headers[name])
}
}
return store
}
error (ctx) {
// Don't record AbortError as an error - it's user-initiated cancellation
if (!ctx.error || ctx.error.name !== 'AbortError') {
return super.error(ctx)
}
}
asyncEnd (ctx) {
ctx.res = ctx.result
return this.finish(ctx)
}
configure (config) {
return super.configure(normalizeConfig(config))
}
}
// Add configured headers to span with appropriate tags
function addConfiguredHeaders (span, rawHeaders, configuredHeaders, headerType) {
const headers = normalizeHeaders(rawHeaders)
for (const [key, tag] of configuredHeaders) {
const value = headers[key]
if (value) {
span.setTag(tag || `${headerType}.${key}`, value)
}
}
}
// Normalize headers to an object, handling different undici formats:
// - Array format: alternating key-value pairs (undici >= 6.0.0)
// - String format: HTTP header lines like "key: value\r\n" (undici 5.x)
// - Object format: already a headers object
function normalizeHeaders (headers) {
if (!headers) return {}
// String format (undici 5.x): "key: value\r\nkey2: value2\r\n"
if (typeof headers === 'string') {
const result = {}
const lines = headers.split('\r\n')
for (const line of lines) {
if (!line) continue
const colonIndex = line.indexOf(':')
if (colonIndex > 0) {
const key = line.slice(0, colonIndex).toLowerCase().trim()
const value = line.slice(colonIndex + 1).trim()
result[key] = value
}
}
return result
}
// Array format (undici >= 6.0.0): alternating key-value pairs
if (Array.isArray(headers)) {
const result = {}
for (let i = 0; i < headers.length; i += 2) {
const key = headers[i]
if (typeof key === 'string') {
result[key.toLowerCase()] = headers[i + 1]
} else if (Buffer.isBuffer(key)) {
result[key.toString().toLowerCase()] = headers[i + 1]?.toString?.() || headers[i + 1]
}
}
return result
}
// Object format: use as-is
return headers
}
function normalizeConfig (config) {
const validateStatus = getStatusValidator(config)
const hooks = getHooks(config)
return {
...config,
validateStatus,
hooks
}
}
function getStatusValidator (config) {
if (typeof config.validateStatus === 'function') {
return config.validateStatus
} else if (Object.hasOwn(config, 'validateStatus')) {
log.error('Expected `validateStatus` to be a function.')
}
return defaultValidateStatus
}
function defaultValidateStatus (code) {
return code < 400 || code >= 500
}
function getHooks (config) {
const request = config.hooks?.request ?? noop
return { request }
}
function noop () {}
module.exports = UndiciPlugin

@@ -5,3 +5,3 @@ 'use strict'

const { storage } = require('../../datadog-core')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')

@@ -285,7 +285,7 @@ const {

this.command = getEnvironmentVariable('DD_CIVISIBILITY_TEST_COMMAND')
this.command = getValueFromEnvSources('DD_CIVISIBILITY_TEST_COMMAND')
this.frameworkVersion = frameworkVersion
const testSessionSpanContext = this.tracer.extract('text_map', {
'x-datadog-trace-id': getEnvironmentVariable('DD_CIVISIBILITY_TEST_SESSION_ID'),
'x-datadog-parent-id': getEnvironmentVariable('DD_CIVISIBILITY_TEST_MODULE_ID')
'x-datadog-trace-id': getValueFromEnvSources('DD_CIVISIBILITY_TEST_SESSION_ID'),
'x-datadog-parent-id': getValueFromEnvSources('DD_CIVISIBILITY_TEST_MODULE_ID')
})

@@ -410,3 +410,3 @@

provider: this.ciProviderName,
autoInjected: !!getEnvironmentVariable('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
autoInjected: !!getValueFromEnvSources('DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER')
})

@@ -413,0 +413,0 @@ this.tracer._exporter.flush(onFinish)

@@ -13,2 +13,21 @@ 'use strict'

const ddTraceSymbol = Symbol.for('dd-trace')
Object.defineProperty(globalThis, ddTraceSymbol, {
value: {
beforeExitHandlers: new Set(),
},
enumerable: false,
configurable: true, // Allow this to be overridden by loading the tracer
writable: false
})
process.once('beforeExit', function mainBeforeExit () {
if (globalThis[ddTraceSymbol]?.beforeExitHandlers) {
for (const handler of globalThis[ddTraceSymbol].beforeExitHandlers) {
handler()
}
}
})
global._ddtrace.default = global._ddtrace

@@ -15,0 +34,0 @@ global._ddtrace.tracer = global._ddtrace

@@ -15,3 +15,3 @@ 'use strict'

const orchestrionConfig = require('../../../../../datadog-instrumentations/src/orchestrion-config')
const { getEnvironmentVariable } = require('../../../config-helper')
const { getEnvironmentVariable } = require('../../../config/helper')
const { LOG_MESSAGE, REWRITTEN_MESSAGE } = require('./constants')

@@ -18,0 +18,0 @@ const { incrementTelemetryIfNeeded } = require('./rewriter-telemetry')

@@ -76,5 +76,3 @@ 'use strict'

const cleanUp = removeAllListeners(process, 'uncaughtException')
const handler = () => {
process.removeListener('uncaughtException', handler)
}
const handler = () => {}

@@ -86,3 +84,3 @@ setTimeout(() => {

process.on('uncaughtException', handler)
process.once('uncaughtException', handler)
}

@@ -89,0 +87,0 @@ }

@@ -6,3 +6,7 @@ 'use strict'

const os = require('os')
const { getEnvironmentVariable, getEnvironmentVariables } = require('../../dd-trace/src/config-helper')
const {
getEnvironmentVariable,
getEnvironmentVariables,
getValueFromEnvSources
} = require('./config/helper')
const { getIsAzureFunction, getIsFlexConsumptionAzureFunction } = require('./serverless')

@@ -41,4 +45,2 @@

COMPUTERNAME,
DD_AAS_DOTNET_EXTENSION_VERSION,
DD_AZURE_RESOURCE_GROUP,
FUNCTIONS_EXTENSION_VERSION,

@@ -54,2 +56,5 @@ FUNCTIONS_WORKER_RUNTIME,

const DD_AAS_DOTNET_EXTENSION_VERSION = getValueFromEnvSources('DD_AAS_DOTNET_EXTENSION_VERSION')
const DD_AZURE_RESOURCE_GROUP = getValueFromEnvSources('DD_AZURE_RESOURCE_GROUP')
const subscriptionID = extractSubscriptionID(WEBSITE_OWNER_NAME)

@@ -56,0 +61,0 @@

'use strict'
const { storage } = require('../../datadog-core')
const baggageStorage = storage('baggage')
/**
* Spec (API semantics):
* - OpenTelemetry Baggage API: https://opentelemetry.io/docs/specs/otel/baggage/api/
*
* In-process baggage is a string->string map stored in async local storage.
* @typedef {import('../../datadog-core/src/storage').Store<string>} BaggageStore
*/
/**
* @type {{ enterWith: (store?: BaggageStore) => void, getStore: () => (BaggageStore | undefined) }}
*/
const baggageStorage =
/** @type {{ enterWith: (store?: BaggageStore) => void, getStore: () => (BaggageStore | undefined) }} */ (
/** @type {unknown} */ (storage('baggage'))
)
// TODO: Implement metadata https://opentelemetry.io/docs/specs/otel/baggage/api/#set-value
/**
* @param {string} key
* @param {string} value
* @param {object} [metadata] Not used yet
*/
function setBaggageItem (key, value) {
storage('baggage').enterWith({ ...baggageStorage.getStore(), [key]: value })
return storage('baggage').getStore()
function setBaggageItem (key, value, metadata) {
if (typeof key !== 'string' || typeof value !== 'string' || key === '') {
return baggageStorage.getStore() ?? {}
}
const store = baggageStorage.getStore()
const newStore = { ...store, [key]: value }
baggageStorage.enterWith(newStore)
return newStore
}

@@ -17,9 +40,10 @@

* @param {string} key
* @returns {string | undefined}
*/
function getBaggageItem (key) {
return storage('baggage').getStore()?.[key]
return baggageStorage.getStore()?.[key]
}
function getAllBaggageItems () {
return storage('baggage').getStore() ?? {}
return baggageStorage.getStore() ?? {}
}

@@ -29,7 +53,7 @@

* @param {string} keyToRemove
* @returns {Record<string, unknown>}
*/
function removeBaggageItem (keyToRemove) {
const { [keyToRemove]: _, ...newBaggage } = storage('baggage').getStore()
storage('baggage').enterWith(newBaggage)
const store = baggageStorage.getStore() ?? {}
const { [keyToRemove]: _, ...newBaggage } = store
baggageStorage.enterWith(newBaggage)
return newBaggage

@@ -39,4 +63,5 @@ }

function removeAllBaggageItems () {
storage('baggage').enterWith()
return storage('baggage').getStore()
const newContext = /** @type {BaggageStore} */ ({})
baggageStorage.enterWith(newContext)
return newContext
}

@@ -43,0 +68,0 @@

@@ -7,3 +7,3 @@ 'use strict'

const log = require('../../log')
const { getEnvironmentVariables } = require('../../config-helper')
const { getEnvironmentVariables } = require('../../config/helper')
const getDebuggerConfig = require('../../debugger/config')

@@ -78,2 +78,6 @@

env: {
// NOTE: We intentionally use `getEnvironmentVariables()` here (raw env)
// instead of stable-config resolution helpers. The DI worker is a forked
// process that should see exactly the parent process's environment, and
// we explicitly override a few DD_ vars below to disable tracing/DI there.
...getEnvironmentVariables(),

@@ -80,0 +84,0 @@ DD_CIVISIBILITY_ENABLED: 'false',

@@ -6,3 +6,3 @@ 'use strict'

const log = require('../../log')
const { getEnvironmentVariable } = require('../../config-helper')
const { getValueFromEnvSources } = require('../../config/helper')

@@ -55,3 +55,3 @@ const {

} else {
const apiKey = getEnvironmentVariable('DD_API_KEY')
const apiKey = getValueFromEnvSources('DD_API_KEY')
if (!apiKey) {

@@ -58,0 +58,0 @@ return done(new Error('Known tests were not fetched because Datadog API key is not defined.'))

@@ -5,3 +5,3 @@ 'use strict'

const { safeJSONStringify } = require('../../../exporters/common/util')
const { getEnvironmentVariable } = require('../../../config-helper')
const { getValueFromEnvSources } = require('../../../config/helper')

@@ -33,3 +33,3 @@ const { CoverageCIVisibilityEncoder } = require('../../../encode/coverage-ci-visibility')

headers: {
'dd-api-key': getEnvironmentVariable('DD_API_KEY'),
'dd-api-key': getValueFromEnvSources('DD_API_KEY'),
...form.getHeaders()

@@ -36,0 +36,0 @@ },

@@ -6,3 +6,3 @@ 'use strict'

const { JSONEncoder } = require('../../encode/json-encoder')
const { getEnvironmentVariable } = require('../../../config-helper')
const { getValueFromEnvSources } = require('../../../config/helper')

@@ -28,3 +28,3 @@ const BaseWriter = require('../../../exporters/common/writer')

headers: {
'dd-api-key': getEnvironmentVariable('DD_API_KEY'),
'dd-api-key': getValueFromEnvSources('DD_API_KEY'),
'Content-Type': 'application/json'

@@ -31,0 +31,0 @@ },

@@ -5,3 +5,3 @@ 'use strict'

const log = require('../../../log')
const { getEnvironmentVariable } = require('../../../config-helper')
const { getValueFromEnvSources } = require('../../../config/helper')

@@ -34,3 +34,3 @@ const { AgentlessCiVisibilityEncoder } = require('../../../encode/agentless-ci-visibility')

headers: {
'dd-api-key': getEnvironmentVariable('DD_API_KEY'),
'dd-api-key': getValueFromEnvSources('DD_API_KEY'),
'Content-Type': 'application/msgpack'

@@ -37,0 +37,0 @@ },

@@ -71,3 +71,3 @@ 'use strict'

process.once('beforeExit', () => {
const flush = () => {
if (this._writer) {

@@ -82,3 +82,4 @@ this._writer.flush()

}
})
}
globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(flush.bind(this))
}

@@ -85,0 +86,0 @@

@@ -8,3 +8,3 @@ 'use strict'

const request = require('../../../exporters/common/request')
const { getEnvironmentVariable } = require('../../../config-helper')
const { getValueFromEnvSources } = require('../../../config/helper')

@@ -55,3 +55,3 @@ const log = require('../../../log')

headers: {
'dd-api-key': getEnvironmentVariable('DD_API_KEY')
'dd-api-key': getValueFromEnvSources('DD_API_KEY')
},

@@ -293,3 +293,3 @@ timeout: 15_000,

log.debug('It is shallow clone, unshallowing...')
if (!isFalse(getEnvironmentVariable('DD_CIVISIBILITY_GIT_UNSHALLOW_ENABLED'))) {
if (!isFalse(getValueFromEnvSources('DD_CIVISIBILITY_GIT_UNSHALLOW_ENABLED'))) {
unshallowRepository(false)

@@ -296,0 +296,0 @@ }

@@ -13,3 +13,3 @@ 'use strict'

} = require('../../../plugins/util/test')
const { getEnvironmentVariable } = require('../../../config-helper')
const { getEnvironmentVariable, getValueFromEnvSources } = require('../../../config/helper')
const Writer = require('./writer')

@@ -27,3 +27,3 @@

}
if (getEnvironmentVariable('DD_PLAYWRIGHT_WORKER')) {
if (getValueFromEnvSources('DD_PLAYWRIGHT_WORKER')) {
return PLAYWRIGHT_WORKER_TRACE_PAYLOAD_CODE

@@ -34,3 +34,3 @@ }

}
if (getEnvironmentVariable('DD_VITEST_WORKER')) {
if (getValueFromEnvSources('DD_VITEST_WORKER')) {
return VITEST_WORKER_TRACE_PAYLOAD_CODE

@@ -56,3 +56,3 @@ }

}
if (getEnvironmentVariable('DD_VITEST_WORKER')) {
if (getValueFromEnvSources('DD_VITEST_WORKER')) {
return VITEST_WORKER_LOGS_PAYLOAD_CODE

@@ -59,0 +59,0 @@ }

'use strict'
const { JSONEncoder } = require('../../encode/json-encoder')
const { getEnvironmentVariable } = require('../../../config-helper')
const { getEnvironmentVariable } = require('../../../config/helper')
const log = require('../../../log')

@@ -5,0 +5,0 @@ const {

@@ -5,3 +5,3 @@ 'use strict'

const log = require('../../log')
const { getEnvironmentVariable } = require('../../config-helper')
const { getValueFromEnvSources } = require('../../config/helper')
const {

@@ -53,3 +53,3 @@ incrementCountMetric,

} else {
const apiKey = getEnvironmentVariable('DD_API_KEY')
const apiKey = getValueFromEnvSources('DD_API_KEY')
if (!apiKey) {

@@ -56,0 +56,0 @@ return done(new Error('Skippable suites were not fetched because Datadog API key is not defined.'))

@@ -5,3 +5,3 @@ 'use strict'

const log = require('../../log')
const { getEnvironmentVariable } = require('../../config-helper')
const { getValueFromEnvSources } = require('../../config/helper')

@@ -16,7 +16,7 @@ function getWinstonLogSubmissionParameters (config) {

headers: {
'DD-API-KEY': getEnvironmentVariable('DD_API_KEY')
'DD-API-KEY': getValueFromEnvSources('DD_API_KEY')
}
}
if (!getEnvironmentVariable('DD_AGENTLESS_LOG_SUBMISSION_URL')) {
if (!getValueFromEnvSources('DD_AGENTLESS_LOG_SUBMISSION_URL')) {
return defaultParameters

@@ -26,3 +26,3 @@ }

try {
const url = new URL(getEnvironmentVariable('DD_AGENTLESS_LOG_SUBMISSION_URL'))
const url = new URL(getValueFromEnvSources('DD_AGENTLESS_LOG_SUBMISSION_URL'))
return {

@@ -29,0 +29,0 @@ host: url.hostname,

@@ -6,3 +6,3 @@ 'use strict'

const log = require('../../log')
const { getEnvironmentVariable } = require('../../config-helper')
const { getValueFromEnvSources } = require('../../config/helper')
const {

@@ -52,3 +52,3 @@ incrementCountMetric,

} else {
const apiKey = getEnvironmentVariable('DD_API_KEY')
const apiKey = getValueFromEnvSources('DD_API_KEY')
if (!apiKey) {

@@ -131,7 +131,7 @@ return done(new Error('Request to settings endpoint was not done because Datadog API key is not defined.'))

if (getEnvironmentVariable('DD_CIVISIBILITY_DANGEROUSLY_FORCE_COVERAGE')) {
if (getValueFromEnvSources('DD_CIVISIBILITY_DANGEROUSLY_FORCE_COVERAGE')) {
settings.isCodeCoverageEnabled = true
log.debug('Dangerously set code coverage to true')
}
if (getEnvironmentVariable('DD_CIVISIBILITY_DANGEROUSLY_FORCE_TEST_SKIPPING')) {
if (getValueFromEnvSources('DD_CIVISIBILITY_DANGEROUSLY_FORCE_TEST_SKIPPING')) {
settings.isSuitesSkippingEnabled = true

@@ -138,0 +138,0 @@ log.debug('Dangerously set test skipping to true')

@@ -5,3 +5,3 @@ 'use strict'

const id = require('../../id')
const { getEnvironmentVariable } = require('../../config-helper')
const { getValueFromEnvSources } = require('../../config/helper')
const log = require('../../log')

@@ -39,3 +39,3 @@

} else {
const apiKey = getEnvironmentVariable('DD_API_KEY')
const apiKey = getValueFromEnvSources('DD_API_KEY')
if (!apiKey) {

@@ -42,0 +42,0 @@ return done(new Error('Test management tests were not fetched because Datadog API key is not defined.'))

'use strict'
const RemoteConfigCapabilities = require('../remote_config/capabilities')
const log = require('../log')
module.exports = {
enable
}
/**
* @typedef {object} RemoteConfigOptions
* @property {boolean} [dynamic_instrumentation_enabled] - Enable Dynamic Instrumentation
* @property {boolean} [code_origin_enabled] - Enable code origin tagging for spans
* @property {Array<{header: string, tag_name?: string}>} [tracing_header_tags] - HTTP headers to tag
* @property {Array<string>} [tracing_tags] - Global tags (format: "key:value")
* @property {number} [tracing_sampling_rate] - Global sampling rate (0.0-1.0)
* @property {boolean} [log_injection_enabled] - Enable trace context log injection
* @property {boolean} [tracing_enabled] - Enable/disable tracing globally
* @property {Array<object>} [tracing_sampling_rules] - Trace sampling rules configuration
*/
/**
* @typedef {ReturnType<import('../config')>} Config
*/
/**
* Manages multiple APM_TRACING configurations with priority-based merging
*/
class RCClientLibConfigManager {
/**
* @param {string} currentService - Current service name
* @param {string} currentEnv - Current environment name
*/
constructor (currentService, currentEnv) {
this.configs = new Map() // config_id -> { conf, priority }
this.currentService = currentService
this.currentEnv = currentEnv
}
/**
* Calculate priority based on target specificity. Higher values take precedence.
* Priority order (highest → lowest):
* Service+Env (5) > Service (4) > Env (3) > Cluster (2) > Org (1)
*
* @param {object} conf - Remote config object with service_target and k8s_target_v2 properties
* @returns {number} Priority value from 1 (org-level) to 5 (service+env specific)
*/
calculatePriority (conf) {
const serviceTarget = conf.service_target
const k8sTarget = conf.k8s_target_v2
if (serviceTarget) {
const service = serviceTarget.service
const env = serviceTarget.env
const hasSpecificService = service && service !== '*'
const hasSpecificEnv = env && env !== '*'
if (hasSpecificService && hasSpecificEnv) return 5
if (hasSpecificService) return 4
if (hasSpecificEnv) return 3
}
if (k8sTarget) return 2
return 1 // Org level
}
/**
* Check if config matches current service/env
*
* @param {object} conf - Remote config object with service_target property
* @returns {boolean} True if config matches current service/env or has no filter
*/
matchesCurrentServiceEnv (conf) {
const serviceTarget = conf.service_target
if (!serviceTarget) return true // No filter means match all
const service = serviceTarget.service
const env = serviceTarget.env
// Check service match
if (service && service !== '*' && service !== this.currentService) {
log.debug('[config/remote_config] Ignoring config for service: %s (current: %s)',
service, this.currentService)
return false
}
// Check env match
if (env && env !== '*' && env !== this.currentEnv) {
log.debug('[config/remote_config] Ignoring config for env: %s (current: %s)',
env, this.currentEnv)
return false
}
return true
}
/**
* Add or update a config
*
* @param {string} configId - Unique identifier for the config
* @param {object} conf - Remote config object to add
*/
addConfig (configId, conf) {
if (!this.matchesCurrentServiceEnv(conf)) {
return
}
const priority = this.calculatePriority(conf)
this.configs.set(configId, { conf, priority })
log.debug('[config/remote_config] Added config %s with priority %d', configId, priority)
}
/**
* Remove a config
*
* @param {string} configId - Unique identifier for the config to remove
*/
removeConfig (configId) {
const removed = this.configs.delete(configId)
if (removed) {
log.debug('[config/remote_config] Removed config %s', configId)
}
}
/**
* Get merged lib_config with higher priority configs overriding lower priority ones
*
* @returns {RemoteConfigOptions|null} Merged config object or null if no configs present
*/
getMergedLibConfig () {
if (this.configs.size === 0) return null
let hasLibConfig = false
const merged = [...this.configs.values()]
.sort((a, b) => a.priority - b.priority)
.reduce((merged, { conf }) => {
if (conf.lib_config != null) hasLibConfig = true
return Object.assign(merged, conf.lib_config)
}, {})
return hasLibConfig ? merged : null
}
}
/**
* Configures remote config for core APM tracing functionality
*
* @param {object} rc - RemoteConfig instance
* @param {object} config - Tracer config
* @param {Function} enableOrDisableTracing - Function to enable/disable tracing based on config
* @param {import('../remote_config')} rc - RemoteConfig instance
* @param {Config} config - Tracer config
* @param {() => void} onConfigUpdated - Function to call when config is updated
*/
function enable (rc, config, enableOrDisableTracing) {
// Register core APM tracing capabilities
function enable (rc, config, onConfigUpdated) {
// This tracer supports receiving config subsets via the APM_TRACING product handler.
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_MULTICONFIG, true)
// Tracing
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_ENABLED, true)
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_SAMPLE_RATE, true)
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_SAMPLE_RULES, true)
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_CUSTOM_TAGS, true)
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_HTTP_HEADER_TAGS, true)
// Log Management
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_LOGS_INJECTION, true)
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_SAMPLE_RATE, true)
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_ENABLED, true)
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_SAMPLE_RULES, true)
// APM_TRACING product handler - manages tracer configuration
rc.setProductHandler('APM_TRACING', (action, conf) => {
if (action === 'unapply') {
config.configure({}, true)
} else {
config.configure(conf.lib_config, true)
// Debugger
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_ENABLE_DYNAMIC_INSTRUMENTATION, true)
// Code Origin
rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_ENABLE_CODE_ORIGIN, true)
const rcClientLibConfigManager = new RCClientLibConfigManager(config.service, config.env)
// Subscribe to APM_TRACING product (setBatchHandler used below doesn't automatically subscribe)
rc.subscribeProducts('APM_TRACING')
// Use a batch handler to process all changes before updating the config. This is important in case there's
// conflicting configs between, for example, the org and service level.
rc.setBatchHandler(['APM_TRACING'], (transaction) => {
const { toUnapply, toApply, toModify } = transaction
for (const item of toUnapply) {
rcClientLibConfigManager.removeConfig(item.id)
transaction.ack(item.path)
}
enableOrDisableTracing(config, rc)
for (const item of [...toApply, ...toModify]) {
rcClientLibConfigManager.addConfig(item.id, item.file)
transaction.ack(item.path)
}
// Get merged config and apply it
const mergedLibConfig = rcClientLibConfigManager.getMergedLibConfig()
config.setRemoteConfig(mergedLibConfig)
onConfigUpdated()
})
}
module.exports = {
enable
}

@@ -10,3 +10,3 @@ 'use strict'

const log = require('../log')
const defaults = require('../config_defaults')
const defaults = require('../config/defaults')
const pkg = require('../../../../package.json')

@@ -13,0 +13,0 @@ const processTags = require('../process-tags')

@@ -159,3 +159,3 @@ 'use strict'

}
process.once('beforeExit', () => this.onInterval())
globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(this.onInterval.bind(this))
}

@@ -162,0 +162,0 @@

@@ -9,3 +9,3 @@ 'use strict'

const { MsgpackEncoder } = require('../msgpack')
const defaults = require('../config_defaults')
const defaults = require('../config/defaults')

@@ -12,0 +12,0 @@ const msgpack = new MsgpackEncoder()

@@ -209,3 +209,3 @@ 'use strict'

function isInstanceOfCoreType (type, variable, fallback = `${variable} instanceof ${type}`) {
return `(process[Symbol.for('datadog:node:util:types')]?.is${type}?.(${variable}) ?? ${fallback})`
return `(globalThis[Symbol.for('dd-trace')].utilTypes?.is${type}?.(${variable}) ?? ${fallback})`
}

@@ -212,0 +212,0 @@

@@ -5,3 +5,3 @@ 'use strict'

const { format } = require('node:url')
const defaults = require('../../config_defaults')
const defaults = require('../../config/defaults')
const log = require('./log')

@@ -8,0 +8,0 @@

@@ -9,3 +9,3 @@ 'use strict'

const { version } = require('../../../../../package.json')
const { getEnvironmentVariable } = require('../../config-helper')
const { getValueFromEnvSources } = require('../../config/helper')
const log = require('./log')

@@ -27,4 +27,4 @@ const JSONBuffer = require('./json-buffer')

const ddtags = [
['env', getEnvironmentVariable('DD_ENV')],
['version', getEnvironmentVariable('DD_VERSION')],
['env', getValueFromEnvSources('DD_ENV')],
['version', getValueFromEnvSources('DD_VERSION')],
['debugger_version', version],

@@ -31,0 +31,0 @@ ['host_name', hostname],

'use strict'
const { getEnvironmentVariable } = require('../../../config-helper')
const { getEnvironmentVariable } = require('../../../config/helper')

@@ -5,0 +5,0 @@ const largeObjectSkipThreshold = Number(

@@ -13,2 +13,4 @@ 'use strict'

let ackId = 0
let rcAckCallbacks = null
let rc = null

@@ -19,7 +21,27 @@ // eslint-disable-next-line eslint-rules/eslint-process-env

module.exports = {
isStarted,
start,
configure
configure,
stop
}
function start (config, rc) {
/**
* Check if the Debugger worker is currently running
*
* @returns {boolean} True if the worker is started, false otherwise
*/
function isStarted () {
return worker !== null
}
/**
* Start the Debugger worker thread.
* Creates a worker thread, sets up message channels, and registers
* the LIVE_DEBUGGING product handler with remote config.
* Does nothing if the worker is already started.
*
* @param {object} config - The tracer configuration object
* @param {object} rcInstance - The RemoteConfig instance
*/
function start (config, rcInstance) {
if (worker !== null) return

@@ -29,3 +51,4 @@

const rcAckCallbacks = new Map()
rc = rcInstance
rcAckCallbacks = new Map()
const probeChannel = new MessageChannel()

@@ -35,3 +58,3 @@ const logChannel = new MessageChannel()

process[Symbol.for('datadog:node:util:types')] = types
globalThis[Symbol.for('dd-trace')].utilTypes = types

@@ -91,15 +114,6 @@ readProbeFile(config.dynamicInstrumentation.probeFile, (probes) => {

worker.on('exit', (code) => {
worker.once('exit', (code) => {
const error = new Error(`Dynamic Instrumentation worker thread exited unexpectedly with code ${code}`)
log.error('[debugger] worker thread exited unexpectedly', error)
// Be nice, clean up now that the worker thread encountered an issue and we can't continue
rc.removeProductHandler('LIVE_DEBUGGING')
worker.removeAllListeners()
configChannel = null
for (const ackId of rcAckCallbacks.keys()) {
rcAckCallbacks.get(ackId)(error)
rcAckCallbacks.delete(ackId)
}
cleanup(error) // Be nice, clean up now that the worker thread encountered an issue and we can't continue
})

@@ -116,2 +130,9 @@

/**
* Reconfigure the Debugger worker with updated settings.
* Sends the new configuration to the worker thread via the config channel.
* Does nothing if the worker is not started.
*
* @param {object} config - The updated tracer configuration object
*/
function configure (config) {

@@ -122,2 +143,49 @@ if (configChannel === null) return

/**
* Stop the Debugger worker thread.
* Terminates the worker and cleans up resources.
* Safe to call even if the worker is not started.
*/
function stop () {
if (worker === null) return
log.debug('[debugger] Stopping Dynamic Instrumentation client...')
try {
worker.terminate()
cleanup() // Graceful shutdown - termination succeeded
} catch (err) {
log.error('[debugger] Error terminating worker', err)
cleanup(err) // Cleanup with error - termination failed
}
}
/**
* Internal cleanup function to reset all debugger resources.
* Called when stopping the debugger or when the worker exits unexpectedly.
*
* @param {Error} [error] - Optional error to pass to pending ack callbacks (for unexpected exits)
*/
function cleanup (error) {
if (rc) {
rc.removeProductHandler('LIVE_DEBUGGING')
rc = null
}
if (worker) {
worker.removeAllListeners()
worker = null
}
configChannel = null
// Call any pending ack callbacks
// Pass error for unexpected exits, or undefined for graceful shutdown
if (rcAckCallbacks) {
for (const ackId of rcAckCallbacks.keys()) {
rcAckCallbacks.get(ackId)(error)
rcAckCallbacks.delete(ackId)
}
rcAckCallbacks = null
}
}
function readProbeFile (path, cb) {

@@ -124,0 +192,0 @@ if (!path) return

@@ -11,3 +11,3 @@ 'use strict'

const Histogram = require('./histogram')
const defaults = require('./config_defaults')
const defaults = require('./config/defaults')

@@ -364,3 +364,3 @@ const MAX_BUFFER_SIZE = 1024 // limit from the agent

process.once('beforeExit', flush)
globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(flush)
}

@@ -367,0 +367,0 @@

@@ -7,3 +7,3 @@ 'use strict'

const { memoize } = require('../log/utils')
const { getEnvironmentVariable } = require('../config-helper')
const { getValueFromEnvSources } = require('../config/helper')
const { truncateSpan, normalizeSpan } = require('./tags-processors')

@@ -35,3 +35,3 @@

this._reset()
this._debugEncoding = isTrue(getEnvironmentVariable('DD_TRACE_ENCODING_DEBUG'))
this._debugEncoding = isTrue(getValueFromEnvSources('DD_TRACE_ENCODING_DEBUG'))
this._config = this._writer?._config

@@ -38,0 +38,0 @@ }

@@ -5,3 +5,3 @@ 'use strict'

const exporters = require('../../../ext/exporters')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getEnvironmentVariable } = require('../../dd-trace/src/config/helper')
const constants = require('./constants')

@@ -8,0 +8,0 @@

@@ -5,3 +5,3 @@ 'use strict'

const log = require('../../log')
const defaults = require('../../config_defaults')
const defaults = require('../../config/defaults')
const Writer = require('./writer')

@@ -35,5 +35,3 @@

process.once('beforeExit', () => {
this.flush()
})
globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(this.flush.bind(this))
}

@@ -40,0 +38,0 @@

'use strict'
const { inspect } = require('util')
const request = require('../common/request')

@@ -29,3 +31,6 @@ const { startupLog } = require('../../startup-log')

const { _headers, _lookup, _protocolVersion, _url } = this
makeRequest(_protocolVersion, data, count, _url, _headers, _lookup, true, (err, res, status) => {
makeRequest(_protocolVersion, data, count, _url, _headers, _lookup, (err, res, status) => {
// Note that logging will only happen once, regardless of how many times this is called.
startupLog(status !== 404 && status !== 200 ? { status, message: err?.message ?? inspect(err) } : undefined)
if (status) {

@@ -43,4 +48,2 @@ runtimeMetrics.increment(`${METRIC_PREFIX}.responses`, true)

startupLog({ agentError: err })
if (err) {

@@ -73,3 +76,3 @@ log.errorWithoutTelemetry('Error sending payload to the agent (status code: %s)', err.status, err)

function makeRequest (version, data, count, url, headers, lookup, needsStartupLog, cb) {
function makeRequest (version, data, count, url, headers, lookup, cb) {
const options = {

@@ -85,3 +88,3 @@ path: `/v${version}/traces`,

'Datadog-Meta-Lang-Version': process.version,
'Datadog-Meta-Lang-Interpreter': process.jsEngine || 'v8'
'Datadog-Meta-Lang-Interpreter': process.versions.bun ? 'JavaScriptCore' : 'v8'
},

@@ -94,13 +97,5 @@ lookup,

request(data, options, (err, res, status) => {
if (needsStartupLog) {
// Note that logging will only happen once, regardless of how many times this is called.
startupLog({
agentError: status !== 404 && status !== 200 ? err : undefined
})
}
cb(err, res, status)
})
request(data, options, cb)
}
module.exports = AgentWriter

@@ -5,3 +5,3 @@ 'use strict'

const defaults = require('../../config_defaults')
const defaults = require('../../config/defaults')
const { incrementCountMetric, TELEMETRY_EVENTS_ENQUEUED_FOR_SERIALIZATION } = require('../../ci-visibility/telemetry')

@@ -8,0 +8,0 @@ const request = require('./request')

'use strict'
const fs = require('fs')
const { getEnvironmentVariable } = require('../../config-helper')
const { getValueFromEnvSources } = require('../../config/helper')
const DD_EXTERNAL_ENV = getEnvironmentVariable('DD_EXTERNAL_ENV')
const DD_EXTERNAL_ENV = getValueFromEnvSources('DD_EXTERNAL_ENV')

@@ -8,0 +8,0 @@ // The second part is the PCF / Garden regexp. We currently assume no suffix($) to avoid matching pod UIDs

@@ -80,3 +80,3 @@ 'use strict'

})
res.on('end', () => {
res.once('end', () => {
activeRequests--

@@ -83,0 +83,0 @@ const buffer = Buffer.concat(chunks)

'use strict'
const { getEnvironmentVariable } = require('../../config-helper')
const { getValueFromEnvSources } = require('../../config/helper')

@@ -9,3 +9,3 @@ function safeJSONStringify (value) {

(key, value) => key === 'dd-api-key' ? undefined : value,
getEnvironmentVariable('DD_TRACE_BEAUTIFUL_LOGS') ? 2 : undefined
getValueFromEnvSources('DD_TRACE_BEAUTIFUL_LOGS') ? 2 : undefined
)

@@ -12,0 +12,0 @@ }

@@ -5,3 +5,3 @@ 'use strict'

const defaults = require('../../config_defaults')
const defaults = require('../../config/defaults')
const { Writer } = require('./writer')

@@ -8,0 +8,0 @@

@@ -67,3 +67,3 @@ 'use strict'

_sendFile (task, file, filename) {
if (!file) return
if (!file || file.length === 0) return

@@ -70,0 +70,0 @@ const form = new FormData()

@@ -83,3 +83,3 @@ 'use strict'

})
proc.on('exit', function (code) {
proc.once('exit', function (code) {
if (code !== 0) {

@@ -86,0 +86,0 @@ log.error('Telemetry forwarder exited with code', code)

'use strict'
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getValueFromEnvSources } = require('./config/helper')
const { isFalse } = require('./util')

@@ -9,5 +9,5 @@

const ddTraceDisabled = getEnvironmentVariable('DD_TRACE_ENABLED')
? isFalse(getEnvironmentVariable('DD_TRACE_ENABLED'))
: String(getEnvironmentVariable('OTEL_TRACES_EXPORTER')).toLowerCase() === 'none'
const ddTraceDisabled = getValueFromEnvSources('DD_TRACE_ENABLED')
? isFalse(getValueFromEnvSources('DD_TRACE_ENABLED'))
: String(getValueFromEnvSources('OTEL_TRACES_EXPORTER')).toLowerCase() === 'none'

@@ -14,0 +14,0 @@ module.exports = ddTraceDisabled || inJestWorker

@@ -6,3 +6,3 @@ 'use strict'

const { ERROR_MESSAGE, ERROR_TYPE } = require('../constants')
const { getEnvironmentVariable } = require('../config-helper')
const { getValueFromEnvSources } = require('../config/helper')
const { ImpendingTimeout } = require('./runtime/errors')

@@ -30,3 +30,3 @@

let apmFlushDeadline = Number.parseInt(getEnvironmentVariable('DD_APM_FLUSH_DEADLINE_MILLISECONDS')) || 100
let apmFlushDeadline = Number.parseInt(getValueFromEnvSources('DD_APM_FLUSH_DEADLINE_MILLISECONDS')) || 100
apmFlushDeadline = apmFlushDeadline < 0 ? 100 : apmFlushDeadline

@@ -33,0 +33,0 @@

'use strict'
const { getEnvironmentVariable } = require('../config-helper')
const { getValueFromEnvSources } = require('../config/helper')
const { registerLambdaHook } = require('./runtime/ritm')

@@ -10,3 +10,3 @@

*/
const _DD_TRACE_DISABLED_INSTRUMENTATIONS = getEnvironmentVariable('DD_TRACE_DISABLED_INSTRUMENTATIONS') || ''
const _DD_TRACE_DISABLED_INSTRUMENTATIONS = getValueFromEnvSources('DD_TRACE_DISABLED_INSTRUMENTATIONS') || ''
const _disabledInstrumentations = new Set(

@@ -13,0 +13,0 @@ _DD_TRACE_DISABLED_INSTRUMENTATIONS ? _DD_TRACE_DISABLED_INSTRUMENTATIONS.split(',') : []

@@ -8,3 +8,3 @@ 'use strict'

const shimmer = require('../../../../datadog-shimmer')
const { getEnvironmentVariable } = require('../../config-helper')
const { getEnvironmentVariable, getValueFromEnvSources } = require('../../config/helper')
const { _extractModuleNameAndHandlerPath, _extractModuleRootAndHandler, _getLambdaFilePaths } = require('./ritm')

@@ -63,3 +63,3 @@

const lambdaTaskRoot = getEnvironmentVariable('LAMBDA_TASK_ROOT')
const originalLambdaHandler = getEnvironmentVariable('DD_LAMBDA_HANDLER')
const originalLambdaHandler = getValueFromEnvSources('DD_LAMBDA_HANDLER')

@@ -66,0 +66,0 @@ if (originalLambdaHandler === undefined) {

@@ -13,3 +13,3 @@ /**

const log = require('../../log')
const { getEnvironmentVariable } = require('../../config-helper')
const { getEnvironmentVariable, getValueFromEnvSources } = require('../../config/helper')
const Hook = require('../../../../datadog-instrumentations/src/helpers/hook')

@@ -83,3 +83,3 @@ const instrumentations = require('../../../../datadog-instrumentations/src/helpers/instrumentations')

const lambdaTaskRoot = getEnvironmentVariable('LAMBDA_TASK_ROOT')
const originalLambdaHandler = getEnvironmentVariable('DD_LAMBDA_HANDLER')
const originalLambdaHandler = getValueFromEnvSources('DD_LAMBDA_HANDLER')

@@ -86,0 +86,0 @@ if (originalLambdaHandler !== undefined && lambdaTaskRoot !== undefined) {

@@ -20,2 +20,5 @@ 'use strict'

ROOT_PARENT_ID: 'undefined',
DEFAULT_PROMPT_NAME: 'unnamed-prompt',
INTERNAL_CONTEXT_VARIABLE_KEYS: '_dd_context_variable_keys',
INTERNAL_QUERY_VARIABLE_KEYS: '_dd_query_variable_keys',

@@ -28,2 +31,3 @@ MODEL_NAME: '_ml_obs.meta.model_name',

INPUT_VALUE: '_ml_obs.meta.input.value',
INPUT_PROMPT: '_ml_obs.meta.input.prompt',

@@ -47,3 +51,6 @@ OUTPUT_DOCUMENTS: '_ml_obs.meta.output.documents',

INSTRUMENTATION_METHOD_ANNOTATED: 'annotated',
INSTRUMENTATION_METHOD_UNKNOWN: 'unknown'
INSTRUMENTATION_METHOD_UNKNOWN: 'unknown',
ROUTING_API_KEY: '_dd.llmobs.routing.api_key',
ROUTING_SITE: '_dd.llmobs.routing.site'
}

@@ -139,5 +139,5 @@ 'use strict'

function handleEvalMetricAppend (payload) {
function handleEvalMetricAppend ({ payload, routing }) {
try {
evalWriter.append(payload)
evalWriter.append(payload, routing)
} catch (e) {

@@ -144,0 +144,0 @@ log.warn(

@@ -84,4 +84,6 @@ 'use strict'

annotationContext (options, fn) { return fn() }
routingContext (options, fn) { return fn() }
}
module.exports = NoopLLMObs

@@ -425,12 +425,11 @@ 'use strict'

const { id, version } = response.prompt // ResponsePrompt
// TODO: Add proper tagger API for prompt metadata
if (id && version) {
const normalizedVariables = normalizePromptVariables(inputs.prompt.variables)
const chatTemplate = extractChatTemplateFromInstructions(response.instructions, normalizedVariables)
this._tagger._setTag(span, '_ml_obs.meta.input.prompt', {
this._tagger.tagPrompt(span, {
id,
version,
variables: normalizedVariables,
chat_template: chatTemplate
})
template: chatTemplate
}, true)
const tags = { [PROMPT_TRACKING_INSTRUMENTATION_METHOD]: INSTRUMENTATION_METHOD_AUTO }

@@ -437,0 +436,0 @@ if (hasMultimodalInputs(inputs.prompt.variables)) {

@@ -8,3 +8,3 @@ 'use strict'

const logger = require('../log')
const { getEnvironmentVariable } = require('../config-helper')
const { getValueFromEnvSources } = require('../config/helper')
const Span = require('../opentracing/span')

@@ -53,3 +53,3 @@ const { SPAN_KIND, OUTPUT_VALUE, INPUT_VALUE } = require('./constants/tags')

const DD_LLMOBS_ENABLED = getEnvironmentVariable('DD_LLMOBS_ENABLED')
const DD_LLMOBS_ENABLED = getValueFromEnvSources('DD_LLMOBS_ENABLED')

@@ -67,3 +67,3 @@ if (DD_LLMOBS_ENABLED != null && !isTrue(DD_LLMOBS_ENABLED)) {

// based on `APM_TRACING` RC product updates.
this._config.configure({ llmobs })
this._config.updateOptions({ llmobs })

@@ -247,3 +247,3 @@ // configure writers and channel subscribers

const { inputData, outputData, metadata, metrics, tags } = options
const { inputData, outputData, metadata, metrics, tags, prompt } = options

@@ -271,2 +271,5 @@ if (inputData || outputData) {

}
if (prompt) {
this._tagger.tagPrompt(span, prompt)
}
} catch (e) {

@@ -412,3 +415,3 @@ if (e.ddErrorTag) {

// When OTel tracing is enabled, add source:otel tag to allow backend to wait for OTel span conversion
if (isTrue(getEnvironmentVariable('DD_TRACE_OTEL_ENABLED'))) {
if (isTrue(getValueFromEnvSources('DD_TRACE_OTEL_ENABLED'))) {
evaluationTags.source = 'otel'

@@ -427,3 +430,5 @@ }

}
evalMetricAppendCh.publish(payload)
const currentStore = storage.getStore()
const routing = currentStore?.routingContext
evalMetricAppendCh.publish({ payload, routing })
} finally {

@@ -450,2 +455,24 @@ telemetry.recordSubmitEvaluation(options, err)

routingContext (options, fn) {
if (!this.enabled) return fn()
if (!options?.ddApiKey) {
throw new Error('ddApiKey is required for routing context')
}
const currentStore = storage.getStore()
if (currentStore?.routingContext) {
logger.warn(
'[LLM Observability] Nested routing context detected. Inner context will override outer context. ' +
'Spans created in the inner context will only be sent to the inner context.'
)
}
const store = {
...currentStore,
routingContext: {
apiKey: options.ddApiKey,
site: options.ddSite
}
}
return storage.run(store, fn)
}
flush () {

@@ -452,0 +479,0 @@ if (!this.enabled) return

@@ -29,3 +29,6 @@ 'use strict'

SESSION_ID,
NAME
NAME,
INPUT_PROMPT,
ROUTING_API_KEY,
ROUTING_SITE
} = require('./constants/tags')

@@ -82,3 +85,9 @@ const { UNSERIALIZABLE_VALUE_TEXT } = require('./constants/text')

this.#writer.append(formattedEvent)
const mlObsTags = LLMObsTagger.tagMap.get(span)
const routing = {
apiKey: mlObsTags[ROUTING_API_KEY],
site: mlObsTags[ROUTING_SITE]
}
this.#writer.append(formattedEvent, routing)
} catch (e) {

@@ -127,7 +136,2 @@ // this should be a rare case

// Handle prompt metadata for reusable prompts
if (mlObsTags['_ml_obs.meta.input.prompt']) {
input.prompt = mlObsTags['_ml_obs.meta.input.prompt']
}
if (spanKind === 'llm' && mlObsTags[OUTPUT_MESSAGES]) {

@@ -183,2 +187,8 @@ llmObsSpan.output = mlObsTags[OUTPUT_MESSAGES]

const prompt = mlObsTags[INPUT_PROMPT]
if (prompt && spanKind === 'llm') {
// by this point, we should have logged a warning if the span kind was not llm
meta.input.prompt = prompt
}
const llmObsSpanEvent = {

@@ -185,0 +195,0 @@ trace_id: span.context().toTraceId(true),

@@ -31,3 +31,11 @@ 'use strict'

DECORATOR,
PROPAGATED_ML_APP_KEY
PROPAGATED_ML_APP_KEY,
DEFAULT_PROMPT_NAME,
INTERNAL_CONTEXT_VARIABLE_KEYS,
INTERNAL_QUERY_VARIABLE_KEYS,
INPUT_PROMPT,
ROUTING_API_KEY,
ROUTING_SITE,
PROMPT_TRACKING_INSTRUMENTATION_METHOD,
INSTRUMENTATION_METHOD_ANNOTATED
} = require('./constants/tags')

@@ -114,2 +122,14 @@ const { storage } = require('./storage')

if (annotationContextName) this._setTag(span, NAME, annotationContextName)
// apply annotation context prompt
const annotationContextPrompt = annotationContext?.prompt
if (annotationContextPrompt) this.tagPrompt(span, annotationContextPrompt)
const routing = storage.getStore()?.routingContext
if (routing) {
this._setTag(span, ROUTING_API_KEY, routing.apiKey)
if (routing.site) {
this._setTag(span, ROUTING_SITE, routing.site)
}
}
}

@@ -199,2 +219,156 @@

/**
* Tags a prompt on an LLMObs span.
* @param {import('../opentracing/span')} span
* @param {string | Record<string, unknown>} prompt
* @param {boolean?} strictValidation
* whether to validate the prompt against the strict schema, used for auto-instrumentation
*/
tagPrompt (span, prompt, strictValidation = false) {
const spanKind = registry.get(span)?.[SPAN_KIND]
if (spanKind !== 'llm') {
log.warn('Dropping prompt on non-LLM span kind, annotating prompts is only supported for LLM span kinds.')
return
}
if (!prompt || typeof prompt !== 'object') {
this.#handleFailure('Prompt must be an object.', 'invalid_prompt')
return
}
const mlApp = registry.get(span)?.[ML_APP] // this should be defined at this point
const {
id,
version,
tags,
variables,
template,
contextVariables,
queryVariables,
} = prompt
if (strictValidation) {
if (id == null) {
this.#handleFailure('Prompt ID is required.', 'invalid_prompt')
return
}
if (template == null) {
this.#handleFailure('Prompt template is required.', 'invalid_prompt')
return
}
}
const finalPromptId = id ?? `${mlApp}_${DEFAULT_PROMPT_NAME}`
const finalCtxVariablesKeys = contextVariables ?? ['context']
const finalQueryVariablesKeys = queryVariables ?? ['question']
// validate prompt id
if (typeof finalPromptId !== 'string') {
this.#handleFailure('Prompt ID must be a string.', 'invalid_prompt')
return
}
// validate prompt context variables keys
if (Array.isArray(finalCtxVariablesKeys)) {
for (const key of finalCtxVariablesKeys) {
if (typeof key !== 'string') {
this.#handleFailure('Prompt context variables keys must be an array of strings.', 'invalid_prompt')
return
}
}
} else if (finalCtxVariablesKeys) {
this.#handleFailure('Prompt context variables keys must be an array.', 'invalid_prompt')
return
}
// validate prompt query variables keys
if (Array.isArray(finalQueryVariablesKeys)) {
for (const key of finalQueryVariablesKeys) {
if (typeof key !== 'string') {
this.#handleFailure('Prompt query variables keys must be an array of strings.', 'invalid_prompt')
return
}
}
} else if (finalQueryVariablesKeys) {
this.#handleFailure('Prompt query variables keys must be an array.', 'invalid_prompt')
return
}
// validate prompt version
if (version && typeof version !== 'string') {
this.#handleFailure('Prompt version must be a string.', 'invalid_prompt')
return
}
// validate prompt tags
if (tags && (typeof tags !== 'object' || tags instanceof Map)) {
this.#handleFailure('Prompt tags must be an non-Map object.', 'invalid_prompt')
return
} else if (tags) {
for (const [key, value] of Object.entries(tags)) {
if (typeof key !== 'string' || typeof value !== 'string') {
this.#handleFailure('Prompt tags must be an object of string key-value pairs.', 'invalid_prompt')
return
}
}
}
// validate prompt template is either string or list of messages
if (template && !(typeof template === 'string' || Array.isArray(template))) {
this.#handleFailure('Prompt template must be a string or an array of messages.', 'invalid_prompt')
return
}
if (Array.isArray(template)) {
for (const message of template) {
if (typeof message !== 'object' || !message.role || !message.content) {
this.#handleFailure(
'Prompt chat template must be an array of objects with role and content properties.', 'invalid_prompt'
)
return
}
}
}
// validate variables are a string-string mapping
if (variables && (typeof variables !== 'object' || variables instanceof Map)) {
this.#handleFailure('Prompt variables must be an non-Map object.', 'invalid_prompt')
return
} else if (variables) {
for (const [key, value] of Object.entries(variables)) {
if (typeof key !== 'string' || typeof value !== 'string') {
this.#handleFailure('Prompt variables must be an object of string key-value pairs.', 'invalid_prompt')
return
}
}
}
let finalTemplate, finalChatTemplate
if (typeof template === 'string') {
finalTemplate = template
} else if (Array.isArray(template)) {
finalChatTemplate = template.map(message => ({ role: message.role, content: message.content }))
}
const validatedPrompt = {}
if (finalPromptId) validatedPrompt.id = finalPromptId
if (version) validatedPrompt.version = version
if (variables) validatedPrompt.variables = variables
if (finalTemplate) validatedPrompt.template = finalTemplate
if (finalChatTemplate?.length) validatedPrompt.chat_template = finalChatTemplate
if (tags) validatedPrompt.tags = tags
if (finalCtxVariablesKeys) validatedPrompt[INTERNAL_CONTEXT_VARIABLE_KEYS] = finalCtxVariablesKeys
if (finalQueryVariablesKeys) validatedPrompt[INTERNAL_QUERY_VARIABLE_KEYS] = finalQueryVariablesKeys
const currentPrompt = registry.get(span)?.[INPUT_PROMPT]
if (currentPrompt) {
Object.assign(currentPrompt, validatedPrompt)
} else {
this._setTag(span, INPUT_PROMPT, validatedPrompt)
}
this.tagSpanTags(span, { [PROMPT_TRACKING_INSTRUMENTATION_METHOD]: INSTRUMENTATION_METHOD_ANNOTATED })
}
changeKind (span, newKind) {

@@ -201,0 +375,0 @@ this._setTag(span, SPAN_KIND, newKind)

@@ -6,3 +6,3 @@ 'use strict'

const request = require('../../exporters/common/request')
const { getEnvironmentVariable } = require('../../config-helper')
const { getEnvironmentVariable } = require('../../config/helper')

@@ -20,3 +20,22 @@ const logger = require('../../log')

class LLMObsBuffer {
constructor ({ events, size, routing = {}, isDefault = false, limit = 1000 }) {
this.events = events
this.size = size
this.routing = routing
this.isDefault = isDefault
this.limit = limit
}
clear () {
this.events = []
this.size = 0
}
}
class BaseLLMObsWriter {
#destroyer
/** @type {Map<string, LLMObsBuffer>} */
#multiTenantBuffers = new Map()
constructor ({ interval, timeout, eventType, config, endpoint, intake }) {

@@ -27,8 +46,8 @@ this._interval = interval ?? getEnvironmentVariable('_DD_LLMOBS_FLUSH_INTERVAL') ?? 1000 // 1s

this._buffer = []
this._bufferLimit = 1000
this._bufferSize = 0
/** @type {LLMObsBuffer} */
this._buffer = new LLMObsBuffer({ events: [], size: 0, isDefault: true })
this._config = config
this._endpoint = endpoint
this._baseEndpoint = endpoint // should not be unset
this._intake = intake

@@ -40,25 +59,38 @@

this._beforeExitHandler = () => {
this.destroy()
}
process.once('beforeExit', this._beforeExitHandler)
const destroyer = this.destroy.bind(this)
globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(destroyer)
this._destroyed = false
this.#destroyer = destroyer
}
// Split on protocol separator to preserve it
// path.join will remove some slashes unnecessarily
#buildUrl (baseUrl, endpoint) {
const [protocol, rest] = baseUrl.split('://')
return protocol + '://' + path.join(rest, endpoint)
}
get url () {
if (this._agentless == null) return null
return this.#buildUrl(this._baseUrl.href, this._endpoint)
}
const baseUrl = this._baseUrl.href
const endpoint = this._endpoint
// Split on protocol separator to preserve it
// path.join will remove some slashes unnecessarily
const [protocol, rest] = baseUrl.split('://')
return protocol + '://' + path.join(rest, endpoint)
_getBuffer (routing) {
if (!routing?.apiKey) {
return this._buffer
}
const apiKey = routing.apiKey
let buffer = this.#multiTenantBuffers.get(apiKey)
if (!buffer) {
buffer = new LLMObsBuffer({ events: [], size: 0, routing })
this.#multiTenantBuffers.set(apiKey, buffer)
}
return buffer
}
append (event, byteLength) {
if (this._buffer.length >= this._bufferLimit) {
logger.warn(`${this.constructor.name} event buffer full (limit is ${this._bufferLimit}), dropping event`)
append (event, routing, byteLength) {
const buffer = this._getBuffer(routing)
if (buffer.events.length >= buffer.limit) {
logger.warn(`${this.constructor.name} event buffer full (limit is ${buffer.limit}), dropping event`)
telemetry.recordDroppedPayload(1, this._eventType, 'buffer_full')

@@ -68,36 +100,82 @@ return

this._bufferSize += byteLength || Buffer.byteLength(JSON.stringify(event))
this._buffer.push(event)
const eventSize = byteLength || Buffer.byteLength(JSON.stringify(event))
buffer.size += eventSize
buffer.events.push(event)
}
flush () {
const noAgentStrategy = this._agentless == null
if (this._buffer.length === 0 || noAgentStrategy) {
if (this._agentless == null) {
return
}
const events = this._buffer
this._buffer = []
this._bufferSize = 0
const payload = this._encode(this.makePayload(events))
// Flush default buffer
if (this._buffer.events.length > 0) {
const events = this._buffer.events
this._buffer.clear()
log.debug('Encoded LLMObs payload: %s', payload)
const payload = this._encode(this.makePayload(events))
const options = this._getOptions()
log.debug('Encoded LLMObs payload: %s', payload)
request(payload, options, (err, resp, code) => {
parseResponseAndLog(err, code, events.length, this.url, this._eventType)
})
const options = this._getOptions()
request(payload, options, (err, resp, code) => {
parseResponseAndLog(err, code, events.length, this.url, this._eventType)
})
}
// Flush multi-tenant buffers
for (const [apiKey, buffer] of this.#multiTenantBuffers) {
if (buffer.events.length === 0) continue
const events = buffer.events
buffer.clear()
const payload = this._encode(this.makePayload(events))
const site = buffer.routing.site || this._config.site
const options = {
headers: {
'Content-Type': 'application/json',
'DD-API-KEY': apiKey
},
method: 'POST',
timeout: this._timeout,
url: new URL(format({
protocol: 'https:',
hostname: `${this._intake}.${site}`
})),
path: this._baseEndpoint
}
const url = this.#buildUrl(options.url.href, options.path)
const maskedApiKey = apiKey ? `****${apiKey.slice(-4)}` : ''
log.debug('Encoding and flushing multi-tenant buffer for %s', maskedApiKey)
log.debug('Encoded LLMObs payload: %s', payload)
request(payload, options, (err, resp, code) => {
parseResponseAndLog(err, code, events.length, url, this._eventType)
})
}
this.#cleanupEmptyBuffers()
}
#cleanupEmptyBuffers () {
for (const [key, buffer] of this.#multiTenantBuffers) {
if (buffer.events.length === 0) {
this.#multiTenantBuffers.delete(key)
}
}
}
makePayload (events) {}
destroy () {
if (!this._destroyed) {
if (this.#destroyer) {
logger.debug(`Stopping ${this.constructor.name}`)
clearInterval(this._periodic)
process.removeListener('beforeExit', this._beforeExitHandler)
globalThis[Symbol.for('dd-trace')].beforeExitHandlers.delete(this.#destroyer)
this.flush()
this._destroyed = true
this.#destroyer = undefined
}

@@ -118,6 +196,7 @@ }

if (this._agentless) {
const site = this._config.site
return {
url: new URL(format({
protocol: 'https:',
hostname: `${this._intake}.${this._config.site}`
hostname: `${this._intake}.${site}`
})),

@@ -124,0 +203,0 @@ endpoint: this._endpoint

@@ -27,3 +27,3 @@ 'use strict'

append (event) {
append (event, routing) {
const eventSizeBytes = Buffer.byteLength(JSON.stringify(event))

@@ -43,3 +43,4 @@ telemetry.recordLLMObsRawSpanSize(event, eventSizeBytes)

if (this._bufferSize + eventSizeBytes > EVP_PAYLOAD_SIZE_LIMIT) {
const buffer = this._getBuffer(routing)
if (buffer.size + processedEventSizeBytes > EVP_PAYLOAD_SIZE_LIMIT) {
logger.debug('Flushing queue because queuing next event will exceed EvP payload limit')

@@ -49,3 +50,3 @@ this.flush()

super.append(event, processedEventSizeBytes)
super.append(event, routing, processedEventSizeBytes)
}

@@ -52,0 +53,0 @@

'use strict'
const { inspect } = require('util')
const { isTrue } = require('../util')
const { getEnvironmentVariable } = require('../config-helper')
const { getValueFromEnvSources } = require('../config/helper')
const { traceChannel, debugChannel, infoChannel, warnChannel, errorChannel } = require('./channels')

@@ -115,4 +115,4 @@ const logWriter = require('./writer')

fleetStableConfigValue ??
getEnvironmentVariable('DD_TRACE_DEBUG') ??
(getEnvironmentVariable('OTEL_LOG_LEVEL') === 'debug' || undefined) ??
getValueFromEnvSources('DD_TRACE_DEBUG') ??
(getValueFromEnvSources('OTEL_LOG_LEVEL') === 'debug' || undefined) ??
localStableConfigValue ??

@@ -130,4 +130,4 @@ config.enabled

fleetStableConfigValue ??
getEnvironmentVariable('DD_TRACE_LOG_LEVEL') ??
getEnvironmentVariable('OTEL_LOG_LEVEL') ??
getValueFromEnvSources('DD_TRACE_LOG_LEVEL') ??
getValueFromEnvSources('OTEL_LOG_LEVEL') ??
localStableConfigValue ??

@@ -134,0 +134,0 @@ config.logLevel

@@ -26,6 +26,6 @@ 'use strict'

this.aiguard = noopAIGuard
this.setBaggageItem = () => {}
this.getBaggageItem = () => {}
this.setBaggageItem = (key, value) => {}
this.getBaggageItem = (key) => {}
this.getAllBaggageItems = () => {}
this.removeBaggageItem = () => {}
this.removeBaggageItem = (keyToRemove) => {}
this.removeAllBaggageItems = () => {}

@@ -32,0 +32,0 @@ }

@@ -26,2 +26,3 @@ 'use strict'

class BaseFFEWriter {
#destroyer
/**

@@ -60,8 +61,6 @@ * @param {BaseFFEWriterOptions} options - Writer configuration options

this._beforeExitHandler = () => {
this.destroy()
}
process.once('beforeExit', this._beforeExitHandler)
const destroyer = this.destroy.bind(this)
globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(destroyer)
this._destroyed = false
this.#destroyer = destroyer
this._droppedEvents = 0

@@ -146,8 +145,8 @@ }

destroy () {
if (!this._destroyed) {
if (this.#destroyer) {
log.debug(() => `Stopping ${this.constructor.name}`)
clearInterval(this._periodic)
process.removeListener('beforeExit', this._beforeExitHandler)
this.flush()
this._destroyed = true
globalThis[Symbol.for('dd-trace')].beforeExitHandlers.delete(this.#destroyer)
this.#destroyer = undefined

@@ -154,0 +153,0 @@ if (this._droppedEvents > 0) {

@@ -93,3 +93,3 @@ 'use strict'

res.on('end', () => {
res.once('end', () => {
if (res.statusCode >= 200 && res.statusCode < 300) {

@@ -109,3 +109,3 @@ resultCallback({ code: 0 })

req.on('timeout', () => {
req.once('timeout', () => {
req.destroy()

@@ -112,0 +112,0 @@ const error = new Error('Request timeout')

@@ -8,2 +8,3 @@ 'use strict'

const log = require('../log')
const DatadogSpanContext = require('../opentracing/span_context')
const TextMapPropagator = require('../opentracing/propagation/text_map')

@@ -15,2 +16,37 @@ const TraceState = require('../opentracing/propagation/tracestate')

function normalizeLinkContext (context) {
if (!context) return
// OTel API bridge SpanContext wrapper
if (context._ddContext) return context._ddContext
// Datadog span context
if (typeof context.toTraceId === 'function' && typeof context.toSpanId === 'function') {
return context
}
// Standard OTel SpanContext (traceId/spanId)
if (typeof context.traceId !== 'string' || typeof context.spanId !== 'string') {
// Invalid
return
}
let sampling
if (typeof context.traceFlags === 'number') {
sampling = { priority: context.traceFlags & 1 }
}
let tracestate
if (context.traceState?.serialize) {
tracestate = TraceState.fromString(context.traceState.serialize())
}
return new DatadogSpanContext({
traceId: id(context.traceId, 16),
spanId: id(context.spanId, 16),
sampling,
tracestate
})
}
class Tracer {

@@ -101,3 +137,3 @@ constructor (library, config, tracerProvider) {

const parentSpan = api.trace.getSpan(context)
const parentSpanContext = parentSpan && parentSpan.spanContext()
const parentSpanContext = parentSpan?.spanContext()
let spanContext

@@ -113,8 +149,14 @@ if (parentSpanContext && api.trace.isSpanContextValid(parentSpanContext)) {

const spanKind = options.kind || api.SpanKind.INTERNAL
const links = (options.links || []).map(link => {
return {
context: link.context,
attributes: sanitizeAttributes(link.attributes)
const links = []
if (options.links?.length) {
for (const link of options.links) {
const ddContext = normalizeLinkContext(link?.context)
if (!ddContext) continue
links.push({
context: ddContext,
attributes: sanitizeAttributes(link.attributes)
})
}
})
}
const attributes = sanitizeAttributes(options.attributes)

@@ -121,0 +163,0 @@

@@ -37,2 +37,7 @@ 'use strict'

const baggageExpr = new RegExp(`^${baggagePrefix}(.+)$`)
// W3C Baggage key grammar: key = token (RFC 7230).
// Spec (up-to-date): "Propagation format for distributed context: Baggage" §3.3.1
// https://www.w3.org/TR/baggage/#header-content
// https://www.rfc-editor.org/rfc/rfc7230#section-3.2.6
const baggageTokenExpr = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/
const tagKeyExpr = /^_dd\.p\.[\x21-\x2B\x2D-\x7E]+$/ // ASCII minus spaces and commas

@@ -43,2 +48,5 @@ const tagValueExpr = /^[\x20-\x2B\x2D-\x7E]*$/ // ASCII minus commas

const httpHeaderNameExpr = /^[0-9A-Za-z!#$%&'*+\-.^_`|~]+$/
// Compatible with Node's internal header value validation (allows HTAB, SP-~, and \x80-\xFF only)
// https://github.com/nodejs/node/blob/main/lib/_http_common.js
const invalidHeaderValueCharExpr = /[^\t\x20-\x7E\x80-\xFF]/
const traceparentExpr = /^([a-f0-9]{2})-([a-f0-9]{32})-([a-f0-9]{16})-([a-f0-9]{2})(-.*)?$/i

@@ -129,9 +137,2 @@ const traceparentKey = 'traceparent'

_encodeOtelBaggageKey (key) {
let encoded = encodeURIComponent(key)
encoded = encoded.replaceAll('(', '%28')
encoded = encoded.replaceAll(')', '%29')
return encoded
}
_injectBaggageItems (spanContext, carrier) {

@@ -151,3 +152,8 @@ if (this._config.legacyBaggageEnabled) {

carrier[headerName] = String(baggageItems[key])
let headerValue = String(baggageItems[key])
// Avoid Node throwing ERR_INVALID_CHAR when setting header values (e.g. newline from decoded OTEL baggage).
if (invalidHeaderValueCharExpr.test(headerValue)) {
headerValue = encodeURIComponent(headerValue)
}
carrier[headerName] = headerValue
}

@@ -164,3 +170,9 @@ }

for (const [key, value] of Object.entries(baggageItems)) {
const item = `${this._encodeOtelBaggageKey(String(key).trim())}=${encodeURIComponent(String(value).trim())},`
const baggageKey = String(key).trim()
if (!baggageKey || !baggageTokenExpr.test(baggageKey)) continue
// Do not trim values. If callers include leading/trailing whitespace, it must be percent-encoded.
// W3C list-member allows optional properties after ';'.
// https://www.w3.org/TR/baggage/#header-content
const item = `${baggageKey}=${encodeURIComponent(String(value))},`
itemCounter += 1

@@ -648,9 +660,2 @@ byteCounter += Buffer.byteLength(item)

_decodeOtelBaggageKey (key) {
let decoded = decodeURIComponent(key)
decoded = decoded.replaceAll('%28', '(')
decoded = decoded.replaceAll('%29', ')')
return decoded
}
_extractLegacyBaggageItems (carrier, spanContext) {

@@ -677,3 +682,13 @@ if (this._config.legacyBaggageEnabled) {

for (const keyValue of baggages) {
if (!keyValue.includes('=')) {
if (!keyValue) continue
// Per W3C baggage, list-members can contain optional properties after `;`.
// Example: key=value;prop=1;prop2
// https://www.w3.org/TR/baggage/#header-content
const semicolonIdx = keyValue.indexOf(';')
const member = (semicolonIdx === -1 ? keyValue : keyValue.slice(0, semicolonIdx)).trim()
if (!member) continue
const eqIdx = member.indexOf('=')
if (eqIdx === -1) {
tracerMetrics.count('context_header_style.malformed', ['header_style:baggage']).inc()

@@ -683,6 +698,7 @@ removeAllBaggageItems()

}
let [key, value] = keyValue.split('=')
key = this._decodeOtelBaggageKey(key.trim())
value = decodeURIComponent(value.trim())
if (!key || !value) {
const key = member.slice(0, eqIdx).trim()
let value = member.slice(eqIdx + 1).trim()
if (!baggageTokenExpr.test(key) || !value) {
tracerMetrics.count('context_header_style.malformed', ['header_style:baggage']).inc()

@@ -692,2 +708,10 @@ removeAllBaggageItems()

}
try {
value = decodeURIComponent(value)
} catch {
tracerMetrics.count('context_header_style.malformed', ['header_style:baggage']).inc()
removeAllBaggageItems()
return
}
if (spanContext && (tagAllKeys || keysToSpanTag?.has(key))) {

@@ -694,0 +718,0 @@ spanContext._trace.tags['baggage.' + key] = value

@@ -15,3 +15,3 @@ 'use strict'

const telemetryMetrics = require('../telemetry/metrics')
const { getEnvironmentVariable } = require('../config-helper')
const { getValueFromEnvSources } = require('../config/helper')
const SpanContext = require('./span_context')

@@ -21,4 +21,4 @@

const DD_TRACE_EXPERIMENTAL_STATE_TRACKING = getEnvironmentVariable('DD_TRACE_EXPERIMENTAL_STATE_TRACKING')
const DD_TRACE_EXPERIMENTAL_SPAN_COUNTS = getEnvironmentVariable('DD_TRACE_EXPERIMENTAL_SPAN_COUNTS')
const DD_TRACE_EXPERIMENTAL_STATE_TRACKING = getValueFromEnvSources('DD_TRACE_EXPERIMENTAL_STATE_TRACKING')
const DD_TRACE_EXPERIMENTAL_SPAN_COUNTS = getValueFromEnvSources('DD_TRACE_EXPERIMENTAL_SPAN_COUNTS')

@@ -28,3 +28,3 @@ const unfinishedRegistry = createRegistry('unfinished')

const OTEL_ENABLED = !!getEnvironmentVariable('DD_TRACE_OTEL_ENABLED')
const OTEL_ENABLED = !!getValueFromEnvSources('DD_TRACE_OTEL_ENABLED')
const ALLOWED = new Set(['string', 'number', 'boolean'])

@@ -31,0 +31,0 @@

'use strict'
const { channel } = require('dc-polyfill')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getEnvironmentVariable, getValueFromEnvSources } = require('./config/helper')
const { isFalse, isTrue, normalizePluginEnvName } = require('./util')

@@ -27,3 +28,3 @@ const plugins = require('./plugins')

const DD_TRACE_DISABLED_PLUGINS = getEnvironmentVariable('DD_TRACE_DISABLED_PLUGINS')
const DD_TRACE_DISABLED_PLUGINS = getValueFromEnvSources('DD_TRACE_DISABLED_PLUGINS')

@@ -45,3 +46,3 @@ const disabledPlugins = new Set(

if (!pluginClasses[Plugin.id]) {
const enabled = getEnvEnabled(Plugin)
const enabled = getEnabled(Plugin)

@@ -59,5 +60,5 @@ // TODO: remove the need to load the plugin class in order to disable the plugin

function getEnvEnabled (Plugin) {
function getEnabled (Plugin) {
const envName = `DD_TRACE_${Plugin.id.toUpperCase()}_ENABLED`
return getEnvironmentVariable(normalizePluginEnvName(envName))
return getValueFromEnvSources(normalizePluginEnvName(envName))
}

@@ -100,3 +101,4 @@

const pluginConfig = this._configsByName[name] || {
enabled: this._tracerConfig.plugins !== false && (!Plugin.experimental || isTrue(getEnvEnabled(Plugin)))
enabled: this._tracerConfig.plugins !== false &&
(!Plugin.experimental || isTrue(getEnabled(Plugin)))
}

@@ -103,0 +105,0 @@

'use strict'
const { readFileSync } = require('fs')
const { getEnvironmentVariable, getEnvironmentVariables } = require('../../config-helper')
const { getEnvironmentVariable, getEnvironmentVariables, getValueFromEnvSources } = require('../../config/helper')
const {

@@ -123,3 +123,2 @@ GIT_BRANCH,

GIT_URL_1: JENKINS_GIT_REPOSITORY_URL_1,
DD_CUSTOM_TRACE_ID,
NODE_NAME,

@@ -130,2 +129,3 @@ NODE_LABELS,

} = env
const DD_CUSTOM_TRACE_ID = getValueFromEnvSources('DD_CUSTOM_TRACE_ID')

@@ -694,7 +694,4 @@ tags = {

if (env.CODEBUILD_INITIATOR?.startsWith('codepipeline/')) {
const {
CODEBUILD_BUILD_ARN,
DD_ACTION_EXECUTION_ID,
DD_PIPELINE_EXECUTION_ID
} = env
const DD_ACTION_EXECUTION_ID = getValueFromEnvSources('DD_ACTION_EXECUTION_ID')
const DD_PIPELINE_EXECUTION_ID = getValueFromEnvSources('DD_PIPELINE_EXECUTION_ID')
tags = {

@@ -704,3 +701,3 @@ [CI_PROVIDER_NAME]: 'awscodepipeline',

[CI_ENV_VARS]: JSON.stringify({
CODEBUILD_BUILD_ARN,
CODEBUILD_BUILD_ARN: env.CODEBUILD_BUILD_ARN,
DD_PIPELINE_EXECUTION_ID,

@@ -707,0 +704,0 @@ DD_ACTION_EXECUTION_ID

@@ -10,7 +10,7 @@ 'use strict'

const log = require('../../log')
const { getEnvironmentVariable } = require('../../config-helper')
const { getValueFromEnvSources } = require('../../config/helper')
const { isTrue } = require('../../util')
let isGitEnabled = isTrue(getEnvironmentVariable('DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_ENABLED'))
const GIT_CACHE_DIR = getEnvironmentVariable('DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_DIR') ||
let isGitEnabled = isTrue(getValueFromEnvSources('DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_ENABLED'))
const GIT_CACHE_DIR = getValueFromEnvSources('DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_DIR') ||
path.join(os.tmpdir(), 'dd-trace-git-cache')

@@ -17,0 +17,0 @@

@@ -7,3 +7,3 @@ 'use strict'

const log = require('../../log')
const { getEnvironmentVariable } = require('../../config-helper')
const { getEnvironmentVariable } = require('../../config/helper')
const satisfies = require('../../../../../vendor/dist/semifies')

@@ -10,0 +10,0 @@

'use strict'
const { getEnvironmentVariables } = require('../../config-helper')
const { getValueFromEnvSources } = require('../../config/helper')
const {

@@ -24,12 +24,11 @@ GIT_COMMIT_SHA,

function removeEmptyValues (tags) {
return Object.keys(tags).reduce((filteredTags, tag) => {
if (!tags[tag]) {
return filteredTags
function removeEmptyValues (tagsAndValues) {
const filteredTags = {}
for (let i = 0; i < tagsAndValues.length; i += 2) {
const value = tagsAndValues[i + 1]
if (value) {
filteredTags[tagsAndValues[i]] = value
}
return {
...filteredTags,
[tag]: tags[tag]
}
}, {})
}
return filteredTags
}

@@ -51,18 +50,16 @@

function getUserProviderGitMetadata () {
const {
DD_GIT_COMMIT_SHA,
DD_GIT_BRANCH,
DD_GIT_REPOSITORY_URL,
DD_GIT_TAG,
DD_GIT_COMMIT_MESSAGE,
DD_GIT_COMMIT_COMMITTER_NAME,
DD_GIT_COMMIT_COMMITTER_EMAIL,
DD_GIT_COMMIT_COMMITTER_DATE,
DD_GIT_COMMIT_AUTHOR_NAME,
DD_GIT_COMMIT_AUTHOR_EMAIL,
DD_GIT_COMMIT_AUTHOR_DATE,
DD_GIT_PULL_REQUEST_BASE_BRANCH,
DD_GIT_PULL_REQUEST_BASE_BRANCH_SHA,
DD_GIT_COMMIT_HEAD_SHA
} = getEnvironmentVariables()
const DD_GIT_COMMIT_SHA = getValueFromEnvSources('DD_GIT_COMMIT_SHA')
const DD_GIT_BRANCH = getValueFromEnvSources('DD_GIT_BRANCH')
const DD_GIT_REPOSITORY_URL = getValueFromEnvSources('DD_GIT_REPOSITORY_URL')
const DD_GIT_TAG = getValueFromEnvSources('DD_GIT_TAG')
const DD_GIT_COMMIT_MESSAGE = getValueFromEnvSources('DD_GIT_COMMIT_MESSAGE')
const DD_GIT_COMMIT_COMMITTER_NAME = getValueFromEnvSources('DD_GIT_COMMIT_COMMITTER_NAME')
const DD_GIT_COMMIT_COMMITTER_EMAIL = getValueFromEnvSources('DD_GIT_COMMIT_COMMITTER_EMAIL')
const DD_GIT_COMMIT_COMMITTER_DATE = getValueFromEnvSources('DD_GIT_COMMIT_COMMITTER_DATE')
const DD_GIT_COMMIT_AUTHOR_NAME = getValueFromEnvSources('DD_GIT_COMMIT_AUTHOR_NAME')
const DD_GIT_COMMIT_AUTHOR_EMAIL = getValueFromEnvSources('DD_GIT_COMMIT_AUTHOR_EMAIL')
const DD_GIT_COMMIT_AUTHOR_DATE = getValueFromEnvSources('DD_GIT_COMMIT_AUTHOR_DATE')
const DD_GIT_PULL_REQUEST_BASE_BRANCH = getValueFromEnvSources('DD_GIT_PULL_REQUEST_BASE_BRANCH')
const DD_GIT_PULL_REQUEST_BASE_BRANCH_SHA = getValueFromEnvSources('DD_GIT_PULL_REQUEST_BASE_BRANCH_SHA')
const DD_GIT_COMMIT_HEAD_SHA = getValueFromEnvSources('DD_GIT_COMMIT_HEAD_SHA')

@@ -73,24 +70,25 @@ const branch = normalizeRef(DD_GIT_BRANCH)

// if DD_GIT_BRANCH is a tag, we associate its value to TAG too
if ((DD_GIT_BRANCH || '').includes('origin/tags') || (DD_GIT_BRANCH || '').includes('refs/heads/tags')) {
if ((DD_GIT_BRANCH ?? '').includes('origin/tags') || (DD_GIT_BRANCH ?? '').includes('refs/heads/tags')) {
tag = normalizeRef(DD_GIT_BRANCH)
}
return removeEmptyValues({
[GIT_COMMIT_SHA]: DD_GIT_COMMIT_SHA,
[GIT_BRANCH]: branch,
[GIT_REPOSITORY_URL]: filterSensitiveInfoFromRepository(DD_GIT_REPOSITORY_URL),
[GIT_TAG]: tag,
[GIT_COMMIT_MESSAGE]: DD_GIT_COMMIT_MESSAGE,
[GIT_COMMIT_COMMITTER_NAME]: DD_GIT_COMMIT_COMMITTER_NAME,
[GIT_COMMIT_COMMITTER_DATE]: DD_GIT_COMMIT_COMMITTER_DATE,
[GIT_COMMIT_COMMITTER_EMAIL]: DD_GIT_COMMIT_COMMITTER_EMAIL,
[GIT_COMMIT_AUTHOR_NAME]: DD_GIT_COMMIT_AUTHOR_NAME,
[GIT_COMMIT_AUTHOR_EMAIL]: DD_GIT_COMMIT_AUTHOR_EMAIL,
[GIT_COMMIT_AUTHOR_DATE]: DD_GIT_COMMIT_AUTHOR_DATE,
[GIT_PULL_REQUEST_BASE_BRANCH]: DD_GIT_PULL_REQUEST_BASE_BRANCH,
[GIT_PULL_REQUEST_BASE_BRANCH_SHA]: DD_GIT_PULL_REQUEST_BASE_BRANCH_SHA,
[GIT_COMMIT_HEAD_SHA]: DD_GIT_COMMIT_HEAD_SHA
})
// Key value pairs are grouped in pairs of two
return removeEmptyValues([
GIT_COMMIT_SHA, DD_GIT_COMMIT_SHA,
GIT_BRANCH, branch,
GIT_REPOSITORY_URL, filterSensitiveInfoFromRepository(DD_GIT_REPOSITORY_URL),
GIT_TAG, tag,
GIT_COMMIT_MESSAGE, DD_GIT_COMMIT_MESSAGE,
GIT_COMMIT_COMMITTER_NAME, DD_GIT_COMMIT_COMMITTER_NAME,
GIT_COMMIT_COMMITTER_DATE, DD_GIT_COMMIT_COMMITTER_DATE,
GIT_COMMIT_COMMITTER_EMAIL, DD_GIT_COMMIT_COMMITTER_EMAIL,
GIT_COMMIT_AUTHOR_NAME, DD_GIT_COMMIT_AUTHOR_NAME,
GIT_COMMIT_AUTHOR_EMAIL, DD_GIT_COMMIT_AUTHOR_EMAIL,
GIT_COMMIT_AUTHOR_DATE, DD_GIT_COMMIT_AUTHOR_DATE,
GIT_PULL_REQUEST_BASE_BRANCH, DD_GIT_PULL_REQUEST_BASE_BRANCH,
GIT_PULL_REQUEST_BASE_BRANCH_SHA, DD_GIT_PULL_REQUEST_BASE_BRANCH_SHA,
GIT_COMMIT_HEAD_SHA, DD_GIT_COMMIT_HEAD_SHA
])
}
module.exports = { getUserProviderGitMetadata, validateGitRepositoryUrl, validateGitCommitSha }
'use strict'
const log = require('./log')
const { profiler } = require('./profiling')
// Stop profiler upon exit in order to collect and export the current profile
process.once('beforeExit', () => { profiler.stop() })
globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(() => { profiler.stop() })
module.exports = {
start: config => {
const { service, version, env, url, hostname, port, tags, repositoryUrl, commitSHA, injectionEnabled } = config
const { enabled, sourceMap, exporters } = config.profiling
const { heartbeatInterval } = config.telemetry
const logger = {
debug: (message) => log.debug(message),
info: (message) => log.info(message),
warn: (message) => log.warn(message),
error: (...args) => log.error(...args)
}
const libraryInjected = injectionEnabled.length > 0
let activation
if (enabled === 'auto') {
activation = 'auto'
} else if (enabled === 'true') {
activation = 'manual'
} // else activation = undefined
return profiler.start({
service,
version,
env,
logger,
sourceMap,
exporters,
url,
hostname,
port,
tags,
repositoryUrl,
commitSHA,
libraryInjected,
activation,
heartbeatInterval
})
// Forward the full tracer config to the profiling layer.
// Profiling code is responsible for deriving the specific options it needs.
return profiler.start(config)
},

@@ -48,0 +13,0 @@

@@ -11,4 +11,3 @@ 'use strict'

const { getAzureTagsFromMetadata, getAzureAppMetadata, getAzureFunctionMetadata } = require('../azure_metadata')
const { getEnvironmentVariables } = require('../config-helper')
const defaults = require('../config_defaults')
const { getEnvironmentVariable, getValueFromEnvSources } = require('../config/helper')
const { AgentExporter } = require('./exporters/agent')

@@ -22,10 +21,12 @@ const { FileExporter } = require('./exporters/file')

const { tagger } = require('./tagger')
class Config {
constructor (options = {}) {
// TODO: Remove entries that were already resolved in config.
// For the others, move them over to config.
const AWS_LAMBDA_FUNCTION_NAME = getEnvironmentVariable('AWS_LAMBDA_FUNCTION_NAME')
const NODE_OPTIONS = getEnvironmentVariable('NODE_OPTIONS')
// TODO: Move initialization of these values to packages/dd-trace/src/config/index.js, and just read from config
const {
AWS_LAMBDA_FUNCTION_NAME: functionname,
DD_AGENT_HOST,
DD_ENV,
DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED, // used for testing
DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED,
DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED,

@@ -45,3 +46,2 @@ DD_PROFILING_CODEHOTSPOTS_ENABLED,

DD_PROFILING_PROFILERS,
DD_PROFILING_SOURCE_MAP,
DD_PROFILING_TIMELINE_ENABLED,

@@ -52,30 +52,28 @@ DD_PROFILING_UPLOAD_PERIOD,

DD_PROFILING_WALLTIME_ENABLED,
DD_SERVICE,
DD_TAGS,
DD_TRACE_AGENT_PORT,
DD_TRACE_AGENT_URL,
DD_VERSION,
NODE_OPTIONS
} = getEnvironmentVariables()
DD_TAGS
} = getProfilingEnvValues()
const env = options.env ?? DD_ENV
const service = options.service || DD_SERVICE || 'node'
const host = os.hostname()
const version = options.version ?? DD_VERSION
// Must be longer than one minute so pad with five seconds
const flushInterval = options.interval ?? (Number(DD_PROFILING_UPLOAD_PERIOD) * 1000 || 65 * 1000)
const uploadTimeout = options.uploadTimeout ?? (Number(DD_PROFILING_UPLOAD_TIMEOUT) || 60 * 1000)
const sourceMap = options.sourceMap ?? DD_PROFILING_SOURCE_MAP ?? true
const pprofPrefix = options.pprofPrefix ?? DD_PROFILING_PPROF_PREFIX ?? ''
this.service = service
this.env = env
// TODO: Remove the fallback. Just use the value from the config.
this.service = options.service || 'node'
this.env = options.env
this.host = host
this.functionname = functionname
this.functionname = AWS_LAMBDA_FUNCTION_NAME
this.version = version
this.version = options.version
this.tags = Object.assign(
tagger.parse(DD_TAGS),
tagger.parse(options.tags),
tagger.parse({ env, host, service, version, functionname }),
tagger.parse({
env: options.env,
host,
service: this.service,
version: this.version,
functionname: AWS_LAMBDA_FUNCTION_NAME
}),
getAzureTagsFromMetadata(getIsAzureFunction() ? getAzureFunctionMetadata() : getAzureAppMetadata())

@@ -111,3 +109,3 @@ )

this.uploadTimeout = uploadTimeout
this.sourceMap = sourceMap
this.sourceMap = options.sourceMap
this.debugSourceMaps = isTrue(options.debugSourceMaps ?? DD_PROFILING_DEBUG_SOURCE_MAPS)

@@ -121,8 +119,6 @@ this.endpointCollectionEnabled = isTrue(options.endpointCollection ??

DD_PROFILING_V8_PROFILER_BUG_WORKAROUND ?? true)
const hostname = (options.hostname ?? DD_AGENT_HOST) || defaults.hostname
const port = (options.port ?? DD_TRACE_AGENT_PORT) || defaults.port
this.url = new URL(options.url ?? DD_TRACE_AGENT_URL ?? format({
this.url = new URL(options.url || format({
protocol: 'http:',
hostname,
port
hostname: options.hostname,
port: options.port
}))

@@ -448,1 +444,48 @@

}
function getProfilingEnvValues () {
return {
DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED:
getValueFromEnvSources('DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED'),
DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED:
getValueFromEnvSources('DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED'),
DD_PROFILING_CODEHOTSPOTS_ENABLED:
getValueFromEnvSources('DD_PROFILING_CODEHOTSPOTS_ENABLED'),
DD_PROFILING_CPU_ENABLED:
getValueFromEnvSources('DD_PROFILING_CPU_ENABLED'),
DD_PROFILING_DEBUG_SOURCE_MAPS:
getValueFromEnvSources('DD_PROFILING_DEBUG_SOURCE_MAPS'),
DD_PROFILING_DEBUG_UPLOAD_COMPRESSION:
getValueFromEnvSources('DD_PROFILING_DEBUG_UPLOAD_COMPRESSION'),
DD_PROFILING_ENDPOINT_COLLECTION_ENABLED:
getValueFromEnvSources('DD_PROFILING_ENDPOINT_COLLECTION_ENABLED'),
DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES:
getValueFromEnvSources('DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES'),
DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE:
getValueFromEnvSources('DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE'),
DD_PROFILING_EXPERIMENTAL_OOM_MAX_HEAP_EXTENSION_COUNT:
getValueFromEnvSources('DD_PROFILING_EXPERIMENTAL_OOM_MAX_HEAP_EXTENSION_COUNT'),
DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED:
getValueFromEnvSources('DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED'),
DD_PROFILING_HEAP_ENABLED:
getValueFromEnvSources('DD_PROFILING_HEAP_ENABLED'),
DD_PROFILING_HEAP_SAMPLING_INTERVAL:
getValueFromEnvSources('DD_PROFILING_HEAP_SAMPLING_INTERVAL'),
DD_PROFILING_PPROF_PREFIX:
getValueFromEnvSources('DD_PROFILING_PPROF_PREFIX'),
DD_PROFILING_PROFILERS:
getValueFromEnvSources('DD_PROFILING_PROFILERS'),
DD_PROFILING_TIMELINE_ENABLED:
getValueFromEnvSources('DD_PROFILING_TIMELINE_ENABLED'),
DD_PROFILING_UPLOAD_PERIOD:
getValueFromEnvSources('DD_PROFILING_UPLOAD_PERIOD'),
DD_PROFILING_UPLOAD_TIMEOUT:
getValueFromEnvSources('DD_PROFILING_UPLOAD_TIMEOUT'),
DD_PROFILING_V8_PROFILER_BUG_WORKAROUND:
getValueFromEnvSources('DD_PROFILING_V8_PROFILER_BUG_WORKAROUND'),
DD_PROFILING_WALLTIME_ENABLED:
getValueFromEnvSources('DD_PROFILING_WALLTIME_ENABLED'),
DD_TAGS:
getValueFromEnvSources('DD_TAGS')
}
}

@@ -6,3 +6,3 @@ 'use strict'

const { SourceMapper, heap, encode } = require('@datadog/pprof')
const { getEnvironmentVariable } = require('../config-helper')
const { getValueFromEnvSources } = require('../config/helper')
const { AgentExporter } = require('./exporters/agent')

@@ -21,5 +21,5 @@ const { FileExporter } = require('./exporters/file')

}
const injectionEnabled = (getEnvironmentVariable('DD_INJECTION_ENABLED') ?? '').split(',')
const injectionEnabled = (getValueFromEnvSources('DD_INJECTION_ENABLED') ?? '').split(',')
const libraryInjected = injectionEnabled.length > 0
const profilingEnabled = (getEnvironmentVariable('DD_PROFILING_ENABLED') ?? '').toLowerCase()
const profilingEnabled = (getValueFromEnvSources('DD_PROFILING_ENABLED') ?? '').toLowerCase()
const activation = ['true', '1'].includes(profilingEnabled)

@@ -67,3 +67,3 @@ ? 'manual'

* - Tags (eg. "service:nodejs_oom_test,version:1.0.0")
* - Profiletype (eg. space,wall,cpu)
* - Profile type (eg. space,wall,cpu)
* - JSON profile filepath

@@ -74,4 +74,4 @@ */

const profileType = process.argv[4]
const profile = JSON.parse(fs.readFileSync(process.argv[5]))
const profile = JSON.parse(fs.readFileSync(process.argv[5], 'utf8'))
exportProfile(urls, tags, profileType, profile)

@@ -76,3 +76,3 @@ 'use strict'

stream.on('data', chunk => chunks.push(chunk))
stream.on('end', () => {
stream.once('end', () => {
callback(null, Buffer.concat(chunks))

@@ -79,0 +79,0 @@ })

@@ -9,2 +9,3 @@ 'use strict'

const { availableParallelism, libuvThreadPoolSize } = require('../libuv-size')
const processTags = require('../../process-tags')

@@ -26,3 +27,3 @@ class EventSerializer {

getEventJSON ({ profiles, infos, start, end, tags = {}, endpointCounts }) {
return JSON.stringify({
const event = {
attachments: Object.keys(profiles).map(t => this.typeToFile(t)),

@@ -82,3 +83,9 @@ start: start.toISOString(),

}
})
}
if (processTags.serialized) {
event[processTags.PROFILING_FIELD_NAME] = processTags.serialized
}
return JSON.stringify(event)
}

@@ -85,0 +92,0 @@ }

'use strict'
const { getEnvironmentVariable } = require('../config-helper')
const { getEnvironmentVariable } = require('../config/helper')
const { Profiler, ServerlessProfiler } = require('./profiler')

@@ -5,0 +5,0 @@ const WallProfiler = require('./profilers/wall')

'use strict'
const os = require('node:os')
const { getEnvironmentVariable } = require('../config-helper')
const { getEnvironmentVariable } = require('../config/helper')

@@ -6,0 +6,0 @@ function getLibuvThreadPoolSize (envVar) {

@@ -8,2 +8,3 @@ 'use strict'

const crashtracker = require('../crashtracking')
const log = require('../log')
const { Config } = require('./config')

@@ -67,2 +68,4 @@ const { snapshotKinds } = require('./constants')

get serverless () { return false }
get flushInterval () {

@@ -72,5 +75,54 @@ return this.#config?.flushInterval

start (options) {
start (config) {
const {
service,
version,
env,
url,
hostname,
port,
tags,
repositoryUrl,
commitSHA,
injectionEnabled
} = config
const { enabled, sourceMap, exporters } = config.profiling
const { heartbeatInterval } = config.telemetry
// TODO: Unify with main logger and rewrite template strings to use printf formatting.
const logger = {
debug (message) { log.debug(message) },
info (message) { log.info(message) },
warn (message) { log.warn(message) },
error (...args) { log.error(...args) }
}
const libraryInjected = injectionEnabled.length > 0
let activation
if (enabled === 'auto') {
activation = 'auto'
} else if (enabled === 'true') {
activation = 'manual'
} // else activation = undefined
const options = {
service,
version,
env,
logger,
sourceMap,
exporters,
url,
hostname,
port,
tags,
repositoryUrl,
commitSHA,
libraryInjected,
activation,
heartbeatInterval
}
return this._start(options).catch((err) => {
logError(options.logger, 'Error starting profiler. For troubleshooting tips, see ' +
logError(logger, 'Error starting profiler. For troubleshooting tips, see ' +
'<https://dtdg.co/nodejs-profiler-troubleshooting>', err)

@@ -248,2 +300,3 @@ return false

return {
serverless: this.serverless,
settings: this.#config.systemInfoReport

@@ -358,2 +411,4 @@ }

get serverless () { return true }
get profiledIntervals () {

@@ -360,0 +415,0 @@ return this.#profiledIntervals

'use strict'
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { getValueFromEnvSources } = require('./config/helper')
const NoopProxy = require('./noop/proxy')

@@ -133,3 +134,6 @@ const DatadogTracer = require('./tracer')

const tracingRemoteConfig = require('./config/remote_config')
tracingRemoteConfig.enable(rc, config, this._enableOrDisableTracing.bind(this))
tracingRemoteConfig.enable(rc, config, () => {
this.#updateTracing(config)
this.#updateDebugger(config, rc)
})

@@ -187,3 +191,3 @@ rc.setProductHandler('AGENT_CONFIG', (action, conf) => {

this._enableOrDisableTracing(config)
this.#updateTracing(config)

@@ -201,3 +205,3 @@ this._modules.rewriter.enable(config)

if (config.ciVisAgentlessLogSubmissionEnabled) {
if (getEnvironmentVariable('DD_API_KEY')) {
if (getValueFromEnvSources('DD_API_KEY')) {
const LogSubmissionPlugin = require('./ci-visibility/log-submission/log-submission-plugin')

@@ -248,3 +252,3 @@ const automaticLogPlugin = new LogSubmissionPlugin(this)

_enableOrDisableTracing (config) {
#updateTracing (config) {
if (config.tracing !== false) {

@@ -295,2 +299,27 @@ if (config.appsec.enabled) {

/**
* Updates the debugger (Dynamic Instrumentation) state based on remote config changes.
* Handles starting, stopping, and reconfiguring the debugger dynamically.
*
* @param {object} config - The tracer configuration object
* @param {object} rc - The RemoteConfig instance
*/
#updateDebugger (config, rc) {
const shouldBeEnabled = config.dynamicInstrumentation.enabled
const isCurrentlyStarted = DynamicInstrumentation.isStarted()
if (shouldBeEnabled) {
if (isCurrentlyStarted) {
log.debug('[proxy] Reconfiguring Dynamic Instrumentation via remote config')
DynamicInstrumentation.configure(config)
} else {
log.debug('[proxy] Starting Dynamic Instrumentation via remote config')
DynamicInstrumentation.start(config, rc)
}
} else if (isCurrentlyStarted) {
log.debug('[proxy] Stopping Dynamic Instrumentation via remote config')
DynamicInstrumentation.stop()
}
}
/**
* @override

@@ -297,0 +326,0 @@ */

@@ -34,5 +34,8 @@ 'use strict'

ASM_RASP_CMDI: 1n << 37n,
APM_TRACING_ENABLE_DYNAMIC_INSTRUMENTATION: 1n << 38n,
APM_TRACING_ENABLE_CODE_ORIGIN: 1n << 40n,
ASM_DD_MULTICONFIG: 1n << 42n,
ASM_TRACE_TAGGING_RULES: 1n << 43n,
ASM_EXTENDED_DATA_COLLECTION: 1n << 44n,
APM_TRACING_MULTICONFIG: 1n << 45n,
FFE_FLAG_CONFIGURATION_RULES: 1n << 46n,

@@ -39,0 +42,0 @@ /*

@@ -11,3 +11,3 @@ 'use strict'

const tagger = require('../tagger')
const defaults = require('../config_defaults')
const defaults = require('../config/defaults')
const processTags = require('../process-tags')

@@ -14,0 +14,0 @@ const Scheduler = require('./scheduler')

@@ -10,4 +10,4 @@ 'use strict'

const parse = require('../../../vendor/dist/module-details-from-path')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
const { isRelativeRequire } = require('../../datadog-instrumentations/src/helpers/shared-utils')
const { getEnvironmentVariable, getValueFromEnvSources } = require('./config/helper')

@@ -67,2 +67,3 @@ const origRequire = Module.prototype.require

try {
// @ts-expect-error Module._resolveFilename is not typed
filename = Module._resolveFilename(request, this)

@@ -76,5 +77,6 @@ } catch {

if (cache[filename]) {
const externalCacheEntry = require.cache[filename]
// require.cache was potentially altered externally
if (require.cache[filename] && require.cache[filename].exports !== cache[filename].original) {
return require.cache[filename].exports
if (externalCacheEntry && externalCacheEntry.exports !== cache[filename].original) {
return externalCacheEntry.exports
}

@@ -119,3 +121,3 @@

const inAWSLambda = getEnvironmentVariable('AWS_LAMBDA_FUNCTION_NAME') !== undefined
const hasLambdaHandler = getEnvironmentVariable('DD_LAMBDA_HANDLER') !== undefined
const hasLambdaHandler = getValueFromEnvSources('DD_LAMBDA_HANDLER') !== undefined
const segments = filename.split(path.sep)

@@ -134,2 +136,3 @@ const filenameFromNodeModule = segments.includes('node_modules')

// @ts-expect-error Module._resolveLookupPaths is not typed
const paths = Module._resolveLookupPaths(name, this, true)

@@ -143,2 +146,3 @@ if (!paths) {

try {
// @ts-expect-error Module._findPath is not typed
res = Module._findPath(name, [basedir, ...paths])

@@ -145,0 +149,0 @@ } catch {

@@ -11,3 +11,3 @@ 'use strict'

const log = require('../log')
const { getEnvironmentVariable } = require('../config-helper')
const { getValueFromEnvSources } = require('../config/helper')

@@ -17,3 +17,3 @@ const { NODE_MAJOR } = require('../../../../version')

// It is only a variable for testing. Think about alternatives.
const DD_RUNTIME_METRICS_FLUSH_INTERVAL = getEnvironmentVariable('DD_RUNTIME_METRICS_FLUSH_INTERVAL') ?? '10000'
const DD_RUNTIME_METRICS_FLUSH_INTERVAL = getValueFromEnvSources('DD_RUNTIME_METRICS_FLUSH_INTERVAL') ?? '10000'
const INTERVAL = Number.parseInt(DD_RUNTIME_METRICS_FLUSH_INTERVAL, 10)

@@ -20,0 +20,0 @@

'use strict'
const { getEnvironmentVariable } = require('./config-helper')
const { getEnvironmentVariable, getValueFromEnvSources } = require('./config/helper')
const { isFalse } = require('./util')

@@ -22,3 +22,3 @@

function enableGCPPubSubPushSubscription () {
const isGCPPubSubPushSubscriptionEnabled = getEnvironmentVariable('DD_TRACE_GCP_PUBSUB_PUSH_ENABLED')
const isGCPPubSubPushSubscriptionEnabled = getValueFromEnvSources('DD_TRACE_GCP_PUBSUB_PUSH_ENABLED')
return getEnvironmentVariable('K_SERVICE') !== undefined && !isFalse(isGCPPubSubPushSubscriptionEnabled)

@@ -25,0 +25,0 @@ }

@@ -7,4 +7,4 @@ 'use strict'

const GitMetadataTagger = require('./git_metadata_tagger')
const { getEnvironmentVariable } = require('./config-helper')
const processTags = require('./process-tags')
const { getValueFromEnvSources } = require('./config/helper')

@@ -92,3 +92,3 @@ const startedSpans = new WeakSet()

_erase (trace, active) {
if (getEnvironmentVariable('DD_TRACE_EXPERIMENTAL_STATE_TRACKING') === 'true') {
if (getValueFromEnvSources('DD_TRACE_EXPERIMENTAL_STATE_TRACKING') === 'true') {
const started = new Set()

@@ -95,0 +95,0 @@ const startedIds = new Set()

@@ -5,5 +5,4 @@ 'use strict'

const { inspect } = require('util')
const tracerVersion = require('../../../package.json').version
const defaults = require('./config_defaults')
const defaults = require('./config/defaults')
const { info, warn } = require('./log/writer')

@@ -19,19 +18,11 @@

/**
* @param {{ agentError: { code: string, message: string } }} [options]
* @param {{ status: number, message: string } } [agentError]
*/
function startupLog ({ agentError } = {}) {
if (!config || !pluginManager) {
function startupLog (agentError) {
if (alreadyRan || !config || !config.startupLogs || !pluginManager) {
return
}
if (alreadyRan) {
return
}
alreadyRan = true
if (!config.startupLogs) {
return
}
const out = tracerInfo()

@@ -47,4 +38,4 @@

errors.agentError = {
code: agentError.code ?? '',
message: `Agent Error:${agentError.message}`
code: agentError.status,
message: `Agent Error: ${agentError.message}`
}

@@ -51,0 +42,0 @@ }

@@ -6,2 +6,14 @@ 'use strict'

/**
* RetryData is information that `telemetry.js` keeps in-memory to be merged into the next payload.
*
* @callback GetRetryData
* @returns {{ payload: Record<string, unknown>, reqType: string } | null}
*/
/**
* @typedef {import('./send-data').TelemetryConfig & {
* appsec?: { apiSecurity?: { endpointCollectionEnabled?: boolean, endpointCollectionMessageLimit?: number } }
* }} TelemetryConfig
*/
const fastifyRouteCh = dc.channel('apm:fastify:route:added')

@@ -11,6 +23,15 @@ const expressRouteCh = dc.channel('apm:express:route:added')

/** @type {TelemetryConfig} */
let config
/** @type {import('./send-data').TelemetryApplication} */
let application
/** @type {import('./send-data').TelemetryHost} */
let host
/** @type {GetRetryData} */
let getRetryData
/** @type {import('./send-data').SendDataCallback} */
let updateRetryData

@@ -22,3 +43,6 @@

*/
/** @type {Map<string, { method: string, path: string, operationName: string }>} */
const pendingEndpoints = new Map()
/** @type {Set<string>} */
const wildcardEndpoints = new Set()

@@ -28,2 +52,7 @@ let flushScheduled = false

/**
* @param {string} method
* @param {string} path
* @returns {string}
*/
function endpointKey (method, path) {

@@ -33,8 +62,19 @@ return `${method.toUpperCase()} ${path}`

/**
* @returns {void}
*/
function scheduleFlush () {
if (flushScheduled) return
flushScheduled = true
setImmediate(flushAndSend).unref()
// this used to be setImmediate() instead, but it was making the system test flaky
// don't ask me why
setTimeout(flushAndSend).unref()
}
/**
* @param {string} method
* @param {string} path
* @param {string} operationName
* @returns {void}
*/
function recordEndpoint (method, path, operationName) {

@@ -48,2 +88,5 @@ const key = endpointKey(method, path)

/**
* @param {{ routeOptions?: { path?: string, method: string | string[] } } | null | undefined} routeData
*/
function onFastifyRoute (routeData) {

@@ -59,2 +102,5 @@ const routeOptions = routeData?.routeOptions

/**
* @param {{ method?: string, path?: string }} param0
*/
function onExpressRoute ({ method, path }) {

@@ -80,2 +126,5 @@ if (!method || !path) return

/**
* @param {{ method: string, path: string, operationName: string }[]} endpoints
*/
function buildEndpointObjects (endpoints) {

@@ -93,2 +142,5 @@ return endpoints.map(({ method, path, operationName }) => {

/**
* @returns {void}
*/
function flushAndSend () {

@@ -102,3 +154,4 @@ flushScheduled = false

pendingEndpoints.delete(key)
if (batchEndpoints.length >= config.appsec?.apiSecurity?.endpointCollectionMessageLimit) break
// Config is set when endpoint collection is enabled; message limit is optional
if (batchEndpoints.length >= (config.appsec?.apiSecurity?.endpointCollectionMessageLimit ?? 0)) break
}

@@ -111,3 +164,6 @@

/** @type {import('./send-data').TelemetryRequestType} */
let reqType = 'app-endpoints'
/** @type {import('./send-data').TelemetryPayload} */
let payload = payloadObj

@@ -134,4 +190,11 @@

function start (_config = {}, _application, _host, getRetryDataFunction, updateRetryDataFunction) {
if (!_config?.appsec?.apiSecurity?.endpointCollectionEnabled) return
/**
* @param {TelemetryConfig} _config
* @param {import('./send-data').TelemetryApplication} _application
* @param {import('./send-data').TelemetryHost} _host
* @param {GetRetryData} getRetryDataFunction
* @param {import('./send-data').SendDataCallback} updateRetryDataFunction
*/
function start (_config, _application, _host, getRetryDataFunction, updateRetryDataFunction) {
if (!_config.appsec?.apiSecurity?.endpointCollectionEnabled) return

@@ -156,3 +219,2 @@ config = _config

flushScheduled = false
config = application = host = getRetryData = updateRetryData = null
}

@@ -159,0 +221,0 @@

@@ -6,6 +6,89 @@ 'use strict'

const { isTrue } = require('../util')
const { getEnvironmentVariable } = require('../config-helper')
const { getValueFromEnvSources } = require('../config/helper')
/**
* @typedef {Record<string, unknown>} TelemetryPayloadObject
*/
/**
* Telemetry "request_type" values sent by this library.
*
* @typedef {'app-started'
* | 'app-integrations-change'
* | 'app-heartbeat'
* | 'app-extended-heartbeat'
* | 'app-client-configuration-change'
* | 'app-closing'
* | 'app-dependencies-loaded'
* | 'app-endpoints'
* | 'generate-metrics'
* | 'distributions'
* | 'logs'
* | 'message-batch'} TelemetryRequestType
*/
/**
* @typedef {{ request_type: string, payload: TelemetryPayloadObject }} MessageBatchItem
*/
/**
* @typedef {MessageBatchItem[]} MessageBatchPayload
*/
/**
* Telemetry payloads are usually single objects, but some request types (e.g. `message-batch`)
* send arrays.
*
* @typedef {TelemetryPayloadObject | MessageBatchPayload} TelemetryPayload
*/
/**
* @typedef {{language_name: string, tracer_version: string} & Record<string, unknown>} TelemetryApplication
*/
/**
* @typedef {Exclude<TelemetryRequestType, 'message-batch'>} NonBatchTelemetryRequestType
*/
/**
* @typedef {{
* payload: TelemetryPayloadObject,
* reqType: NonBatchTelemetryRequestType
* } | {
* payload: MessageBatchPayload,
* reqType: 'message-batch'
* }} SendDataRetryObject
*/
/**
* @typedef {{
* hostname: string,
* os: string,
* architecture: string,
* os_version?: string,
* kernel_version?: string,
* kernel_release?: string,
* kernel_name?: string
* } & Record<string, unknown>} TelemetryHost
*/
/**
* @typedef {{
* hostname?: string,
* port?: string | number,
* url?: string | URL,
* site?: string,
* apiKey?: string,
* isCiVisibility?: boolean,
* spanAttributeSchema?: string,
* tags: Record<string, string>,
* telemetry?: { debug?: boolean }
* }} TelemetryConfig
*/
/**
* @callback SendDataCallback
* @param {Error | null | undefined} error
* @param {SendDataRetryObject} retryObj
* @returns {void}
*/
let agentTelemetry = true
/**
* @param {TelemetryConfig} config
* @param {TelemetryApplication} application
* @param {TelemetryRequestType} reqType
* @returns {Record<string, string>}
*/
function getHeaders (config, application, reqType) {

@@ -29,2 +112,5 @@ const headers = {

/**
* @param {string | undefined} site
*/
function getAgentlessTelemetryEndpoint (site) {

@@ -39,2 +125,6 @@ if (site === 'datad0g.com') { // staging

/**
* @param {TelemetryPayload} payload
* @returns {TelemetryPayload}
*/
function getPayload (payload) {

@@ -50,2 +140,11 @@ // Some telemetry endpoints payloads accept collections of elements such as the 'logs' endpoint.

// TODO(BridgeAR): Simplify this code. A lot does not need to be recalculated on every call.
/**
* @param {TelemetryConfig} config
* @param {TelemetryApplication} application
* @param {TelemetryHost} host
* @param {TelemetryRequestType} reqType
* @param {TelemetryPayload} [payload]
* @param {SendDataCallback} [cb]
*/
function sendData (config, application, host, reqType, payload = {}, cb = () => {}) {

@@ -61,3 +160,3 @@ const {

const isCiVisibilityAgentlessMode = isCiVisibility &&
isTrue(getEnvironmentVariable('DD_CIVISIBILITY_AGENTLESS_ENABLED'))
isTrue(getValueFromEnvSources('DD_CIVISIBILITY_AGENTLESS_ENABLED'))

@@ -96,3 +195,3 @@ if (isCiVisibilityAgentlessMode) {

request(data, options, (error) => {
if (error && getEnvironmentVariable('DD_API_KEY') && config.site) {
if (error && getValueFromEnvSources('DD_API_KEY') && config.site) {
if (agentTelemetry) {

@@ -104,3 +203,3 @@ log.warn('Agent telemetry failed, started agentless telemetry')

const backendUrl = getAgentlessTelemetryEndpoint(config.site)
const backendHeader = { ...options.headers, 'DD-API-KEY': getEnvironmentVariable('DD_API_KEY') }
const backendHeader = { ...options.headers, 'DD-API-KEY': getValueFromEnvSources('DD_API_KEY') }
const backendOptions = {

@@ -107,0 +206,0 @@ ...options,

@@ -16,2 +16,74 @@ 'use strict'

/**
* @typedef {Record<string, unknown>} TelemetryPayloadObject
*/
/**
* @typedef {string | number | boolean | null | undefined | URL | Record<string, unknown> | unknown[]} ConfigValue
*/
/**
* @typedef {{
* name: string,
* enabled: boolean,
* auto_enabled: boolean,
* process_tags: typeof processTags.tagsObject
* }} Integration
*/
/**
* @typedef {{ _enabled: boolean }} Plugin
*/
/**
* @typedef {{ _pluginsByName: Record<string, Plugin> }} PluginManager
*/
/**
* @typedef {{
* service_name: string | undefined,
* env: string | undefined,
* service_version: string | undefined,
* tracer_version: string,
* language_name: 'nodejs',
* language_version: string
* process_tags: typeof processTags.tagsObject
* }} TelemetryApplication
*/
/**
* @typedef {{
* hostname: string,
* os: string,
* architecture: string,
* os_version?: string,
* kernel_version?: string,
* kernel_release?: string,
* kernel_name?: string
* }} TelemetryHost
*/
/**
* @typedef {{
* telemetry: {
* enabled: boolean,
* heartbeatInterval: number,
* debug?: boolean,
* dependencyCollection?: boolean,
* logCollection?: boolean
* },
* service: string | undefined,
* env: string | undefined,
* version: string | undefined,
* tags: Record<string, string>,
* url?: string | URL,
* hostname?: string,
* port?: string | number,
* site?: string,
* apiKey?: string,
* isCiVisibility?: boolean,
* spanAttributeSchema?: string,
* installSignature?: { id?: string, time?: string, type?: string },
* sca?: { enabled?: boolean },
* appsec: { enabled: boolean, apiSecurity?: {
* endpointCollectionEnabled?: boolean,
* endpointCollectionMessageLimit?: number
* } },
* profiling: { enabled: boolean | 'true' | 'false' | 'auto' }
* }} TelemetryConfig
*/
const telemetryStartChannel = dc.channel('datadog:telemetry:start')

@@ -21,15 +93,40 @@ const telemetryStopChannel = dc.channel('datadog:telemetry:stop')

/** @type {TelemetryConfig | undefined} */
let config
/** @type {PluginManager} */
let pluginManager
/** @type {TelemetryApplication} */
let application
let host
let heartbeatTimeout
/** @type {TelemetryHost} */
const host = createHostObject()
/** @type {ReturnType<typeof setInterval> | undefined} */
let heartbeatInterval
/** @type {ReturnType<typeof setInterval> | undefined} */
let extendedInterval
/** @type {Integration[]} */
let integrations
/** @type {Map<string, { name: string, value: ConfigValue, origin: string, seq_id: number }>} */
const configWithOrigin = new Map()
/**
* Retry information that `telemetry.js` keeps in-memory to be merged into the next payload.
*
* @typedef {{ payload: TelemetryPayloadObject, reqType: string }} RetryData
*/
/** @type {{ payload: TelemetryPayloadObject, reqType: string } | null} */
let retryData = null
const extendedHeartbeatPayload = {}
/** @type {TelemetryPayloadObject[]} */
let heartbeatFailedIntegrations = []
/** @type {TelemetryPayloadObject[]} */
let heartbeatFailedDependencies = []
const sentIntegrations = new Set()

@@ -43,33 +140,30 @@

/**
* @param {Error | null | undefined} error
* @param {import('./send-data').SendDataRetryObject} retryObj
*/
function updateRetryData (error, retryObj) {
if (error) {
if (retryObj.reqType === 'message-batch') {
const payload = retryObj.payload[0].payload
const reqType = retryObj.payload[0].request_type
retryData = { payload, reqType }
if (!error) {
retryData = null
return
}
if (retryObj.reqType !== 'message-batch') {
retryData = retryObj
return
}
// Since this payload failed twice it now gets save in to the extended heartbeat
const failedPayload = retryObj.payload[1].payload
const failedReqType = retryObj.payload[1].request_type
retryData = {
payload: retryObj.payload[0].payload,
reqType: retryObj.payload[0].request_type,
}
// save away the dependencies and integration request for extended heartbeat.
if (failedReqType === 'app-integrations-change') {
if (extendedHeartbeatPayload.integrations) {
extendedHeartbeatPayload.integrations.push(failedPayload)
} else {
extendedHeartbeatPayload.integrations = [failedPayload]
}
}
if (failedReqType === 'app-dependencies-loaded') {
if (extendedHeartbeatPayload.dependencies) {
extendedHeartbeatPayload.dependencies.push(failedPayload)
} else {
extendedHeartbeatPayload.dependencies = [failedPayload]
}
}
} else {
retryData = retryObj
}
} else {
retryData = null
// Since this payload failed twice it now gets save in to the extended heartbeat
const failedPayload = retryObj.payload[1].payload
const failedReqType = retryObj.payload[1].request_type
// save away the dependencies and integration request for extended heartbeat.
if (failedReqType === 'app-integrations-change') {
heartbeatFailedIntegrations.push(failedPayload)
} else if (failedReqType === 'app-dependencies-loaded') {
heartbeatFailedDependencies.push(failedPayload)
}

@@ -79,14 +173,13 @@ }

function getIntegrations () {
const newIntegrations = []
for (const pluginName in pluginManager._pluginsByName) {
if (sentIntegrations.has(pluginName)) {
continue
const newIntegrations = /** @type {Integration[]} */ ([])
for (const pluginName of Object.keys(pluginManager._pluginsByName ?? {})) {
if (!sentIntegrations.has(pluginName)) {
newIntegrations.push({
name: pluginName,
enabled: pluginManager._pluginsByName[pluginName]._enabled,
auto_enabled: true,
[processTags.TELEMETRY_FIELD_NAME]: processTags.tagsObject
})
sentIntegrations.add(pluginName)
}
newIntegrations.push({
name: pluginName,
enabled: pluginManager._pluginsByName[pluginName]._enabled,
auto_enabled: true,
[processTags.TELEMETRY_FIELD_NAME]: processTags.tagsObject
})
sentIntegrations.add(pluginName)
}

@@ -96,4 +189,7 @@ return newIntegrations

/**
* @param {TelemetryConfig} config
*/
function getProducts (config) {
const products = {
return {
appsec: {

@@ -107,9 +203,7 @@ enabled: config.appsec.enabled

}
if (errors.profilingError) {
products.profiler.error = errors.profilingError
errors.profilingError = {}
}
return products
}
/**
* @param {TelemetryConfig} config
*/
function getInstallSignature (config) {

@@ -126,2 +220,5 @@ const { installSignature: sig } = config

/**
* @param {TelemetryConfig} config
*/
function appStarted (config) {

@@ -136,7 +233,6 @@ const app = {

}
// TODO: add app.error with correct error codes
// if (errors.agentError) {
// app.error = errors.agentError
// errors.agentError = {}
// }
if (errors.agentError) {
app.error = errors.agentError
errors.agentError = undefined
}
return app

@@ -158,7 +254,6 @@ }

function onBeforeExit () {
process.removeListener('beforeExit', onBeforeExit)
appClosing()
}
/**
* @param {TelemetryConfig} config
* @returns {TelemetryApplication}
*/
function createAppObject (config) {

@@ -176,37 +271,33 @@ return {

/**
* @returns {TelemetryHost}
*/
function createHostObject () {
const osName = os.type()
if (osName === 'Linux' || osName === 'Darwin') {
return {
hostname: os.hostname(),
os: osName,
architecture: os.arch(),
kernel_version: os.version(),
kernel_release: os.release(),
kernel_name: osName
}
const base = {
hostname: os.hostname(),
os: osName,
architecture: os.arch(),
}
if (osName === 'Windows_NT') {
return {
hostname: os.hostname(),
os: osName,
architecture: os.arch(),
os_version: os.version()
}
if (os.platform() === 'win32') {
base.os_version = os.version() // Optional
} else {
base.kernel_version = os.version()
base.kernel_release = os.release()
base.kernel_name = osName
}
return {
hostname: os.hostname(), // TODO is this enough?
os: osName
}
return base
}
function getTelemetryData () {
return { config, application, host, heartbeatInterval }
return { config, application, host, heartbeatInterval: config?.telemetry.heartbeatInterval }
}
/**
* @param {{ reqType: string, payload: TelemetryPayloadObject }[]} payload
*/
function createBatchPayload (payload) {
const batchPayload = payload.map(item => {
return payload.map(item => {
return {

@@ -217,6 +308,15 @@ request_type: item.reqType,

})
return batchPayload
}
/**
* @param {import('./send-data').NonBatchTelemetryRequestType} currReqType
* @param {TelemetryPayloadObject} [currPayload]
* @returns {{
* reqType: 'message-batch',
* payload: import('./send-data').MessageBatchPayload
* } | {
* reqType: import('./send-data').NonBatchTelemetryRequestType,
* payload: TelemetryPayloadObject
* }}
*/
function createPayload (currReqType, currPayload = {}) {

@@ -232,4 +332,8 @@ if (getRetryData()) {

function heartbeat (config, application, host) {
heartbeatTimeout = setTimeout(() => {
/**
* @param {TelemetryConfig} config
* @param {TelemetryApplication} application
*/
function heartbeat (config, application) {
heartbeatInterval = setInterval(() => {
metricsManager.send(config, application, host)

@@ -240,20 +344,27 @@ telemetryLogger.send(config, application, host)

sendData(config, application, host, reqType, payload, updateRetryData)
heartbeat(config, application, host)
}, heartbeatInterval).unref()
return heartbeatTimeout
}, config.telemetry.heartbeatInterval).unref()
}
/**
* @param {TelemetryConfig} config
*/
function extendedHeartbeat (config) {
extendedInterval = setInterval(() => {
const appPayload = appStarted(config)
const payload = {
...appPayload,
...extendedHeartbeatPayload
if (heartbeatFailedIntegrations.length > 0) {
appPayload.integrations = heartbeatFailedIntegrations
heartbeatFailedIntegrations = []
}
sendData(config, application, host, 'app-extended-heartbeat', payload)
Object.keys(extendedHeartbeatPayload).forEach(key => delete extendedHeartbeatPayload[key])
if (heartbeatFailedDependencies.length > 0) {
appPayload.dependencies = heartbeatFailedDependencies
heartbeatFailedDependencies = []
}
sendData(config, application, host, 'app-extended-heartbeat', appPayload)
}, 1000 * 60 * 60 * 24).unref()
return extendedInterval
}
/**
* @param {TelemetryConfig} aConfig
* @param {PluginManager} thePluginManager
*/
function start (aConfig, thePluginManager) {

@@ -270,4 +381,2 @@ if (!aConfig.telemetry.enabled) {

application = createAppObject(config)
host = createHostObject()
heartbeatInterval = config.telemetry.heartbeatInterval
integrations = getIntegrations()

@@ -286,7 +395,7 @@

heartbeat(config, application, host)
heartbeat(config, application)
extendedHeartbeat(config)
process.on('beforeExit', onBeforeExit)
globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(appClosing)
telemetryStartChannel.publish(getTelemetryData())

@@ -300,4 +409,4 @@ }

clearInterval(extendedInterval)
clearTimeout(heartbeatTimeout)
process.removeListener('beforeExit', onBeforeExit)
clearInterval(heartbeatInterval)
globalThis[Symbol.for('dd-trace')].beforeExitHandlers.delete(appClosing)

@@ -324,2 +433,5 @@ telemetryStopChannel.publish(getTelemetryData())

/**
* @param {Record<string, string | number | boolean> | null | undefined} map
*/
function formatMapForTelemetry (map) {

@@ -379,2 +491,6 @@ // format from an object to a string map in order for

/**
* @param {{ name: string, value: ConfigValue, origin: string }[]} changes
* @param {TelemetryConfig} config
*/
function updateConfig (changes, config) {

@@ -387,3 +503,2 @@ if (!config.telemetry.enabled) return

const application = createAppObject(config)
const host = createHostObject()

@@ -397,11 +512,12 @@ const changed = configWithOrigin.size > 0

if (namesNeedFormatting.has(entry.name)) {
entry.value = formatMapForTelemetry(entry.value)
} else if (entry.name === 'url') {
if (entry.value) {
entry.value = entry.value.toString()
if (namesNeedFormatting.has(name)) {
// @ts-expect-error entry.value is known to be a map for these config names
entry.value = formatMapForTelemetry(value)
} else if (name === 'url') {
if (value) {
entry.value = value.toString()
}
} else if (entry.name === 'DD_TRACE_SAMPLING_RULES') {
entry.value = JSON.stringify(entry.value)
} else if (Array.isArray(entry.value)) {
} else if (name === 'DD_TRACE_SAMPLING_RULES') {
entry.value = JSON.stringify(value)
} else if (Array.isArray(value)) {
entry.value = value.join(',')

@@ -423,2 +539,5 @@ }

/**
* @param {TelemetryConfig['profiling']['enabled']} profilingEnabled
*/
function profilingEnabledToBoolean (profilingEnabled) {

@@ -425,0 +544,0 @@ if (typeof profilingEnabled === 'boolean') {

'use strict'
const pkg = require('./pkg')
const { GRPC_CLIENT_ERROR_STATUSES, GRPC_SERVER_ERROR_STATUSES } = require('./constants')
const { getEnvironmentVariable: getEnv } = require('./config-helper')
// eslint-disable-next-line @stylistic/max-len
const qsRegex = String.raw`(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:(?:\s|%20)*(?:=|%3D)[^&]+|(?:"|%22)(?:\s|%20)*(?::|%3A)(?:\s|%20)*(?:"|%22)(?:%2[^2]|%[^2]|[^"%])+(?:"|%22))|bearer(?:\s|%20)+[a-z0-9\._\-]+|token(?::|%3A)[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L](?:[\w=-]|%3D)+\.ey[I-L](?:[\w=-]|%3D)+(?:\.(?:[\w.+\/=-]|%3D|%2F|%2B)+)?|[\-]{5}BEGIN(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY[\-]{5}[^\-]+[\-]{5}END(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY|ssh-rsa(?:\s|%20)*(?:[a-z0-9\/\.+]|%2F|%5C|%2B){100,}`
// eslint-disable-next-line @stylistic/max-len
const defaultWafObfuscatorKeyRegex = String.raw`(?i)pass|pw(?:or)?d|secret|(?:api|private|public|access)[_-]?key|token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)|bearer|authorization|jsessionid|phpsessid|asp\.net[_-]sessionid|sid|jwt`
// eslint-disable-next-line @stylistic/max-len
const defaultWafObfuscatorValueRegex = String.raw`(?i)(?:p(?:ass)?w(?:or)?d|pass(?:[_-]?phrase)?|secret(?:[_-]?key)?|(?:(?:api|private|public|access)[_-]?)key(?:[_-]?id)?|(?:(?:auth|access|id|refresh)[_-]?)?token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?|jsessionid|phpsessid|asp\.net(?:[_-]|-)sessionid|sid|jwt)(?:\s*=([^;&]+)|"\s*:\s*("[^"]+"|\d+))|bearer\s+([a-z0-9\._\-]+)|token\s*:\s*([a-z0-9]{13})|gh[opsu]_([0-9a-zA-Z]{36})|ey[I-L][\w=-]+\.(ey[I-L][\w=-]+(?:\.[\w.+\/=-]+)?)|[\-]{5}BEGIN[a-z\s]+PRIVATE\sKEY[\-]{5}([^\-]+)[\-]{5}END[a-z\s]+PRIVATE\sKEY|ssh-rsa\s*([a-z0-9\/\.+]{100,})`
const service = getEnv('AWS_LAMBDA_FUNCTION_NAME') ||
getEnv('FUNCTION_NAME') || // Google Cloud Function Name set by deprecated runtimes
getEnv('K_SERVICE') || // Google Cloud Function Name set by newer runtimes
getEnv('WEBSITE_SITE_NAME') || // set by Azure Functions
pkg.name ||
'node'
module.exports = {
apiKey: undefined,
appKey: undefined,
apmTracingEnabled: true,
'appsec.apiSecurity.enabled': true,
'appsec.apiSecurity.sampleDelay': 30,
'appsec.apiSecurity.endpointCollectionEnabled': true,
'appsec.apiSecurity.endpointCollectionMessageLimit': 300,
'appsec.blockedTemplateGraphql': undefined,
'appsec.blockedTemplateHtml': undefined,
'appsec.blockedTemplateJson': undefined,
'appsec.enabled': undefined,
'appsec.eventTracking.mode': 'identification',
// TODO appsec.extendedHeadersCollection is deprecated, to delete in a major
'appsec.extendedHeadersCollection.enabled': false,
'appsec.extendedHeadersCollection.redaction': true,
'appsec.extendedHeadersCollection.maxHeaders': 50,
'appsec.obfuscatorKeyRegex': defaultWafObfuscatorKeyRegex,
'appsec.obfuscatorValueRegex': defaultWafObfuscatorValueRegex,
'appsec.rasp.enabled': true,
// TODO Deprecated, to delete in a major
'appsec.rasp.bodyCollection': false,
'appsec.rateLimit': 100,
'appsec.rules': undefined,
'appsec.sca.enabled': null,
'appsec.stackTrace.enabled': true,
'appsec.stackTrace.maxDepth': 32,
'appsec.stackTrace.maxStackTraces': 2,
'appsec.wafTimeout': 5e3, // µs
baggageMaxBytes: 8192,
baggageMaxItems: 64,
baggageTagKeys: 'user.id,session.id,account.id',
clientIpEnabled: false,
clientIpHeader: null,
'cloudPayloadTagging.requestsEnabled': false,
'cloudPayloadTagging.responsesEnabled': false,
'cloudPayloadTagging.maxDepth': 10,
'cloudPayloadTagging.rules': [],
'crashtracking.enabled': true,
'codeOriginForSpans.enabled': true,
'codeOriginForSpans.experimental.exit_spans.enabled': false,
dbmPropagationMode: 'disabled',
'dogstatsd.hostname': '127.0.0.1',
'dogstatsd.port': '8125',
dsmEnabled: false,
'dynamicInstrumentation.captureTimeoutMs': 15,
'dynamicInstrumentation.enabled': false,
'dynamicInstrumentation.probeFile': undefined,
'dynamicInstrumentation.redactedIdentifiers': [],
'dynamicInstrumentation.redactionExcludedIdentifiers': [],
'dynamicInstrumentation.uploadIntervalSeconds': 1,
env: undefined,
'experimental.aiguard.enabled': false,
'experimental.aiguard.endpoint': undefined,
'experimental.aiguard.maxMessagesLength': 16,
'experimental.aiguard.maxContentSize': 512 * 1024,
'experimental.aiguard.timeout': 10_000, // ms
'experimental.enableGetRumData': false,
'experimental.exporter': undefined,
'experimental.flaggingProvider.enabled': false,
'experimental.flaggingProvider.initializationTimeoutMs': 30_000,
flushInterval: 2000,
flushMinSpans: 1000,
gitMetadataEnabled: true,
graphqlErrorExtensions: [],
'grpc.client.error.statuses': GRPC_CLIENT_ERROR_STATUSES,
'grpc.server.error.statuses': GRPC_SERVER_ERROR_STATUSES,
headerTags: [],
'heapSnapshot.count': 0,
'heapSnapshot.destination': '',
'heapSnapshot.interval': 3600,
hostname: '127.0.0.1',
'iast.dbRowsToTaint': 1,
'iast.deduplicationEnabled': true,
'iast.enabled': false,
'iast.maxConcurrentRequests': 2,
'iast.maxContextOperations': 2,
'iast.redactionEnabled': true,
'iast.redactionNamePattern': null,
'iast.redactionValuePattern': null,
'iast.requestSampling': 30,
'iast.securityControlsConfiguration': null,
'iast.telemetryVerbosity': 'INFORMATION',
'iast.stackTrace.enabled': true,
injectionEnabled: [],
'installSignature.id': null,
'installSignature.time': null,
'installSignature.type': null,
instrumentationSource: 'manual',
injectForce: null,
isAzureFunction: false,
isCiVisibility: false,
isEarlyFlakeDetectionEnabled: false,
isFlakyTestRetriesEnabled: false,
flakyTestRetriesCount: 5,
isGCPFunction: false,
isGCPPubSubPushSubscriptionEnabled: true,
isGitUploadEnabled: false,
isIntelligentTestRunnerEnabled: false,
isManualApiEnabled: false,
'langchain.spanCharLimit': 128,
'langchain.spanPromptCompletionSampleRate': 1,
'llmobs.agentlessEnabled': undefined,
'llmobs.enabled': false,
'llmobs.mlApp': undefined,
ciVisibilityTestSessionName: '',
ciVisAgentlessLogSubmissionEnabled: false,
legacyBaggageEnabled: true,
isTestDynamicInstrumentationEnabled: false,
isServiceUserProvided: false,
testManagementAttemptToFixRetries: 20,
isTestManagementEnabled: false,
isImpactedTestsEnabled: false,
logInjection: true,
otelLogsEnabled: false,
otelUrl: undefined,
otelLogsUrl: undefined, // Will be computed using agent host
otelHeaders: undefined,
otelLogsHeaders: '',
otelProtocol: 'http/protobuf',
otelLogsProtocol: 'http/protobuf',
otelLogsTimeout: 10_000,
otelTimeout: 10_000,
otelBatchTimeout: 5000,
otelMaxExportBatchSize: 512,
otelMaxQueueSize: 2048,
otelMetricsEnabled: false,
otelMetricsUrl: undefined, // Will be computed using agent host
otelMetricsHeaders: '',
otelMetricsProtocol: 'http/protobuf',
otelMetricsTimeout: 10_000,
otelMetricsExportTimeout: 7500,
otelMetricsExportInterval: 10_000,
otelMetricsTemporalityPreference: 'DELTA', // DELTA, CUMULATIVE, or LOWMEMORY
lookup: undefined,
inferredProxyServicesEnabled: false,
memcachedCommandEnabled: false,
middlewareTracingEnabled: true,
openAiLogsEnabled: false,
'openai.spanCharLimit': 128,
peerServiceMapping: {},
plugins: true,
port: '8126',
'profiling.enabled': undefined,
'propagateProcessTags.enabled': undefined,
'profiling.exporters': 'agent',
'profiling.sourceMap': true,
'profiling.longLivedThreshold': undefined,
protocolVersion: '0.4',
queryStringObfuscation: qsRegex,
'remoteConfig.enabled': true,
'remoteConfig.pollInterval': 5, // seconds
reportHostname: false,
resourceRenamingEnabled: false,
'runtimeMetrics.enabled': false,
'runtimeMetrics.eventLoop': true,
'runtimeMetrics.gc': true,
runtimeMetricsRuntimeId: false,
sampleRate: undefined,
'sampler.rateLimit': 100,
'sampler.rules': [],
'sampler.spanSamplingRules': [],
scope: undefined,
service,
serviceMapping: {},
site: 'datadoghq.com',
spanAttributeSchema: 'v0',
spanComputePeerService: false,
spanLeakDebug: 0,
spanRemoveIntegrationFromService: false,
startupLogs: false,
'stats.enabled': false,
tags: {},
tagsHeaderMaxLength: 512,
'telemetry.debug': false,
'telemetry.dependencyCollection': true,
'telemetry.enabled': true,
'telemetry.heartbeatInterval': 60_000,
'telemetry.logCollection': true,
'telemetry.metrics': true,
traceEnabled: true,
traceId128BitGenerationEnabled: true,
traceId128BitLoggingEnabled: true,
tracePropagationExtractFirst: false,
tracePropagationBehaviorExtract: 'continue',
'tracePropagationStyle.inject': ['datadog', 'tracecontext', 'baggage'],
'tracePropagationStyle.extract': ['datadog', 'tracecontext', 'baggage'],
'tracePropagationStyle.otelPropagators': false,
traceWebsocketMessagesEnabled: true,
traceWebsocketMessagesInheritSampling: true,
traceWebsocketMessagesSeparateTraces: true,
tracing: true,
url: undefined,
version: pkg.version,
instrumentation_config_id: undefined,
'vertexai.spanCharLimit': 128,
'vertexai.spanPromptCompletionSampleRate': 1,
'trace.aws.addSpanPointers': true,
'trace.dynamoDb.tablePrimaryKeys': undefined,
'trace.nativeSpanEvents': false
}
'use strict'
const os = require('os')
const fs = require('fs')
const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
class StableConfig {
constructor () {
this.warnings = [] // Logger hasn't been initialized yet, so we can't use log.warn
this.localEntries = {}
this.fleetEntries = {}
this.wasm_loaded = false
const { localConfigPath, fleetConfigPath } = this._getStableConfigPaths()
if (!fs.existsSync(localConfigPath) && !fs.existsSync(fleetConfigPath)) {
// Bail out early if files don't exist to avoid unnecessary library loading
return
}
const localConfig = this._readConfigFromPath(localConfigPath)
const fleetConfig = this._readConfigFromPath(fleetConfigPath)
if (!localConfig && !fleetConfig) {
// Bail out early if files are empty or we can't read them to avoid unnecessary library loading
return
}
// Note: we don't enforce loading because there may be cases where the library is not available and we
// want to avoid breaking the application. In those cases, we will not have the file-based configuration.
let libdatadog
try {
libdatadog = require('@datadog/libdatadog')
this.wasm_loaded = true
} catch {
this.warnings.push('Can\'t load libdatadog library')
return
}
const libconfig = libdatadog.maybeLoad('library_config')
if (libconfig === undefined) {
this.warnings.push('Can\'t load library_config library')
return
}
try {
const configurator = new libconfig.JsConfigurator()
// Intentionally pass through the raw environment variables for reporting.
// eslint-disable-next-line eslint-rules/eslint-process-env
configurator.set_envp(Object.entries(process.env).map(([key, value]) => `${key}=${value}`))
configurator.set_args(process.argv)
configurator.get_configuration(localConfig.toString(), fleetConfig.toString()).forEach((entry) => {
if (entry.source === 'local_stable_config') {
this.localEntries[entry.name] = entry.value
} else if (entry.source === 'fleet_stable_config') {
this.fleetEntries[entry.name] = entry.value
}
})
} catch (e) {
this.warnings.push(`Error parsing configuration from file: ${e.message}`)
}
}
_readConfigFromPath (path) {
try {
return fs.readFileSync(path, 'utf8')
} catch (err) {
if (err.code !== 'ENOENT') {
this.warnings.push(`Error reading config file at ${path}. ${err.code}: ${err.message}`)
}
return '' // Always return a string to avoid undefined.toString() errors
}
}
_getStableConfigPaths () {
let localConfigPath = ''
let fleetConfigPath = ''
switch (os.type().toLowerCase()) {
case 'linux':
localConfigPath = '/etc/datadog-agent/application_monitoring.yaml'
fleetConfigPath = '/etc/datadog-agent/managed/datadog-agent/stable/application_monitoring.yaml'
break
case 'darwin':
localConfigPath = '/opt/datadog-agent/etc/application_monitoring.yaml'
fleetConfigPath = '/opt/datadog-agent/etc/managed/datadog-agent/stable/application_monitoring.yaml'
break
case 'win32':
localConfigPath = String.raw`C:\ProgramData\Datadog\application_monitoring.yaml`
fleetConfigPath = String.raw`C:\ProgramData\Datadog\managed\datadog-agent\stable\application_monitoring.yaml`
break
default:
break
}
// Allow overriding the paths for testing
if (getEnvironmentVariable('DD_TEST_LOCAL_CONFIG_PATH') !== undefined) {
localConfigPath = getEnvironmentVariable('DD_TEST_LOCAL_CONFIG_PATH')
}
if (getEnvironmentVariable('DD_TEST_FLEET_CONFIG_PATH') !== undefined) {
fleetConfigPath = getEnvironmentVariable('DD_TEST_FLEET_CONFIG_PATH')
}
return { localConfigPath, fleetConfigPath }
}
}
module.exports = StableConfig
'use strict'
/* eslint-disable eslint-rules/eslint-process-env */
const { deprecate } = require('util')
const { supportedConfigurations, aliases, deprecations } = require('./supported-configurations.json')
/**
* Types for environment variable handling.
*
* @typedef {keyof typeof supportedConfigurations} SupportedEnvKey
* @typedef {Partial<typeof process.env> & Partial<Record<SupportedEnvKey, string|undefined>>} TracerEnv
*/
const aliasToCanonical = {}
for (const canonical of Object.keys(aliases)) {
for (const alias of aliases[canonical]) {
if (aliasToCanonical[alias]) {
throw new Error(`The alias ${alias} is already used for ${aliasToCanonical[alias]}.`)
}
aliasToCanonical[alias] = canonical
}
}
const deprecationMethods = {}
for (const deprecation of Object.keys(deprecations)) {
deprecationMethods[deprecation] = deprecate(
() => {},
`The environment variable ${deprecation} is deprecated.` +
(aliasToCanonical[deprecation]
? ` Please use ${aliasToCanonical[deprecation]} instead.`
: ` ${deprecations[deprecation]}`),
`DATADOG_${deprecation}`
)
}
module.exports = {
/**
* Returns the environment variables that are supported by the tracer
* (including all non-Datadog/OTEL specific environment variables).
*
* This should only be called once in config.js to avoid copying the object frequently.
*
* @returns {TracerEnv} The environment variables
*/
getEnvironmentVariables () {
const configs = {}
for (const [key, value] of Object.entries(process.env)) {
if (key.startsWith('DD_') || key.startsWith('OTEL_') || aliasToCanonical[key]) {
if (supportedConfigurations[key]) {
configs[key] = value
} else if (aliasToCanonical[key] && configs[aliasToCanonical[key]] === undefined) {
// The alias should only be used if the actual configuration is not set
// In case that more than a single alias exist, use the one defined first in our own order
for (const alias of aliases[aliasToCanonical[key]]) {
if (process.env[alias] !== undefined) {
configs[aliasToCanonical[key]] = value
break
}
}
// TODO(BridgeAR) Implement logging. It would have to use a timeout to
// lazily log the message after all loading being done otherwise.
// debug(
// `Missing configuration ${env} in supported-configurations file. The environment variable is ignored.`
// )
}
deprecationMethods[key]?.()
} else {
configs[key] = value
}
}
return configs
},
/**
* Returns the environment variable, if it's supported or a non Datadog
* configuration. Otherwise, it throws an error.
*
* @param {string} name Environment variable name
* @returns {string|undefined}
* @throws {Error} if the configuration is not supported
*/
// This method, and callers of this method, need to be updated to check for declarative config sources as well.
getEnvironmentVariable (name) {
if ((name.startsWith('DD_') || name.startsWith('OTEL_') || aliasToCanonical[name]) &&
!supportedConfigurations[name]) {
throw new Error(`Missing ${name} env/configuration in "supported-configurations.json" file.`)
}
const config = process.env[name]
if (config === undefined && aliases[name]) {
for (const alias of aliases[name]) {
if (process.env[alias] !== undefined) {
return process.env[alias]
}
}
}
return config
}
}

Sorry, the diff of this file is too big to display

'use strict'
const fs = require('fs')
const path = require('path')
const gitPropertiesCommitSHARegex = /git\.commit\.sha=([a-f\d]{40})/
const gitPropertiesRepositoryUrlRegex = /git\.repository_url=([\w\d:@/.-]+)/
const repositoryUrlRegex = /^([\w\d:@/.-]+)$/
const remoteOriginRegex = /^\[remote\s+"origin"\]/i
const gitHeadRefRegex = /ref:\s+(refs\/[A-Za-z0-9._/-]+)/
const commitSHARegex = /^[0-9a-f]{40}$/
function removeUserSensitiveInfo (repositoryUrl) {
try {
// repository URLs can contain username and password, so we want to filter those out
const parsedUrl = new URL(repositoryUrl)
if (parsedUrl.username || parsedUrl.password) {
return `${parsedUrl.origin}${parsedUrl.pathname}`
}
return repositoryUrl
} catch {
// if protocol isn't https, no password will be used
return repositoryUrl
}
}
function getGitMetadataFromGitProperties (gitPropertiesString) {
if (!gitPropertiesString) {
return {}
}
const commitSHAMatch = gitPropertiesString.match(gitPropertiesCommitSHARegex)
const repositoryUrlMatch = gitPropertiesString.match(gitPropertiesRepositoryUrlRegex)
const repositoryUrl = repositoryUrlMatch ? repositoryUrlMatch[1] : undefined
return {
commitSHA: commitSHAMatch ? commitSHAMatch[1] : undefined,
repositoryUrl: removeUserSensitiveInfo(repositoryUrl)
}
}
function getRemoteOriginURL (gitConfigContent) {
if (!gitConfigContent) {
return
}
const lines = gitConfigContent.split('\n')
let index = 0
// find the remote origin section
for (; index < lines.length; index++) {
const line = lines[index]
if (line[0] !== '[') continue // fast path
if (remoteOriginRegex.test(line)) break
}
// find the url key/value in the [remote "origin"] section
index++
for (; index < lines.length; index++) {
const line = lines[index]
if (line[0] === '[') return // abort, section didn't contain a url
const splitAt = line.indexOf('=')
if (splitAt === -1) continue
const key = line.slice(0, splitAt).trim().toLowerCase()
if (key !== 'url') continue
const repositoryUrlValue = line.slice(splitAt + 1).trim()
const repositoryUrlMatch = repositoryUrlValue.match(repositoryUrlRegex)
if (!repositoryUrlMatch) continue
return removeUserSensitiveInfo(repositoryUrlMatch[0])
}
}
function getGitHeadRef (gitHeadContent) {
if (!gitHeadContent) {
return
}
// Extract the ref after 'ref: '
const gitRefMatch = gitHeadContent.match(gitHeadRefRegex)
return gitRefMatch?.[1]
}
function resolveGitHeadSHA (DD_GIT_FOLDER_PATH) {
const gitHeadPath = path.join(DD_GIT_FOLDER_PATH, 'HEAD')
try {
const gitHeadContent = fs.readFileSync(gitHeadPath, 'utf8')
if (!gitHeadContent) {
return
}
const headContent = gitHeadContent.trim()
// Handle detached head case
if (commitSHARegex.test(headContent)) {
return headContent
}
// Handle ref case - extract the ref and read the SHA from the ref file
const gitHeadRef = getGitHeadRef(headContent)
if (!gitHeadRef) {
return
}
const gitHeadRefPath = path.join(DD_GIT_FOLDER_PATH, gitHeadRef)
const gitHeadRefContent = fs.readFileSync(gitHeadRefPath, 'utf8')
if (gitHeadRefContent) {
const headRefContent = gitHeadRefContent.trim()
if (commitSHARegex.test(headRefContent)) {
return headRefContent
}
}
} catch {}
}
module.exports = {
getGitMetadataFromGitProperties,
removeUserSensitiveInfo,
getGitHeadRef,
getRemoteOriginURL,
resolveGitHeadSHA,
}
{
"supportedConfigurations": {
"DD_AAS_DOTNET_EXTENSION_VERSION": ["A"],
"DD_ACTION_EXECUTION_ID": ["A"],
"DD_AGENT_HOST": ["A"],
"DD_AGENTLESS_LOG_SUBMISSION_ENABLED": ["A"],
"DD_AGENTLESS_LOG_SUBMISSION_URL": ["A"],
"DD_AI_GUARD_ENABLED": ["A"],
"DD_AI_GUARD_ENDPOINT": ["A"],
"DD_AI_GUARD_MAX_CONTENT_SIZE": ["A"],
"DD_AI_GUARD_MAX_MESSAGES_LENGTH": ["A"],
"DD_AI_GUARD_TIMEOUT": ["A"],
"DD_API_KEY": ["A"],
"DD_API_SECURITY_ENABLED": ["A"],
"DD_API_SECURITY_SAMPLE_DELAY": ["A"],
"DD_API_SECURITY_ENDPOINT_COLLECTION_ENABLED": ["A"],
"DD_API_SECURITY_ENDPOINT_COLLECTION_MESSAGE_LIMIT": ["A"],
"DD_APM_FLUSH_DEADLINE_MILLISECONDS": ["A"],
"DD_APM_TRACING_ENABLED": ["A"],
"DD_APP_KEY": ["A"],
"DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE": ["A"],
"DD_APPSEC_COLLECT_ALL_HEADERS": ["A"],
"DD_APPSEC_ENABLED": ["A"],
"DD_APPSEC_GRAPHQL_BLOCKED_TEMPLATE_JSON": ["A"],
"DD_APPSEC_HEADER_COLLECTION_REDACTION_ENABLED": ["A"],
"DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML": ["A"],
"DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON": ["A"],
"DD_APPSEC_MAX_COLLECTED_HEADERS": ["A"],
"DD_APPSEC_MAX_STACK_TRACE_DEPTH": ["A"],
"DD_APPSEC_MAX_STACK_TRACES": ["A"],
"DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP": ["A"],
"DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP": ["A"],
"DD_APPSEC_RASP_COLLECT_REQUEST_BODY": ["A"],
"DD_APPSEC_RASP_ENABLED": ["A"],
"DD_APPSEC_RULES": ["A"],
"DD_APPSEC_SCA_ENABLED": ["A"],
"DD_APPSEC_STACK_TRACE_ENABLED": ["A"],
"DD_APPSEC_TRACE_RATE_LIMIT": ["A"],
"DD_APPSEC_WAF_TIMEOUT": ["A"],
"DD_AZURE_RESOURCE_GROUP": ["A"],
"DD_CIVISIBILITY_AGENTLESS_ENABLED": ["A"],
"DD_CIVISIBILITY_AGENTLESS_URL": ["A"],
"DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER": ["A"],
"DD_CIVISIBILITY_DANGEROUSLY_FORCE_COVERAGE": ["A"],
"DD_CIVISIBILITY_DANGEROUSLY_FORCE_TEST_SKIPPING": ["A"],
"DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED": ["A"],
"DD_CIVISIBILITY_ENABLED": ["A"],
"DD_CIVISIBILITY_FLAKY_RETRY_COUNT": ["A"],
"DD_CIVISIBILITY_FLAKY_RETRY_ENABLED": ["A"],
"DD_CIVISIBILITY_GIT_UNSHALLOW_ENABLED": ["A"],
"DD_CIVISIBILITY_GIT_UPLOAD_ENABLED": ["A"],
"DD_CIVISIBILITY_IMPACTED_TESTS_DETECTION_ENABLED": ["A"],
"DD_CIVISIBILITY_ITR_ENABLED": ["A"],
"DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS": ["A"],
"DD_CIVISIBILITY_MANUAL_API_ENABLED": ["A"],
"DD_CIVISIBILITY_TEST_COMMAND": ["A"],
"DD_CIVISIBILITY_TEST_MODULE_ID": ["A"],
"DD_CIVISIBILITY_TEST_SESSION_ID": ["A"],
"DD_CODE_ORIGIN_FOR_SPANS_ENABLED": ["A"],
"DD_CODE_ORIGIN_FOR_SPANS_EXPERIMENTAL_EXIT_SPANS_ENABLED": ["A"],
"DD_CRASHTRACKING_ENABLED": ["A"],
"DD_CUSTOM_TRACE_ID": ["A"],
"DD_DATA_STREAMS_ENABLED": ["A"],
"DD_DBM_PROPAGATION_MODE": ["A"],
"DD_DOGSTATSD_HOST": ["A"],
"DD_DOGSTATSD_PORT": ["A"],
"DD_DYNAMIC_INSTRUMENTATION_CAPTURE_TIMEOUT_MS": ["A"],
"DD_DYNAMIC_INSTRUMENTATION_ENABLED": ["A"],
"DD_DYNAMIC_INSTRUMENTATION_PROBE_FILE": ["A"],
"DD_DYNAMIC_INSTRUMENTATION_REDACTED_IDENTIFIERS": ["A"],
"DD_DYNAMIC_INSTRUMENTATION_REDACTION_EXCLUDED_IDENTIFIERS": ["A"],
"DD_DYNAMIC_INSTRUMENTATION_UPLOAD_INTERVAL_SECONDS": ["A"],
"DD_ENV": ["A"],
"DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED": ["A"],
"DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED": ["A"],
"DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED": ["A"],
"DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_ENABLED": ["A"],
"DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_DIR": ["A"],
"DD_EXTERNAL_ENV": ["A"],
"DD_FLAGGING_PROVIDER_ENABLED": ["A"],
"DD_GIT_BRANCH": ["A"],
"DD_GIT_COMMIT_AUTHOR_DATE": ["A"],
"DD_GIT_COMMIT_AUTHOR_EMAIL": ["A"],
"DD_GIT_COMMIT_AUTHOR_NAME": ["A"],
"DD_GIT_COMMIT_COMMITTER_DATE": ["A"],
"DD_GIT_COMMIT_COMMITTER_EMAIL": ["A"],
"DD_GIT_COMMIT_COMMITTER_NAME": ["A"],
"DD_GIT_COMMIT_MESSAGE": ["A"],
"DD_GIT_COMMIT_SHA": ["A"],
"DD_GIT_PROPERTIES_FILE": ["A"],
"DD_GIT_FOLDER_PATH": ["A"],
"DD_GIT_REPOSITORY_URL": ["A"],
"DD_GIT_TAG": ["A"],
"DD_GIT_PULL_REQUEST_BASE_BRANCH": ["A"],
"DD_GIT_PULL_REQUEST_BASE_BRANCH_SHA": ["A"],
"DD_GRPC_CLIENT_ERROR_STATUSES": ["A"],
"DD_GRPC_SERVER_ERROR_STATUSES": ["A"],
"DD_HEAP_SNAPSHOT_COUNT": ["A"],
"DD_HEAP_SNAPSHOT_INTERVAL": ["A"],
"DD_HEAP_SNAPSHOT_DESTINATION": ["A"],
"DD_IAST_DB_ROWS_TO_TAINT": ["A"],
"DD_IAST_DEDUPLICATION_ENABLED": ["A"],
"DD_IAST_ENABLED": ["A"],
"DD_IAST_MAX_CONCURRENT_REQUESTS": ["A"],
"DD_IAST_MAX_CONTEXT_OPERATIONS": ["A"],
"DD_IAST_REDACTION_ENABLED": ["A"],
"DD_IAST_REDACTION_NAME_PATTERN": ["A"],
"DD_IAST_REDACTION_VALUE_PATTERN": ["A"],
"DD_IAST_REQUEST_SAMPLING": ["A"],
"DD_IAST_SECURITY_CONTROLS_CONFIGURATION": ["A"],
"DD_IAST_STACK_TRACE_ENABLED": ["A"],
"DD_IAST_TELEMETRY_VERBOSITY": ["A"],
"DD_INJECT_FORCE": ["A"],
"DD_INJECTION_ENABLED": ["A"],
"DD_INSTRUMENTATION_CONFIG_ID": ["A"],
"DD_INSTRUMENTATION_INSTALL_ID": ["A"],
"DD_INSTRUMENTATION_INSTALL_TIME": ["A"],
"DD_INSTRUMENTATION_INSTALL_TYPE": ["A"],
"DD_INSTRUMENTATION_TELEMETRY_ENABLED": ["A"],
"DD_INTERNAL_PROFILING_LONG_LIVED_THRESHOLD": ["A"],
"DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED": ["A"],
"DD_LAMBDA_HANDLER": ["A"],
"DD_LANGCHAIN_SPAN_CHAR_LIMIT": ["A"],
"DD_LANGCHAIN_SPAN_PROMPT_COMPLETION_SAMPLE_RATE": ["A"],
"DD_LLMOBS_AGENTLESS_ENABLED": ["A"],
"DD_LLMOBS_ENABLED": ["A"],
"DD_LLMOBS_ML_APP": ["A"],
"DD_LOG_LEVEL": ["A"],
"DD_LOGS_INJECTION": ["A"],
"DD_LOGS_OTEL_ENABLED": ["A"],
"DD_METRICS_OTEL_ENABLED": ["A"],
"DD_MINI_AGENT_PATH": ["A"],
"DD_OPENAI_LOGS_ENABLED": ["A"],
"DD_OPENAI_SPAN_CHAR_LIMIT": ["A"],
"DD_PIPELINE_EXECUTION_ID": ["A"],
"DD_PLAYWRIGHT_WORKER": ["A"],
"DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED": ["A"],
"DD_PROFILING_CODEHOTSPOTS_ENABLED": ["A"],
"DD_PROFILING_CPU_ENABLED": ["A"],
"DD_PROFILING_DEBUG_SOURCE_MAPS": ["A"],
"DD_PROFILING_DEBUG_UPLOAD_COMPRESSION": ["A"],
"DD_PROFILING_ENABLED": ["A"],
"DD_PROFILING_ENDPOINT_COLLECTION_ENABLED": ["A"],
"DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES": ["A"],
"DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE": ["A"],
"DD_PROFILING_EXPERIMENTAL_OOM_MAX_HEAP_EXTENSION_COUNT": ["A"],
"DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED": ["A"],
"DD_PROFILING_EXPORTERS": ["A"],
"DD_PROFILING_HEAP_ENABLED": ["A"],
"DD_PROFILING_HEAP_SAMPLING_INTERVAL": ["A"],
"DD_PROFILING_PPROF_PREFIX": ["A"],
"DD_PROFILING_PROFILERS": ["A"],
"DD_PROFILING_SOURCE_MAP": ["A"],
"DD_PROFILING_TIMELINE_ENABLED": ["A"],
"DD_PROFILING_UPLOAD_PERIOD": ["A"],
"DD_PROFILING_UPLOAD_TIMEOUT": ["A"],
"DD_PROFILING_V8_PROFILER_BUG_WORKAROUND": ["A"],
"DD_PROFILING_WALLTIME_ENABLED": ["A"],
"DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS": ["A"],
"DD_REMOTE_CONFIGURATION_ENABLED": ["A"],
"DD_RUNTIME_METRICS_ENABLED": ["A"],
"DD_RUNTIME_METRICS_EVENT_LOOP_ENABLED": ["A"],
"DD_RUNTIME_METRICS_GC_ENABLED": ["A"],
"DD_RUNTIME_METRICS_FLUSH_INTERVAL": ["A"],
"DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED": ["A"],
"DD_TRACE_GCP_PUBSUB_PUSH_ENABLED": ["A"],
"DD_SERVICE_MAPPING": ["A"],
"DD_SERVICE": ["A"],
"DD_SITE": ["A"],
"DD_SPAN_SAMPLING_RULES_FILE": ["A"],
"DD_SPAN_SAMPLING_RULES": ["A"],
"DD_TAGS": ["A"],
"DD_TELEMETRY_DEBUG": ["A"],
"DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED": ["A"],
"DD_TELEMETRY_FORWARDER_PATH": ["A"],
"DD_TELEMETRY_HEARTBEAT_INTERVAL": ["A"],
"DD_TELEMETRY_LOG_COLLECTION_ENABLED": ["A"],
"DD_TELEMETRY_METRICS_ENABLED": ["A"],
"DD_TEST_FAILED_TEST_REPLAY_ENABLED": ["A"],
"DD_TEST_FLEET_CONFIG_PATH": ["A"],
"DD_TEST_LOCAL_CONFIG_PATH": ["A"],
"DD_TEST_MANAGEMENT_ATTEMPT_TO_FIX_RETRIES": ["A"],
"DD_TEST_MANAGEMENT_ENABLED": ["A"],
"DD_TEST_SESSION_NAME": ["A"],
"DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED": ["A"],
"DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED": ["A"],
"DD_TRACE_AEROSPIKE_ENABLED": ["A"],
"DD_TRACE_AI_ENABLED": ["A"],
"DD_TRACE_ANTHROPIC_ENABLED": ["A"],
"DD_TRACE_AGENT_PORT": ["A"],
"DD_TRACE_AGENT_PROTOCOL_VERSION": ["A"],
"DD_TRACE_AGENT_URL": ["A"],
"DD_TRACE_AMQP10_ENABLED": ["A"],
"DD_TRACE_AMQPLIB_ENABLED": ["A"],
"DD_TRACE_APOLLO_ENABLED": ["A"],
"DD_TRACE_APOLLO_GATEWAY_ENABLED": ["A"],
"DD_TRACE_APOLLO_SERVER_CORE_ENABLED": ["A"],
"DD_TRACE_APOLLO_SERVER_ENABLED": ["A"],
"DD_TRACE_APOLLO_SERVER_EXPRESS_ENABLED": ["A"],
"DD_TRACE_APOLLO_SERVER_FASTIFY_ENABLED": ["A"],
"DD_TRACE_APOLLO_SUBGRAPH_ENABLED": ["A"],
"DD_TRACE_AVSC_ENABLED": ["A"],
"DD_TRACE_AWS_ADD_SPAN_POINTERS": ["A"],
"DD_TRACE_AWS_SDK_AWS_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_AWS_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_BEDROCKRUNTIME_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_BEDROCKRUNTIME_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_CLOUDWATCHLOGS_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_CLOUDWATCHLOGS_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_DYNAMODB_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_DYNAMODB_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_EVENTBRIDGE_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_EVENTBRIDGE_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_KINESIS_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_KINESIS_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_LAMBDA_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_LAMBDA_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_NODE_HTTP_HANDLER_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_REDSHIFT_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_REDSHIFT_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_S3_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_S3_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SFN_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SFN_CLIENT_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SFN_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SMITHY_CLIENT_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SNS_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SNS_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SQS_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_SQS_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_STATES_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_STATES_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_STEPFUNCTIONS_BATCH_PROPAGATION_ENABLED": ["A"],
"DD_TRACE_AWS_SDK_STEPFUNCTIONS_ENABLED": ["A"],
"DD_TRACE_AXIOS_ENABLED": ["A"],
"DD_TRACE_AZURE_EVENT_HUBS_ENABLED": ["A"],
"DD_TRACE_AZURE_EVENTHUBS_BATCH_LINKS_ENABLED": ["A"],
"DD_TRACE_AZURE_FUNCTIONS_ENABLED": ["A"],
"DD_TRACE_AZURE_SERVICE_BUS_ENABLED": ["A"],
"DD_TRACE_AZURE_SERVICEBUS_BATCH_LINKS_ENABLED": ["A"],
"DD_TRACE_BAGGAGE_MAX_BYTES": ["A"],
"DD_TRACE_BAGGAGE_MAX_ITEMS": ["A"],
"DD_TRACE_BAGGAGE_TAG_KEYS": ["A"],
"DD_TRACE_BEAUTIFUL_LOGS": ["A"],
"DD_TRACE_BLUEBIRD_ENABLED": ["A"],
"DD_TRACE_BULLMQ_ENABLED": ["A"],
"DD_TRACE_BODY_PARSER_ENABLED": ["A"],
"DD_TRACE_BSON_ENABLED": ["A"],
"DD_TRACE_BUNYAN_ENABLED": ["A"],
"DD_TRACE_CASSANDRA_DRIVER_ENABLED": ["A"],
"DD_TRACE_CHILD_PROCESS_ENABLED": ["A"],
"DD_TRACE_CLIENT_IP_ENABLED": ["A"],
"DD_TRACE_CLIENT_IP_HEADER": ["A"],
"DD_TRACE_CLOUD_PAYLOAD_TAGGING_MAX_DEPTH": ["A"],
"DD_TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING": ["A"],
"DD_TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING": ["A"],
"DD_TRACE_COLLECTIONS_ENABLED": ["A"],
"DD_TRACE_COMMONPLUGIN_ENABLED": ["A"],
"DD_TRACE_CONFLUENTINC_KAFKA_JAVASCRIPT_ENABLED": ["A"],
"DD_TRACE_CONNECT_ENABLED": ["A"],
"DD_TRACE_COOKIE_ENABLED": ["A"],
"DD_TRACE_COOKIE_PARSER_ENABLED": ["A"],
"DD_TRACE_COUCHBASE_ENABLED": ["A"],
"DD_TRACE_CRYPTO_ENABLED": ["A"],
"DD_TRACE_CUCUMBER_CUCUMBER_ENABLED": ["A"],
"DD_TRACE_CUCUMBER_ENABLED": ["A"],
"DD_TRACE_CYPRESS_ENABLED": ["A"],
"DD_TRACE_DD_TRACE_API_ENABLED": ["A"],
"DD_TRACE_DEBUG": ["A"],
"DD_TRACE_DISABLED_INSTRUMENTATIONS": ["A"],
"DD_TRACE_DISABLED_PLUGINS": ["A"],
"DD_TRACE_DNS_ENABLED": ["A"],
"DD_TRACE_DYNAMODB_TABLE_PRIMARY_KEYS": ["A"],
"DD_TRACE_ELASTIC_ELASTICSEARCH_ENABLED": ["A"],
"DD_TRACE_ELASTIC_TRANSPORT_ENABLED": ["A"],
"DD_TRACE_ELASTICSEARCH_ENABLED": ["A"],
"DD_TRACE_ENABLED": ["A"],
"DD_TRACE_ENCODING_DEBUG": ["A"],
"DD_TRACE_EXPERIMENTAL_B3_ENABLED": ["A"],
"DD_TRACE_EXPERIMENTAL_EXPORTER": ["A"],
"DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED": ["A"],
"DD_TRACE_EXPERIMENTAL_SPAN_COUNTS": ["A"],
"DD_TRACE_EXPERIMENTAL_STATE_TRACKING": ["A"],
"DD_TRACE_EXPRESS_ENABLED": ["A"],
"DD_TRACE_EXPRESS_MONGO_SANITIZE_ENABLED": ["A"],
"DD_TRACE_EXPRESS_SESSION_ENABLED": ["A"],
"DD_TRACE_FASTIFY_ENABLED": ["A"],
"DD_TRACE_FETCH_ENABLED": ["A"],
"DD_TRACE_FIND_MY_WAY_ENABLED": ["A"],
"DD_TRACE_FLUSH_INTERVAL": ["A"],
"DD_TRACE_FS_ENABLED": ["A"],
"DD_TRACE_GENERIC_POOL_ENABLED": ["A"],
"DD_TRACE_GIT_METADATA_ENABLED": ["A"],
"DD_TRACE_GLOBAL_TAGS": ["A"],
"DD_TRACE_GOOGLE_CLOUD_PUBSUB_ENABLED": ["A"],
"DD_TRACE_GOOGLE_CLOUD_VERTEXAI_ENABLED": ["A"],
"DD_TRACE_GOOGLE_GAX_ENABLED": ["A"],
"DD_TRACE_GOOGLE_GENAI_ENABLED": ["A"],
"DD_TRACE_GRAPHQL_ENABLED": ["A"],
"DD_TRACE_GRAPHQL_ERROR_EXTENSIONS": ["A"],
"DD_TRACE_GRAPHQL_TAG_ENABLED": ["A"],
"DD_TRACE_GRAPHQL_TOOLS_ENABLED": ["A"],
"DD_TRACE_GRAPHQL_TOOLS_EXECUTOR_ENABLED": ["A"],
"DD_TRACE_GRAPHQL_YOGA_ENABLED": ["A"],
"DD_TRACE_GRPC_ENABLED": ["A"],
"DD_TRACE_GRPC_GRPC_JS_ENABLED": ["A"],
"DD_TRACE_GRPC_PROTO_LOADER_ENABLED": ["A"],
"DD_TRACE_HANDLEBARS_ENABLED": ["A"],
"DD_TRACE_HAPI_BOOM_ENABLED": ["A"],
"DD_TRACE_HAPI_ENABLED": ["A"],
"DD_TRACE_HAPI_HAPI_ENABLED": ["A"],
"DD_TRACE_HEADER_TAGS": ["A"],
"DD_TRACE_HONO_ENABLED": ["A"],
"DD_TRACE_HTTP_ENABLED": ["A"],
"DD_TRACE_HTTP2_ENABLED": ["A"],
"DD_TRACE_HTTPS_ENABLED": ["A"],
"DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED": ["A"],
"DD_TRACE_IOREDIS_ENABLED": ["A"],
"DD_TRACE_IOVALKEY_ENABLED": ["A"],
"DD_TRACE_JEST_CIRCUS_ENABLED": ["A"],
"DD_TRACE_JEST_CONFIG_ENABLED": ["A"],
"DD_TRACE_JEST_CORE_ENABLED": ["A"],
"DD_TRACE_JEST_ENABLED": ["A"],
"DD_TRACE_JEST_ENVIRONMENT_JSDOM_ENABLED": ["A"],
"DD_TRACE_JEST_ENVIRONMENT_NODE_ENABLED": ["A"],
"DD_TRACE_JEST_GLOBALS_ENABLED": ["A"],
"DD_TRACE_JEST_REPORTERS_ENABLED": ["A"],
"DD_TRACE_JEST_RUNTIME_ENABLED": ["A"],
"DD_TRACE_JEST_TEST_SEQUENCER_ENABLED": ["A"],
"DD_TRACE_JEST_TRANSFORM_ENABLED": ["A"],
"DD_TRACE_JEST_WORKER_ENABLED": ["A"],
"DD_TRACE_KAFKAJS_ENABLED": ["A"],
"DD_TRACE_KNEX_ENABLED": ["A"],
"DD_TRACE_KOA_ENABLED": ["A"],
"DD_TRACE_KOA_ROUTE_ENABLED": ["A"],
"DD_TRACE_KOA_ROUTER_ENABLED": ["A"],
"DD_TRACE_KOA_WEBSOCKET_ENABLED": ["A"],
"DD_TRACE_LANGCHAIN_ANTHROPIC_ENABLED": ["A"],
"DD_TRACE_LANGCHAIN_COHERE_ENABLED": ["A"],
"DD_TRACE_LANGCHAIN_CORE_ENABLED": ["A"],
"DD_TRACE_LANGCHAIN_ENABLED": ["A"],
"DD_TRACE_LANGCHAIN_GOOGLE_GENAI_ENABLED": ["A"],
"DD_TRACE_LANGCHAIN_OPENAI_ENABLED": ["A"],
"DD_TRACE_LDAPJS_ENABLED": ["A"],
"DD_TRACE_LDAPJS_PROMISE_ENABLED": ["A"],
"DD_TRACE_LEGACY_BAGGAGE_ENABLED": ["A"],
"DD_TRACE_LIMITD_CLIENT_ENABLED": ["A"],
"DD_TRACE_LODASH_ENABLED": ["A"],
"DD_TRACE_LOG_LEVEL": ["A"],
"DD_TRACE_LOOPBACK_ENABLED": ["A"],
"DD_TRACE_MARIADB_ENABLED": ["A"],
"DD_TRACE_MEMCACHED_COMMAND_ENABLED": ["A"],
"DD_TRACE_MEMCACHED_ENABLED": ["A"],
"DD_TRACE_MICROGATEWAY_CORE_ENABLED": ["A"],
"DD_TRACE_MIDDIE_ENABLED": ["A"],
"DD_TRACE_MIDDLEWARE_TRACING_ENABLED": ["A"],
"DD_TRACE_MOCHA_EACH_ENABLED": ["A"],
"DD_TRACE_MOCHA_ENABLED": ["A"],
"DD_TRACE_MOLECULER_ENABLED": ["A"],
"DD_TRACE_MONGODB_CORE_ENABLED": ["A"],
"DD_TRACE_MONGODB_ENABLED": ["A"],
"DD_TRACE_MONGODB_HEARTBEAT_ENABLED": ["A"],
"DD_TRACE_MONGOOSE_ENABLED": ["A"],
"DD_TRACE_MQUERY_ENABLED": ["A"],
"DD_TRACE_MULTER_ENABLED": ["A"],
"DD_TRACE_MYSQL_ENABLED": ["A"],
"DD_TRACE_MYSQL2_ENABLED": ["A"],
"DD_TRACE_NATIVE_SPAN_EVENTS": ["A"],
"DD_TRACE_NET_ENABLED": ["A"],
"DD_TRACE_NEXT_ENABLED": ["A"],
"DD_TRACE_NODE_CHILD_PROCESS_ENABLED": ["A"],
"DD_TRACE_NODE_REDIS_CLIENT_ENABLED": ["A"],
"DD_TRACE_NODE_SERIALIZE_ENABLED": ["A"],
"DD_TRACE_NYC_ENABLED": ["A"],
"DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP": ["A"],
"DD_TRACE_OPENAI_ENABLED": ["A"],
"DD_TRACE_OPENSEARCH_ENABLED": ["A"],
"DD_TRACE_OPENSEARCH_PROJECT_OPENSEARCH_ENABLED": ["A"],
"DD_TRACE_OPENTELEMETRY_SDK_TRACE_NODE_ENABLED": ["A"],
"DD_TRACE_ORACLEDB_ENABLED": ["A"],
"DD_TRACE_OTEL_ENABLED": ["A"],
"DD_TRACE_PARTIAL_FLUSH_MIN_SPANS": ["A"],
"DD_TRACE_PASSPORT_ENABLED": ["A"],
"DD_TRACE_PASSPORT_HTTP_ENABLED": ["A"],
"DD_TRACE_PASSPORT_LOCAL_ENABLED": ["A"],
"DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED": ["A"],
"DD_TRACE_PEER_SERVICE_MAPPING": ["A"],
"DD_TRACE_PG_CURSOR_ENABLED": ["A"],
"DD_TRACE_PG_ENABLED": ["A"],
"DD_TRACE_PG_NATIVE_ENABLED": ["A"],
"DD_TRACE_PG_QUERY_STREAM_ENABLED": ["A"],
"DD_TRACE_PINO_ENABLED": ["A"],
"DD_TRACE_PINO_PRETTY_ENABLED": ["A"],
"DD_TRACE_PLAYWRIGHT_CORE_ENABLED": ["A"],
"DD_TRACE_PLAYWRIGHT_ENABLED": ["A"],
"DD_TRACE_PLAYWRIGHT_TEST_ENABLED": ["A"],
"DD_TRACE_PRISMA_ENABLED": ["A"],
"DD_TRACE_PROCESS_ENABLED": ["A"],
"DD_TRACE_PROMISE_ENABLED": ["A"],
"DD_TRACE_PROMISE_JS_ENABLED": ["A"],
"DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT": ["A"],
"DD_TRACE_PROPAGATION_EXTRACT_FIRST": ["A"],
"DD_TRACE_PROPAGATION_STYLE_EXTRACT": ["A"],
"DD_TRACE_PROPAGATION_STYLE_INJECT": ["A"],
"DD_TRACE_PROPAGATION_STYLE": ["A"],
"DD_TRACE_PROTOBUFJS_ENABLED": ["A"],
"DD_TRACE_PUG_ENABLED": ["A"],
"DD_TRACE_Q_ENABLED": ["A"],
"DD_TRACE_RATE_LIMIT": ["A"],
"DD_TRACE_REACT_DOM_ENABLED": ["A"],
"DD_TRACE_REACT_ENABLED": ["A"],
"DD_TRACE_REDIS_CLIENT_ENABLED": ["A"],
"DD_TRACE_REDIS_ENABLED": ["A"],
"DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED": ["A"],
"DD_TRACE_REPORT_HOSTNAME": ["A"],
"DD_TRACE_REQUEST_ENABLED": ["A"],
"DD_TRACE_RESOURCE_RENAMING_ENABLED": ["A"],
"DD_TRACE_RESTIFY_ENABLED": ["A"],
"DD_TRACE_RHEA_ENABLED": ["A"],
"DD_TRACE_ROUTER_ENABLED": ["A"],
"DD_TRACE_SAMPLE_RATE": ["A"],
"DD_TRACE_SAMPLING_RULES": ["A"],
"DD_TRACE_SCOPE": ["A"],
"DD_TRACE_SELENIUM_ENABLED": ["A"],
"DD_TRACE_SELENIUM_WEBDRIVER_ENABLED": ["A"],
"DD_TRACE_SEQUELIZE_ENABLED": ["A"],
"DD_TRACE_SHAREDB_ENABLED": ["A"],
"DD_TRACE_SMITHY_SMITHY_CLIENT_ENABLED": ["A"],
"DD_TRACE_SPAN_ATTRIBUTE_SCHEMA": ["A"],
"DD_TRACE_SPAN_LEAK_DEBUG": ["A"],
"DD_TRACE_SQLITE3_ENABLED": ["A"],
"DD_TRACE_STARTUP_LOGS": ["A"],
"DD_TRACE_STATS_COMPUTATION_ENABLED": ["A"],
"DD_TRACE_SUFFIXPLUGIN_ENABLED": ["A"],
"DD_TRACE_TAGS": ["A"],
"DD_TRACE_TEDIOUS_ENABLED": ["A"],
"DD_TRACE_UNDICI_ENABLED": ["A"],
"DD_TRACE_URL_ENABLED": ["A"],
"DD_TRACE_VITEST_ENABLED": ["A"],
"DD_TRACE_VITEST_RUNNER_ENABLED": ["A"],
"DD_TRACE_VM_ENABLED": ["A"],
"DD_TRACE_WEBSOCKET_MESSAGES_ENABLED":["A"],
"DD_TRACE_WEBSOCKET_MESSAGES_INHERIT_SAMPLING": ["A"],
"DD_TRACE_WEBSOCKET_MESSAGES_SEPARATE_TRACES":["A"],
"DD_TRACE_WHEN_ENABLED": ["A"],
"DD_TRACE_WINSTON_ENABLED": ["A"],
"DD_TRACE_WORKERPOOL_ENABLED": ["A"],
"DD_TRACE_WS_ENABLED": ["A"],
"DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH": ["A"],
"DD_TRACING_ENABLED": ["A"],
"DD_VERSION": ["A"],
"DD_VERTEXAI_SPAN_CHAR_LIMIT": ["A"],
"DD_VERTEXAI_SPAN_PROMPT_COMPLETION_SAMPLE_RATE": ["A"],
"DD_VITEST_WORKER": ["A"],
"OTEL_LOG_LEVEL": ["A"],
"OTEL_LOGS_EXPORTER": ["A"],
"OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": ["A"],
"OTEL_EXPORTER_OTLP_LOGS_HEADERS": ["A"],
"OTEL_EXPORTER_OTLP_LOGS_PROTOCOL": ["A"],
"OTEL_EXPORTER_OTLP_LOGS_TIMEOUT": ["A"],
"OTEL_EXPORTER_OTLP_ENDPOINT": ["A"],
"OTEL_EXPORTER_OTLP_HEADERS": ["A"],
"OTEL_EXPORTER_OTLP_PROTOCOL": ["A"],
"OTEL_EXPORTER_OTLP_TIMEOUT": ["A"],
"OTEL_BSP_SCHEDULE_DELAY": ["A"],
"OTEL_BSP_MAX_EXPORT_BATCH_SIZE": ["A"],
"OTEL_BSP_MAX_QUEUE_SIZE": ["A"],
"OTEL_EXPORTER_OTLP_METRICS_ENDPOINT": ["A"],
"OTEL_EXPORTER_OTLP_METRICS_HEADERS": ["A"],
"OTEL_EXPORTER_OTLP_METRICS_PROTOCOL": ["A"],
"OTEL_EXPORTER_OTLP_METRICS_TIMEOUT": ["A"],
"OTEL_METRIC_EXPORT_INTERVAL": ["A"],
"OTEL_METRIC_EXPORT_TIMEOUT": ["A"],
"OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE": ["A"],
"OTEL_METRICS_EXPORTER": ["A"],
"OTEL_PROPAGATORS": ["A"],
"OTEL_RESOURCE_ATTRIBUTES": ["A"],
"OTEL_SDK_DISABLED": ["A"],
"OTEL_SERVICE_NAME": ["A"],
"OTEL_TRACES_EXPORTER": ["A"],
"OTEL_TRACES_SAMPLER_ARG": ["A"],
"OTEL_TRACES_SAMPLER": ["A"]
},
"aliases": {
"DD_AGENT_HOST": ["DD_TRACE_AGENT_HOSTNAME"],
"DD_API_KEY": ["DATADOG_API_KEY"],
"DD_API_SECURITY_ENABLED": ["DD_EXPERIMENTAL_API_SECURITY_ENABLED"],
"DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE": ["DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING"],
"DD_DOGSTATSD_HOST": ["DD_DOGSTATSD_HOSTNAME"],
"DD_INSTRUMENTATION_TELEMETRY_ENABLED": ["DD_TRACE_TELEMETRY_ENABLED"],
"DD_PROFILING_CODEHOTSPOTS_ENABLED": ["DD_PROFILING_EXPERIMENTAL_CODEHOTSPOTS_ENABLED"],
"DD_PROFILING_CPU_ENABLED": ["DD_PROFILING_EXPERIMENTAL_CPU_ENABLED"],
"DD_PROFILING_ENABLED": ["DD_EXPERIMENTAL_PROFILING_ENABLED"],
"DD_PROFILING_ENDPOINT_COLLECTION_ENABLED": ["DD_PROFILING_EXPERIMENTAL_ENDPOINT_COLLECTION_ENABLED"],
"DD_PROFILING_TIMELINE_ENABLED": ["DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED"],
"DD_REMOTE_CONFIGURATION_ENABLED": ["DD_REMOTE_CONFIG_ENABLED" ],
"DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED": ["DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED"],
"DD_SERVICE": ["DD_SERVICE_NAME"],
"DD_TRACE_AGENT_URL": ["DD_TRACE_URL"]
},
"deprecations": {
"DD_PROFILING_EXPERIMENTAL_ENDPOINT_COLLECTION_ENABLED": "DD_PROFILING_ENDPOINT_COLLECTION_ENABLED",
"DD_PROFILING_EXPERIMENTAL_CPU_ENABLED": "DD_PROFILING_CPU_ENABLED",
"DD_EXPERIMENTAL_PROFILING_ENABLED": "DD_PROFILING_ENABLED",
"DD_PROFILING_EXPERIMENTAL_CODEHOTSPOTS_ENABLED": "DD_PROFILING_CODEHOTSPOTS_ENABLED",
"DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED": "DD_PROFILING_TIMELINE_ENABLED",
"DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED": "DD_RUNTIME_METRICS_RUNTIME_ID_ENABLED"
}
}

Sorry, the diff of this file is too big to display