dd-trace 5.99.1 → 5.100.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/LICENSE-3rdparty.csv +0 -1
  2. package/package.json +4 -4
  3. package/packages/datadog-instrumentations/src/cucumber.js +69 -5
  4. package/packages/datadog-instrumentations/src/express.js +3 -2
  5. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  6. package/packages/datadog-instrumentations/src/hono.js +15 -4
  7. package/packages/datadog-instrumentations/src/jest.js +84 -58
  8. package/packages/datadog-instrumentations/src/mocha/main.js +18 -22
  9. package/packages/datadog-instrumentations/src/mocha/utils.js +114 -96
  10. package/packages/datadog-instrumentations/src/mocha/worker.js +2 -2
  11. package/packages/datadog-instrumentations/src/path-to-regexp.js +44 -0
  12. package/packages/datadog-instrumentations/src/playwright.js +108 -18
  13. package/packages/datadog-instrumentations/src/router.js +53 -33
  14. package/packages/datadog-instrumentations/src/vitest.js +76 -30
  15. package/packages/datadog-plugin-aws-sdk/src/base.js +1 -1
  16. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +1 -1
  17. package/packages/datadog-plugin-bullmq/src/consumer.js +3 -2
  18. package/packages/datadog-plugin-bullmq/src/producer.js +25 -11
  19. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +32 -9
  20. package/packages/datadog-plugin-cypress/src/support.js +22 -21
  21. package/packages/datadog-plugin-grpc/src/client.js +1 -1
  22. package/packages/datadog-plugin-grpc/src/server.js +1 -1
  23. package/packages/datadog-plugin-mongodb-core/src/index.js +2 -3
  24. package/packages/datadog-plugin-playwright/src/index.js +6 -0
  25. package/packages/datadog-plugin-router/src/index.js +13 -0
  26. package/packages/dd-trace/index.js +4 -3
  27. package/packages/dd-trace/src/aiguard/sdk.js +2 -2
  28. package/packages/dd-trace/src/baggage.js +10 -0
  29. package/packages/dd-trace/src/config/generated-config-types.d.ts +17 -41
  30. package/packages/dd-trace/src/config/index.js +6 -5
  31. package/packages/dd-trace/src/config/normalize-service.js +31 -0
  32. package/packages/dd-trace/src/config/supported-configurations.json +15 -32
  33. package/packages/dd-trace/src/debugger/config.js +1 -1
  34. package/packages/dd-trace/src/encode/0.4.js +1 -1
  35. package/packages/dd-trace/src/encode/tags-processors.js +3 -3
  36. package/packages/dd-trace/src/heap_snapshots.js +4 -4
  37. package/packages/dd-trace/src/openfeature/eval-metrics-hook.js +2 -2
  38. package/packages/dd-trace/src/opentelemetry/context_manager.js +11 -8
  39. package/packages/dd-trace/src/opentelemetry/span-helpers.js +170 -0
  40. package/packages/dd-trace/src/opentelemetry/span.js +14 -42
  41. package/packages/dd-trace/src/opentelemetry/tracer.js +11 -36
  42. package/packages/dd-trace/src/opentracing/propagation/text_map.js +31 -10
  43. package/packages/dd-trace/src/opentracing/propagation/tracestate.js +42 -12
  44. package/packages/dd-trace/src/opentracing/span.js +3 -2
  45. package/packages/dd-trace/src/plugins/util/ci.js +119 -32
  46. package/packages/dd-trace/src/plugins/util/test.js +293 -27
  47. package/packages/dd-trace/src/profiling/ssi-heuristics.js +2 -2
  48. package/packages/dd-trace/src/propagation-hash/index.js +1 -1
  49. package/packages/dd-trace/src/proxy.js +3 -3
  50. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +1 -1
  51. package/packages/dd-trace/src/span_processor.js +1 -1
  52. package/packages/dd-trace/src/telemetry/telemetry.js +7 -5
  53. package/packages/dd-trace/src/tracer_metadata.js +1 -1
  54. package/vendor/dist/path-to-regexp/LICENSE +0 -21
  55. package/vendor/dist/path-to-regexp/index.js +0 -1
@@ -15,8 +15,8 @@ let isModifiedTest = false
15
15
  let isTestIsolationEnabled = false
16
16
  // Array of test names that have been retried and the reason
17
17
  const retryReasonsByTestName = new Map()
18
- // Track quarantined test errors - we catch them in Cypress.on('fail') but need to report to Datadog
19
- const quarantinedTestErrors = new Map()
18
+ // Track test errors suppressed by test management so we can still report them to Datadog.
19
+ const suppressedTestFailures = new Map()
20
20
 
21
21
  // Track the most recently loaded window in the AUT. Updated via the 'window:load'
22
22
  // event so we always get the real app window (after cy.visit()), not the
@@ -61,13 +61,12 @@ Cypress.on('fail', (err, runnable) => {
61
61
  }
62
62
 
63
63
  const testName = runnable.fullTitle()
64
- const { isQuarantined, isDisabled } = getTestProperties(testName)
64
+ const { isAttemptToFix, isQuarantined, isDisabled } = getTestProperties(testName)
65
65
 
66
66
  // Suppress failures for quarantined or disabled tests so they don't affect the exit code.
67
- // This applies regardless of attempt-to-fix status: per spec, quarantined/disabled test
68
- // results are always ignored.
69
- if (isQuarantined || isDisabled) {
70
- quarantinedTestErrors.set(testName, err)
67
+ // Attempt-to-fix ignores quarantine/disabled suppression and keeps the normal framework result.
68
+ if (!isAttemptToFix && (isQuarantined || isDisabled)) {
69
+ suppressedTestFailures.set(testName, { error: err, isQuarantined, isDisabled })
71
70
  return
72
71
  }
73
72
 
@@ -245,13 +244,14 @@ afterEach(function () {
245
244
  const currentTest = Cypress.mocha.getRunner().suite.ctx.currentTest
246
245
  const testName = currentTest.fullTitle()
247
246
 
248
- // Check if this was a quarantined test that we suppressed the failure for
249
- const quarantinedError = quarantinedTestErrors.get(testName)
250
- const isQuarantinedTestThatFailed = !!quarantinedError
247
+ // Check if this was a test management test that we suppressed the failure for.
248
+ const suppressedTestFailure = suppressedTestFailures.get(testName)
249
+ const suppressedError = suppressedTestFailure && suppressedTestFailure.error
250
+ const isTestManagementTestThatFailed = !!suppressedError
251
251
 
252
- // For quarantined tests, convert Error to a serializable format for cy.task
253
- const errorToReport = isQuarantinedTestThatFailed
254
- ? { message: quarantinedError.message, stack: quarantinedError.stack }
252
+ // For suppressed test management tests, convert Error to a serializable format for cy.task.
253
+ const errorToReport = isTestManagementTestThatFailed
254
+ ? { message: suppressedError.message, stack: suppressedError.stack }
255
255
  : currentTest.err
256
256
 
257
257
  const testInfo = {
@@ -259,16 +259,17 @@ afterEach(function () {
259
259
  testItTitle: currentTest.title,
260
260
  testSuite: Cypress.mocha.getRootSuite().file,
261
261
  testSuiteAbsolutePath: Cypress.spec && Cypress.spec.absolute,
262
- // For quarantined tests, report the actual state (failed) to Datadog, not what Cypress thinks (passed)
263
- state: isQuarantinedTestThatFailed ? 'failed' : currentTest.state,
264
- // For quarantined tests, include the actual error that was suppressed
262
+ // Report the actual failed state to Datadog, not the pass state Cypress sees after suppression.
263
+ state: isTestManagementTestThatFailed ? 'failed' : currentTest.state,
264
+ // Include the actual error that was suppressed.
265
265
  error: errorToReport,
266
266
  isNew: currentTest._ddIsNew,
267
267
  isEfdRetry: currentTest._ddIsEfdRetry,
268
268
  isAttemptToFix: currentTest._ddIsAttemptToFix,
269
269
  isModified: currentTest._ddIsModified,
270
- // Mark quarantined tests that failed so the plugin knows to tag them appropriately
271
- isQuarantined: isQuarantinedTestThatFailed,
270
+ // Mark suppressed tests so the plugin can tag them with the correct test management reason.
271
+ isQuarantined: isTestManagementTestThatFailed && suppressedTestFailure.isQuarantined,
272
+ isDisabled: isTestManagementTestThatFailed && suppressedTestFailure.isDisabled,
272
273
  }
273
274
  try {
274
275
  const invocationDetails = Cypress.mocha.getRunner().currentRunnable.invocationDetails
@@ -292,9 +293,9 @@ afterEach(function () {
292
293
  // ignore error and continue
293
294
  }
294
295
 
295
- // Clean up the quarantined error tracking
296
- if (isQuarantinedTestThatFailed) {
297
- quarantinedTestErrors.delete(testName)
296
+ // Clean up the suppressed error tracking.
297
+ if (isTestManagementTestThatFailed) {
298
+ suppressedTestFailures.delete(testName)
298
299
  }
299
300
 
300
301
  cy.task('dd:afterEach', { test: testInfo, coverage })
@@ -64,7 +64,7 @@ class GrpcClientPlugin extends ClientPlugin {
64
64
 
65
65
  error ({ span = this.activeSpan, error }) {
66
66
  this.addCode(span, error.code)
67
- if (error.code && !this._tracerConfig.grpc.client.error.statuses.includes(error.code)) {
67
+ if (error.code && !this._tracerConfig.DD_GRPC_CLIENT_ERROR_STATUSES.includes(error.code)) {
68
68
  return
69
69
  }
70
70
  this.addError(error, span)
@@ -70,7 +70,7 @@ class GrpcServerPlugin extends ServerPlugin {
70
70
  if (!span) return
71
71
 
72
72
  this.addCode(span, error.code)
73
- if (error.code && !this._tracerConfig.grpc.server.error.statuses.includes(error.code)) {
73
+ if (error.code && !this._tracerConfig.DD_GRPC_SERVER_ERROR_STATUSES.includes(error.code)) {
74
74
  return
75
75
  }
76
76
  this.addError(error)
@@ -160,10 +160,9 @@ function limitDepth (input) {
160
160
  input, output, depth,
161
161
  } = queue.pop()
162
162
  const nextDepth = depth + 1
163
- for (const key in input) {
164
- if (typeof input[key] === 'function') continue
165
-
163
+ for (const key of Object.keys(input)) {
166
164
  let child = input[key]
165
+ if (typeof child === 'function') continue
167
166
 
168
167
  if (isBSON(child)) {
169
168
  child = typeof child.toJSON === 'function' ? child.toJSON() : '?'
@@ -39,6 +39,7 @@ const {
39
39
  TEST_SUITE,
40
40
  TEST_HAS_DYNAMIC_NAME,
41
41
  DYNAMIC_NAME_RE,
42
+ TEST_FINAL_STATUS,
42
43
  } = require('../../dd-trace/src/plugins/util/test')
43
44
  const { RESOURCE_NAME } = require('../../../ext/tags')
44
45
  const { COMPONENT } = require('../../dd-trace/src/constants')
@@ -319,6 +320,7 @@ class PlaywrightPlugin extends CiPlugin {
319
320
  hasFailedAttemptToFixRetries,
320
321
  isAtrRetry,
321
322
  isModified,
323
+ finalStatus,
322
324
  onDone,
323
325
  }) => {
324
326
  if (!span) return
@@ -379,6 +381,9 @@ class PlaywrightPlugin extends CiPlugin {
379
381
  span.setTag(TEST_RETRY_REASON, TEST_RETRY_REASON_TYPES.efd)
380
382
  }
381
383
  }
384
+ if (finalStatus) {
385
+ span.setTag(TEST_FINAL_STATUS, finalStatus)
386
+ }
382
387
  for (const step of steps) {
383
388
  const stepStartTime = step.startTime.getTime()
384
389
  const stepSpan = this.tracer.startSpan('playwright.step', {
@@ -451,6 +456,7 @@ class PlaywrightPlugin extends CiPlugin {
451
456
  )
452
457
 
453
458
  span.setTag(TEST_STATUS, 'skip')
459
+ span.setTag(TEST_FINAL_STATUS, 'skip')
454
460
 
455
461
  if (isNew) {
456
462
  span.setTag(TEST_IS_NEW, 'true')
@@ -157,6 +157,13 @@ class RouterPlugin extends WebPlugin {
157
157
  }
158
158
 
159
159
  function isMoreSpecificThan (routeA, routeB) {
160
+ // Concrete paths beat catch-all wildcards (`/*splat`, `/api/*`) on the same
161
+ // request so that `/foo/bar` wins over `/foo/*splat` regardless of length.
162
+ if (routeA && routeB) {
163
+ const aWild = hasWildcard(routeA)
164
+ const bWild = hasWildcard(routeB)
165
+ if (aWild !== bWild) return !aWild
166
+ }
160
167
  if (!routeIsRegex(routeA) && routeIsRegex(routeB)) {
161
168
  return true
162
169
  }
@@ -167,4 +174,10 @@ function routeIsRegex (route) {
167
174
  return route.includes('(/')
168
175
  }
169
176
 
177
+ function hasWildcard (route) {
178
+ // RegExp routes are encoded as `(/.../)` and may legitimately contain `*`,
179
+ // so only treat plain string patterns as wildcards.
180
+ return !routeIsRegex(route) && route.includes('*')
181
+ }
182
+
170
183
  module.exports = RouterPlugin
@@ -30,9 +30,10 @@ if (!global._ddtrace) {
30
30
  configurable: true,
31
31
  writable: true,
32
32
  })
33
-
34
- global._ddtrace.default = global._ddtrace
35
- global._ddtrace.tracer = global._ddtrace
36
33
  }
37
34
 
38
35
  module.exports = global._ddtrace
36
+ // Static aliases so cjs-module-lexer surfaces them as ESM named exports
37
+ // (`import { tracer } from 'dd-trace'`).
38
+ module.exports.tracer = global._ddtrace
39
+ module.exports.default = global._ddtrace
@@ -70,7 +70,7 @@ class AIGuard extends NoopAIGuard {
70
70
  constructor (tracer, config) {
71
71
  super()
72
72
 
73
- if (!config.apiKey || !config.appKey) {
73
+ if (!config.apiKey || !config.DD_APP_KEY) {
74
74
  log.error('AIGuard: missing api and/or app keys, use env DD_API_KEY and DD_APP_KEY')
75
75
  this.#initialized = false
76
76
  return
@@ -78,7 +78,7 @@ class AIGuard extends NoopAIGuard {
78
78
  this.#tracer = tracer
79
79
  this.#headers = {
80
80
  'DD-API-KEY': config.apiKey,
81
- 'DD-APPLICATION-KEY': config.appKey,
81
+ 'DD-APPLICATION-KEY': config.DD_APP_KEY,
82
82
  'DD-AI-GUARD-VERSION': tracerVersion,
83
83
  'DD-AI-GUARD-SOURCE': 'SDK',
84
84
  'DD-AI-GUARD-LANGUAGE': 'nodejs',
@@ -66,8 +66,18 @@ function removeAllBaggageItems () {
66
66
  return EMPTY_STORE
67
67
  }
68
68
 
69
+ /**
70
+ * @param {BaggageStore} items Frozen in place; do not mutate after.
71
+ */
72
+ function setAllBaggageItems (items) {
73
+ Object.freeze(items)
74
+ baggageStorage.enterWith(items)
75
+ return items
76
+ }
77
+
69
78
  module.exports = {
70
79
  setBaggageItem,
80
+ setAllBaggageItems,
71
81
  getBaggageItem,
72
82
  getAllBaggageItems,
73
83
  removeBaggageItem,
@@ -5,7 +5,6 @@ export interface GeneratedConfig {
5
5
  _DD_APM_TRACING_AGENTLESS_ENABLED: boolean;
6
6
  apiKey: string | undefined;
7
7
  apmTracingEnabled: boolean;
8
- appKey: string | undefined;
9
8
  appsec: {
10
9
  apiSecurity: {
11
10
  downstreamBodyAnalysisSampleRate: number;
@@ -63,9 +62,6 @@ export interface GeneratedConfig {
63
62
  };
64
63
  };
65
64
  };
66
- crashtracking: {
67
- enabled: boolean;
68
- };
69
65
  dbm: {
70
66
  injectSqlBaseHash: boolean;
71
67
  };
@@ -74,6 +70,7 @@ export interface GeneratedConfig {
74
70
  DD_AGENTLESS_LOG_SUBMISSION_ENABLED: boolean;
75
71
  DD_AGENTLESS_LOG_SUBMISSION_URL: string | undefined;
76
72
  DD_APM_FLUSH_DEADLINE_MILLISECONDS: number;
73
+ DD_APP_KEY: string | undefined;
77
74
  DD_AZURE_RESOURCE_GROUP: string | undefined;
78
75
  DD_CIVISIBILITY_AGENTLESS_ENABLED: boolean;
79
76
  DD_CIVISIBILITY_AGENTLESS_URL: string | undefined;
@@ -87,9 +84,11 @@ export interface GeneratedConfig {
87
84
  DD_CIVISIBILITY_TEST_COMMAND: string | undefined;
88
85
  DD_CIVISIBILITY_TEST_MODULE_ID: string | undefined;
89
86
  DD_CIVISIBILITY_TEST_SESSION_ID: string | undefined;
87
+ DD_CRASHTRACKING_ENABLED: boolean;
90
88
  DD_CUSTOM_TRACE_ID: string | undefined;
91
89
  DD_ENABLE_LAGE_PACKAGE_NAME: boolean;
92
90
  DD_ENABLE_NX_SERVICE_NAME: boolean;
91
+ DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED: boolean;
93
92
  DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_DIR: string;
94
93
  DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_ENABLED: boolean;
95
94
  DD_EXPERIMENTAL_TEST_OPT_SETTINGS_CACHE: string;
@@ -111,12 +110,22 @@ export interface GeneratedConfig {
111
110
  DD_GIT_PULL_REQUEST_BASE_BRANCH_SHA: string | undefined;
112
111
  DD_GIT_REPOSITORY_URL: string | undefined;
113
112
  DD_GIT_TAG: string | undefined;
113
+ DD_GRPC_CLIENT_ERROR_STATUSES: number[];
114
+ DD_GRPC_SERVER_ERROR_STATUSES: number[];
115
+ DD_HEAP_SNAPSHOT_COUNT: number;
116
+ DD_HEAP_SNAPSHOT_DESTINATION: string;
117
+ DD_HEAP_SNAPSHOT_INTERVAL: number;
114
118
  DD_INJECT_FORCE: boolean;
115
119
  DD_INJECTION_ENABLED: string | undefined;
116
120
  DD_INSTRUMENTATION_CONFIG_ID: string | undefined;
121
+ DD_INSTRUMENTATION_INSTALL_ID: string | undefined;
122
+ DD_INSTRUMENTATION_INSTALL_TIME: string | undefined;
123
+ DD_INSTRUMENTATION_INSTALL_TYPE: string | undefined;
124
+ DD_INTERNAL_PROFILING_LONG_LIVED_THRESHOLD: number;
117
125
  DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED: boolean;
118
126
  DD_LAMBDA_HANDLER: string | undefined;
119
127
  DD_LOGS_OTEL_ENABLED: boolean;
128
+ DD_METRICS_OTEL_ENABLED: boolean;
120
129
  DD_MINI_AGENT_PATH: string | undefined;
121
130
  DD_PIPELINE_EXECUTION_ID: string | undefined;
122
131
  DD_PLAYWRIGHT_WORKER: string | undefined;
@@ -166,6 +175,7 @@ export interface GeneratedConfig {
166
175
  DD_TRACE_APOLLO_SERVER_FASTIFY_ENABLED: boolean;
167
176
  DD_TRACE_APOLLO_SUBGRAPH_ENABLED: boolean;
168
177
  DD_TRACE_AVSC_ENABLED: boolean;
178
+ DD_TRACE_AWS_ADD_SPAN_POINTERS: boolean;
169
179
  DD_TRACE_AWS_SDK_AWS_BATCH_PROPAGATION_ENABLED: boolean;
170
180
  DD_TRACE_AWS_SDK_AWS_ENABLED: boolean;
171
181
  DD_TRACE_AWS_SDK_BATCH_PROPAGATION_ENABLED: boolean;
@@ -229,6 +239,7 @@ export interface GeneratedConfig {
229
239
  DD_TRACE_DISABLED_INSTRUMENTATIONS: string;
230
240
  DD_TRACE_DISABLED_PLUGINS: string | undefined;
231
241
  DD_TRACE_DNS_ENABLED: boolean;
242
+ DD_TRACE_DYNAMODB_TABLE_PRIMARY_KEYS: string | undefined;
232
243
  DD_TRACE_ELASTIC_ELASTICSEARCH_ENABLED: boolean;
233
244
  DD_TRACE_ELASTIC_TRANSPORT_ENABLED: boolean;
234
245
  DD_TRACE_ELASTICSEARCH_ENABLED: boolean;
@@ -316,6 +327,7 @@ export interface GeneratedConfig {
316
327
  DD_TRACE_MULTER_ENABLED: boolean;
317
328
  DD_TRACE_MYSQL_ENABLED: boolean;
318
329
  DD_TRACE_MYSQL2_ENABLED: boolean;
330
+ DD_TRACE_NATIVE_SPAN_EVENTS: boolean;
319
331
  DD_TRACE_NET_ENABLED: boolean;
320
332
  DD_TRACE_NEXT_ENABLED: boolean;
321
333
  DD_TRACE_NODE_CHILD_PROCESS_ENABLED: boolean;
@@ -344,6 +356,7 @@ export interface GeneratedConfig {
344
356
  DD_TRACE_PROCESS_ENABLED: boolean;
345
357
  DD_TRACE_PROMISE_ENABLED: boolean;
346
358
  DD_TRACE_PROMISE_JS_ENABLED: boolean;
359
+ DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT: "continue" | "restart" | "ignore";
347
360
  DD_TRACE_PROPAGATION_EXTRACT_FIRST: boolean;
348
361
  DD_TRACE_PROPAGATION_STYLE: string[];
349
362
  DD_TRACE_PROTOBUFJS_ENABLED: boolean;
@@ -417,24 +430,7 @@ export interface GeneratedConfig {
417
430
  flakyTestRetriesCount: number;
418
431
  flushInterval: number;
419
432
  flushMinSpans: number;
420
- grpc: {
421
- client: {
422
- error: {
423
- statuses: number[];
424
- };
425
- };
426
- server: {
427
- error: {
428
- statuses: number[];
429
- };
430
- };
431
- };
432
433
  headerTags: string[];
433
- heapSnapshot: {
434
- count: number;
435
- destination: string;
436
- interval: number;
437
- };
438
434
  hostname: string;
439
435
  iast: {
440
436
  dbRowsToTaint: number;
@@ -453,11 +449,6 @@ export interface GeneratedConfig {
453
449
  telemetryVerbosity: string;
454
450
  };
455
451
  inferredProxyServicesEnabled: boolean;
456
- installSignature: {
457
- id: string | undefined;
458
- time: string | undefined;
459
- type: string | undefined;
460
- };
461
452
  isEarlyFlakeDetectionEnabled: boolean;
462
453
  isFlakyTestRetriesEnabled: boolean;
463
454
  isGitUploadEnabled: boolean;
@@ -511,15 +502,10 @@ export interface GeneratedConfig {
511
502
  OTEL_TRACES_EXPORTER: "none" | "otlp" | undefined;
512
503
  OTEL_TRACES_SAMPLER: "always_on" | "always_off" | "traceidratio" | "parentbased_always_on" | "parentbased_always_off" | "parentbased_traceidratio";
513
504
  OTEL_TRACES_SAMPLER_ARG: number | undefined;
514
- otelMetricsEnabled: boolean;
515
505
  peerServiceMapping: Record<string, string>;
516
506
  port: string | number;
517
507
  profiling: {
518
508
  enabled: 'true' | 'false' | 'auto';
519
- longLivedThreshold: number;
520
- };
521
- propagateProcessTags: {
522
- enabled: boolean;
523
509
  };
524
510
  protocolVersion: string;
525
511
  queryStringObfuscation: string;
@@ -562,18 +548,8 @@ export interface GeneratedConfig {
562
548
  metrics: boolean;
563
549
  };
564
550
  testManagementAttemptToFixRetries: number;
565
- trace: {
566
- aws: {
567
- addSpanPointers: boolean;
568
- };
569
- dynamoDb: {
570
- tablePrimaryKeys: string | undefined;
571
- };
572
- nativeSpanEvents: boolean;
573
- };
574
551
  traceId128BitGenerationEnabled: boolean;
575
552
  traceId128BitLoggingEnabled: boolean;
576
- tracePropagationBehaviorExtract: "continue" | "restart" | "ignore";
577
553
  tracePropagationStyle: {
578
554
  extract: string[];
579
555
  inject: string[];
@@ -39,6 +39,7 @@ const {
39
39
  parseErrors,
40
40
  generateTelemetry,
41
41
  } = require('./defaults')
42
+ const { normalizeService } = require('./normalize-service')
42
43
  const { transformers } = require('./parsers')
43
44
 
44
45
  const RUNTIME_ID = uuid()
@@ -358,10 +359,10 @@ class Config extends ConfigBase {
358
359
  if (this.DD_LOGS_OTEL_ENABLED) {
359
360
  setAndTrack(this, 'logInjection', false)
360
361
  }
361
- if (this.otelMetricsEnabled &&
362
+ if (this.DD_METRICS_OTEL_ENABLED &&
362
363
  trackedConfigOrigins.has('OTEL_METRICS_EXPORTER') &&
363
364
  this.OTEL_METRICS_EXPORTER === 'none') {
364
- setAndTrack(this, 'otelMetricsEnabled', false)
365
+ setAndTrack(this, 'DD_METRICS_OTEL_ENABLED', false)
365
366
  }
366
367
 
367
368
  if (this.OTEL_TRACES_EXPORTER === 'otlp' && this.protocolVersion && this.protocolVersion !== '0.4') {
@@ -513,7 +514,7 @@ class Config extends ConfigBase {
513
514
  const NX_TASK_TARGET_PROJECT = getEnvironmentVariable('NX_TASK_TARGET_PROJECT')
514
515
  if (NX_TASK_TARGET_PROJECT) {
515
516
  if (this.DD_ENABLE_NX_SERVICE_NAME) {
516
- setAndTrack(this, 'service', NX_TASK_TARGET_PROJECT)
517
+ setAndTrack(this, 'service', normalizeService(NX_TASK_TARGET_PROJECT) || 'node')
517
518
  isServiceNameInferred = true
518
519
  } else if (DD_MAJOR < 6) {
519
520
  log.warn(
@@ -536,7 +537,7 @@ class Config extends ConfigBase {
536
537
  )
537
538
  : undefined
538
539
 
539
- setAndTrack(this, 'service', serverlessName || pkg.name || 'node')
540
+ setAndTrack(this, 'service', normalizeService(serverlessName) || normalizeService(pkg.name) || 'node')
540
541
  this.tags.service ??= /** @type {string} */ (this.service)
541
542
  isServiceNameInferred = true
542
543
  }
@@ -560,7 +561,7 @@ class Config extends ConfigBase {
560
561
 
561
562
  if (IS_SERVERLESS) {
562
563
  setAndTrack(this, 'telemetry.enabled', false)
563
- setAndTrack(this, 'crashtracking.enabled', false)
564
+ setAndTrack(this, 'DD_CRASHTRACKING_ENABLED', false)
564
565
  setAndTrack(this, 'remoteConfig.enabled', false)
565
566
  }
566
567
 
@@ -0,0 +1,31 @@
1
+ 'use strict'
2
+
3
+ const MAX_SERVICE_LENGTH = 100
4
+
5
+ /**
6
+ * Normalize an inferred service name so APM and runtime metrics agree.
7
+ *
8
+ * The trace agent normalizes span service names on the wire, but the
9
+ * DogStatsD client uses a different tag-value sanitizer, so an inferred
10
+ * `@scope/name` package name appears as `scope/name` in APM and
11
+ * `_scope/name` in runtime metrics. Pre-normalizing pins both consumers
12
+ * (and telemetry / process tags) to the same value.
13
+ *
14
+ * @see https://github.com/DataDog/datadog-agent/blob/main/pkg/trace/traceutil/normalize.go
15
+ * @param {string | undefined} name
16
+ */
17
+ function normalizeService (name) {
18
+ if (!name) return
19
+
20
+ let normalized = name.toLowerCase()
21
+ .replaceAll(/[^a-z0-9_:./-]/g, '_')
22
+ .replace(/^[^a-z0-9]+/, '')
23
+
24
+ if (normalized.length > MAX_SERVICE_LENGTH) {
25
+ normalized = normalized.slice(0, MAX_SERVICE_LENGTH)
26
+ }
27
+
28
+ return normalized
29
+ }
30
+
31
+ module.exports = { normalizeService }
@@ -421,8 +421,7 @@
421
421
  {
422
422
  "implementation": "A",
423
423
  "type": "string",
424
- "default": null,
425
- "internalPropertyName": "appKey"
424
+ "default": null
426
425
  }
427
426
  ],
428
427
  "DD_AZURE_RESOURCE_GROUP": [
@@ -595,8 +594,7 @@
595
594
  {
596
595
  "implementation": "A",
597
596
  "type": "boolean",
598
- "default": "true",
599
- "internalPropertyName": "crashtracking.enabled"
597
+ "default": "true"
600
598
  }
601
599
  ],
602
600
  "DD_CUSTOM_TRACE_ID": [
@@ -770,8 +768,7 @@
770
768
  {
771
769
  "implementation": "B",
772
770
  "type": "boolean",
773
- "default": "true",
774
- "internalPropertyName": "propagateProcessTags.enabled"
771
+ "default": "true"
775
772
  }
776
773
  ],
777
774
  "DD_EXPERIMENTAL_TEST_OPT_SETTINGS_CACHE": [
@@ -926,7 +923,6 @@
926
923
  "implementation": "C",
927
924
  "type": "string",
928
925
  "default": "1-16",
929
- "internalPropertyName": "grpc.client.error.statuses",
930
926
  "transform": "setGRPCRange"
931
927
  }
932
928
  ],
@@ -935,7 +931,6 @@
935
931
  "implementation": "C",
936
932
  "type": "string",
937
933
  "default": "2-16",
938
- "internalPropertyName": "grpc.server.error.statuses",
939
934
  "transform": "setGRPCRange"
940
935
  }
941
936
  ],
@@ -943,24 +938,21 @@
943
938
  {
944
939
  "implementation": "A",
945
940
  "type": "int",
946
- "default": "0",
947
- "internalPropertyName": "heapSnapshot.count"
941
+ "default": "0"
948
942
  }
949
943
  ],
950
944
  "DD_HEAP_SNAPSHOT_DESTINATION": [
951
945
  {
952
946
  "implementation": "A",
953
947
  "type": "string",
954
- "default": "",
955
- "internalPropertyName": "heapSnapshot.destination"
948
+ "default": ""
956
949
  }
957
950
  ],
958
951
  "DD_HEAP_SNAPSHOT_INTERVAL": [
959
952
  {
960
953
  "implementation": "A",
961
954
  "type": "int",
962
- "default": "3600",
963
- "internalPropertyName": "heapSnapshot.interval"
955
+ "default": "3600"
964
956
  }
965
957
  ],
966
958
  "DD_IAST_DB_ROWS_TO_TAINT": [
@@ -1124,24 +1116,21 @@
1124
1116
  {
1125
1117
  "implementation": "A",
1126
1118
  "type": "string",
1127
- "default": null,
1128
- "internalPropertyName": "installSignature.id"
1119
+ "default": null
1129
1120
  }
1130
1121
  ],
1131
1122
  "DD_INSTRUMENTATION_INSTALL_TIME": [
1132
1123
  {
1133
1124
  "implementation": "A",
1134
1125
  "type": "string",
1135
- "default": null,
1136
- "internalPropertyName": "installSignature.time"
1126
+ "default": null
1137
1127
  }
1138
1128
  ],
1139
1129
  "DD_INSTRUMENTATION_INSTALL_TYPE": [
1140
1130
  {
1141
1131
  "implementation": "A",
1142
1132
  "type": "string",
1143
- "default": null,
1144
- "internalPropertyName": "installSignature.type"
1133
+ "default": null
1145
1134
  }
1146
1135
  ],
1147
1136
  "DD_INSTRUMENTATION_TELEMETRY_ENABLED": [
@@ -1159,8 +1148,7 @@
1159
1148
  {
1160
1149
  "implementation": "A",
1161
1150
  "type": "int",
1162
- "default": "30000",
1163
- "internalPropertyName": "profiling.longLivedThreshold"
1151
+ "default": "30000"
1164
1152
  }
1165
1153
  ],
1166
1154
  "DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED": [
@@ -1257,8 +1245,7 @@
1257
1245
  {
1258
1246
  "implementation": "A",
1259
1247
  "type": "boolean",
1260
- "default": "false",
1261
- "internalPropertyName": "otelMetricsEnabled"
1248
+ "default": "false"
1262
1249
  }
1263
1250
  ],
1264
1251
  "DD_MINI_AGENT_PATH": [
@@ -1942,8 +1929,7 @@
1942
1929
  {
1943
1930
  "implementation": "A",
1944
1931
  "type": "boolean",
1945
- "default": "true",
1946
- "internalPropertyName": "trace.aws.addSpanPointers"
1932
+ "default": "true"
1947
1933
  }
1948
1934
  ],
1949
1935
  "DD_TRACE_AWS_SDK_AWS_BATCH_PROPAGATION_ENABLED": [
@@ -2475,8 +2461,7 @@
2475
2461
  {
2476
2462
  "implementation": "A",
2477
2463
  "type": "string",
2478
- "default": null,
2479
- "internalPropertyName": "trace.dynamoDb.tablePrimaryKeys"
2464
+ "default": null
2480
2465
  }
2481
2466
  ],
2482
2467
  "DD_TRACE_ELASTICSEARCH_ENABLED": [
@@ -3174,8 +3159,7 @@
3174
3159
  {
3175
3160
  "implementation": "A",
3176
3161
  "type": "boolean",
3177
- "default": "false",
3178
- "internalPropertyName": "trace.nativeSpanEvents"
3162
+ "default": "false"
3179
3163
  }
3180
3164
  ],
3181
3165
  "DD_TRACE_NET_ENABLED": [
@@ -3418,8 +3402,7 @@
3418
3402
  "type": "string",
3419
3403
  "allowed": "continue|restart|ignore",
3420
3404
  "transform": "toLowerCase",
3421
- "default": "continue",
3422
- "internalPropertyName": "tracePropagationBehaviorExtract"
3405
+ "default": "continue"
3423
3406
  }
3424
3407
  ],
3425
3408
  "DD_TRACE_PROPAGATION_EXTRACT_FIRST": [
@@ -9,7 +9,7 @@ module.exports = function getDebuggerConfig (config, inputPath) {
9
9
  hostname: config.hostname,
10
10
  logLevel: config.logLevel,
11
11
  port: config.port,
12
- propagateProcessTags: config.propagateProcessTags,
12
+ propagateProcessTags: { enabled: config.DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED },
13
13
  repositoryUrl: config.repositoryUrl,
14
14
  runtimeId: config.tags['runtime-id'],
15
15
  service: config.service,
@@ -11,7 +11,7 @@ function formatSpan (span, config) {
11
11
  span = normalizeSpan(truncateSpan(span, false))
12
12
  if (span.span_events) {
13
13
  // ensure span events are encoded as tags if agent doesn't support native top level span events
14
- if (config.trace.nativeSpanEvents) {
14
+ if (config.DD_TRACE_NATIVE_SPAN_EVENTS) {
15
15
  formatSpanEvents(span)
16
16
  } else {
17
17
  span.meta.events = JSON.stringify(span.span_events)
@@ -34,18 +34,18 @@ function truncateSpan (span, shouldTruncateResourceName = true) {
34
34
  if (shouldTruncateResourceName && span.resource && span.resource.length > MAX_RESOURCE_NAME_LENGTH) {
35
35
  span.resource = `${span.resource.slice(0, MAX_RESOURCE_NAME_LENGTH)}...`
36
36
  }
37
- for (let metaKey in span.meta) {
37
+ for (let metaKey of Object.keys(span.meta)) {
38
38
  const val = span.meta[metaKey]
39
39
  if (metaKey.length > MAX_META_KEY_LENGTH) {
40
40
  delete span.meta[metaKey]
41
41
  metaKey = `${metaKey.slice(0, MAX_META_KEY_LENGTH)}...`
42
- span.metrics[metaKey] = val
42
+ span.meta[metaKey] = val
43
43
  }
44
44
  if (val && val.length > MAX_META_VALUE_LENGTH) {
45
45
  span.meta[metaKey] = `${val.slice(0, MAX_META_VALUE_LENGTH)}...`
46
46
  }
47
47
  }
48
- for (let metricsKey in span.metrics) {
48
+ for (let metricsKey of Object.keys(span.metrics)) {
49
49
  const val = span.metrics[metricsKey]
50
50
  if (metricsKey.length > MAX_METRIC_KEY_LENGTH) {
51
51
  delete span.metrics[metricsKey]