dd-trace 5.40.0 → 5.41.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.
@@ -37,6 +37,7 @@ dev,@eslint/eslintrc,MIT,Copyright OpenJS Foundation and other contributors, <ww
37
37
  dev,@eslint/js,MIT,Copyright OpenJS Foundation and other contributors, <www.openjsf.org>
38
38
  dev,@msgpack/msgpack,ISC,Copyright 2019 The MessagePack Community
39
39
  dev,@stylistic/eslint-plugin-js,MIT,Copyright OpenJS Foundation and other contributors, <www.openjsf.org>
40
+ dev,application-config-path,MIT,Copyright (c) 2015, 2023 Linus Unnebäck
40
41
  dev,autocannon,MIT,Copyright 2016 Matteo Collina
41
42
  dev,aws-sdk,Apache 2.0,Copyright 2012-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
42
43
  dev,axios,MIT,Copyright 2014-present Matt Zabriskie
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "5.40.0",
3
+ "version": "5.41.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -82,7 +82,7 @@
82
82
  "node": ">=18"
83
83
  },
84
84
  "dependencies": {
85
- "@datadog/libdatadog": "^0.4.0",
85
+ "@datadog/libdatadog": "^0.5.0",
86
86
  "@datadog/native-appsec": "8.4.0",
87
87
  "@datadog/native-iast-rewriter": "2.8.0",
88
88
  "@datadog/native-iast-taint-tracking": "3.3.0",
@@ -95,7 +95,7 @@
95
95
  "crypto-randomuuid": "^1.0.0",
96
96
  "dc-polyfill": "^0.1.4",
97
97
  "ignore": "^5.2.4",
98
- "import-in-the-middle": "1.11.2",
98
+ "import-in-the-middle": "1.13.1",
99
99
  "istanbul-lib-coverage": "3.2.0",
100
100
  "jest-docblock": "^29.7.0",
101
101
  "koalas": "^1.0.2",
@@ -122,6 +122,7 @@
122
122
  "@msgpack/msgpack": "^3.0.0-beta3",
123
123
  "@stylistic/eslint-plugin-js": "^3.0.1",
124
124
  "@types/node": "^16.0.0",
125
+ "application-config-path": "^1.0.0",
125
126
  "autocannon": "^4.5.2",
126
127
  "aws-sdk": "^2.1446.0",
127
128
  "axios": "^1.7.4",
@@ -10,9 +10,7 @@ class GraphQLParsePlugin extends TracingPlugin {
10
10
  this.startSpan('graphql.parse', {
11
11
  service: this.config.service,
12
12
  type: 'graphql',
13
- meta: {
14
- 'graphql.source': ''
15
- }
13
+ meta: {}
16
14
  })
17
15
  }
18
16
 
@@ -25,7 +25,10 @@ class MongodbCorePlugin extends DatabasePlugin {
25
25
  'out.port': options.port
26
26
  }
27
27
  })
28
- ops.comment = this.injectDbmComment(span, ops.comment, service)
28
+ const comment = this.injectDbmComment(span, ops.comment, service)
29
+ if (comment) {
30
+ ops.comment = comment
31
+ }
29
32
  }
30
33
 
31
34
  getPeerService (tags) {
@@ -11,7 +11,7 @@ const tagger = require('./tagger')
11
11
  const get = require('../../datadog-core/src/utils/src/get')
12
12
  const has = require('../../datadog-core/src/utils/src/has')
13
13
  const set = require('../../datadog-core/src/utils/src/set')
14
- const { isTrue, isFalse } = require('./util')
14
+ const { isTrue, isFalse, normalizeProfilingEnabledValue } = require('./util')
15
15
  const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('./plugins/util/tags')
16
16
  const { getGitMetadataFromGitProperties, removeUserSensitiveInfo } = require('./git_properties')
17
17
  const { updateConfig } = require('./telemetry')
@@ -236,6 +236,12 @@ function reformatSpanSamplingRules (rules) {
236
236
 
237
237
  class Config {
238
238
  constructor (options = {}) {
239
+ if (!isInServerlessEnvironment()) {
240
+ // Bail out early if we're in a serverless environment, stable config isn't supported
241
+ const StableConfig = require('./config_stable')
242
+ this.stableConfig = new StableConfig()
243
+ }
244
+
239
245
  options = {
240
246
  ...options,
241
247
  appsec: options.appsec != null ? options.appsec : options.experimental?.appsec,
@@ -244,13 +250,24 @@ class Config {
244
250
 
245
251
  // Configure the logger first so it can be used to warn about other configs
246
252
  const logConfig = log.getConfig()
247
- this.debug = logConfig.enabled
253
+ this.debug = log.isEnabled(
254
+ this.stableConfig?.fleetEntries?.DD_TRACE_DEBUG,
255
+ this.stableConfig?.localEntries?.DD_TRACE_DEBUG
256
+ )
248
257
  this.logger = coalesce(options.logger, logConfig.logger)
249
- this.logLevel = coalesce(options.logLevel, logConfig.logLevel)
250
-
258
+ this.logLevel = log.getLogLevel(
259
+ options.logLevel,
260
+ this.stableConfig?.fleetEntries?.DD_TRACE_LOG_LEVEL,
261
+ this.stableConfig?.localEntries?.DD_TRACE_LOG_LEVEL
262
+ )
251
263
  log.use(this.logger)
252
264
  log.toggle(this.debug, this.logLevel)
253
265
 
266
+ // Process stable config warnings, if any
267
+ for (const warning of this.stableConfig?.warnings ?? []) {
268
+ log.warn(warning)
269
+ }
270
+
254
271
  checkIfBothOtelAndDdEnvVarSet()
255
272
 
256
273
  const DD_API_KEY = coalesce(
@@ -337,7 +354,9 @@ class Config {
337
354
  }
338
355
 
339
356
  this._applyDefaults()
357
+ this._applyLocalStableConfig()
340
358
  this._applyEnvironment()
359
+ this._applyFleetStableConfig()
341
360
  this._applyOptions(options)
342
361
  this._applyCalculated()
343
362
  this._applyRemote({})
@@ -576,6 +595,45 @@ class Config {
576
595
  this._setValue(defaults, 'trace.dynamoDb.tablePrimaryKeys', undefined)
577
596
  }
578
597
 
598
+ _applyLocalStableConfig () {
599
+ const obj = setHiddenProperty(this, '_localStableConfig', {})
600
+ this._applyStableConfig(this.stableConfig?.localEntries ?? {}, obj)
601
+ }
602
+
603
+ _applyFleetStableConfig () {
604
+ const obj = setHiddenProperty(this, '_fleetStableConfig', {})
605
+ this._applyStableConfig(this.stableConfig?.fleetEntries ?? {}, obj)
606
+ }
607
+
608
+ _applyStableConfig (config, obj) {
609
+ const {
610
+ DD_APPSEC_ENABLED,
611
+ DD_APPSEC_SCA_ENABLED,
612
+ DD_DATA_STREAMS_ENABLED,
613
+ DD_DYNAMIC_INSTRUMENTATION_ENABLED,
614
+ DD_ENV,
615
+ DD_IAST_ENABLED,
616
+ DD_LOGS_INJECTION,
617
+ DD_PROFILING_ENABLED,
618
+ DD_RUNTIME_METRICS_ENABLED,
619
+ DD_SERVICE,
620
+ DD_VERSION
621
+ } = config
622
+
623
+ this._setBoolean(obj, 'appsec.enabled', DD_APPSEC_ENABLED)
624
+ this._setBoolean(obj, 'appsec.sca.enabled', DD_APPSEC_SCA_ENABLED)
625
+ this._setBoolean(obj, 'dsmEnabled', DD_DATA_STREAMS_ENABLED)
626
+ this._setBoolean(obj, 'dynamicInstrumentation.enabled', DD_DYNAMIC_INSTRUMENTATION_ENABLED)
627
+ this._setString(obj, 'env', DD_ENV)
628
+ this._setBoolean(obj, 'iast.enabled', DD_IAST_ENABLED)
629
+ this._setBoolean(obj, 'logInjection', DD_LOGS_INJECTION)
630
+ const profilingEnabled = normalizeProfilingEnabledValue(DD_PROFILING_ENABLED)
631
+ this._setString(obj, 'profiling.enabled', profilingEnabled)
632
+ this._setBoolean(obj, 'runtimeMetrics', DD_RUNTIME_METRICS_ENABLED)
633
+ this._setString(obj, 'service', DD_SERVICE)
634
+ this._setString(obj, 'version', DD_VERSION)
635
+ }
636
+
579
637
  _applyEnvironment () {
580
638
  const {
581
639
  AWS_LAMBDA_FUNCTION_NAME,
@@ -715,8 +773,8 @@ class Config {
715
773
  const env = setHiddenProperty(this, '_env', {})
716
774
  setHiddenProperty(this, '_envUnprocessed', {})
717
775
 
718
- tagger.add(tags, OTEL_RESOURCE_ATTRIBUTES, true)
719
- tagger.add(tags, DD_TAGS)
776
+ tagger.add(tags, parseSpaceSeparatedTags(handleOtel(OTEL_RESOURCE_ATTRIBUTES)))
777
+ tagger.add(tags, parseSpaceSeparatedTags(DD_TAGS))
720
778
  tagger.add(tags, DD_TRACE_TAGS)
721
779
  tagger.add(tags, DD_TRACE_GLOBAL_TAGS)
722
780
 
@@ -831,16 +889,13 @@ class Config {
831
889
  this._envUnprocessed.peerServiceMapping = DD_TRACE_PEER_SERVICE_MAPPING
832
890
  }
833
891
  this._setString(env, 'port', DD_TRACE_AGENT_PORT)
834
- const profilingEnabledEnv = coalesce(
835
- DD_EXPERIMENTAL_PROFILING_ENABLED,
836
- DD_PROFILING_ENABLED,
837
- this._isInServerlessEnvironment() ? 'false' : undefined
892
+ const profilingEnabled = normalizeProfilingEnabledValue(
893
+ coalesce(
894
+ DD_EXPERIMENTAL_PROFILING_ENABLED,
895
+ DD_PROFILING_ENABLED,
896
+ this._isInServerlessEnvironment() ? 'false' : undefined
897
+ )
838
898
  )
839
- const profilingEnabled = isTrue(profilingEnabledEnv)
840
- ? 'true'
841
- : isFalse(profilingEnabledEnv)
842
- ? 'false'
843
- : profilingEnabledEnv === 'auto' ? 'auto' : undefined
844
899
  this._setString(env, 'profiling.enabled', profilingEnabled)
845
900
  this._setString(env, 'profiling.exporters', DD_PROFILING_EXPORTERS)
846
901
  this._setBoolean(env, 'profiling.sourceMap', DD_PROFILING_SOURCE_MAP && !isFalse(DD_PROFILING_SOURCE_MAP))
@@ -1347,9 +1402,33 @@ class Config {
1347
1402
  // eslint-disable-next-line @stylistic/js/max-len
1348
1403
  // https://github.com/DataDog/dd-go/blob/prod/trace/apps/tracer-telemetry-intake/telemetry-payload/static/config_norm_rules.json
1349
1404
  _merge () {
1350
- const containers = [this._remote, this._options, this._env, this._calculated, this._defaults]
1351
- const origins = ['remote_config', 'code', 'env_var', 'calculated', 'default']
1352
- const unprocessedValues = [this._remoteUnprocessed, this._optsUnprocessed, this._envUnprocessed, {}, {}]
1405
+ const containers = [
1406
+ this._remote,
1407
+ this._options,
1408
+ this._fleetStableConfig,
1409
+ this._env,
1410
+ this._localStableConfig,
1411
+ this._calculated,
1412
+ this._defaults
1413
+ ]
1414
+ const origins = [
1415
+ 'remote_config',
1416
+ 'code',
1417
+ 'fleet_stable_config',
1418
+ 'env_var',
1419
+ 'local_stable_config',
1420
+ 'calculated',
1421
+ 'default'
1422
+ ]
1423
+ const unprocessedValues = [
1424
+ this._remoteUnprocessed,
1425
+ this._optsUnprocessed,
1426
+ {},
1427
+ this._envUnprocessed,
1428
+ {},
1429
+ {},
1430
+ {}
1431
+ ]
1353
1432
  const changes = []
1354
1433
 
1355
1434
  for (const name in this._defaults) {
@@ -1394,6 +1473,21 @@ class Config {
1394
1473
  }
1395
1474
  }
1396
1475
 
1476
+ function handleOtel (tagString) {
1477
+ return tagString
1478
+ ?.replace(/(^|,)deployment\.environment=/, '$1env:')
1479
+ .replace(/(^|,)service\.name=/, '$1service:')
1480
+ .replace(/(^|,)service\.version=/, '$1version:')
1481
+ .replace(/=/g, ':')
1482
+ }
1483
+
1484
+ function parseSpaceSeparatedTags (tagString) {
1485
+ if (tagString && !tagString.includes(',')) {
1486
+ tagString = tagString.replace(/\s+/g, ',')
1487
+ }
1488
+ return tagString
1489
+ }
1490
+
1397
1491
  function maybeInt (number) {
1398
1492
  const parsed = parseInt(number)
1399
1493
  return isNaN(parsed) ? undefined : parsed
@@ -0,0 +1,100 @@
1
+ const os = require('os')
2
+ const fs = require('fs')
3
+
4
+ class StableConfig {
5
+ constructor () {
6
+ this.warnings = [] // Logger hasn't been initialized yet, so we can't use log.warn
7
+ this.localEntries = {}
8
+ this.fleetEntries = {}
9
+ this.wasm_loaded = false
10
+
11
+ const { localConfigPath, fleetConfigPath } = this._getStableConfigPaths()
12
+ if (!fs.existsSync(localConfigPath) && !fs.existsSync(fleetConfigPath)) {
13
+ // Bail out early if files don't exist to avoid unnecessary library loading
14
+ return
15
+ }
16
+
17
+ const localConfig = this._readConfigFromPath(localConfigPath)
18
+ const fleetConfig = this._readConfigFromPath(fleetConfigPath)
19
+ if (!localConfig && !fleetConfig) {
20
+ // Bail out early if files are empty or we can't read them to avoid unnecessary library loading
21
+ return
22
+ }
23
+
24
+ // Note: we don't enforce loading because there may be cases where the library is not available and we
25
+ // want to avoid breaking the application. In those cases, we will not have the file-based configuration.
26
+ let libdatadog
27
+ try {
28
+ libdatadog = require('@datadog/libdatadog')
29
+ this.wasm_loaded = true
30
+ } catch (e) {
31
+ this.warnings.push('Can\'t load libdatadog library')
32
+ return
33
+ }
34
+
35
+ const libconfig = libdatadog.maybeLoad('library_config')
36
+ if (libconfig === undefined) {
37
+ this.warnings.push('Can\'t load library_config library')
38
+ return
39
+ }
40
+
41
+ try {
42
+ const configurator = new libconfig.JsConfigurator()
43
+ configurator.set_envp(Object.entries(process.env).map(([key, value]) => `${key}=${value}`))
44
+ configurator.set_args(process.argv)
45
+ configurator.get_configuration(localConfig.toString(), fleetConfig.toString()).forEach((entry) => {
46
+ if (entry.source === 'local_stable_config') {
47
+ this.localEntries[entry.name] = entry.value
48
+ } else if (entry.source === 'fleet_stable_config') {
49
+ this.fleetEntries[entry.name] = entry.value
50
+ }
51
+ })
52
+ } catch (e) {
53
+ this.warnings.push(`Error parsing configuration from file: ${e.message}`)
54
+ }
55
+ }
56
+
57
+ _readConfigFromPath (path) {
58
+ try {
59
+ return fs.readFileSync(path, 'utf8')
60
+ } catch (err) {
61
+ if (err.code !== 'ENOENT') {
62
+ this.warnings.push(`Error reading config file at ${path}. ${err.code}: ${err.message}`)
63
+ }
64
+ return '' // Always return a string to avoid undefined.toString() errors
65
+ }
66
+ }
67
+
68
+ _getStableConfigPaths () {
69
+ let localConfigPath = ''
70
+ let fleetConfigPath = ''
71
+ switch (os.type().toLowerCase()) {
72
+ case 'linux':
73
+ localConfigPath = '/etc/datadog-agent/application_monitoring.yaml'
74
+ fleetConfigPath = '/etc/datadog-agent/managed/datadog-agent/stable/application_monitoring.yaml'
75
+ break
76
+ case 'darwin':
77
+ localConfigPath = '/opt/datadog-agent/etc/application_monitoring.yaml'
78
+ fleetConfigPath = '/opt/datadog-agent/etc/managed/datadog-agent/stable/application_monitoring.yaml'
79
+ break
80
+ case 'win32':
81
+ localConfigPath = 'C:\\ProgramData\\Datadog\\application_monitoring.yaml'
82
+ fleetConfigPath = 'C:\\ProgramData\\Datadog\\managed\\datadog-agent\\stable\\application_monitoring.yaml'
83
+ break
84
+ default:
85
+ break
86
+ }
87
+
88
+ // Allow overriding the paths for testing
89
+ if (process.env.DD_TEST_LOCAL_CONFIG_PATH !== undefined) {
90
+ localConfigPath = process.env.DD_TEST_LOCAL_CONFIG_PATH
91
+ }
92
+ if (process.env.DD_TEST_FLEET_CONFIG_PATH !== undefined) {
93
+ fleetConfigPath = process.env.DD_TEST_FLEET_CONFIG_PATH
94
+ }
95
+
96
+ return { localConfigPath, fleetConfigPath }
97
+ }
98
+ }
99
+
100
+ module.exports = StableConfig
@@ -212,7 +212,6 @@ function extractError (trace, error) {
212
212
  function addTag (meta, metrics, key, value, nested) {
213
213
  switch (typeof value) {
214
214
  case 'string':
215
- if (!value) break
216
215
  meta[key] = value
217
216
  break
218
217
  case 'number':
@@ -2,6 +2,7 @@
2
2
 
3
3
  const log = require('../../log')
4
4
  const { storage: llmobsStorage } = require('../storage')
5
+ const telemetry = require('../telemetry')
5
6
 
6
7
  const TracingPlugin = require('../../plugins/tracing')
7
8
  const LLMObsTagger = require('../tagger')
@@ -36,6 +37,8 @@ class LLMObsPlugin extends TracingPlugin {
36
37
  // register options may not be set for operations we do not trace with llmobs
37
38
  // ie OpenAI fine tuning jobs, file jobs, etc.
38
39
  if (registerOptions) {
40
+ telemetry.incrementLLMObsSpanStartCount({ autoinstrumented: true, integration: this.constructor.id })
41
+
39
42
  ctx.llmobs = {} // initialize context-based namespace
40
43
  llmobsStorage.enterWith({ span })
41
44
  ctx.llmobs.parent = parent
@@ -1,6 +1,7 @@
1
1
  const BaseLLMObsPlugin = require('./base')
2
2
  const { storage } = require('../../../../datadog-core')
3
3
  const llmobsStore = storage('llmobs')
4
+ const telemetry = require('../telemetry')
4
5
 
5
6
  const {
6
7
  extractRequestParams,
@@ -46,6 +47,8 @@ class BedrockRuntimeLLMObsPlugin extends BaseLLMObsPlugin {
46
47
  }
47
48
 
48
49
  setLLMObsTags ({ request, span, response, modelProvider, modelName }) {
50
+ telemetry.incrementLLMObsSpanStartCount({ autoinstrumented: true, integration: 'bedrock' })
51
+
49
52
  const parent = llmobsStore.getStore()?.span
50
53
  this._tagger.registerLLMObsSpan(span, {
51
54
  parent,
@@ -21,6 +21,7 @@ const LlmHandler = require('./handlers/llm')
21
21
  const EmbeddingHandler = require('./handlers/embedding')
22
22
 
23
23
  class LangChainLLMObsPlugin extends LLMObsPlugin {
24
+ static get id () { return 'langchain' }
24
25
  static get prefix () {
25
26
  return 'tracing:apm:langchain:invoke'
26
27
  }
@@ -3,6 +3,7 @@
3
3
  const LLMObsPlugin = require('./base')
4
4
 
5
5
  class OpenAiLLMObsPlugin extends LLMObsPlugin {
6
+ static get id () { return 'openai' }
6
7
  static get prefix () {
7
8
  return 'tracing:apm:openai:request'
8
9
  }
@@ -14,6 +14,7 @@ const Span = require('../opentracing/span')
14
14
 
15
15
  const tracerVersion = require('../../../../package.json').version
16
16
  const logger = require('../log')
17
+ const telemetry = require('./telemetry')
17
18
 
18
19
  const LLMObsTagger = require('./tagger')
19
20
 
@@ -88,6 +89,8 @@ class LLMObs extends NoopLLMObs {
88
89
 
89
90
  const kind = validateKind(options.kind) // will throw if kind is undefined or not an expected kind
90
91
 
92
+ telemetry.incrementLLMObsSpanStartCount({ autoinstrumented: false, kind })
93
+
91
94
  // name is required for spans generated with `trace`
92
95
  // while `kind` is required, this should never throw (as otherwise it would have thrown above)
93
96
  const name = options.name || kind
@@ -133,6 +136,8 @@ class LLMObs extends NoopLLMObs {
133
136
  const llmobs = this
134
137
 
135
138
  function wrapped () {
139
+ telemetry.incrementLLMObsSpanStartCount({ autoinstrumented: false, kind })
140
+
136
141
  const span = llmobs._tracer.scope().active()
137
142
  const fnArgs = arguments
138
143
 
@@ -0,0 +1,12 @@
1
+ 'use strict'
2
+
3
+ const telemetryMetrics = require('../telemetry/metrics')
4
+ const llmobsMetrics = telemetryMetrics.manager.namespace('mlobs')
5
+
6
+ function incrementLLMObsSpanStartCount (tags, value = 1) {
7
+ llmobsMetrics.count('span.start', tags).inc(value)
8
+ }
9
+
10
+ module.exports = {
11
+ incrementLLMObsSpanStartCount
12
+ }
@@ -105,23 +105,36 @@ const log = {
105
105
 
106
106
  deprecate (code, message) {
107
107
  return this._deprecate(code, message)
108
+ },
109
+
110
+ isEnabled (fleetStableConfigValue = undefined, localStableConfigValue = undefined) {
111
+ return isTrue(coalesce(
112
+ fleetStableConfigValue,
113
+ process.env?.DD_TRACE_DEBUG,
114
+ process.env?.OTEL_LOG_LEVEL === 'debug' || undefined,
115
+ localStableConfigValue,
116
+ config.enabled
117
+ ))
118
+ },
119
+
120
+ getLogLevel (
121
+ optionsValue = undefined,
122
+ fleetStableConfigValue = undefined,
123
+ localStableConfigValue = undefined
124
+ ) {
125
+ return coalesce(
126
+ optionsValue,
127
+ fleetStableConfigValue,
128
+ process.env?.DD_TRACE_LOG_LEVEL,
129
+ process.env?.OTEL_LOG_LEVEL,
130
+ localStableConfigValue,
131
+ config.logLevel
132
+ )
108
133
  }
109
134
  }
110
135
 
111
136
  log.reset()
112
137
 
113
- const enabled = isTrue(coalesce(
114
- process.env.DD_TRACE_DEBUG,
115
- process.env.OTEL_LOG_LEVEL === 'debug',
116
- config.enabled
117
- ))
118
-
119
- const logLevel = coalesce(
120
- process.env.DD_TRACE_LOG_LEVEL,
121
- process.env.OTEL_LOG_LEVEL,
122
- config.logLevel
123
- )
124
-
125
- log.toggle(enabled, logLevel)
138
+ log.toggle(log.isEnabled(), log.getLogLevel())
126
139
 
127
140
  module.exports = log
@@ -328,22 +328,34 @@ function getGitMetadata (ciMetadata) {
328
328
  committerDate
329
329
  ] = sanitizedExec('git', ['show', '-s', '--format=%an,%ae,%aI,%cn,%ce,%cI']).split(',')
330
330
 
331
- return {
332
- [GIT_REPOSITORY_URL]:
333
- filterSensitiveInfoFromRepository(repositoryUrl || sanitizedExec('git', ['ls-remote', '--get-url'])),
331
+ const tags = {
334
332
  [GIT_COMMIT_MESSAGE]:
335
333
  commitMessage || sanitizedExec('git', ['show', '-s', '--format=%s']),
336
- [GIT_COMMIT_AUTHOR_DATE]: authorDate,
337
- [GIT_COMMIT_AUTHOR_NAME]: ciAuthorName || authorName,
338
- [GIT_COMMIT_AUTHOR_EMAIL]: ciAuthorEmail || authorEmail,
339
- [GIT_COMMIT_COMMITTER_DATE]: committerDate,
340
- [GIT_COMMIT_COMMITTER_NAME]: committerName,
341
- [GIT_COMMIT_COMMITTER_EMAIL]: committerEmail,
342
334
  [GIT_BRANCH]: branch || sanitizedExec('git', ['rev-parse', '--abbrev-ref', 'HEAD']),
343
335
  [GIT_COMMIT_SHA]: commitSHA || sanitizedExec('git', ['rev-parse', 'HEAD']),
344
- [GIT_TAG]: tag,
345
336
  [CI_WORKSPACE_PATH]: ciWorkspacePath || sanitizedExec('git', ['rev-parse', '--show-toplevel'])
346
337
  }
338
+
339
+ const entries = [
340
+ GIT_REPOSITORY_URL,
341
+ filterSensitiveInfoFromRepository(repositoryUrl || sanitizedExec('git', ['ls-remote', '--get-url'])),
342
+ GIT_COMMIT_AUTHOR_DATE, authorDate,
343
+ GIT_COMMIT_AUTHOR_NAME, ciAuthorName || authorName,
344
+ GIT_COMMIT_AUTHOR_EMAIL, ciAuthorEmail || authorEmail,
345
+ GIT_COMMIT_COMMITTER_DATE, committerDate,
346
+ GIT_COMMIT_COMMITTER_NAME, committerName,
347
+ GIT_COMMIT_COMMITTER_EMAIL, committerEmail,
348
+ GIT_TAG, tag
349
+ ]
350
+
351
+ for (let i = 0; i < entries.length; i += 2) {
352
+ const value = entries[i + 1]
353
+ if (value) {
354
+ tags[entries[i]] = value
355
+ }
356
+ }
357
+
358
+ return tags
347
359
  }
348
360
 
349
361
  module.exports = {
@@ -475,8 +475,9 @@ function addRequestTags (context, spanType) {
475
475
  function addResponseTags (context) {
476
476
  const { req, res, paths, span, inferredProxySpan } = context
477
477
 
478
- if (paths.length > 0) {
479
- span.setTag(HTTP_ROUTE, paths.join(''))
478
+ const route = paths.join('')
479
+ if (route) {
480
+ span.setTag(HTTP_ROUTE, route)
480
481
  }
481
482
 
482
483
  span.addTags({
@@ -6,13 +6,7 @@ const ERROR_MESSAGE = constants.ERROR_MESSAGE
6
6
  const ERROR_STACK = constants.ERROR_STACK
7
7
  const ERROR_TYPE = constants.ERROR_TYPE
8
8
 
9
- const otelTagMap = {
10
- 'deployment.environment': 'env',
11
- 'service.name': 'service',
12
- 'service.version': 'version'
13
- }
14
-
15
- function add (carrier, keyValuePairs, parseOtelTags = false) {
9
+ function add (carrier, keyValuePairs) {
16
10
  if (!carrier || !keyValuePairs) return
17
11
 
18
12
  if (Array.isArray(keyValuePairs)) {
@@ -22,14 +16,13 @@ function add (carrier, keyValuePairs, parseOtelTags = false) {
22
16
  if (typeof keyValuePairs === 'string') {
23
17
  const segments = keyValuePairs.split(',')
24
18
  for (const segment of segments) {
25
- const separatorIndex = parseOtelTags ? segment.indexOf('=') : segment.indexOf(':')
26
- if (separatorIndex === -1) continue
27
-
28
- let key = segment.slice(0, separatorIndex)
29
- const value = segment.slice(separatorIndex + 1)
19
+ const separatorIndex = segment.indexOf(':')
30
20
 
31
- if (parseOtelTags && key in otelTagMap) {
32
- key = otelTagMap[key]
21
+ let value = ''
22
+ let key = segment
23
+ if (separatorIndex !== -1) {
24
+ key = segment.slice(0, separatorIndex)
25
+ value = segment.slice(separatorIndex + 1)
33
26
  }
34
27
 
35
28
  carrier[key.trim()] = value.trim()
@@ -79,11 +79,20 @@ function hasOwn (object, prop) {
79
79
  return Object.prototype.hasOwnProperty.call(object, prop)
80
80
  }
81
81
 
82
+ function normalizeProfilingEnabledValue (configValue) {
83
+ return isTrue(configValue)
84
+ ? 'true'
85
+ : isFalse(configValue)
86
+ ? 'false'
87
+ : configValue === 'auto' ? 'auto' : undefined
88
+ }
89
+
82
90
  module.exports = {
83
91
  isTrue,
84
92
  isFalse,
85
93
  isError,
86
94
  globMatch,
87
95
  calculateDDBasePath,
88
- hasOwn
96
+ hasOwn,
97
+ normalizeProfilingEnabledValue
89
98
  }