dd-trace 3.19.0 → 3.21.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 (82) hide show
  1. package/index.d.ts +8 -1
  2. package/package.json +5 -4
  3. package/packages/datadog-instrumentations/src/grpc/client.js +9 -5
  4. package/packages/datadog-instrumentations/src/grpc/server.js +8 -4
  5. package/packages/datadog-instrumentations/src/helpers/register.js +4 -0
  6. package/packages/datadog-instrumentations/src/jest.js +20 -17
  7. package/packages/datadog-instrumentations/src/mocha.js +8 -4
  8. package/packages/datadog-instrumentations/src/next.js +6 -1
  9. package/packages/datadog-instrumentations/src/pg.js +3 -4
  10. package/packages/datadog-instrumentations/src/playwright.js +11 -1
  11. package/packages/datadog-plugin-amqp10/src/consumer.js +3 -1
  12. package/packages/datadog-plugin-amqp10/src/producer.js +3 -1
  13. package/packages/datadog-plugin-amqplib/src/client.js +3 -4
  14. package/packages/datadog-plugin-amqplib/src/consumer.js +3 -1
  15. package/packages/datadog-plugin-amqplib/src/producer.js +3 -1
  16. package/packages/datadog-plugin-aws-sdk/src/base.js +3 -0
  17. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +2 -1
  18. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +4 -2
  19. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +4 -3
  20. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -1
  21. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -0
  22. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +2 -1
  23. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +2 -1
  24. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +8 -1
  25. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +7 -1
  26. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +3 -4
  27. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +3 -1
  28. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +3 -1
  29. package/packages/datadog-plugin-http/src/client.js +2 -1
  30. package/packages/datadog-plugin-http2/src/client.js +2 -1
  31. package/packages/datadog-plugin-jest/src/util.js +10 -1
  32. package/packages/datadog-plugin-kafkajs/src/consumer.js +6 -1
  33. package/packages/datadog-plugin-kafkajs/src/producer.js +3 -1
  34. package/packages/datadog-plugin-pg/src/index.js +5 -5
  35. package/packages/datadog-plugin-rhea/src/consumer.js +3 -1
  36. package/packages/datadog-plugin-rhea/src/producer.js +5 -1
  37. package/packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js +2 -1
  38. package/packages/dd-trace/src/appsec/iast/analyzers/ldap-injection-analyzer.js +2 -1
  39. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +22 -5
  40. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +40 -4
  41. package/packages/dd-trace/src/appsec/iast/analyzers/weak-cipher-analyzer.js +2 -1
  42. package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +2 -1
  43. package/packages/dd-trace/src/appsec/iast/index.js +1 -1
  44. package/packages/dd-trace/src/appsec/iast/path-line.js +2 -1
  45. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/range-utils.js +37 -0
  46. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +29 -0
  47. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js +35 -0
  48. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +95 -0
  49. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +144 -0
  50. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +113 -0
  51. package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +8 -0
  52. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +4 -76
  53. package/packages/dd-trace/src/config.js +59 -25
  54. package/packages/dd-trace/src/constants.js +3 -1
  55. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +14 -4
  56. package/packages/dd-trace/src/git_metadata_tagger.js +17 -0
  57. package/packages/dd-trace/src/git_properties.js +32 -0
  58. package/packages/dd-trace/src/plugin_manager.js +0 -2
  59. package/packages/dd-trace/src/plugins/client.js +2 -3
  60. package/packages/dd-trace/src/plugins/consumer.js +2 -17
  61. package/packages/dd-trace/src/plugins/incoming.js +7 -0
  62. package/packages/dd-trace/src/plugins/{outbound.js → outgoing.js} +2 -2
  63. package/packages/dd-trace/src/plugins/producer.js +2 -17
  64. package/packages/dd-trace/src/plugins/server.js +2 -2
  65. package/packages/dd-trace/src/plugins/tracing.js +0 -11
  66. package/packages/dd-trace/src/plugins/util/ci.js +62 -7
  67. package/packages/dd-trace/src/plugins/util/tags.js +5 -1
  68. package/packages/dd-trace/src/plugins/util/test.js +34 -17
  69. package/packages/dd-trace/src/profiling/constants.js +0 -1
  70. package/packages/dd-trace/src/profiling/profilers/space.js +1 -3
  71. package/packages/dd-trace/src/proxy.js +4 -0
  72. package/packages/dd-trace/src/serverless.js +25 -0
  73. package/packages/dd-trace/src/span_processor.js +3 -0
  74. package/packages/dd-trace/src/telemetry/send-data.js +13 -3
  75. package/packages/dd-trace/src/tracer.js +3 -2
  76. package/version.js +9 -0
  77. package/packages/dd-trace/src/plugins/inbound.js +0 -7
  78. package/packages/dd-trace/src/service-naming/index.js +0 -41
  79. package/packages/dd-trace/src/service-naming/schemas/definition.js +0 -28
  80. package/packages/dd-trace/src/service-naming/schemas/index.js +0 -6
  81. package/packages/dd-trace/src/service-naming/schemas/v0.js +0 -66
  82. package/packages/dd-trace/src/service-naming/schemas/v1.js +0 -58
@@ -0,0 +1,113 @@
1
+ const sensitiveHandler = require('./evidence-redaction/sensitive-handler')
2
+
3
+ class VulnerabilityFormatter {
4
+ constructor () {
5
+ this._redactVulnearbilities = true
6
+ }
7
+
8
+ setRedactVulnerabilities (shouldRedactVulnerabilities) {
9
+ this._redactVulnearbilities = shouldRedactVulnerabilities
10
+ }
11
+
12
+ extractSourcesFromVulnerability (vulnerability) {
13
+ if (!vulnerability.evidence.ranges) {
14
+ return []
15
+ }
16
+ return vulnerability.evidence.ranges.map(range => (
17
+ {
18
+ origin: range.iinfo.type,
19
+ name: range.iinfo.parameterName,
20
+ value: range.iinfo.parameterValue
21
+ }
22
+ ))
23
+ }
24
+
25
+ getRedactedValueParts (type, evidence, sourcesIndexes, sources) {
26
+ const scrubbingResult = sensitiveHandler.scrubEvidence(type, evidence, sourcesIndexes, sources)
27
+ if (scrubbingResult) {
28
+ const { redactedValueParts, redactedSources } = scrubbingResult
29
+ redactedSources.forEach(i => {
30
+ delete sources[i].value
31
+ sources[i].redacted = true
32
+ })
33
+ return { valueParts: redactedValueParts }
34
+ }
35
+
36
+ return this.getUnredactedValueParts(evidence, sourcesIndexes)
37
+ }
38
+
39
+ getUnredactedValueParts (evidence, sourcesIndexes) {
40
+ const valueParts = []
41
+ let fromIndex = 0
42
+ evidence.ranges.forEach((range, rangeIndex) => {
43
+ if (fromIndex < range.start) {
44
+ valueParts.push({ value: evidence.value.substring(fromIndex, range.start) })
45
+ }
46
+ valueParts.push({ value: evidence.value.substring(range.start, range.end), source: sourcesIndexes[rangeIndex] })
47
+ fromIndex = range.end
48
+ })
49
+ if (fromIndex < evidence.value.length) {
50
+ valueParts.push({ value: evidence.value.substring(fromIndex) })
51
+ }
52
+ return { valueParts }
53
+ }
54
+
55
+ formatEvidence (type, evidence, sourcesIndexes, sources) {
56
+ if (!evidence.ranges) {
57
+ return { value: evidence.value }
58
+ }
59
+
60
+ return this._redactVulnearbilities
61
+ ? this.getRedactedValueParts(type, evidence, sourcesIndexes, sources)
62
+ : this.getUnredactedValueParts(evidence, sourcesIndexes)
63
+ }
64
+
65
+ formatVulnerability (vulnerability, sourcesIndexes, sources) {
66
+ const formattedVulnerability = {
67
+ type: vulnerability.type,
68
+ hash: vulnerability.hash,
69
+ evidence: this.formatEvidence(vulnerability.type, vulnerability.evidence, sourcesIndexes, sources),
70
+ location: {
71
+ spanId: vulnerability.location.spanId
72
+ }
73
+ }
74
+ if (vulnerability.location.path) {
75
+ formattedVulnerability.location.path = vulnerability.location.path
76
+ }
77
+ if (vulnerability.location.line) {
78
+ formattedVulnerability.location.line = vulnerability.location.line
79
+ }
80
+ return formattedVulnerability
81
+ }
82
+
83
+ toJson (vulnerabilitiesToFormat) {
84
+ const sources = []
85
+
86
+ const vulnerabilities = vulnerabilitiesToFormat.map(vulnerability => {
87
+ const vulnerabilitySources = this.extractSourcesFromVulnerability(vulnerability)
88
+ const sourcesIndexes = []
89
+ vulnerabilitySources.forEach((source) => {
90
+ let sourceIndex = sources.findIndex(
91
+ existingSource =>
92
+ existingSource.origin === source.origin &&
93
+ existingSource.name === source.name &&
94
+ existingSource.value === source.value
95
+ )
96
+ if (sourceIndex === -1) {
97
+ sourceIndex = sources.length
98
+ sources.push(source)
99
+ }
100
+ sourcesIndexes.push(sourceIndex)
101
+ })
102
+
103
+ return this.formatVulnerability(vulnerability, sourcesIndexes, sources)
104
+ })
105
+
106
+ return {
107
+ sources,
108
+ vulnerabilities
109
+ }
110
+ }
111
+ }
112
+
113
+ module.exports = new VulnerabilityFormatter()
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ WEAK_HASH: 'WEAK_HASH',
3
+ WEAK_CIPHER: 'WEAK_CIPHER',
4
+ SQL_INJECTION: 'SQL_INJECTION',
5
+ PATH_TRAVERSAL: 'PATH_TRAVERSAL',
6
+ COMMAND_INJECTION: 'COMMAND_INJECTION',
7
+ LDAP_INJECTION: 'LDAP_INJECTION'
8
+ }
@@ -1,5 +1,6 @@
1
1
  const { MANUAL_KEEP } = require('../../../../../ext/tags')
2
2
  const LRU = require('lru-cache')
3
+ const vulnerabilitiesFormatter = require('./vulnerabilities-formatter')
3
4
  const VULNERABILITIES_KEY = 'vulnerabilities'
4
5
  const IAST_JSON_TAG_KEY = '_dd.iast.json'
5
6
  const VULNERABILITY_HASHES_MAX_SIZE = 1000
@@ -60,57 +61,6 @@ function isValidVulnerability (vulnerability) {
60
61
  vulnerability.location && vulnerability.location.spanId
61
62
  }
62
63
 
63
- function formatEvidence (evidence, sourcesIndexes) {
64
- if (!evidence.ranges) {
65
- return { value: evidence.value }
66
- }
67
-
68
- const valueParts = []
69
- let fromIndex = 0
70
- evidence.ranges.forEach((range, rangeIndex) => {
71
- if (fromIndex < range.start) {
72
- valueParts.push({ value: evidence.value.substring(fromIndex, range.start) })
73
- }
74
- valueParts.push({ value: evidence.value.substring(range.start, range.end), source: sourcesIndexes[rangeIndex] })
75
- fromIndex = range.end
76
- })
77
- if (fromIndex < evidence.value.length) {
78
- valueParts.push({ value: evidence.value.substring(fromIndex) })
79
- }
80
- return { valueParts }
81
- }
82
-
83
- function extractSourcesFromVulnerability (vulnerability) {
84
- if (!vulnerability.evidence.ranges) {
85
- return []
86
- }
87
- return vulnerability.evidence.ranges.map(range => (
88
- {
89
- origin: range.iinfo.type,
90
- name: range.iinfo.parameterName,
91
- value: range.iinfo.parameterValue
92
- }
93
- ))
94
- }
95
-
96
- function jsonVulnerabilityFromVulnerability (vulnerability, sourcesIndexes) {
97
- const jsonVulnerability = {
98
- type: vulnerability.type,
99
- hash: vulnerability.hash,
100
- evidence: formatEvidence(vulnerability.evidence, sourcesIndexes),
101
- location: {
102
- spanId: vulnerability.location.spanId
103
- }
104
- }
105
- if (vulnerability.location.path) {
106
- jsonVulnerability.location.path = vulnerability.location.path
107
- }
108
- if (vulnerability.location.line) {
109
- jsonVulnerability.location.line = vulnerability.location.line
110
- }
111
- return jsonVulnerability
112
- }
113
-
114
64
  function sendVulnerabilities (vulnerabilities, rootSpan) {
115
65
  if (vulnerabilities && vulnerabilities.length) {
116
66
  let span = rootSpan
@@ -124,31 +74,8 @@ function sendVulnerabilities (vulnerabilities, rootSpan) {
124
74
  }
125
75
 
126
76
  if (span && span.addTags) {
127
- const jsonToSend = {
128
- sources: [],
129
- vulnerabilities: []
130
- }
131
-
132
- deduplicateVulnerabilities(vulnerabilities).forEach((vulnerability) => {
133
- if (isValidVulnerability(vulnerability)) {
134
- const sourcesIndexes = []
135
- const vulnerabilitySources = extractSourcesFromVulnerability(vulnerability)
136
- vulnerabilitySources.forEach((source) => {
137
- let sourceIndex = jsonToSend.sources.findIndex(
138
- existingSource =>
139
- existingSource.origin === source.origin &&
140
- existingSource.name === source.name &&
141
- existingSource.value === source.value
142
- )
143
- if (sourceIndex === -1) {
144
- sourceIndex = jsonToSend.sources.length
145
- jsonToSend.sources.push(source)
146
- }
147
- sourcesIndexes.push(sourceIndex)
148
- })
149
- jsonToSend.vulnerabilities.push(jsonVulnerabilityFromVulnerability(vulnerability, sourcesIndexes))
150
- }
151
- })
77
+ const validAndDedupVulnerabilities = deduplicateVulnerabilities(vulnerabilities).filter(isValidVulnerability)
78
+ const jsonToSend = vulnerabilitiesFormatter.toJson(validAndDedupVulnerabilities)
152
79
 
153
80
  if (jsonToSend.vulnerabilities.length > 0) {
154
81
  const tags = {}
@@ -194,6 +121,7 @@ function deduplicateVulnerabilities (vulnerabilities) {
194
121
 
195
122
  function start (config, _tracer) {
196
123
  deduplicationEnabled = config.iast.deduplicationEnabled
124
+ vulnerabilitiesFormatter.setRedactVulnerabilities(config.iast.redactionEnabled)
197
125
  if (deduplicationEnabled) {
198
126
  startClearCacheTimer()
199
127
  }
@@ -2,13 +2,15 @@
2
2
 
3
3
  const fs = require('fs')
4
4
  const os = require('os')
5
+ const uuid = require('crypto-randomuuid')
5
6
  const URL = require('url').URL
6
7
  const log = require('./log')
7
8
  const pkg = require('./pkg')
8
9
  const coalesce = require('koalas')
9
10
  const tagger = require('./tagger')
10
11
  const { isTrue, isFalse } = require('./util')
11
- const uuid = require('crypto-randomuuid')
12
+ const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('./plugins/util/tags')
13
+ const { getGitMetadataFromGitProperties } = require('./git_properties')
12
14
 
13
15
  const fromEntries = Object.fromEntries || (entries =>
14
16
  entries.reduce((obj, [k, v]) => Object.assign(obj, { [k]: v }), {}))
@@ -34,19 +36,6 @@ function safeJsonParse (input) {
34
36
  }
35
37
  }
36
38
 
37
- const namingVersions = ['v0', 'v1']
38
- const defaultVersion = 'v0'
39
-
40
- function validateNamingVersion (versionString) {
41
- if (!namingVersions.includes(versionString)) {
42
- log.warn(
43
- `Unexpected input for config.spanAttributeSchema, picked default ${defaultVersion}`
44
- )
45
- return defaultVersion
46
- }
47
- return versionString
48
- }
49
-
50
39
  // Shallow clone with property name remapping
51
40
  function remapify (input, mappings) {
52
41
  if (!input) return
@@ -172,6 +161,8 @@ class Config {
172
161
  process.env.DD_SERVICE_NAME ||
173
162
  this.tags.service ||
174
163
  process.env.AWS_LAMBDA_FUNCTION_NAME ||
164
+ process.env.FUNCTION_NAME || // Google Cloud Function Name set by deprecated runtimes
165
+ process.env.K_SERVICE || // Google Cloud Function Name set by newer runtimes
175
166
  pkg.name ||
176
167
  'node'
177
168
  const DD_SERVICE_MAPPING = coalesce(
@@ -196,9 +187,18 @@ class Config {
196
187
  process.env.DD_TRACE_STARTUP_LOGS,
197
188
  false
198
189
  )
190
+
191
+ const inAWSLambda = process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined
192
+
193
+ const isDeprecatedGCPFunction = process.env.FUNCTION_NAME !== undefined && process.env.GCP_PROJECT !== undefined
194
+ const isNewerGCPFunction = process.env.K_SERVICE !== undefined && process.env.FUNCTION_TARGET !== undefined
195
+ const isGCPFunction = isDeprecatedGCPFunction || isNewerGCPFunction
196
+
197
+ const inServerlessEnvironment = inAWSLambda || isGCPFunction
198
+
199
199
  const DD_TRACE_TELEMETRY_ENABLED = coalesce(
200
200
  process.env.DD_TRACE_TELEMETRY_ENABLED,
201
- !process.env.AWS_LAMBDA_FUNCTION_NAME
201
+ !inServerlessEnvironment
202
202
  )
203
203
  const DD_TELEMETRY_DEBUG_ENABLED = coalesce(
204
204
  process.env.DD_TELEMETRY_DEBUG_ENABLED,
@@ -273,9 +273,7 @@ class Config {
273
273
  process.env.DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED,
274
274
  false
275
275
  )
276
- const DD_TRACE_SPAN_ATTRIBUTE_SCHEMA = validateNamingVersion(
277
- process.env.DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
278
- )
276
+
279
277
  const DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH = coalesce(
280
278
  process.env.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH,
281
279
  '512'
@@ -284,7 +282,7 @@ class Config {
284
282
  const DD_TRACE_STATS_COMPUTATION_ENABLED = coalesce(
285
283
  options.stats,
286
284
  process.env.DD_TRACE_STATS_COMPUTATION_ENABLED,
287
- false
285
+ isGCPFunction
288
286
  )
289
287
 
290
288
  const DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED = coalesce(
@@ -351,12 +349,10 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
351
349
  maybeFile(process.env.DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON)
352
350
  )
353
351
 
354
- const inAWSLambda = process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined
355
-
356
352
  const remoteConfigOptions = options.remoteConfig || {}
357
353
  const DD_REMOTE_CONFIGURATION_ENABLED = coalesce(
358
354
  process.env.DD_REMOTE_CONFIGURATION_ENABLED && isTrue(process.env.DD_REMOTE_CONFIGURATION_ENABLED),
359
- !inAWSLambda
355
+ !inServerlessEnvironment
360
356
  )
361
357
  const DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS = coalesce(
362
358
  parseInt(remoteConfigOptions.pollInterval),
@@ -403,11 +399,22 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
403
399
  true
404
400
  )
405
401
 
402
+ const DD_IAST_REDACTION_ENABLED = coalesce(
403
+ iastOptions && iastOptions.redactionEnabled,
404
+ !isFalse(process.env.DD_IAST_REDACTION_ENABLED),
405
+ true
406
+ )
407
+
406
408
  const DD_CIVISIBILITY_GIT_UPLOAD_ENABLED = coalesce(
407
409
  process.env.DD_CIVISIBILITY_GIT_UPLOAD_ENABLED,
408
410
  true
409
411
  )
410
412
 
413
+ const DD_TRACE_GIT_METADATA_ENABLED = coalesce(
414
+ process.env.DD_TRACE_GIT_METADATA_ENABLED,
415
+ true
416
+ )
417
+
411
418
  const ingestion = options.ingestion || {}
412
419
  const dogstatsd = coalesce(options.dogstatsd, {})
413
420
  const sampler = {
@@ -439,7 +446,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
439
446
  })
440
447
  }
441
448
 
442
- const defaultFlushInterval = inAWSLambda ? 0 : 2000
449
+ const defaultFlushInterval = inServerlessEnvironment ? 0 : 2000
443
450
 
444
451
  this.tracing = !isFalse(DD_TRACING_ENABLED)
445
452
  this.dbmPropagationMode = DD_DBM_PROPAGATION_MODE
@@ -482,7 +489,6 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
482
489
  sourceMap: !isFalse(DD_PROFILING_SOURCE_MAP),
483
490
  exporters: DD_PROFILING_EXPORTERS
484
491
  }
485
- this.spanAttributeSchema = DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
486
492
  this.lookup = options.lookup
487
493
  this.startupLogs = isTrue(DD_TRACE_STARTUP_LOGS)
488
494
  // Disabled for CI Visibility's agentless
@@ -513,7 +519,8 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
513
519
  requestSampling: DD_IAST_REQUEST_SAMPLING,
514
520
  maxConcurrentRequests: DD_IAST_MAX_CONCURRENT_REQUESTS,
515
521
  maxContextOperations: DD_IAST_MAX_CONTEXT_OPERATIONS,
516
- deduplicationEnabled: DD_IAST_DEDUPLICATION_ENABLED
522
+ deduplicationEnabled: DD_IAST_DEDUPLICATION_ENABLED,
523
+ redactionEnabled: DD_IAST_REDACTION_ENABLED
517
524
  }
518
525
 
519
526
  this.isCiVisibility = isTrue(DD_IS_CIVISIBILITY)
@@ -522,6 +529,31 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
522
529
  this.isGitUploadEnabled = this.isCiVisibility &&
523
530
  (this.isIntelligentTestRunnerEnabled && !isFalse(DD_CIVISIBILITY_GIT_UPLOAD_ENABLED))
524
531
 
532
+ this.gitMetadataEnabled = isTrue(DD_TRACE_GIT_METADATA_ENABLED)
533
+
534
+ if (this.gitMetadataEnabled) {
535
+ this.repositoryUrl = coalesce(
536
+ process.env.DD_GIT_REPOSITORY_URL,
537
+ this.tags[GIT_REPOSITORY_URL]
538
+ )
539
+ this.commitSHA = coalesce(
540
+ process.env.DD_GIT_COMMIT_SHA,
541
+ this.tags[GIT_COMMIT_SHA]
542
+ )
543
+ if (!this.repositoryUrl || !this.commitSHA) {
544
+ const DD_GIT_PROPERTIES_FILE = coalesce(
545
+ process.env.DD_GIT_PROPERTIES_FILE,
546
+ `${process.cwd()}/git.properties`
547
+ )
548
+ const gitPropertiesString = maybeFile(DD_GIT_PROPERTIES_FILE)
549
+ if (gitPropertiesString) {
550
+ const { commitSHA, repositoryUrl } = getGitMetadataFromGitProperties(gitPropertiesString)
551
+ this.commitSHA = this.commitSHA || commitSHA
552
+ this.repositoryUrl = this.repositoryUrl || repositoryUrl
553
+ }
554
+ }
555
+ }
556
+
525
557
  this.stats = {
526
558
  enabled: isTrue(DD_TRACE_STATS_COMPUTATION_ENABLED)
527
559
  }
@@ -529,6 +561,8 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
529
561
  this.traceId128BitGenerationEnabled = isTrue(DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED)
530
562
  this.traceId128BitLoggingEnabled = isTrue(DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED)
531
563
 
564
+ this.isGCPFunction = isGCPFunction
565
+
532
566
  tagger.add(this.tags, {
533
567
  service: this.service,
534
568
  env: this.env,
@@ -25,5 +25,7 @@ module.exports = {
25
25
  ERROR_MESSAGE: 'error.message',
26
26
  ERROR_STACK: 'error.stack',
27
27
  COMPONENT: 'component',
28
- CLIENT_PORT_KEY: 'network.destination.port'
28
+ CLIENT_PORT_KEY: 'network.destination.port',
29
+ SCI_REPOSITORY_URL: '_dd.git.repository_url',
30
+ SCI_COMMIT_SHA: '_dd.git.commit.sha'
29
31
  }
@@ -129,12 +129,17 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
129
129
  _encodeEventContent (bytes, content) {
130
130
  const keysLength = Object.keys(content).length
131
131
 
132
+ let totalKeysLength = keysLength
132
133
  if (content.meta.test_session_id) {
133
- this._encodeMapPrefix(bytes, keysLength + 3)
134
- } else {
135
- this._encodeMapPrefix(bytes, keysLength)
134
+ totalKeysLength = totalKeysLength + 1
136
135
  }
137
-
136
+ if (content.meta.test_module_id) {
137
+ totalKeysLength = totalKeysLength + 1
138
+ }
139
+ if (content.meta.test_suite_id) {
140
+ totalKeysLength = totalKeysLength + 1
141
+ }
142
+ this._encodeMapPrefix(bytes, totalKeysLength)
138
143
  if (content.type) {
139
144
  this._encodeString(bytes, 'type')
140
145
  this._encodeString(bytes, content.type)
@@ -170,15 +175,20 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
170
175
  this._encodeString(bytes, 'test_session_id')
171
176
  this._encodeId(bytes, id(content.meta.test_session_id, 10))
172
177
  delete content.meta.test_session_id
178
+ }
173
179
 
180
+ if (content.meta.test_module_id) {
174
181
  this._encodeString(bytes, 'test_module_id')
175
182
  this._encodeId(bytes, id(content.meta.test_module_id, 10))
176
183
  delete content.meta.test_module_id
184
+ }
177
185
 
186
+ if (content.meta.test_suite_id) {
178
187
  this._encodeString(bytes, 'test_suite_id')
179
188
  this._encodeId(bytes, id(content.meta.test_suite_id, 10))
180
189
  delete content.meta.test_suite_id
181
190
  }
191
+
182
192
  this._encodeString(bytes, 'meta')
183
193
  this._encodeMap(bytes, content.meta)
184
194
  this._encodeString(bytes, 'metrics')
@@ -0,0 +1,17 @@
1
+ const { SCI_COMMIT_SHA, SCI_REPOSITORY_URL } = require('./constants')
2
+
3
+ class GitMetadataTagger {
4
+ constructor (config) {
5
+ this._config = config
6
+ }
7
+
8
+ tagGitMetadata (spanContext) {
9
+ if (this._config.gitMetadataEnabled) {
10
+ // These tags are added only to the local root span
11
+ spanContext._trace.tags[SCI_COMMIT_SHA] = this._config.commitSHA
12
+ spanContext._trace.tags[SCI_REPOSITORY_URL] = this._config.repositoryUrl
13
+ }
14
+ }
15
+ }
16
+
17
+ module.exports = GitMetadataTagger
@@ -0,0 +1,32 @@
1
+ const commitSHARegex = /git\.commit\.sha=([a-f\d]{40})/
2
+ const repositoryUrlRegex = /git\.repository_url=([\w\d:@/.-]+)/
3
+
4
+ function getGitMetadataFromGitProperties (gitPropertiesString) {
5
+ if (!gitPropertiesString) {
6
+ return {}
7
+ }
8
+ const commitSHAMatch = gitPropertiesString.match(commitSHARegex)
9
+ const repositoryUrlMatch = gitPropertiesString.match(repositoryUrlRegex)
10
+
11
+ const repositoryUrl = repositoryUrlMatch ? repositoryUrlMatch[1] : undefined
12
+ let parsedUrl = repositoryUrl
13
+
14
+ if (repositoryUrl) {
15
+ try {
16
+ // repository URLs can contain username and password, so we want to filter those out
17
+ parsedUrl = new URL(repositoryUrl)
18
+ if (parsedUrl.password) {
19
+ parsedUrl = `${parsedUrl.origin}${parsedUrl.pathname}`
20
+ }
21
+ } catch (e) {
22
+ // if protocol isn't https, no password will be used
23
+ }
24
+ }
25
+
26
+ return {
27
+ commitSHA: commitSHAMatch ? commitSHAMatch[1] : undefined,
28
+ repositoryUrl: parsedUrl
29
+ }
30
+ }
31
+
32
+ module.exports = { getGitMetadataFromGitProperties }
@@ -4,7 +4,6 @@ const { channel } = require('../../diagnostics_channel')
4
4
  const { isFalse } = require('./util')
5
5
  const plugins = require('./plugins')
6
6
  const log = require('./log')
7
- const Nomenclature = require('./service-naming')
8
7
 
9
8
  const loadChannel = channel('dd-trace:instrumentation:load')
10
9
 
@@ -97,7 +96,6 @@ module.exports = class PluginManager {
97
96
  // like instrumenter.enable()
98
97
  configure (config = {}) {
99
98
  this._tracerConfig = config
100
- Nomenclature.configure(config)
101
99
 
102
100
  for (const name in pluginClasses) {
103
101
  this.loadPlugin(name)
@@ -1,10 +1,9 @@
1
1
  'use strict'
2
2
 
3
- const OutboundPlugin = require('./outbound')
3
+ const OutgoingPlugin = require('./outgoing')
4
4
 
5
- class ClientPlugin extends OutboundPlugin {
5
+ class ClientPlugin extends OutgoingPlugin {
6
6
  static get operation () { return 'request' }
7
- static get kind () { return 'client' }
8
7
  }
9
8
 
10
9
  module.exports = ClientPlugin
@@ -1,24 +1,9 @@
1
1
  'use strict'
2
2
 
3
- const InboundPlugin = require('./inbound')
3
+ const IncomingPlugin = require('./incoming')
4
4
 
5
- class ConsumerPlugin extends InboundPlugin {
5
+ class ConsumerPlugin extends IncomingPlugin {
6
6
  static get operation () { return 'receive' }
7
- static get kind () { return 'consumer' }
8
- static get type () { return 'messaging' }
9
-
10
- startSpan (options) {
11
- const spanDefaults = {
12
- service: this.config.service || this.serviceName(),
13
- kind: this.constructor.kind
14
- }
15
- Object.keys(spanDefaults).forEach(
16
- key => {
17
- if (!options[key]) options[key] = spanDefaults[key]
18
- }
19
- )
20
- return super.startSpan(this.operationName(), options)
21
- }
22
7
  }
23
8
 
24
9
  module.exports = ConsumerPlugin
@@ -0,0 +1,7 @@
1
+ 'use strict'
2
+
3
+ const TracingPlugin = require('./tracing')
4
+
5
+ class IncomingPlugin extends TracingPlugin {}
6
+
7
+ module.exports = IncomingPlugin
@@ -4,7 +4,7 @@ const { CLIENT_PORT_KEY } = require('../constants')
4
4
  const TracingPlugin = require('./tracing')
5
5
 
6
6
  // TODO: Exit span on finish when AsyncResource instances are removed.
7
- class OutboundPlugin extends TracingPlugin {
7
+ class OutgoingPlugin extends TracingPlugin {
8
8
  constructor (...args) {
9
9
  super(...args)
10
10
 
@@ -29,4 +29,4 @@ class OutboundPlugin extends TracingPlugin {
29
29
  }
30
30
  }
31
31
 
32
- module.exports = OutboundPlugin
32
+ module.exports = OutgoingPlugin
@@ -1,24 +1,9 @@
1
1
  'use strict'
2
2
 
3
- const OutboundPlugin = require('./outbound')
3
+ const OutgoingPlugin = require('./outgoing')
4
4
 
5
- class ProducerPlugin extends OutboundPlugin {
5
+ class ProducerPlugin extends OutgoingPlugin {
6
6
  static get operation () { return 'publish' }
7
- static get kind () { return 'producer' }
8
- static get type () { return 'messaging' }
9
-
10
- startSpan (options) {
11
- const spanDefaults = {
12
- service: this.config.service || this.serviceName(),
13
- kind: this.constructor.kind
14
- }
15
- Object.keys(spanDefaults).forEach(
16
- key => {
17
- if (!options[key]) options[key] = spanDefaults[key]
18
- }
19
- )
20
- return super.startSpan(this.operationName(), options)
21
- }
22
7
  }
23
8
 
24
9
  module.exports = ProducerPlugin
@@ -1,8 +1,8 @@
1
1
  'use strict'
2
2
 
3
- const InboundPlugin = require('./inbound')
3
+ const IncomingPlugin = require('./incoming')
4
4
 
5
- class ServerPlugin extends InboundPlugin {
5
+ class ServerPlugin extends IncomingPlugin {
6
6
  static get operation () { return 'request' }
7
7
  }
8
8
 
@@ -4,7 +4,6 @@ const Plugin = require('./plugin')
4
4
  const { storage } = require('../../../datadog-core')
5
5
  const analyticsSampler = require('../analytics_sampler')
6
6
  const { COMPONENT } = require('../constants')
7
- const Nomenclature = require('../service-naming')
8
7
 
9
8
  class TracingPlugin extends Plugin {
10
9
  constructor (...args) {
@@ -32,16 +31,6 @@ class TracingPlugin extends Plugin {
32
31
  return store && store.span
33
32
  }
34
33
 
35
- serviceName (serviceArgs) {
36
- const { type, id, kind } = this.constructor
37
- return Nomenclature.serviceName(type, kind, id, serviceArgs)
38
- }
39
-
40
- operationName (opNameArgs) {
41
- const { type, id, kind } = this.constructor
42
- return Nomenclature.opName(type, kind, id, opNameArgs)
43
- }
44
-
45
34
  configure (config) {
46
35
  return super.configure({
47
36
  ...config,