dd-trace 4.28.0 → 4.30.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 (58) hide show
  1. package/CONTRIBUTING.md +98 -0
  2. package/README.md +8 -99
  3. package/ci/cypress/after-run.js +1 -0
  4. package/ci/cypress/after-spec.js +1 -0
  5. package/index.d.ts +1499 -1486
  6. package/package.json +3 -3
  7. package/packages/datadog-core/src/utils/src/get.js +11 -0
  8. package/packages/datadog-core/src/utils/src/has.js +14 -0
  9. package/packages/datadog-core/src/utils/src/set.js +16 -0
  10. package/packages/datadog-instrumentations/src/amqplib.js +1 -1
  11. package/packages/datadog-instrumentations/src/cucumber.js +157 -42
  12. package/packages/datadog-instrumentations/src/grpc/server.js +3 -1
  13. package/packages/datadog-instrumentations/src/jest.js +80 -40
  14. package/packages/datadog-instrumentations/src/mocha.js +4 -1
  15. package/packages/datadog-instrumentations/src/mongodb-core.js +34 -3
  16. package/packages/datadog-instrumentations/src/playwright.js +78 -16
  17. package/packages/datadog-plugin-amqplib/src/consumer.js +8 -4
  18. package/packages/datadog-plugin-amqplib/src/producer.js +3 -4
  19. package/packages/datadog-plugin-aws-sdk/src/base.js +3 -2
  20. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +60 -57
  21. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +42 -22
  22. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +64 -30
  23. package/packages/datadog-plugin-cucumber/src/index.js +25 -9
  24. package/packages/datadog-plugin-cypress/src/after-run.js +3 -0
  25. package/packages/datadog-plugin-cypress/src/after-spec.js +3 -0
  26. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +625 -0
  27. package/packages/datadog-plugin-cypress/src/plugin.js +6 -549
  28. package/packages/datadog-plugin-cypress/src/support.js +50 -3
  29. package/packages/datadog-plugin-graphql/src/index.js +1 -1
  30. package/packages/datadog-plugin-graphql/src/resolve.js +10 -8
  31. package/packages/datadog-plugin-grpc/src/util.js +1 -1
  32. package/packages/datadog-plugin-jest/src/index.js +11 -2
  33. package/packages/datadog-plugin-kafkajs/src/consumer.js +4 -3
  34. package/packages/datadog-plugin-kafkajs/src/producer.js +3 -5
  35. package/packages/datadog-plugin-playwright/src/index.js +34 -3
  36. package/packages/datadog-plugin-rhea/src/consumer.js +8 -3
  37. package/packages/datadog-plugin-rhea/src/producer.js +3 -4
  38. package/packages/dd-trace/src/appsec/iast/index.js +10 -0
  39. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +18 -5
  40. package/packages/dd-trace/src/appsec/recommended.json +67 -27
  41. package/packages/dd-trace/src/appsec/remote_config/index.js +1 -1
  42. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -3
  43. package/packages/dd-trace/src/config.js +451 -459
  44. package/packages/dd-trace/src/data_streams_context.js +1 -1
  45. package/packages/dd-trace/src/datastreams/pathway.js +58 -1
  46. package/packages/dd-trace/src/datastreams/processor.js +3 -5
  47. package/packages/dd-trace/src/format.js +0 -1
  48. package/packages/dd-trace/src/opentracing/propagation/text_map.js +2 -2
  49. package/packages/dd-trace/src/opentracing/span.js +4 -4
  50. package/packages/dd-trace/src/plugins/util/test.js +2 -0
  51. package/packages/dd-trace/src/plugins/util/web.js +1 -1
  52. package/packages/dd-trace/src/profiling/exporters/agent.js +77 -32
  53. package/packages/dd-trace/src/telemetry/index.js +22 -34
  54. package/packages/dd-trace/src/tracer.js +3 -3
  55. package/register.js +4 -0
  56. /package/packages/{utils → datadog-core/src/utils}/src/kebabcase.js +0 -0
  57. /package/packages/{utils → datadog-core/src/utils}/src/pick.js +0 -0
  58. /package/packages/{utils → datadog-core/src/utils}/src/uniq.js +0 -0
@@ -8,6 +8,9 @@ const log = require('./log')
8
8
  const pkg = require('./pkg')
9
9
  const coalesce = require('koalas')
10
10
  const tagger = require('./tagger')
11
+ const get = require('../../datadog-core/src/utils/src/get')
12
+ const has = require('../../datadog-core/src/utils/src/has')
13
+ const set = require('../../datadog-core/src/utils/src/set')
11
14
  const { isTrue, isFalse } = require('./util')
12
15
  const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('./plugins/util/tags')
13
16
  const { getGitMetadataFromGitProperties, removeUserSensitiveInfo } = require('./git_properties')
@@ -20,6 +23,13 @@ const fromEntries = Object.fromEntries || (entries =>
20
23
 
21
24
  // eslint-disable-next-line max-len
22
25
  const qsRegex = '(?: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,}'
26
+ const defaultWafObfuscatorKeyRegex = `(?i)(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?\
27
+ |public_?)key)|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)|bearer|authorization`
28
+ const defaultWafObfuscatorValueRegex =
29
+ `(?i)(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|to\
30
+ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:\\s*=[^;]|"\\s*:\\s*"[^"]+")|bearer\
31
+ \\s+[a-z0-9\\._\\-]+|token:[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L][\\w=-]+\\.ey[I-L][\\w=-]+(?:\\.[\\w.+\\/=-]+)?\
32
+ |[\\-]{5}BEGIN[a-z\\s]+PRIVATE\\sKEY[\\-]{5}[^\\-]+[\\-]{5}END[a-z\\s]+PRIVATE\\sKEY|ssh-rsa\\s*[a-z0-9\\/\\.+]{100,}`
23
33
 
24
34
  function maybeFile (filepath) {
25
35
  if (!filepath) return
@@ -94,6 +104,11 @@ function propagationStyle (key, option, defaultValue) {
94
104
  class Config {
95
105
  constructor (options) {
96
106
  options = options || {}
107
+ options = this.options = {
108
+ ...options,
109
+ appsec: options.appsec != null ? options.appsec : options.experimental?.appsec,
110
+ iastOptions: options.experimental?.iast
111
+ }
97
112
 
98
113
  // Configure the logger first so it can be used to warn about other configs
99
114
  this.debug = isTrue(coalesce(
@@ -110,70 +125,6 @@ class Config {
110
125
  log.use(this.logger)
111
126
  log.toggle(this.debug, this.logLevel, this)
112
127
 
113
- const DD_PROFILING_ENABLED = coalesce(
114
- options.profiling, // TODO: remove when enabled by default
115
- process.env.DD_EXPERIMENTAL_PROFILING_ENABLED,
116
- process.env.DD_PROFILING_ENABLED,
117
- false
118
- )
119
- const DD_PROFILING_EXPORTERS = coalesce(
120
- process.env.DD_PROFILING_EXPORTERS,
121
- 'agent'
122
- )
123
- const DD_PROFILING_SOURCE_MAP = process.env.DD_PROFILING_SOURCE_MAP
124
- const DD_RUNTIME_METRICS_ENABLED = coalesce(
125
- options.runtimeMetrics, // TODO: remove when enabled by default
126
- process.env.DD_RUNTIME_METRICS_ENABLED,
127
- false
128
- )
129
- const DD_DBM_PROPAGATION_MODE = coalesce(
130
- options.dbmPropagationMode,
131
- process.env.DD_DBM_PROPAGATION_MODE,
132
- 'disabled'
133
- )
134
- const DD_DATA_STREAMS_ENABLED = coalesce(
135
- options.dsmEnabled,
136
- process.env.DD_DATA_STREAMS_ENABLED,
137
- false
138
- )
139
- const DD_AGENT_HOST = coalesce(
140
- options.hostname,
141
- process.env.DD_AGENT_HOST,
142
- process.env.DD_TRACE_AGENT_HOSTNAME,
143
- '127.0.0.1'
144
- )
145
- const DD_TRACE_AGENT_PORT = coalesce(
146
- options.port,
147
- process.env.DD_TRACE_AGENT_PORT,
148
- '8126'
149
- )
150
- const DD_TRACE_AGENT_URL = coalesce(
151
- options.url,
152
- process.env.DD_TRACE_AGENT_URL,
153
- process.env.DD_TRACE_URL,
154
- null
155
- )
156
- const DD_IS_CIVISIBILITY = coalesce(
157
- options.isCiVisibility,
158
- false
159
- )
160
- const DD_CIVISIBILITY_AGENTLESS_URL = process.env.DD_CIVISIBILITY_AGENTLESS_URL
161
-
162
- const DD_CIVISIBILITY_ITR_ENABLED = coalesce(
163
- process.env.DD_CIVISIBILITY_ITR_ENABLED,
164
- true
165
- )
166
-
167
- const DD_CIVISIBILITY_MANUAL_API_ENABLED = coalesce(
168
- process.env.DD_CIVISIBILITY_MANUAL_API_ENABLED,
169
- false
170
- )
171
-
172
- const DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED = coalesce(
173
- process.env.DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED,
174
- true
175
- )
176
-
177
128
  const DD_TRACE_MEMCACHED_COMMAND_ENABLED = coalesce(
178
129
  process.env.DD_TRACE_MEMCACHED_COMMAND_ENABLED,
179
130
  false
@@ -185,73 +136,12 @@ class Config {
185
136
  process.env.DD_SERVICE_MAPPING.split(',').map(x => x.trim().split(':'))
186
137
  ) : {}
187
138
  )
188
- const DD_TRACE_STARTUP_LOGS = coalesce(
189
- options.startupLogs,
190
- process.env.DD_TRACE_STARTUP_LOGS,
191
- false
192
- )
193
-
194
- const DD_OPENAI_LOGS_ENABLED = coalesce(
195
- options.openAiLogsEnabled,
196
- process.env.DD_OPENAI_LOGS_ENABLED,
197
- false
198
- )
199
139
 
200
140
  const DD_API_KEY = coalesce(
201
141
  process.env.DATADOG_API_KEY,
202
142
  process.env.DD_API_KEY
203
143
  )
204
144
 
205
- const inAWSLambda = process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined
206
-
207
- const isGCPFunction = getIsGCPFunction()
208
- const isAzureFunctionConsumptionPlan = getIsAzureFunctionConsumptionPlan()
209
-
210
- const inServerlessEnvironment = inAWSLambda || isGCPFunction || isAzureFunctionConsumptionPlan
211
-
212
- const DD_INSTRUMENTATION_TELEMETRY_ENABLED = coalesce(
213
- process.env.DD_TRACE_TELEMETRY_ENABLED, // for backward compatibility
214
- process.env.DD_INSTRUMENTATION_TELEMETRY_ENABLED, // to comply with instrumentation telemetry specs
215
- !inServerlessEnvironment
216
- )
217
- const DD_TELEMETRY_HEARTBEAT_INTERVAL = process.env.DD_TELEMETRY_HEARTBEAT_INTERVAL
218
- ? Math.floor(parseFloat(process.env.DD_TELEMETRY_HEARTBEAT_INTERVAL) * 1000)
219
- : 60000
220
- const DD_OPENAI_SPAN_CHAR_LIMIT = process.env.DD_OPENAI_SPAN_CHAR_LIMIT
221
- ? parseInt(process.env.DD_OPENAI_SPAN_CHAR_LIMIT)
222
- : 128
223
- const DD_TELEMETRY_DEBUG = coalesce(
224
- process.env.DD_TELEMETRY_DEBUG,
225
- false
226
- )
227
- const DD_TELEMETRY_METRICS_ENABLED = coalesce(
228
- process.env.DD_TELEMETRY_METRICS_ENABLED,
229
- true
230
- )
231
- const DD_TRACE_AGENT_PROTOCOL_VERSION = coalesce(
232
- options.protocolVersion,
233
- process.env.DD_TRACE_AGENT_PROTOCOL_VERSION,
234
- '0.4'
235
- )
236
- const DD_TRACE_PARTIAL_FLUSH_MIN_SPANS = coalesce(
237
- parseInt(options.flushMinSpans),
238
- parseInt(process.env.DD_TRACE_PARTIAL_FLUSH_MIN_SPANS),
239
- 1000
240
- )
241
- const DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP = coalesce(
242
- process.env.DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP,
243
- qsRegex
244
- )
245
- const DD_TRACE_CLIENT_IP_ENABLED = coalesce(
246
- options.clientIpEnabled,
247
- process.env.DD_TRACE_CLIENT_IP_ENABLED && isTrue(process.env.DD_TRACE_CLIENT_IP_ENABLED),
248
- false
249
- )
250
- const DD_TRACE_CLIENT_IP_HEADER = coalesce(
251
- options.clientIpHeader,
252
- process.env.DD_TRACE_CLIENT_IP_HEADER,
253
- null
254
- )
255
145
  // TODO: Remove the experimental env vars as a major?
256
146
  const DD_TRACE_B3_ENABLED = coalesce(
257
147
  options.experimental && options.experimental.b3,
@@ -287,238 +177,36 @@ class Config {
287
177
  process.env.DD_TRACE_PROPAGATION_EXTRACT_FIRST,
288
178
  false
289
179
  )
290
- const DD_TRACE_RUNTIME_ID_ENABLED = coalesce(
291
- options.experimental && options.experimental.runtimeId,
292
- process.env.DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED,
293
- false
294
- )
295
- const DD_TRACE_EXPORTER = coalesce(
296
- options.experimental && options.experimental.exporter,
297
- process.env.DD_TRACE_EXPERIMENTAL_EXPORTER
298
- )
299
- const DD_TRACE_GET_RUM_DATA_ENABLED = coalesce(
300
- options.experimental && options.experimental.enableGetRumData,
301
- process.env.DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED,
302
- false
303
- )
304
- const DD_TRACE_SPAN_ATTRIBUTE_SCHEMA = validateNamingVersion(
305
- coalesce(
306
- options.spanAttributeSchema,
307
- process.env.DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
308
- )
309
- )
310
- const DD_TRACE_PEER_SERVICE_MAPPING = coalesce(
311
- options.peerServiceMapping,
312
- process.env.DD_TRACE_PEER_SERVICE_MAPPING ? fromEntries(
313
- process.env.DD_TRACE_PEER_SERVICE_MAPPING.split(',').map(x => x.trim().split(':'))
314
- ) : {}
315
- )
316
-
317
- const peerServiceSet = (
318
- options.hasOwnProperty('spanComputePeerService') ||
319
- process.env.hasOwnProperty('DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED')
320
- )
321
- const peerServiceValue = coalesce(
322
- options.spanComputePeerService,
323
- process.env.DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED
324
- )
325
-
326
- const DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED = (
327
- DD_TRACE_SPAN_ATTRIBUTE_SCHEMA === 'v0'
328
- // In v0, peer service is computed only if it is explicitly set to true
329
- ? peerServiceSet && isTrue(peerServiceValue)
330
- // In >v0, peer service is false only if it is explicitly set to false
331
- : (peerServiceSet ? !isFalse(peerServiceValue) : true)
332
- )
333
-
334
- const DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED = coalesce(
335
- options.spanRemoveIntegrationFromService,
336
- isTrue(process.env.DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED)
337
- )
338
- const DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH = coalesce(
339
- process.env.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH,
340
- '512'
341
- )
342
-
343
- const DD_TRACE_STATS_COMPUTATION_ENABLED = coalesce(
344
- options.stats,
345
- process.env.DD_TRACE_STATS_COMPUTATION_ENABLED,
346
- isGCPFunction || isAzureFunctionConsumptionPlan
347
- )
348
-
349
- // the tracer generates 128 bit IDs by default as of v5
350
- const DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED = coalesce(
351
- options.traceId128BitGenerationEnabled,
352
- process.env.DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED,
353
- true
354
- )
355
-
356
- const DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED = coalesce(
357
- options.traceId128BitLoggingEnabled,
358
- process.env.DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED,
359
- false
360
- )
361
-
362
- let appsec = options.appsec != null ? options.appsec : options.experimental && options.experimental.appsec
363
180
 
364
- if (typeof appsec === 'boolean') {
365
- appsec = {
366
- enabled: appsec
181
+ if (typeof options.appsec === 'boolean') {
182
+ options.appsec = {
183
+ enabled: options.appsec
367
184
  }
368
- } else if (appsec == null) {
369
- appsec = {}
185
+ } else if (options.appsec == null) {
186
+ options.appsec = {}
370
187
  }
371
188
 
372
- const DD_APPSEC_ENABLED = coalesce(
373
- appsec.enabled,
374
- process.env.DD_APPSEC_ENABLED && isTrue(process.env.DD_APPSEC_ENABLED)
375
- )
376
- const DD_APPSEC_RULES = coalesce(
377
- appsec.rules,
378
- process.env.DD_APPSEC_RULES
379
- )
380
- const DD_APPSEC_TRACE_RATE_LIMIT = coalesce(
381
- parseInt(appsec.rateLimit),
382
- parseInt(process.env.DD_APPSEC_TRACE_RATE_LIMIT),
383
- 100
384
- )
385
- const DD_APPSEC_WAF_TIMEOUT = coalesce(
386
- parseInt(appsec.wafTimeout),
387
- parseInt(process.env.DD_APPSEC_WAF_TIMEOUT),
388
- 5e3 // µs
389
- )
390
- const DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP = coalesce(
391
- appsec.obfuscatorKeyRegex,
392
- process.env.DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP,
393
- `(?i)(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?)key)|token|consumer_?(?:id|key|se\
394
- cret)|sign(?:ed|ature)|bearer|authorization`
395
- )
396
- const DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP = coalesce(
397
- appsec.obfuscatorValueRegex,
398
- process.env.DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP,
399
- `(?i)(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|to\
400
- ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:\\s*=[^;]|"\\s*:\\s*"[^"]+")|bearer\
401
- \\s+[a-z0-9\\._\\-]+|token:[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L][\\w=-]+\\.ey[I-L][\\w=-]+(?:\\.[\\w.+\\/=-]+)?\
402
- |[\\-]{5}BEGIN[a-z\\s]+PRIVATE\\sKEY[\\-]{5}[^\\-]+[\\-]{5}END[a-z\\s]+PRIVATE\\sKEY|ssh-rsa\\s*[a-z0-9\\/\\.+]{100,}`
403
- )
404
- const DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML = coalesce(
405
- maybeFile(appsec.blockedTemplateHtml),
406
- maybeFile(process.env.DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML)
407
- )
408
- const DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON = coalesce(
409
- maybeFile(appsec.blockedTemplateJson),
410
- maybeFile(process.env.DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON)
411
- )
412
189
  const DD_APPSEC_GRAPHQL_BLOCKED_TEMPLATE_JSON = coalesce(
413
- maybeFile(appsec.blockedTemplateGraphql),
190
+ maybeFile(options.appsec.blockedTemplateGraphql),
414
191
  maybeFile(process.env.DD_APPSEC_GRAPHQL_BLOCKED_TEMPLATE_JSON)
415
192
  )
416
193
  const DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING = coalesce(
417
- appsec.eventTracking && appsec.eventTracking.mode,
194
+ options.appsec.eventTracking && options.appsec.eventTracking.mode,
418
195
  process.env.DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING,
419
196
  'safe'
420
197
  ).toLowerCase()
421
198
  const DD_API_SECURITY_ENABLED = coalesce(
422
- appsec?.apiSecurity?.enabled,
199
+ options.appsec?.apiSecurity?.enabled,
423
200
  process.env.DD_API_SECURITY_ENABLED && isTrue(process.env.DD_API_SECURITY_ENABLED),
424
201
  process.env.DD_EXPERIMENTAL_API_SECURITY_ENABLED && isTrue(process.env.DD_EXPERIMENTAL_API_SECURITY_ENABLED),
425
202
  true
426
203
  )
427
204
  const DD_API_SECURITY_REQUEST_SAMPLE_RATE = coalesce(
428
- appsec?.apiSecurity?.requestSampling,
205
+ options.appsec?.apiSecurity?.requestSampling,
429
206
  parseFloat(process.env.DD_API_SECURITY_REQUEST_SAMPLE_RATE),
430
207
  0.1
431
208
  )
432
209
 
433
- const remoteConfigOptions = options.remoteConfig || {}
434
- const DD_REMOTE_CONFIGURATION_ENABLED = coalesce(
435
- process.env.DD_REMOTE_CONFIGURATION_ENABLED && isTrue(process.env.DD_REMOTE_CONFIGURATION_ENABLED),
436
- !inServerlessEnvironment
437
- )
438
- const DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS = coalesce(
439
- parseFloat(remoteConfigOptions.pollInterval),
440
- parseFloat(process.env.DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS),
441
- 5 // seconds
442
- )
443
-
444
- const iastOptions = options?.experimental?.iast
445
- const DD_IAST_ENABLED = coalesce(
446
- iastOptions &&
447
- (iastOptions === true || iastOptions.enabled === true),
448
- process.env.DD_IAST_ENABLED,
449
- false
450
- )
451
- const DD_TELEMETRY_LOG_COLLECTION_ENABLED = coalesce(
452
- process.env.DD_TELEMETRY_LOG_COLLECTION_ENABLED,
453
- DD_IAST_ENABLED
454
- )
455
-
456
- const DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED = coalesce(
457
- process.env.DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED,
458
- true
459
- )
460
-
461
- const defaultIastRequestSampling = 30
462
- const iastRequestSampling = coalesce(
463
- parseInt(iastOptions?.requestSampling),
464
- parseInt(process.env.DD_IAST_REQUEST_SAMPLING),
465
- defaultIastRequestSampling
466
- )
467
- const DD_IAST_REQUEST_SAMPLING = iastRequestSampling < 0 ||
468
- iastRequestSampling > 100 ? defaultIastRequestSampling : iastRequestSampling
469
-
470
- const DD_IAST_MAX_CONCURRENT_REQUESTS = coalesce(
471
- parseInt(iastOptions?.maxConcurrentRequests),
472
- parseInt(process.env.DD_IAST_MAX_CONCURRENT_REQUESTS),
473
- 2
474
- )
475
-
476
- const DD_IAST_MAX_CONTEXT_OPERATIONS = coalesce(
477
- parseInt(iastOptions?.maxContextOperations),
478
- parseInt(process.env.DD_IAST_MAX_CONTEXT_OPERATIONS),
479
- 2
480
- )
481
-
482
- const DD_IAST_DEDUPLICATION_ENABLED = coalesce(
483
- iastOptions?.deduplicationEnabled,
484
- process.env.DD_IAST_DEDUPLICATION_ENABLED && isTrue(process.env.DD_IAST_DEDUPLICATION_ENABLED),
485
- true
486
- )
487
-
488
- const DD_IAST_REDACTION_ENABLED = coalesce(
489
- iastOptions?.redactionEnabled,
490
- !isFalse(process.env.DD_IAST_REDACTION_ENABLED),
491
- true
492
- )
493
-
494
- const DD_IAST_REDACTION_NAME_PATTERN = coalesce(
495
- iastOptions?.redactionNamePattern,
496
- process.env.DD_IAST_REDACTION_NAME_PATTERN,
497
- null
498
- )
499
-
500
- const DD_IAST_REDACTION_VALUE_PATTERN = coalesce(
501
- iastOptions?.redactionValuePattern,
502
- process.env.DD_IAST_REDACTION_VALUE_PATTERN,
503
- null
504
- )
505
-
506
- const DD_IAST_TELEMETRY_VERBOSITY = coalesce(
507
- iastOptions?.telemetryVerbosity,
508
- process.env.DD_IAST_TELEMETRY_VERBOSITY,
509
- 'INFORMATION'
510
- )
511
-
512
- const DD_CIVISIBILITY_GIT_UPLOAD_ENABLED = coalesce(
513
- process.env.DD_CIVISIBILITY_GIT_UPLOAD_ENABLED,
514
- true
515
- )
516
-
517
- const DD_TRACE_GIT_METADATA_ENABLED = coalesce(
518
- process.env.DD_TRACE_GIT_METADATA_ENABLED,
519
- true
520
- )
521
-
522
210
  // 0: disabled, 1: logging, 2: garbage collection + logging
523
211
  const DD_TRACE_SPAN_LEAK_DEBUG = coalesce(
524
212
  process.env.DD_TRACE_SPAN_LEAK_DEBUG,
@@ -538,10 +226,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
538
226
  null
539
227
  )
540
228
 
541
- const ingestion = options.ingestion || {}
542
- const dogstatsd = coalesce(options.dogstatsd, {})
543
229
  const sampler = {
544
- rateLimit: coalesce(options.rateLimit, process.env.DD_TRACE_RATE_LIMIT, ingestion.rateLimit),
545
230
  rules: coalesce(
546
231
  options.samplingRules,
547
232
  safeJsonParse(process.env.DD_TRACE_SAMPLING_RULES),
@@ -564,74 +249,16 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
564
249
  })
565
250
  }
566
251
 
567
- const defaultFlushInterval = inAWSLambda ? 0 : 2000
568
-
569
- this.dbmPropagationMode = DD_DBM_PROPAGATION_MODE
570
- this.dsmEnabled = isTrue(DD_DATA_STREAMS_ENABLED)
571
- this.openAiLogsEnabled = DD_OPENAI_LOGS_ENABLED
252
+ // TODO: refactor
572
253
  this.apiKey = DD_API_KEY
573
- this.url = DD_CIVISIBILITY_AGENTLESS_URL ? new URL(DD_CIVISIBILITY_AGENTLESS_URL)
574
- : getAgentUrl(DD_TRACE_AGENT_URL, options)
575
- this.site = coalesce(options.site, process.env.DD_SITE, 'datadoghq.com')
576
- this.hostname = DD_AGENT_HOST || (this.url && this.url.hostname)
577
- this.port = String(DD_TRACE_AGENT_PORT || (this.url && this.url.port))
578
- this.flushInterval = coalesce(parseInt(options.flushInterval, 10), defaultFlushInterval)
579
- this.flushMinSpans = DD_TRACE_PARTIAL_FLUSH_MIN_SPANS
580
- this.queryStringObfuscation = DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP
581
- this.clientIpEnabled = DD_TRACE_CLIENT_IP_ENABLED
582
- this.clientIpHeader = DD_TRACE_CLIENT_IP_HEADER
583
- this.plugins = !!coalesce(options.plugins, true)
584
254
  this.serviceMapping = DD_SERVICE_MAPPING
585
- this.dogstatsd = {
586
- hostname: coalesce(dogstatsd.hostname, process.env.DD_DOGSTATSD_HOSTNAME, this.hostname),
587
- port: String(coalesce(dogstatsd.port, process.env.DD_DOGSTATSD_PORT, 8125))
588
- }
589
- this.runtimeMetrics = isTrue(DD_RUNTIME_METRICS_ENABLED)
590
255
  this.tracePropagationStyle = {
591
256
  inject: DD_TRACE_PROPAGATION_STYLE_INJECT,
592
257
  extract: DD_TRACE_PROPAGATION_STYLE_EXTRACT
593
258
  }
594
259
  this.tracePropagationExtractFirst = isTrue(DD_TRACE_PROPAGATION_EXTRACT_FIRST)
595
- this.experimental = {
596
- runtimeId: isTrue(DD_TRACE_RUNTIME_ID_ENABLED),
597
- exporter: DD_TRACE_EXPORTER,
598
- enableGetRumData: isTrue(DD_TRACE_GET_RUM_DATA_ENABLED)
599
- }
600
260
  this.sampler = sampler
601
- this.reportHostname = isTrue(coalesce(options.reportHostname, process.env.DD_TRACE_REPORT_HOSTNAME, false))
602
- this.scope = process.env.DD_TRACE_SCOPE
603
- this.profiling = {
604
- enabled: isTrue(DD_PROFILING_ENABLED),
605
- sourceMap: !isFalse(DD_PROFILING_SOURCE_MAP),
606
- exporters: DD_PROFILING_EXPORTERS
607
- }
608
- this.spanAttributeSchema = DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
609
- this.spanComputePeerService = DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED
610
- this.spanRemoveIntegrationFromService = DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED
611
- this.peerServiceMapping = DD_TRACE_PEER_SERVICE_MAPPING
612
- this.lookup = options.lookup
613
- this.startupLogs = isTrue(DD_TRACE_STARTUP_LOGS)
614
- // Disabled for CI Visibility's agentless
615
- this.telemetry = {
616
- enabled: isTrue(DD_INSTRUMENTATION_TELEMETRY_ENABLED),
617
- heartbeatInterval: DD_TELEMETRY_HEARTBEAT_INTERVAL,
618
- debug: isTrue(DD_TELEMETRY_DEBUG),
619
- logCollection: isTrue(DD_TELEMETRY_LOG_COLLECTION_ENABLED),
620
- metrics: isTrue(DD_TELEMETRY_METRICS_ENABLED),
621
- dependencyCollection: DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED
622
- }
623
- this.protocolVersion = DD_TRACE_AGENT_PROTOCOL_VERSION
624
- this.tagsHeaderMaxLength = parseInt(DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH)
625
261
  this.appsec = {
626
- enabled: DD_APPSEC_ENABLED,
627
- rules: DD_APPSEC_RULES,
628
- customRulesProvided: !!DD_APPSEC_RULES,
629
- rateLimit: DD_APPSEC_TRACE_RATE_LIMIT,
630
- wafTimeout: DD_APPSEC_WAF_TIMEOUT,
631
- obfuscatorKeyRegex: DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP,
632
- obfuscatorValueRegex: DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP,
633
- blockedTemplateHtml: DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML,
634
- blockedTemplateJson: DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON,
635
262
  blockedTemplateGraphql: DD_APPSEC_GRAPHQL_BLOCKED_TEMPLATE_JSON,
636
263
  eventTracking: {
637
264
  enabled: ['extended', 'safe'].includes(DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING),
@@ -644,49 +271,10 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
644
271
  }
645
272
  }
646
273
 
647
- this.remoteConfig = {
648
- enabled: DD_REMOTE_CONFIGURATION_ENABLED,
649
- pollInterval: DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS
650
- }
651
- this.iast = {
652
- enabled: isTrue(DD_IAST_ENABLED),
653
- requestSampling: DD_IAST_REQUEST_SAMPLING,
654
- maxConcurrentRequests: DD_IAST_MAX_CONCURRENT_REQUESTS,
655
- maxContextOperations: DD_IAST_MAX_CONTEXT_OPERATIONS,
656
- deduplicationEnabled: DD_IAST_DEDUPLICATION_ENABLED,
657
- redactionEnabled: DD_IAST_REDACTION_ENABLED,
658
- redactionNamePattern: DD_IAST_REDACTION_NAME_PATTERN,
659
- redactionValuePattern: DD_IAST_REDACTION_VALUE_PATTERN,
660
- telemetryVerbosity: DD_IAST_TELEMETRY_VERBOSITY
661
- }
662
-
663
- this.isCiVisibility = isTrue(DD_IS_CIVISIBILITY)
664
-
665
- this.isIntelligentTestRunnerEnabled = this.isCiVisibility && isTrue(DD_CIVISIBILITY_ITR_ENABLED)
666
- this.isGitUploadEnabled = this.isCiVisibility &&
667
- (this.isIntelligentTestRunnerEnabled && !isFalse(DD_CIVISIBILITY_GIT_UPLOAD_ENABLED))
668
-
669
- this.gitMetadataEnabled = isTrue(DD_TRACE_GIT_METADATA_ENABLED)
670
- this.isManualApiEnabled = this.isCiVisibility && isTrue(DD_CIVISIBILITY_MANUAL_API_ENABLED)
671
- this.isEarlyFlakeDetectionEnabled = this.isCiVisibility && isTrue(DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED)
672
-
673
- this.openaiSpanCharLimit = DD_OPENAI_SPAN_CHAR_LIMIT
674
-
675
274
  // Requires an accompanying DD_APM_OBFUSCATION_MEMCACHED_KEEP_COMMAND=true in the agent
676
275
  this.memcachedCommandEnabled = isTrue(DD_TRACE_MEMCACHED_COMMAND_ENABLED)
677
-
678
- this.stats = {
679
- enabled: isTrue(DD_TRACE_STATS_COMPUTATION_ENABLED)
680
- }
681
-
682
- this.traceId128BitGenerationEnabled = isTrue(DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED)
683
- this.traceId128BitLoggingEnabled = isTrue(DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED)
684
-
685
- this.isGCPFunction = isGCPFunction
686
- this.isAzureFunctionConsumptionPlan = isAzureFunctionConsumptionPlan
687
-
276
+ this.isAzureFunctionConsumptionPlan = getIsAzureFunctionConsumptionPlan()
688
277
  this.spanLeakDebug = Number(DD_TRACE_SPAN_LEAK_DEBUG)
689
-
690
278
  this.installSignature = {
691
279
  id: DD_INSTRUMENTATION_INSTALL_ID,
692
280
  time: DD_INSTRUMENTATION_INSTALL_TIME,
@@ -696,6 +284,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
696
284
  this._applyDefaults()
697
285
  this._applyEnvironment()
698
286
  this._applyOptions(options)
287
+ this._applyCalculated()
699
288
  this._applyRemote({})
700
289
  this._merge()
701
290
 
@@ -754,9 +343,19 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
754
343
  this._applyOptions(options)
755
344
  }
756
345
 
346
+ // TODO: test
347
+ this._applyCalculated()
757
348
  this._merge()
758
349
  }
759
350
 
351
+ _isInServerlessEnvironment () {
352
+ const inAWSLambda = process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined
353
+ const isGCPFunction = getIsGCPFunction()
354
+ const isAzureFunctionConsumptionPlan = getIsAzureFunctionConsumptionPlan()
355
+ return inAWSLambda || isGCPFunction || isAzureFunctionConsumptionPlan
356
+ }
357
+
358
+ // for _merge to work, every config value must have a default value
760
359
  _applyDefaults () {
761
360
  const {
762
361
  AWS_LAMBDA_FUNCTION_NAME,
@@ -774,27 +373,158 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
774
373
 
775
374
  const defaults = this._defaults = {}
776
375
 
777
- this._setValue(defaults, 'service', service)
376
+ this._setValue(defaults, 'appsec.blockedTemplateHtml', undefined)
377
+ this._setValue(defaults, 'appsec.blockedTemplateJson', undefined)
378
+ this._setValue(defaults, 'appsec.enabled', undefined)
379
+ this._setValue(defaults, 'appsec.obfuscatorKeyRegex', defaultWafObfuscatorKeyRegex)
380
+ this._setValue(defaults, 'appsec.obfuscatorValueRegex', defaultWafObfuscatorValueRegex)
381
+ this._setValue(defaults, 'appsec.rateLimit', 100)
382
+ this._setValue(defaults, 'appsec.rules', undefined)
383
+ this._setValue(defaults, 'appsec.wafTimeout', 5e3) // µs
384
+ this._setValue(defaults, 'clientIpEnabled', false)
385
+ this._setValue(defaults, 'clientIpHeader', null)
386
+ this._setValue(defaults, 'dbmPropagationMode', 'disabled')
387
+ this._setValue(defaults, 'dogstatsd.hostname', '127.0.0.1')
388
+ this._setValue(defaults, 'dogstatsd.port', '8125')
389
+ this._setValue(defaults, 'dsmEnabled', false)
778
390
  this._setValue(defaults, 'env', undefined)
779
- this._setValue(defaults, 'version', pkg.version)
780
- this._setUnit(defaults, 'sampleRate', undefined)
781
- this._setBoolean(defaults, 'logInjection', false)
782
- this._setArray(defaults, 'headerTags', [])
391
+ this._setValue(defaults, 'experimental.enableGetRumData', false)
392
+ this._setValue(defaults, 'experimental.exporter', undefined)
393
+ this._setValue(defaults, 'experimental.runtimeId', false)
394
+ this._setValue(defaults, 'flushInterval', 2000)
395
+ this._setValue(defaults, 'flushMinSpans', 1000)
396
+ this._setValue(defaults, 'gitMetadataEnabled', true)
397
+ this._setValue(defaults, 'headerTags', [])
398
+ this._setValue(defaults, 'hostname', '127.0.0.1')
399
+ this._setValue(defaults, 'iast.deduplicationEnabled', true)
400
+ this._setValue(defaults, 'iast.enabled', false)
401
+ this._setValue(defaults, 'iast.maxConcurrentRequests', 2)
402
+ this._setValue(defaults, 'iast.maxContextOperations', 2)
403
+ this._setValue(defaults, 'iast.redactionEnabled', true)
404
+ this._setValue(defaults, 'iast.redactionNamePattern', null)
405
+ this._setValue(defaults, 'iast.redactionValuePattern', null)
406
+ this._setValue(defaults, 'iast.requestSampling', 30)
407
+ this._setValue(defaults, 'iast.telemetryVerbosity', 'INFORMATION')
408
+ this._setValue(defaults, 'isCiVisibility', false)
409
+ this._setValue(defaults, 'isEarlyFlakeDetectionEnabled', false)
410
+ this._setValue(defaults, 'isGCPFunction', false)
411
+ this._setValue(defaults, 'isGitUploadEnabled', false)
412
+ this._setValue(defaults, 'isIntelligentTestRunnerEnabled', false)
413
+ this._setValue(defaults, 'isManualApiEnabled', false)
414
+ this._setValue(defaults, 'logInjection', false)
415
+ this._setValue(defaults, 'lookup', undefined)
416
+ this._setValue(defaults, 'openAiLogsEnabled', false)
417
+ this._setValue(defaults, 'openaiSpanCharLimit', 128)
418
+ this._setValue(defaults, 'peerServiceMapping', {})
419
+ this._setValue(defaults, 'plugins', true)
420
+ this._setValue(defaults, 'port', '8126')
421
+ this._setValue(defaults, 'profiling.enabled', false)
422
+ this._setValue(defaults, 'profiling.exporters', 'agent')
423
+ this._setValue(defaults, 'profiling.sourceMap', true)
424
+ this._setValue(defaults, 'protocolVersion', '0.4')
425
+ this._setValue(defaults, 'queryStringObfuscation', qsRegex)
426
+ this._setValue(defaults, 'remoteConfig.enabled', true)
427
+ this._setValue(defaults, 'remoteConfig.pollInterval', 5) // seconds
428
+ this._setValue(defaults, 'reportHostname', false)
429
+ this._setValue(defaults, 'runtimeMetrics', false)
430
+ this._setValue(defaults, 'sampleRate', undefined)
431
+ this._setValue(defaults, 'sampler.rateLimit', undefined)
432
+ this._setValue(defaults, 'scope', undefined)
433
+ this._setValue(defaults, 'service', service)
434
+ this._setValue(defaults, 'site', 'datadoghq.com')
435
+ this._setValue(defaults, 'spanAttributeSchema', 'v0')
436
+ this._setValue(defaults, 'spanComputePeerService', false)
437
+ this._setValue(defaults, 'spanRemoveIntegrationFromService', false)
438
+ this._setValue(defaults, 'startupLogs', false)
439
+ this._setValue(defaults, 'stats.enabled', false)
783
440
  this._setValue(defaults, 'tags', {})
784
- this._setBoolean(defaults, 'tracing', true)
441
+ this._setValue(defaults, 'tagsHeaderMaxLength', 512)
442
+ this._setValue(defaults, 'telemetry.debug', false)
443
+ this._setValue(defaults, 'telemetry.dependencyCollection', true)
444
+ this._setValue(defaults, 'telemetry.enabled', true)
445
+ this._setValue(defaults, 'telemetry.heartbeatInterval', 60000)
446
+ this._setValue(defaults, 'telemetry.logCollection', false)
447
+ this._setValue(defaults, 'telemetry.metrics', true)
448
+ this._setValue(defaults, 'traceId128BitGenerationEnabled', true)
449
+ this._setValue(defaults, 'traceId128BitLoggingEnabled', false)
450
+ this._setValue(defaults, 'tracing', true)
451
+ this._setValue(defaults, 'url', undefined)
452
+ this._setValue(defaults, 'version', pkg.version)
785
453
  }
786
454
 
787
455
  _applyEnvironment () {
788
456
  const {
457
+ AWS_LAMBDA_FUNCTION_NAME,
458
+ DD_AGENT_HOST,
459
+ DD_APPSEC_ENABLED,
460
+ DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML,
461
+ DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON,
462
+ DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP,
463
+ DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP,
464
+ DD_APPSEC_RULES,
465
+ DD_APPSEC_TRACE_RATE_LIMIT,
466
+ DD_APPSEC_WAF_TIMEOUT,
467
+ DD_DATA_STREAMS_ENABLED,
468
+ DD_DBM_PROPAGATION_MODE,
469
+ DD_DOGSTATSD_HOSTNAME,
470
+ DD_DOGSTATSD_PORT,
789
471
  DD_ENV,
472
+ DD_EXPERIMENTAL_PROFILING_ENABLED,
473
+ JEST_WORKER_ID,
474
+ DD_IAST_DEDUPLICATION_ENABLED,
475
+ DD_IAST_ENABLED,
476
+ DD_IAST_MAX_CONCURRENT_REQUESTS,
477
+ DD_IAST_MAX_CONTEXT_OPERATIONS,
478
+ DD_IAST_REDACTION_ENABLED,
479
+ DD_IAST_REDACTION_NAME_PATTERN,
480
+ DD_IAST_REDACTION_VALUE_PATTERN,
481
+ DD_IAST_REQUEST_SAMPLING,
482
+ DD_IAST_TELEMETRY_VERBOSITY,
483
+ DD_INSTRUMENTATION_TELEMETRY_ENABLED,
790
484
  DD_LOGS_INJECTION,
485
+ DD_OPENAI_LOGS_ENABLED,
486
+ DD_OPENAI_SPAN_CHAR_LIMIT,
487
+ DD_PROFILING_ENABLED,
488
+ DD_PROFILING_EXPORTERS,
489
+ DD_PROFILING_SOURCE_MAP,
490
+ DD_REMOTE_CONFIGURATION_ENABLED,
491
+ DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS,
492
+ DD_RUNTIME_METRICS_ENABLED,
791
493
  DD_SERVICE,
792
494
  DD_SERVICE_NAME,
495
+ DD_SITE,
793
496
  DD_TAGS,
497
+ DD_TELEMETRY_DEBUG,
498
+ DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED,
499
+ DD_TELEMETRY_HEARTBEAT_INTERVAL,
500
+ DD_TELEMETRY_LOG_COLLECTION_ENABLED,
501
+ DD_TELEMETRY_METRICS_ENABLED,
502
+ DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED,
503
+ DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED,
504
+ DD_TRACE_AGENT_HOSTNAME,
505
+ DD_TRACE_AGENT_PORT,
506
+ DD_TRACE_AGENT_PROTOCOL_VERSION,
507
+ DD_TRACE_CLIENT_IP_ENABLED,
508
+ DD_TRACE_CLIENT_IP_HEADER,
509
+ DD_TRACE_EXPERIMENTAL_EXPORTER,
510
+ DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED,
511
+ DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED,
512
+ DD_TRACE_GIT_METADATA_ENABLED,
794
513
  DD_TRACE_GLOBAL_TAGS,
795
514
  DD_TRACE_HEADER_TAGS,
515
+ DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP,
516
+ DD_TRACE_PARTIAL_FLUSH_MIN_SPANS,
517
+ DD_TRACE_PEER_SERVICE_MAPPING,
518
+ DD_TRACE_RATE_LIMIT,
519
+ DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED,
520
+ DD_TRACE_REPORT_HOSTNAME,
796
521
  DD_TRACE_SAMPLE_RATE,
522
+ DD_TRACE_SCOPE,
523
+ DD_TRACE_SPAN_ATTRIBUTE_SCHEMA,
524
+ DD_TRACE_STARTUP_LOGS,
797
525
  DD_TRACE_TAGS,
526
+ DD_TRACE_TELEMETRY_ENABLED,
527
+ DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH,
798
528
  DD_TRACING_ENABLED,
799
529
  DD_VERSION
800
530
  } = process.env
@@ -806,31 +536,281 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
806
536
  tagger.add(tags, DD_TRACE_TAGS)
807
537
  tagger.add(tags, DD_TRACE_GLOBAL_TAGS)
808
538
 
809
- this._setString(env, 'service', DD_SERVICE || DD_SERVICE_NAME || tags.service)
539
+ this._setValue(env, 'appsec.blockedTemplateHtml', maybeFile(DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML))
540
+ this._setValue(env, 'appsec.blockedTemplateJson', maybeFile(DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON))
541
+ this._setBoolean(env, 'appsec.enabled', DD_APPSEC_ENABLED)
542
+ this._setString(env, 'appsec.obfuscatorKeyRegex', DD_APPSEC_OBFUSCATION_PARAMETER_KEY_REGEXP)
543
+ this._setString(env, 'appsec.obfuscatorValueRegex', DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP)
544
+ this._setValue(env, 'appsec.rateLimit', maybeInt(DD_APPSEC_TRACE_RATE_LIMIT))
545
+ this._setString(env, 'appsec.rules', DD_APPSEC_RULES)
546
+ this._setValue(env, 'appsec.wafTimeout', maybeInt(DD_APPSEC_WAF_TIMEOUT))
547
+ this._setBoolean(env, 'clientIpEnabled', DD_TRACE_CLIENT_IP_ENABLED)
548
+ this._setString(env, 'clientIpHeader', DD_TRACE_CLIENT_IP_HEADER)
549
+ this._setString(env, 'dbmPropagationMode', DD_DBM_PROPAGATION_MODE)
550
+ this._setString(env, 'dogstatsd.hostname', DD_DOGSTATSD_HOSTNAME)
551
+ this._setString(env, 'dogstatsd.port', DD_DOGSTATSD_PORT)
552
+ this._setBoolean(env, 'dsmEnabled', DD_DATA_STREAMS_ENABLED)
810
553
  this._setString(env, 'env', DD_ENV || tags.env)
811
- this._setString(env, 'version', DD_VERSION || tags.version)
812
- this._setUnit(env, 'sampleRate', DD_TRACE_SAMPLE_RATE)
813
- this._setBoolean(env, 'logInjection', DD_LOGS_INJECTION)
554
+ this._setBoolean(env, 'experimental.enableGetRumData', DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED)
555
+ this._setString(env, 'experimental.exporter', DD_TRACE_EXPERIMENTAL_EXPORTER)
556
+ this._setBoolean(env, 'experimental.runtimeId', DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED)
557
+ if (AWS_LAMBDA_FUNCTION_NAME) this._setValue(env, 'flushInterval', 0)
558
+ this._setValue(env, 'flushMinSpans', maybeInt(DD_TRACE_PARTIAL_FLUSH_MIN_SPANS))
559
+ this._setBoolean(env, 'gitMetadataEnabled', DD_TRACE_GIT_METADATA_ENABLED)
814
560
  this._setArray(env, 'headerTags', DD_TRACE_HEADER_TAGS)
561
+ this._setString(env, 'hostname', coalesce(DD_AGENT_HOST, DD_TRACE_AGENT_HOSTNAME))
562
+ this._setBoolean(env, 'iast.deduplicationEnabled', DD_IAST_DEDUPLICATION_ENABLED)
563
+ this._setBoolean(env, 'iast.enabled', DD_IAST_ENABLED)
564
+ this._setValue(env, 'iast.maxConcurrentRequests', maybeInt(DD_IAST_MAX_CONCURRENT_REQUESTS))
565
+ this._setValue(env, 'iast.maxContextOperations', maybeInt(DD_IAST_MAX_CONTEXT_OPERATIONS))
566
+ this._setBoolean(env, 'iast.redactionEnabled', DD_IAST_REDACTION_ENABLED && !isFalse(DD_IAST_REDACTION_ENABLED))
567
+ this._setString(env, 'iast.redactionNamePattern', DD_IAST_REDACTION_NAME_PATTERN)
568
+ this._setString(env, 'iast.redactionValuePattern', DD_IAST_REDACTION_VALUE_PATTERN)
569
+ const iastRequestSampling = maybeInt(DD_IAST_REQUEST_SAMPLING)
570
+ if (iastRequestSampling > -1 && iastRequestSampling < 101) {
571
+ this._setValue(env, 'iast.requestSampling', iastRequestSampling)
572
+ }
573
+ this._setString(env, 'iast.telemetryVerbosity', DD_IAST_TELEMETRY_VERBOSITY)
574
+ this._setBoolean(env, 'isGCPFunction', getIsGCPFunction())
575
+ this._setBoolean(env, 'logInjection', DD_LOGS_INJECTION)
576
+ this._setBoolean(env, 'openAiLogsEnabled', DD_OPENAI_LOGS_ENABLED)
577
+ this._setValue(env, 'openaiSpanCharLimit', maybeInt(DD_OPENAI_SPAN_CHAR_LIMIT))
578
+ if (DD_TRACE_PEER_SERVICE_MAPPING) {
579
+ this._setValue(env, 'peerServiceMapping', fromEntries(
580
+ process.env.DD_TRACE_PEER_SERVICE_MAPPING.split(',').map(x => x.trim().split(':'))
581
+ ))
582
+ }
583
+ this._setString(env, 'port', DD_TRACE_AGENT_PORT)
584
+ this._setBoolean(env, 'profiling.enabled', coalesce(DD_EXPERIMENTAL_PROFILING_ENABLED, DD_PROFILING_ENABLED))
585
+ this._setString(env, 'profiling.exporters', DD_PROFILING_EXPORTERS)
586
+ this._setBoolean(env, 'profiling.sourceMap', DD_PROFILING_SOURCE_MAP && !isFalse(DD_PROFILING_SOURCE_MAP))
587
+ this._setString(env, 'protocolVersion', DD_TRACE_AGENT_PROTOCOL_VERSION)
588
+ this._setString(env, 'queryStringObfuscation', DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP)
589
+ this._setBoolean(env, 'remoteConfig.enabled', coalesce(
590
+ DD_REMOTE_CONFIGURATION_ENABLED,
591
+ !this._isInServerlessEnvironment()
592
+ ))
593
+ this._setValue(env, 'remoteConfig.pollInterval', maybeFloat(DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS))
594
+ this._setBoolean(env, 'reportHostname', DD_TRACE_REPORT_HOSTNAME)
595
+ this._setBoolean(env, 'runtimeMetrics', DD_RUNTIME_METRICS_ENABLED)
596
+ this._setUnit(env, 'sampleRate', DD_TRACE_SAMPLE_RATE)
597
+ this._setValue(env, 'sampler.rateLimit', DD_TRACE_RATE_LIMIT)
598
+ this._setString(env, 'scope', DD_TRACE_SCOPE)
599
+ this._setString(env, 'service', DD_SERVICE || DD_SERVICE_NAME || tags.service)
600
+ this._setString(env, 'site', DD_SITE)
601
+ if (DD_TRACE_SPAN_ATTRIBUTE_SCHEMA) {
602
+ this._setString(env, 'spanAttributeSchema', validateNamingVersion(DD_TRACE_SPAN_ATTRIBUTE_SCHEMA))
603
+ }
604
+ this._setBoolean(env, 'spanRemoveIntegrationFromService', DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED)
605
+ this._setBoolean(env, 'startupLogs', DD_TRACE_STARTUP_LOGS)
815
606
  this._setTags(env, 'tags', tags)
607
+ this._setValue(env, 'tagsHeaderMaxLength', DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH)
608
+ this._setBoolean(env, 'telemetry.enabled', coalesce(
609
+ DD_TRACE_TELEMETRY_ENABLED, // for backward compatibility
610
+ DD_INSTRUMENTATION_TELEMETRY_ENABLED, // to comply with instrumentation telemetry specs
611
+ !(this._isInServerlessEnvironment() || JEST_WORKER_ID)
612
+ ))
613
+ this._setBoolean(env, 'telemetry.debug', DD_TELEMETRY_DEBUG)
614
+ this._setBoolean(env, 'telemetry.dependencyCollection', DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED)
615
+ this._setValue(env, 'telemetry.heartbeatInterval', maybeInt(Math.floor(DD_TELEMETRY_HEARTBEAT_INTERVAL * 1000)))
616
+ this._setBoolean(env, 'telemetry.logCollection', coalesce(DD_TELEMETRY_LOG_COLLECTION_ENABLED, DD_IAST_ENABLED))
617
+ this._setBoolean(env, 'telemetry.metrics', DD_TELEMETRY_METRICS_ENABLED)
618
+ this._setBoolean(env, 'traceId128BitGenerationEnabled', DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED)
619
+ this._setBoolean(env, 'traceId128BitLoggingEnabled', DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED)
816
620
  this._setBoolean(env, 'tracing', DD_TRACING_ENABLED)
621
+ this._setString(env, 'version', DD_VERSION || tags.version)
817
622
  }
818
623
 
819
624
  _applyOptions (options) {
820
625
  const opts = this._options = this._options || {}
821
626
  const tags = {}
822
627
 
823
- options = Object.assign({ ingestion: {} }, options, opts)
628
+ options = this.options = Object.assign({ ingestion: {} }, options, opts)
824
629
 
825
630
  tagger.add(tags, options.tags)
826
631
 
827
- this._setString(opts, 'service', options.service || tags.service)
632
+ this._setValue(opts, 'appsec.blockedTemplateHtml', maybeFile(options.appsec.blockedTemplateHtml))
633
+ this._setValue(opts, 'appsec.blockedTemplateJson', maybeFile(options.appsec.blockedTemplateJson))
634
+ this._setBoolean(opts, 'appsec.enabled', options.appsec.enabled)
635
+ this._setString(opts, 'appsec.obfuscatorKeyRegex', options.appsec.obfuscatorKeyRegex)
636
+ this._setString(opts, 'appsec.obfuscatorValueRegex', options.appsec.obfuscatorValueRegex)
637
+ this._setValue(opts, 'appsec.rateLimit', maybeInt(options.appsec.rateLimit))
638
+ this._setString(opts, 'appsec.rules', options.appsec.rules)
639
+ this._setValue(opts, 'appsec.wafTimeout', maybeInt(options.appsec.wafTimeout))
640
+ this._setBoolean(opts, 'clientIpEnabled', options.clientIpEnabled)
641
+ this._setString(opts, 'clientIpHeader', options.clientIpHeader)
642
+ this._setString(opts, 'dbmPropagationMode', options.dbmPropagationMode)
643
+ if (options.dogstatsd) {
644
+ this._setString(opts, 'dogstatsd.hostname', options.dogstatsd.hostname)
645
+ this._setString(opts, 'dogstatsd.port', options.dogstatsd.port)
646
+ }
647
+ this._setBoolean(opts, 'dsmEnabled', options.dsmEnabled)
828
648
  this._setString(opts, 'env', options.env || tags.env)
829
- this._setString(opts, 'version', options.version || tags.version)
830
- this._setUnit(opts, 'sampleRate', coalesce(options.sampleRate, options.ingestion.sampleRate))
831
- this._setBoolean(opts, 'logInjection', options.logInjection)
649
+ this._setBoolean(opts, 'experimental.enableGetRumData',
650
+ options.experimental && options.experimental.enableGetRumData)
651
+ this._setString(opts, 'experimental.exporter', options.experimental && options.experimental.exporter)
652
+ this._setBoolean(opts, 'experimental.runtimeId', options.experimental && options.experimental.runtimeId)
653
+ this._setValue(opts, 'flushInterval', maybeInt(options.flushInterval))
654
+ this._setValue(opts, 'flushMinSpans', maybeInt(options.flushMinSpans))
832
655
  this._setArray(opts, 'headerTags', options.headerTags)
656
+ this._setString(opts, 'hostname', options.hostname)
657
+ this._setBoolean(opts, 'iast.deduplicationEnabled', options.iastOptions && options.iastOptions.deduplicationEnabled)
658
+ this._setBoolean(opts, 'iast.enabled',
659
+ options.iastOptions && (options.iastOptions === true || options.iastOptions.enabled === true))
660
+ const iastRequestSampling = maybeInt(options.iastOptions?.requestSampling)
661
+ this._setValue(opts, 'iast.maxConcurrentRequests',
662
+ maybeInt(options.iastOptions?.maxConcurrentRequests))
663
+ this._setValue(opts, 'iast.maxContextOperations',
664
+ maybeInt(options.iastOptions && options.iastOptions.maxContextOperations))
665
+ this._setBoolean(opts, 'iast.redactionEnabled', options.iastOptions && options.iastOptions.redactionEnabled)
666
+ this._setString(opts, 'iast.redactionNamePattern', options.iastOptions?.redactionNamePattern)
667
+ this._setString(opts, 'iast.redactionValuePattern', options.iastOptions?.redactionValuePattern)
668
+ if (iastRequestSampling > -1 && iastRequestSampling < 101) {
669
+ this._setValue(opts, 'iast.requestSampling', iastRequestSampling)
670
+ }
671
+ this._setString(opts, 'iast.telemetryVerbosity', options.iastOptions && options.iastOptions.telemetryVerbosity)
672
+ this._setBoolean(opts, 'isCiVisibility', options.isCiVisibility)
673
+ this._setBoolean(opts, 'logInjection', options.logInjection)
674
+ this._setString(opts, 'lookup', options.lookup)
675
+ this._setBoolean(opts, 'openAiLogsEnabled', options.openAiLogsEnabled)
676
+ this._setValue(opts, 'peerServiceMapping', options.peerServiceMapping)
677
+ this._setBoolean(opts, 'plugins', options.plugins)
678
+ this._setString(opts, 'port', options.port)
679
+ this._setBoolean(opts, 'profiling.enabled', options.profiling)
680
+ this._setString(opts, 'protocolVersion', options.protocolVersion)
681
+ if (options.remoteConfig) {
682
+ this._setValue(opts, 'remoteConfig.pollInterval', maybeFloat(options.remoteConfig.pollInterval))
683
+ }
684
+ this._setBoolean(opts, 'reportHostname', options.reportHostname)
685
+ this._setBoolean(opts, 'runtimeMetrics', options.runtimeMetrics)
686
+ this._setUnit(opts, 'sampleRate', coalesce(options.sampleRate, options.ingestion.sampleRate))
687
+ const ingestion = options.ingestion || {}
688
+ this._setValue(opts, 'sampler.rateLimit', coalesce(options.rateLimit, ingestion.rateLimit))
689
+ this._setString(opts, 'service', options.service || tags.service)
690
+ this._setString(opts, 'site', options.site)
691
+ if (options.spanAttributeSchema) {
692
+ this._setString(opts, 'spanAttributeSchema', validateNamingVersion(options.spanAttributeSchema))
693
+ }
694
+ this._setBoolean(opts, 'spanRemoveIntegrationFromService', options.spanRemoveIntegrationFromService)
695
+ this._setBoolean(opts, 'startupLogs', options.startupLogs)
833
696
  this._setTags(opts, 'tags', tags)
697
+ this._setBoolean(opts, 'telemetry.logCollection', options.iastOptions &&
698
+ (options.iastOptions === true || options.iastOptions.enabled === true))
699
+ this._setBoolean(opts, 'traceId128BitGenerationEnabled', options.traceId128BitGenerationEnabled)
700
+ this._setBoolean(opts, 'traceId128BitLoggingEnabled', options.traceId128BitLoggingEnabled)
701
+ this._setString(opts, 'version', options.version || tags.version)
702
+ }
703
+
704
+ _isCiVisibility () {
705
+ return coalesce(
706
+ this.options.isCiVisibility,
707
+ this._defaults['isCiVisibility']
708
+ )
709
+ }
710
+
711
+ _isCiVisibilityItrEnabled () {
712
+ return coalesce(
713
+ process.env.DD_CIVISIBILITY_ITR_ENABLED,
714
+ true
715
+ )
716
+ }
717
+
718
+ _getHostname () {
719
+ const DD_CIVISIBILITY_AGENTLESS_URL = process.env.DD_CIVISIBILITY_AGENTLESS_URL
720
+ const url = DD_CIVISIBILITY_AGENTLESS_URL ? new URL(DD_CIVISIBILITY_AGENTLESS_URL)
721
+ : getAgentUrl(this._getTraceAgentUrl(), this.options)
722
+ const DD_AGENT_HOST = coalesce(
723
+ this.options.hostname,
724
+ process.env.DD_AGENT_HOST,
725
+ process.env.DD_TRACE_AGENT_HOSTNAME,
726
+ '127.0.0.1'
727
+ )
728
+ return DD_AGENT_HOST || (url && url.hostname)
729
+ }
730
+
731
+ _getSpanComputePeerService () {
732
+ const DD_TRACE_SPAN_ATTRIBUTE_SCHEMA = validateNamingVersion(
733
+ coalesce(
734
+ this.options.spanAttributeSchema,
735
+ process.env.DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
736
+ )
737
+ )
738
+
739
+ const peerServiceSet = (
740
+ this.options.hasOwnProperty('spanComputePeerService') ||
741
+ process.env.hasOwnProperty('DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED')
742
+ )
743
+ const peerServiceValue = coalesce(
744
+ this.options.spanComputePeerService,
745
+ process.env.DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED
746
+ )
747
+
748
+ const spanComputePeerService = (
749
+ DD_TRACE_SPAN_ATTRIBUTE_SCHEMA === 'v0'
750
+ // In v0, peer service is computed only if it is explicitly set to true
751
+ ? peerServiceSet && isTrue(peerServiceValue)
752
+ // In >v0, peer service is false only if it is explicitly set to false
753
+ : (peerServiceSet ? !isFalse(peerServiceValue) : true)
754
+ )
755
+
756
+ return spanComputePeerService
757
+ }
758
+
759
+ _isCiVisibilityGitUploadEnabled () {
760
+ return coalesce(
761
+ process.env.DD_CIVISIBILITY_GIT_UPLOAD_ENABLED,
762
+ true
763
+ )
764
+ }
765
+
766
+ _isCiVisibilityManualApiEnabled () {
767
+ return isTrue(coalesce(
768
+ process.env.DD_CIVISIBILITY_MANUAL_API_ENABLED,
769
+ false
770
+ ))
771
+ }
772
+
773
+ _isTraceStatsComputationEnabled () {
774
+ return coalesce(
775
+ this.options.stats,
776
+ process.env.DD_TRACE_STATS_COMPUTATION_ENABLED,
777
+ getIsGCPFunction() || getIsAzureFunctionConsumptionPlan()
778
+ )
779
+ }
780
+
781
+ _getTraceAgentUrl () {
782
+ return coalesce(
783
+ this.options.url,
784
+ process.env.DD_TRACE_AGENT_URL,
785
+ process.env.DD_TRACE_URL,
786
+ null
787
+ )
788
+ }
789
+
790
+ // handles values calculated from a mixture of options and env vars
791
+ _applyCalculated () {
792
+ const calc = this._calculated = {}
793
+
794
+ const {
795
+ DD_CIVISIBILITY_AGENTLESS_URL
796
+ } = process.env
797
+
798
+ if (DD_CIVISIBILITY_AGENTLESS_URL) {
799
+ this._setValue(calc, 'url', new URL(DD_CIVISIBILITY_AGENTLESS_URL))
800
+ } else {
801
+ this._setValue(calc, 'url', getAgentUrl(this._getTraceAgentUrl(), this.options))
802
+ }
803
+ if (this._isCiVisibility()) {
804
+ this._setBoolean(calc, 'isEarlyFlakeDetectionEnabled',
805
+ coalesce(process.env.DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED, true))
806
+ this._setBoolean(calc, 'isIntelligentTestRunnerEnabled', isTrue(this._isCiVisibilityItrEnabled()))
807
+ this._setBoolean(calc, 'isManualApiEnabled', this._isCiVisibilityManualApiEnabled())
808
+ }
809
+ this._setString(calc, 'dogstatsd.hostname', this._getHostname())
810
+ this._setBoolean(calc, 'isGitUploadEnabled',
811
+ calc['isIntelligentTestRunnerEnabled'] && !isFalse(this._isCiVisibilityGitUploadEnabled()))
812
+ this._setBoolean(calc, 'spanComputePeerService', this._getSpanComputePeerService())
813
+ this._setBoolean(calc, 'stats.enabled', this._isTraceStatsComputationEnabled())
834
814
  }
835
815
 
836
816
  _applyRemote (options) {
@@ -889,7 +869,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
889
869
  }
890
870
 
891
871
  _setString (obj, name, value) {
892
- obj[name] = value || undefined // unset for empty strings
872
+ obj[name] = value ? String(value) : undefined // unset for empty strings
893
873
  }
894
874
 
895
875
  _setTags (obj, name, value) {
@@ -907,9 +887,12 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
907
887
  // TODO: Report origin changes and errors to telemetry.
908
888
  // TODO: Deeply merge configurations.
909
889
  // TODO: Move change tracking to telemetry.
890
+ // for telemetry reporting, `name`s in `containers` need to be keys from:
891
+ // eslint-disable-next-line max-len
892
+ // https://github.com/DataDog/dd-go/blob/prod/trace/apps/tracer-telemetry-intake/telemetry-payload/static/config_norm_rules.json
910
893
  _merge () {
911
- const containers = [this._remote, this._options, this._env, this._defaults]
912
- const origins = ['remote_config', 'code', 'env_var', 'default']
894
+ const containers = [this._remote, this._options, this._env, this._calculated, this._defaults]
895
+ const origins = ['remote_config', 'code', 'env_var', 'calculated', 'default']
913
896
  const changes = []
914
897
 
915
898
  for (const name in this._defaults) {
@@ -918,9 +901,10 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
918
901
  const origin = origins[i]
919
902
 
920
903
  if ((container[name] !== null && container[name] !== undefined) || container === this._defaults) {
921
- if (this[name] === container[name] && this.hasOwnProperty(name)) break
904
+ if (get(this, name) === container[name] && has(this, name)) break
922
905
 
923
- const value = this[name] = container[name]
906
+ const value = container[name]
907
+ set(this, name, value)
924
908
 
925
909
  changes.push({ name, value, origin })
926
910
 
@@ -930,11 +914,19 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
930
914
  }
931
915
 
932
916
  this.sampler.sampleRate = this.sampleRate
933
-
934
917
  updateConfig(changes, this)
935
918
  }
936
919
  }
937
920
 
921
+ function maybeInt (number) {
922
+ const parsed = parseInt(number)
923
+ return isNaN(parsed) ? undefined : parsed
924
+ }
925
+ function maybeFloat (number) {
926
+ const parsed = parseFloat(number)
927
+ return isNaN(parsed) ? undefined : parsed
928
+ }
929
+
938
930
  function getAgentUrl (url, options) {
939
931
  if (url) return new URL(url)
940
932