| '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']" |
+1
-1
| 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' |
+58
-55
| { | ||
| "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
Network access
Supply chain riskThis module accesses the network.
Found 5 instances in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 2 instances in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 6 instances in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 15 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 2 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 5 instances in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 2 instances in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 6 instances in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 15 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 2 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
4046839
1.33%91839
1.59%213
0.95%+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
Updated