dd-trace 5.97.0 → 5.98.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 (81) hide show
  1. package/index.d.ts +26 -2
  2. package/package.json +1 -1
  3. package/packages/datadog-instrumentations/src/cucumber.js +65 -3
  4. package/packages/datadog-instrumentations/src/cypress-config.js +31 -37
  5. package/packages/datadog-instrumentations/src/jest.js +104 -12
  6. package/packages/datadog-instrumentations/src/mocha/utils.js +8 -0
  7. package/packages/datadog-instrumentations/src/redis.js +12 -6
  8. package/packages/datadog-plugin-aws-sdk/src/base.js +1 -1
  9. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +1 -0
  10. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -0
  11. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -0
  12. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -0
  13. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -0
  14. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -0
  15. package/packages/datadog-plugin-cucumber/src/index.js +6 -0
  16. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +109 -1
  17. package/packages/datadog-plugin-cypress/src/index.js +59 -2
  18. package/packages/datadog-plugin-fs/src/index.js +1 -1
  19. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -1
  20. package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +2 -7
  21. package/packages/datadog-plugin-http/src/client.js +1 -1
  22. package/packages/datadog-plugin-http/src/server.js +10 -2
  23. package/packages/datadog-plugin-http2/src/client.js +1 -1
  24. package/packages/datadog-plugin-http2/src/server.js +10 -2
  25. package/packages/datadog-plugin-mongodb-core/src/index.js +3 -3
  26. package/packages/datadog-plugin-mysql/src/index.js +1 -1
  27. package/packages/datadog-plugin-next/src/index.js +8 -2
  28. package/packages/datadog-plugin-pg/src/index.js +1 -1
  29. package/packages/datadog-plugin-tedious/src/index.js +1 -1
  30. package/packages/datadog-plugin-ws/src/close.js +1 -1
  31. package/packages/datadog-plugin-ws/src/receiver.js +1 -1
  32. package/packages/dd-trace/src/aiguard/sdk.js +22 -22
  33. package/packages/dd-trace/src/appsec/blocked_templates.js +4 -3
  34. package/packages/dd-trace/src/appsec/blocking.js +62 -34
  35. package/packages/dd-trace/src/appsec/sdk/set_user.js +1 -1
  36. package/packages/dd-trace/src/appsec/sdk/track_event.js +5 -5
  37. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +2 -2
  38. package/packages/dd-trace/src/appsec/sdk/utils.js +4 -2
  39. package/packages/dd-trace/src/config/defaults.js +0 -1
  40. package/packages/dd-trace/src/config/generated-config-types.d.ts +5 -0
  41. package/packages/dd-trace/src/config/index.js +55 -28
  42. package/packages/dd-trace/src/config/supported-configurations.json +61 -4
  43. package/packages/dd-trace/src/constants.js +1 -0
  44. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +5 -2
  45. package/packages/dd-trace/src/encode/0.4.js +7 -6
  46. package/packages/dd-trace/src/encode/span-stats.js +4 -1
  47. package/packages/dd-trace/src/log/index.js +0 -10
  48. package/packages/dd-trace/src/openfeature/remote_config.js +6 -1
  49. package/packages/dd-trace/src/opentelemetry/context_manager.js +6 -4
  50. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +17 -2
  51. package/packages/dd-trace/src/opentelemetry/otlp/protobuf_loader.js +14 -2
  52. package/packages/dd-trace/src/opentelemetry/otlp/trace.proto +358 -0
  53. package/packages/dd-trace/src/opentelemetry/otlp/trace_service.proto +78 -0
  54. package/packages/dd-trace/src/opentelemetry/trace/index.js +75 -0
  55. package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +66 -0
  56. package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +332 -0
  57. package/packages/dd-trace/src/opentracing/tracer.js +9 -4
  58. package/packages/dd-trace/src/plugins/log_plugin.js +3 -0
  59. package/packages/dd-trace/src/plugins/plugin.js +6 -11
  60. package/packages/dd-trace/src/plugins/storage.js +2 -2
  61. package/packages/dd-trace/src/plugins/tracing.js +22 -5
  62. package/packages/dd-trace/src/plugins/util/test.js +2 -0
  63. package/packages/dd-trace/src/plugins/util/web.js +6 -88
  64. package/packages/dd-trace/src/profiling/profiler.js +34 -77
  65. package/packages/dd-trace/src/proxy.js +8 -3
  66. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +15 -11
  67. package/packages/dd-trace/src/service-naming/index.js +1 -1
  68. package/packages/dd-trace/src/service-naming/schemas/definition.js +4 -1
  69. package/packages/dd-trace/src/service-naming/schemas/util.js +15 -1
  70. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +24 -1
  71. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +60 -0
  72. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +17 -1
  73. package/packages/dd-trace/src/service-naming/schemas/v0/websocket.js +5 -0
  74. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +17 -0
  75. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +11 -1
  76. package/packages/dd-trace/src/service-naming/schemas/v1/websocket.js +6 -0
  77. package/packages/dd-trace/src/span_stats.js +5 -1
  78. package/packages/dd-trace/src/tracer.js +2 -2
  79. package/vendor/dist/@apm-js-collab/code-transformer/index.js +28 -6
  80. package/vendor/dist/protobufjs/index.js +1 -1
  81. package/packages/dd-trace/src/log/utils.js +0 -16
@@ -6,9 +6,27 @@ const { updateBlockFailureMetric } = require('./telemetry')
6
6
 
7
7
  const detectedSpecificEndpoints = {}
8
8
 
9
- let templateHtml = blockedTemplates.html
10
- let templateJson = blockedTemplates.json
11
- let templateGraphqlJson = blockedTemplates.graphqlJson
9
+ const templateKeyword = '[security_response_id]'
10
+
11
+ const templates = {
12
+ html: {
13
+ body: null,
14
+ idIndex: -1,
15
+ type: 'text/html; charset=utf-8',
16
+ },
17
+ json: {
18
+ body: null,
19
+ idIndex: -1,
20
+ type: 'application/json',
21
+ },
22
+ graphqlJson: {
23
+ body: null,
24
+ idIndex: -1,
25
+ type: 'application/json',
26
+ },
27
+ }
28
+
29
+ setTemplates()
12
30
 
13
31
  let defaultBlockingActionParameters
14
32
 
@@ -17,7 +35,7 @@ const responseBlockedSet = new WeakSet()
17
35
  const blockDelegations = new WeakMap()
18
36
 
19
37
  const specificBlockingTypes = {
20
- GRAPHQL: 'graphql',
38
+ GRAPHQL: 'graphqlJson',
21
39
  }
22
40
 
23
41
  function getSpecificKey (method, url) {
@@ -33,21 +51,14 @@ function getBlockWithRedirectData (actionParameters) {
33
51
  if (!statusCode || statusCode < 300 || statusCode >= 400) {
34
52
  statusCode = 303
35
53
  }
36
- const headers = {
37
- Location: actionParameters.location,
38
- }
39
54
 
40
- return { headers, statusCode }
41
- }
55
+ const headers = { Location: actionParameters.location }
42
56
 
43
- function getSpecificBlockingData (type) {
44
- switch (type) {
45
- case specificBlockingTypes.GRAPHQL:
46
- return {
47
- type: 'application/json',
48
- body: templateGraphqlJson,
49
- }
57
+ if (headers.Location) {
58
+ headers.Location = headers.Location.replace(templateKeyword, actionParameters.security_response_id ?? '')
50
59
  }
60
+
61
+ return { headers, statusCode }
51
62
  }
52
63
 
53
64
  function getBlockWithContentData (req, specificType, actionParameters) {
@@ -56,7 +67,7 @@ function getBlockWithContentData (req, specificType, actionParameters) {
56
67
 
57
68
  const specificBlockingType = specificType || detectedSpecificEndpoints[getSpecificKey(req.method, req.url)]
58
69
  if (specificBlockingType) {
59
- const specificBlockingContent = getSpecificBlockingData(specificBlockingType)
70
+ const specificBlockingContent = getTemplate(specificBlockingType, actionParameters)
60
71
  type = specificBlockingContent?.type
61
72
  body = specificBlockingContent?.body
62
73
  }
@@ -65,23 +76,17 @@ function getBlockWithContentData (req, specificType, actionParameters) {
65
76
  // parse the Accept header, ex: Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8
66
77
  const accept = req.headers.accept?.split(',').map((str) => str.split(';', 1)[0].trim())
67
78
 
79
+ let templateName = 'json'
80
+
68
81
  if (!actionParameters || actionParameters.type === 'auto') {
69
82
  if (accept?.includes('text/html') && !accept.includes('application/json')) {
70
- type = 'text/html; charset=utf-8'
71
- body = templateHtml
72
- } else {
73
- type = 'application/json'
74
- body = templateJson
75
- }
76
- } else {
77
- if (actionParameters.type === 'html') {
78
- type = 'text/html; charset=utf-8'
79
- body = templateHtml
80
- } else {
81
- type = 'application/json'
82
- body = templateJson
83
+ templateName = 'html'
83
84
  }
85
+ } else if (actionParameters.type === 'html') {
86
+ templateName = 'html'
84
87
  }
88
+
89
+ ({ type, body } = getTemplate(templateName, actionParameters))
85
90
  }
86
91
 
87
92
  const statusCode = actionParameters?.status_code || 403
@@ -165,14 +170,37 @@ function getBlockingAction (actions) {
165
170
  }
166
171
 
167
172
  /**
168
- * @param {import('../config/config-base')} config - Tracer configuration
173
+ * @param {import('../config/config-base')} [config] - Tracer configuration
169
174
  */
170
175
  function setTemplates (config) {
171
- templateHtml = config.appsec.blockedTemplateHtml || blockedTemplates.html
176
+ templates.html.body = config?.appsec?.blockedTemplateHtml
177
+ templates.json.body = config?.appsec?.blockedTemplateJson
178
+ templates.graphqlJson.body = config?.appsec?.blockedTemplateGraphql
179
+
180
+ for (const type of Object.keys(templates)) {
181
+ const template = templates[type]
182
+
183
+ // set default template if not set by config
184
+ if (!template.body) template.body = blockedTemplates[type]
185
+
186
+ template.idIndex = template.body.indexOf(templateKeyword)
187
+
188
+ if (template.idIndex !== -1) {
189
+ template.body = [
190
+ template.body.slice(0, template.idIndex),
191
+ template.body.slice(template.idIndex + templateKeyword.length),
192
+ ]
193
+ }
194
+ }
195
+ }
196
+
197
+ function getTemplate (type, actionParameters) {
198
+ const template = templates[type]
199
+ if (template.idIndex === -1) return template
172
200
 
173
- templateJson = config.appsec.blockedTemplateJson || blockedTemplates.json
201
+ const body = template.body[0] + (actionParameters?.security_response_id ?? '') + template.body[1]
174
202
 
175
- templateGraphqlJson = config.appsec.blockedTemplateGraphql || blockedTemplates.graphqlJson
203
+ return { body, type: template.type }
176
204
  }
177
205
 
178
206
  function isBlocked (res) {
@@ -19,7 +19,7 @@ function setUser (tracer, user) {
19
19
  return
20
20
  }
21
21
 
22
- const rootSpan = getRootSpan(tracer)
22
+ const rootSpan = getRootSpan()
23
23
  if (!rootSpan) {
24
24
  log.warn('[ASM] Root span not available in setUser')
25
25
  return
@@ -21,7 +21,7 @@ function trackUserLoginSuccessEvent (tracer, user, metadata) {
21
21
 
22
22
  incrementSdkEventMetric('login_success', 'v1')
23
23
 
24
- const rootSpan = getRootSpan(tracer)
24
+ const rootSpan = getRootSpan()
25
25
  if (!rootSpan) {
26
26
  log.warn('[ASM] Root span not available in trackUserLoginSuccessEvent')
27
27
  return
@@ -54,7 +54,7 @@ function trackUserLoginFailureEvent (tracer, userId, exists, metadata) {
54
54
  ...metadata,
55
55
  }
56
56
 
57
- trackEvent('users.login.failure', fields, 'trackUserLoginFailureEvent', getRootSpan(tracer))
57
+ trackEvent('users.login.failure', fields, 'trackUserLoginFailureEvent', getRootSpan())
58
58
 
59
59
  runWaf('users.login.failure', { login: userId })
60
60
 
@@ -67,7 +67,7 @@ function trackCustomEvent (tracer, eventName, metadata) {
67
67
  return
68
68
  }
69
69
 
70
- trackEvent(eventName, metadata, 'trackCustomEvent', getRootSpan(tracer))
70
+ trackEvent(eventName, metadata, 'trackCustomEvent', getRootSpan())
71
71
 
72
72
  incrementSdkEventMetric('custom', 'v1')
73
73
 
@@ -84,7 +84,7 @@ function trackUserLoginSuccessV2 (tracer, login, user, metadata) {
84
84
 
85
85
  incrementSdkEventMetric('login_success', 'v2')
86
86
 
87
- const rootSpan = getRootSpan(tracer)
87
+ const rootSpan = getRootSpan()
88
88
  if (!rootSpan) {
89
89
  log.warn('[ASM] Root span not available in eventTrackingV2.trackUserLoginSuccess')
90
90
  return
@@ -122,7 +122,7 @@ function trackUserLoginFailureV2 (tracer, login, exists, metadata) {
122
122
 
123
123
  incrementSdkEventMetric('login_failure', 'v2')
124
124
 
125
- const rootSpan = getRootSpan(tracer)
125
+ const rootSpan = getRootSpan()
126
126
  if (!rootSpan) {
127
127
  log.warn('[ASM] Root span not available in eventTrackingV2.trackUserLoginFailure')
128
128
  return
@@ -19,7 +19,7 @@ function checkUserAndSetUser (tracer, user) {
19
19
  return false
20
20
  }
21
21
 
22
- const rootSpan = getRootSpan(tracer)
22
+ const rootSpan = getRootSpan()
23
23
  if (rootSpan) {
24
24
  if (!rootSpan.context()._tags['usr.id']) {
25
25
  setUserTags(user, rootSpan)
@@ -45,7 +45,7 @@ function blockRequest (tracer, req, res) {
45
45
  return false
46
46
  }
47
47
 
48
- const rootSpan = getRootSpan(tracer)
48
+ const rootSpan = getRootSpan()
49
49
  if (!rootSpan) {
50
50
  log.warn('[ASM] Root span not available in blockRequest')
51
51
  return false
@@ -1,7 +1,9 @@
1
1
  'use strict'
2
2
 
3
- function getRootSpan (tracer) {
4
- let span = tracer.scope().active()
3
+ const { storage } = require('../../../../datadog-core')
4
+
5
+ function getRootSpan () {
6
+ let span = storage('legacy').getStore()?.span
5
7
  if (!span) return
6
8
 
7
9
  const context = span.context()
@@ -60,7 +60,6 @@ setWarnInvalidValue(warnInvalidValue)
60
60
  const defaults = {
61
61
  instrumentationSource: 'manual',
62
62
  isServiceUserProvided: false,
63
- isServiceNameInferred: true,
64
63
  plugins: true,
65
64
  isCiVisibility: false,
66
65
  lookup: dns.lookup,
@@ -504,6 +504,10 @@ export interface GeneratedConfig {
504
504
  otelMetricsUrl: string | undefined;
505
505
  otelProtocol: string;
506
506
  otelTimeout: number;
507
+ otelTracesHeaders: Record<string, string> | undefined;
508
+ otelTracesProtocol: string;
509
+ otelTracesTimeout: number;
510
+ otelTracesUrl: string | undefined;
507
511
  peerServiceMapping: Record<string, string>;
508
512
  port: string | number;
509
513
  profiling: {
@@ -526,6 +530,7 @@ export interface GeneratedConfig {
526
530
  enabled: boolean;
527
531
  eventLoop: boolean;
528
532
  gc: boolean;
533
+ native: boolean;
529
534
  };
530
535
  runtimeMetricsRuntimeId: boolean;
531
536
  sampleRate: number | undefined;
@@ -29,7 +29,6 @@ const {
29
29
  getEnvironmentVariable,
30
30
  getEnvironmentVariables,
31
31
  getStableConfigSources,
32
- getValueFromEnvSources,
33
32
  } = require('./helper')
34
33
  const {
35
34
  defaults,
@@ -229,22 +228,6 @@ class Config extends ConfigBase {
229
228
  #applyEnvs (envs, source) {
230
229
  for (const [name, value] of Object.entries(envs)) {
231
230
  const entry = configurationsTable[name]
232
- // TracePropagationStyle is a special case. It is a single option that is used to set both inject and extract.
233
- // TODO: Consider what to do with this later
234
- if (name === 'DD_TRACE_PROPAGATION_STYLE') {
235
- if (
236
- getValueFromEnvSources('DD_TRACE_PROPAGATION_STYLE_INJECT') !== undefined ||
237
- getValueFromEnvSources('DD_TRACE_PROPAGATION_STYLE_EXTRACT') !== undefined
238
- ) {
239
- log.warn(
240
- // eslint-disable-next-line @stylistic/max-len
241
- 'Use either DD_TRACE_PROPAGATION_STYLE or separate DD_TRACE_PROPAGATION_STYLE_INJECT and DD_TRACE_PROPAGATION_STYLE_EXTRACT environment variables'
242
- )
243
- continue
244
- }
245
- this.#applyEnvs({ DD_TRACE_PROPAGATION_STYLE_INJECT: value, DD_TRACE_PROPAGATION_STYLE_EXTRACT: value }, source)
246
- continue
247
- }
248
231
  const parsed = entry.parser(value, name, source)
249
232
  const transformed = parsed !== undefined && entry.transformer ? entry.transformer(parsed, name, source) : parsed
250
233
  const rawValue = transformed !== null && typeof transformed === 'object' ? value : parsed
@@ -293,6 +276,7 @@ class Config extends ConfigBase {
293
276
  } else {
294
277
  if (fullName === 'tracePropagationStyle') {
295
278
  // TracePropagationStyle is special. It is a single option that is used to set both inject and extract.
279
+ // TODO: Consider what to do with this later
296
280
  // @ts-expect-error - Difficult to type this correctly.
297
281
  this.#applyOptions({ inject: value, extract: value }, source, 'tracePropagationStyle')
298
282
  } else {
@@ -374,6 +358,23 @@ class Config extends ConfigBase {
374
358
  setAndTrack(this, 'otelMetricsEnabled', false)
375
359
  }
376
360
 
361
+ const otelTracesEnabled = trackedConfigOrigins.has('OTEL_TRACES_EXPORTER') &&
362
+ this.OTEL_TRACES_EXPORTER === 'otlp'
363
+ if (this.protocolVersion && this.protocolVersion !== '0.4' && otelTracesEnabled) {
364
+ log.warn('DD_TRACE_AGENT_PROTOCOL_VERSION is set, disabling OTLP traces export')
365
+ setAndTrack(this, 'otelTracesEnabled', false)
366
+ } else {
367
+ setAndTrack(this, 'otelTracesEnabled', otelTracesEnabled)
368
+ }
369
+
370
+ if (this.otelTracesProtocol && this.otelTracesProtocol !== 'http/json') {
371
+ log.warn(
372
+ 'OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=%s is not yet supported; only http/json is currently implemented',
373
+ this.otelTracesProtocol
374
+ )
375
+ setAndTrack(this, 'otelTracesProtocol', 'http/json')
376
+ }
377
+
377
378
  if (this.telemetry.heartbeatInterval) {
378
379
  setAndTrack(this, 'telemetry.heartbeatInterval', Math.floor(this.telemetry.heartbeatInterval * 1000))
379
380
  }
@@ -440,8 +441,16 @@ class Config extends ConfigBase {
440
441
  setAndTrack(this, 'runtimeMetrics.enabled', false)
441
442
  }
442
443
 
443
- if (!trackedConfigOrigins.has('sampleRate') && trackedConfigOrigins.has('OTEL_TRACES_SAMPLER')) {
444
- setAndTrack(this, 'sampleRate', getFromOtelSamplerMap(this.OTEL_TRACES_SAMPLER, this.OTEL_TRACES_SAMPLER_ARG))
444
+ if (!trackedConfigOrigins.has('sampleRate')) {
445
+ const effectiveSampler = (trackedConfigOrigins.has('OTEL_TRACES_EXPORTER') &&
446
+ this.OTEL_TRACES_EXPORTER === 'otlp' &&
447
+ !trackedConfigOrigins.has('OTEL_TRACES_SAMPLER'))
448
+ ? 'parentbased_always_on'
449
+ : this.OTEL_TRACES_SAMPLER
450
+ if (effectiveSampler && (trackedConfigOrigins.has('OTEL_TRACES_SAMPLER') ||
451
+ trackedConfigOrigins.has('OTEL_TRACES_EXPORTER'))) {
452
+ setAndTrack(this, 'sampleRate', getFromOtelSamplerMap(effectiveSampler, this.OTEL_TRACES_SAMPLER_ARG))
453
+ }
445
454
  }
446
455
 
447
456
  if (this.DD_SPAN_SAMPLING_RULES_FILE) {
@@ -541,7 +550,10 @@ class Config extends ConfigBase {
541
550
  isServiceNameInferred = true
542
551
  }
543
552
  }
544
- setAndTrack(this, 'isServiceNameInferred', isServiceNameInferred)
553
+
554
+ // This should not be tracked.
555
+ // TODO: Consider moving this outside of the config.
556
+ set(this, 'isServiceNameInferred', isServiceNameInferred)
545
557
 
546
558
  // Add missing tags, in case they are defined otherwise.
547
559
  if (this.service) {
@@ -600,6 +612,13 @@ class Config extends ConfigBase {
600
612
  if (!this.otelMetricsUrl) {
601
613
  setAndTrack(this, 'otelMetricsUrl', `http://${agentHostname}:${DEFAULT_OTLP_PORT}/v1/metrics`)
602
614
  }
615
+ if (!trackedConfigOrigins.has('otelTracesUrl') && this.OTEL_EXPORTER_OTLP_ENDPOINT) {
616
+ // Generic OTLP endpoint: per spec, append /v1/traces signal-specific subpath
617
+ setAndTrack(this, 'otelTracesUrl', this.OTEL_EXPORTER_OTLP_ENDPOINT.replace(/\/$/, '') + '/v1/traces')
618
+ } else if (!this.otelTracesUrl) {
619
+ const tracesHostname = agentHostname === '127.0.0.1' ? 'localhost' : agentHostname
620
+ setAndTrack(this, 'otelTracesUrl', `http://${tracesHostname}:${DEFAULT_OTLP_PORT}/v1/traces`)
621
+ }
603
622
 
604
623
  if (process.platform === 'win32') {
605
624
  // OOM monitoring does not work properly on Windows, so it will be disabled.
@@ -691,13 +710,25 @@ function increaseCounter (event, ddVar, otelVar) {
691
710
  }
692
711
 
693
712
  function getFromOtelSamplerMap (otelTracesSampler, otelTracesSamplerArg) {
713
+ const NON_PARENTBASED_TO_PARENTBASED = {
714
+ always_on: 'parentbased_always_on',
715
+ always_off: 'parentbased_always_off',
716
+ traceidratio: 'parentbased_traceidratio',
717
+ }
694
718
  const OTEL_TRACES_SAMPLER_MAPPING = {
695
- always_on: 1,
696
- always_off: 0,
697
719
  parentbased_always_on: 1,
698
720
  parentbased_always_off: 0,
699
721
  }
700
722
 
723
+ const parentBasedEquivalent = NON_PARENTBASED_TO_PARENTBASED[otelTracesSampler]
724
+ if (parentBasedEquivalent) {
725
+ log.info(
726
+ 'OTEL_TRACES_SAMPLER=%s does not respect upstream sampling decisions; using parent-based equivalent %s instead',
727
+ otelTracesSampler, parentBasedEquivalent
728
+ )
729
+ otelTracesSampler = parentBasedEquivalent
730
+ }
731
+
701
732
  const result = OTEL_TRACES_SAMPLER_MAPPING[otelTracesSampler] ?? otelTracesSamplerArg
702
733
  if (result === undefined) {
703
734
  increaseCounter('otel.env.invalid', 'DD_TRACE_SAMPLE_RATE', 'OTEL_TRACES_SAMPLER')
@@ -712,7 +743,7 @@ function warnWrongOtelSettings () {
712
743
  // eslint-disable-next-line eslint-rules/eslint-env-aliases
713
744
  ['OTEL_LOG_LEVEL', 'DD_TRACE_LOG_LEVEL', 'logLevel'],
714
745
  // eslint-disable-next-line eslint-rules/eslint-env-aliases
715
- ['OTEL_PROPAGATORS', 'DD_TRACE_PROPAGATION_STYLE'],
746
+ ['OTEL_PROPAGATORS', 'DD_TRACE_PROPAGATION_STYLE', 'DD_TRACE_PROPAGATION_STYLE'],
716
747
  // eslint-disable-next-line eslint-rules/eslint-env-aliases
717
748
  ['OTEL_SERVICE_NAME', 'DD_SERVICE', 'service'],
718
749
  ['OTEL_TRACES_SAMPLER', 'DD_TRACE_SAMPLE_RATE'],
@@ -733,11 +764,7 @@ function warnWrongOtelSettings () {
733
764
  increaseCounter('otel.env.hiding', ddEnvVar, otelEnvVar)
734
765
  }
735
766
 
736
- // eslint-disable-next-line eslint-rules/eslint-env-aliases
737
- const invalidOtelValue = otelEnvVar === 'OTEL_PROPAGATORS'
738
- ? trackedConfigOrigins.get(/** @type {ConfigPath} */ ('tracePropagationStyle.inject')) !== otelSource &&
739
- !envs[ddEnvVar]
740
- : !otelSource
767
+ const invalidOtelValue = !otelSource
741
768
  if (invalidOtelValue) {
742
769
  increaseCounter('otel.env.invalid', ddEnvVar, otelEnvVar)
743
770
  }
@@ -46,12 +46,12 @@
46
46
  ],
47
47
  "DD_AI_GUARD_BLOCK": [
48
48
  {
49
- "implementation": "B",
49
+ "implementation": "C",
50
50
  "type": "boolean",
51
51
  "configurationNames": [
52
52
  "experimental.aiguard.block"
53
53
  ],
54
- "default": "false"
54
+ "default": "true"
55
55
  }
56
56
  ],
57
57
  "DD_AI_GUARD_ENABLED": [
@@ -1573,6 +1573,16 @@
1573
1573
  "default": "10000"
1574
1574
  }
1575
1575
  ],
1576
+ "DD_RUNTIME_METRICS_NATIVE": [
1577
+ {
1578
+ "implementation": "A",
1579
+ "type": "boolean",
1580
+ "configurationNames": [
1581
+ "runtimeMetrics.native"
1582
+ ],
1583
+ "default": "true"
1584
+ }
1585
+ ],
1576
1586
  "DD_RUNTIME_METRICS_GC_ENABLED": [
1577
1587
  {
1578
1588
  "implementation": "A",
@@ -3442,7 +3452,10 @@
3442
3452
  "tracePropagationStyle.extract"
3443
3453
  ],
3444
3454
  "default": "datadog, tracecontext, baggage",
3445
- "transform": "toLowerCase"
3455
+ "transform": "toLowerCase",
3456
+ "aliases": [
3457
+ "DD_TRACE_PROPAGATION_STYLE"
3458
+ ]
3446
3459
  }
3447
3460
  ],
3448
3461
  "DD_TRACE_PROPAGATION_STYLE_INJECT": [
@@ -3453,7 +3466,10 @@
3453
3466
  "tracePropagationStyle.inject"
3454
3467
  ],
3455
3468
  "default": "datadog, tracecontext, baggage",
3456
- "transform": "toLowerCase"
3469
+ "transform": "toLowerCase",
3470
+ "aliases": [
3471
+ "DD_TRACE_PROPAGATION_STYLE"
3472
+ ]
3457
3473
  }
3458
3474
  ],
3459
3475
  "DD_TRACE_PROTOBUFJS_ENABLED": [
@@ -3886,6 +3902,47 @@
3886
3902
  "internalPropertyName": "otelHeaders"
3887
3903
  }
3888
3904
  ],
3905
+ "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT": [
3906
+ {
3907
+ "implementation": "A",
3908
+ "type": "string",
3909
+ "default": null,
3910
+ "internalPropertyName": "otelTracesUrl"
3911
+ }
3912
+ ],
3913
+ "OTEL_EXPORTER_OTLP_TRACES_HEADERS": [
3914
+ {
3915
+ "implementation": "B",
3916
+ "type": "map",
3917
+ "default": null,
3918
+ "internalPropertyName": "otelTracesHeaders",
3919
+ "aliases": [
3920
+ "OTEL_EXPORTER_OTLP_HEADERS"
3921
+ ]
3922
+ }
3923
+ ],
3924
+ "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL": [
3925
+ {
3926
+ "implementation": "B",
3927
+ "type": "string",
3928
+ "default": "http/json",
3929
+ "internalPropertyName": "otelTracesProtocol",
3930
+ "aliases": [
3931
+ "OTEL_EXPORTER_OTLP_PROTOCOL"
3932
+ ]
3933
+ }
3934
+ ],
3935
+ "OTEL_EXPORTER_OTLP_TRACES_TIMEOUT": [
3936
+ {
3937
+ "implementation": "B",
3938
+ "type": "int",
3939
+ "internalPropertyName": "otelTracesTimeout",
3940
+ "default": "10000",
3941
+ "aliases": [
3942
+ "OTEL_EXPORTER_OTLP_TIMEOUT"
3943
+ ]
3944
+ }
3945
+ ],
3889
3946
  "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT": [
3890
3947
  {
3891
3948
  "implementation": "A",
@@ -21,6 +21,7 @@ module.exports = {
21
21
  SPAN_SAMPLING_MECHANISM: '_dd.span_sampling.mechanism',
22
22
  SPAN_SAMPLING_RULE_RATE: '_dd.span_sampling.rule_rate',
23
23
  SPAN_SAMPLING_MAX_PER_SECOND: '_dd.span_sampling.max_per_second',
24
+ SVC_SRC_KEY: '_dd.svc_src',
24
25
  DATADOG_LAMBDA_EXTENSION_PATH: '/opt/extensions/datadog-agent',
25
26
  DATADOG_MINI_AGENT_PATH: '/tmp/datadog/mini_agent_ready',
26
27
  DECISION_MAKER_KEY: '_dd.p.dm',
@@ -105,10 +105,13 @@ function getObjectValue (obj, maxLength) {
105
105
  // case 'node': // TODO: What does this subtype represent?
106
106
  case 'regexp':
107
107
  return { type: obj.className, value: obj.description }
108
- case 'date':
108
+ case 'date': {
109
109
  // TODO: This looses millisecond resolution, as that's not retained in the `.toString()` representation contained
110
110
  // in the `description` field. Unfortunately that's all we get from the Chrome DevTools Protocol.
111
- return { type: obj.className, value: `${new Date(obj.description).toISOString().slice(0, -5)}Z` }
111
+ const date = new Date(obj.description)
112
+ const value = Number.isNaN(date.getTime()) ? obj.description : `${date.toISOString().slice(0, -5)}Z`
113
+ return { type: obj.className, value }
114
+ }
112
115
  case 'map':
113
116
  return toMap(obj.className, obj.properties, maxLength, timeBudgetReached)
114
117
  case 'set':
@@ -3,7 +3,6 @@
3
3
  const { MsgpackChunk, MsgpackEncoder } = require('../msgpack')
4
4
  const log = require('../log')
5
5
  const { isTrue } = require('../util')
6
- const { memoize } = require('../log/utils')
7
6
  const { getValueFromEnvSources } = require('../config/helper')
8
7
  const { truncateSpan, normalizeSpan } = require('./tags-processors')
9
8
 
@@ -338,11 +337,13 @@ class AgentEncoder {
338
337
  }
339
338
  }
340
339
 
341
- const memoizedLogDebug = memoize((key, message) => {
342
- log.debug(message)
343
- // return something to store in memoize cache
344
- return true
345
- })
340
+ const seenKeys = new Set()
341
+ const memoizedLogDebug = (key, message) => {
342
+ if (!seenKeys.has(key)) {
343
+ seenKeys.add(key)
344
+ log.debug(message)
345
+ }
346
+ }
346
347
 
347
348
  function formatSpanEvents (span) {
348
349
  for (const spanEvent of span.span_events) {
@@ -31,7 +31,7 @@ class SpanStatsEncoder extends AgentEncoder {
31
31
  }
32
32
 
33
33
  _encodeStat (bytes, stat) {
34
- this._encodeMapPrefix(bytes, 14)
34
+ this._encodeMapPrefix(bytes, 15)
35
35
 
36
36
  this._encodeString(bytes, 'Service')
37
37
  const service = stat.Service || DEFAULT_SERVICE_NAME
@@ -76,6 +76,9 @@ class SpanStatsEncoder extends AgentEncoder {
76
76
 
77
77
  this._encodeString(bytes, 'HTTPEndpoint')
78
78
  this._encodeString(bytes, stat.HTTPEndpoint)
79
+
80
+ this._encodeString(bytes, 'srv_src')
81
+ this._encodeString(bytes, stat.srv_src || '')
79
82
  }
80
83
 
81
84
  _encodeBucket (bytes, bucket) {
@@ -8,7 +8,6 @@ const { getValueFromEnvSources } = require('../config/helper')
8
8
  const { traceChannel, debugChannel, infoChannel, warnChannel, errorChannel } = require('./channels')
9
9
  const logWriter = require('./writer')
10
10
  const { Log, LogConfig, NoTransmitError } = require('./log')
11
- const { memoize } = require('./utils')
12
11
 
13
12
  const config = {
14
13
  enabled: defaults.DD_TRACE_DEBUG,
@@ -16,11 +15,6 @@ const config = {
16
15
  logLevel: defaults.logLevel,
17
16
  }
18
17
 
19
- const deprecate = memoize((code, message) => {
20
- publishFormatted(errorChannel, null, message)
21
- return true
22
- })
23
-
24
18
  // In most places where we know we want to mute a log we use log.error() directly
25
19
  const NO_TRANSMIT = new LogConfig(false)
26
20
 
@@ -82,10 +76,6 @@ const log = {
82
76
  return log
83
77
  },
84
78
 
85
- deprecate (code, message) {
86
- return deprecate(code, message)
87
- },
88
-
89
79
  configure (options) {
90
80
  config.logger = options.logger
91
81
  config.logLevel = options.logLevel ??
@@ -19,9 +19,14 @@ function enable (rc, config, getOpenfeatureProxy) {
19
19
 
20
20
  // Set product handler for FFE_FLAGS
21
21
  rc.setProductHandler('FFE_FLAGS', (action, conf) => {
22
- // Feed UFC config directly to OpenFeature provider
23
22
  if (action === 'apply' || action === 'modify') {
23
+ // Feed UFC config directly to OpenFeature provider
24
24
  getOpenfeatureProxy()._setConfiguration(conf)
25
+ } else if (action === 'unapply') {
26
+ // Clear the configuration so evaluations return PROVIDER_NOT_READY,
27
+ // consistent with Go and Python which also set config to null on RC deletion.
28
+ // The evaluator returns PROVIDER_NOT_READY when config is null/undefined.
29
+ getOpenfeatureProxy()._setConfiguration(null)
25
30
  }
26
31
  })
27
32
  }