dd-trace 3.29.1 → 3.31.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 (49) hide show
  1. package/CONTRIBUTING.md +66 -0
  2. package/MIGRATING.md +0 -14
  3. package/package.json +18 -18
  4. package/packages/datadog-esbuild/index.js +109 -31
  5. package/packages/datadog-instrumentations/index.js +1 -0
  6. package/packages/datadog-instrumentations/src/couchbase.js +41 -5
  7. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +54 -0
  8. package/packages/datadog-instrumentations/src/helpers/hook.js +1 -4
  9. package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -1
  10. package/packages/datadog-instrumentations/src/helpers/register.js +7 -2
  11. package/packages/datadog-instrumentations/src/jest.js +37 -1
  12. package/packages/datadog-plugin-aws-sdk/src/base.js +22 -10
  13. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +16 -0
  14. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +18 -0
  15. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +23 -0
  16. package/packages/datadog-plugin-cassandra-driver/src/index.js +1 -1
  17. package/packages/datadog-plugin-couchbase/src/index.js +32 -30
  18. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
  19. package/packages/datadog-plugin-fetch/src/index.js +1 -0
  20. package/packages/datadog-plugin-http/src/client.js +7 -17
  21. package/packages/datadog-plugin-http/src/server.js +10 -2
  22. package/packages/datadog-plugin-http2/src/client.js +2 -16
  23. package/packages/datadog-plugin-http2/src/server.js +10 -1
  24. package/packages/datadog-plugin-memcached/src/index.js +1 -1
  25. package/packages/datadog-plugin-mongodb-core/src/index.js +2 -2
  26. package/packages/datadog-plugin-mysql/src/index.js +1 -1
  27. package/packages/datadog-plugin-next/src/index.js +2 -2
  28. package/packages/datadog-plugin-oracledb/src/index.js +1 -1
  29. package/packages/datadog-plugin-pg/src/index.js +1 -1
  30. package/packages/datadog-plugin-redis/src/index.js +1 -1
  31. package/packages/datadog-plugin-tedious/src/index.js +1 -1
  32. package/packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js +11 -7
  33. package/packages/dd-trace/src/appsec/passport.js +1 -1
  34. package/packages/dd-trace/src/config.js +7 -5
  35. package/packages/dd-trace/src/plugin_manager.js +6 -1
  36. package/packages/dd-trace/src/plugins/index.js +1 -0
  37. package/packages/dd-trace/src/plugins/tracing.js +16 -9
  38. package/packages/dd-trace/src/proxy.js +2 -2
  39. package/packages/dd-trace/src/serverless.js +51 -7
  40. package/packages/dd-trace/src/service-naming/index.js +7 -11
  41. package/packages/dd-trace/src/service-naming/schemas/definition.js +4 -4
  42. package/packages/dd-trace/src/service-naming/schemas/util.js +21 -3
  43. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +20 -8
  44. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +33 -23
  45. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +33 -1
  46. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +14 -2
  47. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +12 -9
  48. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +33 -1
  49. package/packages/dd-trace/src/dcitm.js +0 -53
@@ -188,6 +188,31 @@ addHook({
188
188
  versions: ['>=24.8.0']
189
189
  }, getTestEnvironment)
190
190
 
191
+ addHook({
192
+ name: '@jest/test-sequencer',
193
+ versions: ['>=24.8.0']
194
+ }, sequencerPackage => {
195
+ shimmer.wrap(sequencerPackage.default.prototype, 'shard', shard => function () {
196
+ const shardedTests = shard.apply(this, arguments)
197
+
198
+ if (!shardedTests.length) {
199
+ return shardedTests
200
+ }
201
+ // TODO: could we get the rootDir from each test?
202
+ const [test] = shardedTests
203
+ const rootDir = test && test.context && test.context.config && test.context.config.rootDir
204
+
205
+ const filteredTests = getJestSuitesToRun(skippableSuites, shardedTests, rootDir || process.cwd())
206
+
207
+ isSuitesSkipped = filteredTests.length !== shardedTests.length
208
+
209
+ skippableSuites = []
210
+
211
+ return filteredTests
212
+ })
213
+ return sequencerPackage
214
+ })
215
+
191
216
  function cliWrapper (cli, jestVersion) {
192
217
  const wrapped = shimmer.wrap(cli, 'runCLI', runCLI => async function () {
193
218
  let onDone
@@ -451,7 +476,18 @@ addHook({
451
476
  return getTestPaths.apply(this, arguments)
452
477
  }
453
478
 
454
- const [{ rootDir }] = arguments
479
+ const [{ rootDir, shard }] = arguments
480
+
481
+ if (shard && shard.shardIndex) {
482
+ // If the user is using jest sharding, we want to apply the filtering of tests in the shard process.
483
+ // The reason for this is the following:
484
+ // The tests for different shards are likely being run in different CI jobs so
485
+ // the requests to the skippable endpoint might be done at different times and their responses might be different.
486
+ // If the skippable endpoint is returning different suites and we filter the list of tests here,
487
+ // the base list of tests that is used for sharding might be different,
488
+ // causing the shards to potentially run the same suite.
489
+ return getTestPaths.apply(this, arguments)
490
+ }
455
491
 
456
492
  const testPaths = await getTestPaths.apply(this, arguments)
457
493
  const { tests } = testPaths
@@ -31,11 +31,10 @@ class BaseAwsSdkPlugin extends ClientPlugin {
31
31
  if (!this.isEnabled(request)) {
32
32
  return
33
33
  }
34
- const serviceName = this.getServiceName()
35
34
  const childOf = this.tracer.scope().active()
36
35
  const tags = {
37
36
  'span.kind': 'client',
38
- 'service.name': serviceName,
37
+ 'service.name': this.serviceName(),
39
38
  'aws.operation': operation,
40
39
  'aws.region': awsRegion,
41
40
  'region': awsRegion,
@@ -45,7 +44,7 @@ class BaseAwsSdkPlugin extends ClientPlugin {
45
44
  }
46
45
  if (this.requestTags) this.requestTags.set(request, tags)
47
46
 
48
- const span = this.tracer.startSpan('aws.request', { childOf, tags })
47
+ const span = this.tracer.startSpan(this.operationFromRequest(request), { childOf, tags })
49
48
 
50
49
  analyticsSampler.sample(span, this.config.measured)
51
50
 
@@ -79,6 +78,26 @@ class BaseAwsSdkPlugin extends ClientPlugin {
79
78
  // implemented by subclasses, or not
80
79
  }
81
80
 
81
+ operationFromRequest (request) {
82
+ // can be overriden by subclasses
83
+ return this.operationName({
84
+ id: 'aws',
85
+ type: 'web',
86
+ kind: 'client',
87
+ awsService: this.serviceIdentifier
88
+ })
89
+ }
90
+
91
+ serviceName () {
92
+ return this.config.service ||
93
+ super.serviceName({
94
+ id: 'aws',
95
+ type: 'web',
96
+ kind: 'client',
97
+ awsService: this.serviceIdentifier
98
+ })
99
+ }
100
+
82
101
  isEnabled (request) {
83
102
  const serviceId = this.serviceIdentifier.toUpperCase()
84
103
  const envVarValue = process.env[`DD_TRACE_AWS_SDK_${serviceId}_ENABLED`]
@@ -122,13 +141,6 @@ class BaseAwsSdkPlugin extends ClientPlugin {
122
141
  configure (config) {
123
142
  super.configure(normalizeConfig(config, this.serviceIdentifier))
124
143
  }
125
-
126
- // TODO: test splitByAwsService when the test suite is fixed
127
- getServiceName () {
128
- return this.config.service
129
- ? this.config.service
130
- : `${this.tracer._service}-aws-${this.serviceIdentifier}`
131
- }
132
144
  }
133
145
 
134
146
  function normalizeConfig (config, serviceIdentifier) {
@@ -48,6 +48,22 @@ class Lambda extends BaseAwsSdkPlugin {
48
48
  }
49
49
  }
50
50
  }
51
+
52
+ operationFromRequest (request) {
53
+ if (request.operation === 'invoke') {
54
+ return this.operationName({
55
+ type: 'web',
56
+ kind: 'client'
57
+ })
58
+ }
59
+
60
+ return this.operationName({
61
+ id: 'aws',
62
+ type: 'web',
63
+ kind: 'client',
64
+ awsService: 'lambda'
65
+ })
66
+ }
51
67
  }
52
68
 
53
69
  module.exports = Lambda
@@ -27,6 +27,24 @@ class Sns extends BaseAwsSdkPlugin {
27
27
  // for example if it contains a phone number?
28
28
  }
29
29
 
30
+ operationFromRequest (request) {
31
+ switch (request.operation) {
32
+ case 'publish':
33
+ case 'publishBatch':
34
+ return this.operationName({
35
+ type: 'messaging',
36
+ kind: 'producer'
37
+ })
38
+ }
39
+
40
+ return this.operationName({
41
+ id: 'aws',
42
+ type: 'web',
43
+ kind: 'client',
44
+ awsService: 'sns'
45
+ })
46
+ }
47
+
30
48
  requestInject (span, request) {
31
49
  const { operation, params } = request
32
50
 
@@ -41,6 +41,29 @@ class Sqs extends BaseAwsSdkPlugin {
41
41
  })
42
42
  }
43
43
 
44
+ operationFromRequest (request) {
45
+ switch (request.operation) {
46
+ case 'receiveMessage':
47
+ return this.operationName({
48
+ type: 'messaging',
49
+ kind: 'consumer'
50
+ })
51
+ case 'sendMessage':
52
+ case 'sendMessageBatch':
53
+ return this.operationName({
54
+ type: 'messaging',
55
+ kind: 'producer'
56
+ })
57
+ }
58
+
59
+ return this.operationName({
60
+ id: 'aws',
61
+ type: 'web',
62
+ kind: 'client',
63
+ awsService: 'sqs'
64
+ })
65
+ }
66
+
44
67
  isEnabled (request) {
45
68
  // TODO(bengl) Figure out a way to make separate plugins for consumer and producer so that
46
69
  // config can be isolated to `.configure()` instead of this whole isEnabled() thing.
@@ -14,7 +14,7 @@ class CassandraDriverPlugin extends DatabasePlugin {
14
14
  }
15
15
 
16
16
  this.startSpan(this.operationName(), {
17
- service: this.serviceName(this.config, this.system),
17
+ service: this.serviceName({ pluginConfig: this.config, system: this.system }),
18
18
  resource: trim(query, 5000),
19
19
  type: 'cassandra',
20
20
  kind: 'client',
@@ -1,51 +1,57 @@
1
1
  'use strict'
2
2
 
3
- const Plugin = require('../../dd-trace/src/plugins/plugin')
3
+ const StoragePlugin = require('../../dd-trace/src/plugins/storage')
4
4
  const { storage } = require('../../datadog-core')
5
- const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
6
5
 
7
- class CouchBasePlugin extends Plugin {
8
- static get id () {
9
- return 'couchbase'
10
- }
6
+ class CouchBasePlugin extends StoragePlugin {
7
+ static get id () { return 'couchbase' }
8
+ static get peerServicePrecursors () { return ['db.couchbase.seed.nodes'] }
11
9
 
12
- addSubs (func, start, finish = defaultFinish) {
10
+ addSubs (func, start) {
13
11
  this.addSub(`apm:couchbase:${func}:start`, start)
14
- this.addSub(`apm:couchbase:${func}:error`, this.addError)
15
- this.addSub(`apm:couchbase:${func}:finish`, finish)
12
+ this.addSub(`apm:couchbase:${func}:error`, error => this.addError(error))
13
+ this.addSub(`apm:couchbase:${func}:finish`, message => this.finish(message))
16
14
  }
17
15
 
18
- startSpan (operation, customTags, store, { bucket, collection }) {
16
+ startSpan (operation, customTags, store, { bucket, collection, seedNodes }) {
19
17
  const tags = {
20
18
  'db.type': 'couchbase',
21
19
  'component': 'couchbase',
22
- 'service.name': this.config.service || `${this.tracer._service}-couchbase`,
23
20
  'resource.name': `couchbase.${operation}`,
24
- 'span.kind': 'client'
21
+ 'span.kind': this.constructor.kind,
22
+ 'db.couchbase.seed.nodes': seedNodes
25
23
  }
26
24
 
25
+ if (bucket) tags['couchbase.bucket.name'] = bucket.name
26
+ if (collection) tags['couchbase.collection.name'] = collection.name
27
+
27
28
  for (const tag in customTags) {
28
29
  tags[tag] = customTags[tag]
29
30
  }
30
- const span = this.tracer.startSpan(`couchbase.${operation}`, {
31
- childOf: store ? store.span : null,
32
- tags
33
- })
34
31
 
35
- if (bucket) span.setTag(`couchbase.bucket.name`, bucket.name)
36
- if (collection) span.setTag(`couchbase.collection.name`, collection.name)
37
-
38
- analyticsSampler.sample(span, this.config.measured)
39
- return span
32
+ return super.startSpan(
33
+ this.operationName({ operation }),
34
+ {
35
+ service: this.serviceName({ pluginConfig: this.config }),
36
+ meta: tags
37
+ }
38
+ )
40
39
  }
41
40
 
42
41
  constructor (...args) {
43
42
  super(...args)
44
43
 
45
- this.addSubs('query', ({ resource, bucket }) => {
44
+ this.addSubs('query', ({ resource, bucket, seedNodes }) => {
46
45
  const store = storage.getStore()
47
- const span = this.startSpan('query', { 'span.type': 'sql', 'resource.name': resource },
48
- store, { bucket })
46
+ const span = this.startSpan(
47
+ 'query', {
48
+ 'span.type': 'sql',
49
+ 'resource.name': resource,
50
+ 'span.kind': this.constructor.kind
51
+ },
52
+ store,
53
+ { bucket, seedNodes }
54
+ )
49
55
  this.enter(span, store)
50
56
  })
51
57
 
@@ -56,16 +62,12 @@ class CouchBasePlugin extends Plugin {
56
62
  this._addCommandSubs('prepend')
57
63
  }
58
64
  _addCommandSubs (name) {
59
- this.addSubs(name, ({ bucket, collection }) => {
65
+ this.addSubs(name, ({ bucket, collection, seedNodes }) => {
60
66
  const store = storage.getStore()
61
- const span = this.startSpan(name, {}, store, { bucket, collection })
67
+ const span = this.startSpan(name, {}, store, { bucket, collection, seedNodes })
62
68
  this.enter(span, store)
63
69
  })
64
70
  }
65
71
  }
66
72
 
67
- function defaultFinish () {
68
- storage.getStore().span.finish()
69
- }
70
-
71
73
  module.exports = CouchBasePlugin
@@ -9,7 +9,7 @@ class ElasticsearchPlugin extends DatabasePlugin {
9
9
  const body = getBody(params.body || params.bulkBody)
10
10
 
11
11
  this.startSpan(this.operationName(), {
12
- service: this.serviceName(this.config),
12
+ service: this.serviceName({ pluginConfig: this.config }),
13
13
  resource: `${params.method} ${quantizePath(params.path)}`,
14
14
  type: 'elasticsearch',
15
15
  kind: 'client',
@@ -21,6 +21,7 @@ class FetchPlugin extends HttpClientPlugin {
21
21
 
22
22
  const store = super.bindStart(message)
23
23
 
24
+ message.headers = headers
24
25
  message.req = new globalThis.Request(req, { headers })
25
26
 
26
27
  return store
@@ -8,8 +8,8 @@ const formats = require('../../../ext/formats')
8
8
  const HTTP_HEADERS = formats.HTTP_HEADERS
9
9
  const urlFilter = require('../../dd-trace/src/plugins/util/urlfilter')
10
10
  const log = require('../../dd-trace/src/log')
11
- const url = require('url')
12
11
  const { CLIENT_PORT_KEY, COMPONENT, ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../dd-trace/src/constants')
12
+ const { URL } = require('url')
13
13
 
14
14
  const HTTP_STATUS_CODE = tags.HTTP_STATUS_CODE
15
15
  const HTTP_REQUEST_HEADERS = tags.HTTP_REQUEST_HEADERS
@@ -36,12 +36,12 @@ class HttpClientPlugin extends ClientPlugin {
36
36
  const method = (options.method || 'GET').toUpperCase()
37
37
  const childOf = store && allowed ? store.span : null
38
38
  // TODO delegate to super.startspan
39
- const span = this.startSpan('http.request', {
39
+ const span = this.startSpan(this.operationName(), {
40
40
  childOf,
41
41
  meta: {
42
42
  [COMPONENT]: this.constructor.id,
43
43
  'span.kind': 'client',
44
- 'service.name': getServiceName(this.tracer, this.config, options),
44
+ 'service.name': this.serviceName({ pluginConfig: this.config, sessionDetails: extractSessionDetails(options) }),
45
45
  'resource.name': method,
46
46
  'span.type': 'http',
47
47
  'http.method': method,
@@ -217,25 +217,15 @@ function hasAmazonSignature (options) {
217
217
  return search && search.toLowerCase().indexOf('x-amz-signature=') !== -1
218
218
  }
219
219
 
220
- function getServiceName (tracer, config, options) {
221
- if (config.splitByDomain) {
222
- return getHost(options)
223
- } else if (config.service) {
224
- return config.service
225
- }
226
-
227
- return tracer._service
228
- }
229
-
230
- function getHost (options) {
220
+ function extractSessionDetails (options) {
231
221
  if (typeof options === 'string') {
232
- return url.parse(options).host
222
+ return new URL(options).host
233
223
  }
234
224
 
235
- const hostname = options.hostname || options.host || 'localhost'
225
+ const host = options.hostname || options.host || 'localhost'
236
226
  const port = options.port
237
227
 
238
- return [hostname, port].filter(val => val).join(':')
228
+ return { host, port }
239
229
  }
240
230
 
241
231
  function startsWith (searchString) {
@@ -23,8 +23,16 @@ class HttpServerPlugin extends ServerPlugin {
23
23
 
24
24
  start ({ req, res, abortController }) {
25
25
  const store = storage.getStore()
26
- const span = web.startSpan(this.tracer, this.config, req, res, 'web.request')
27
-
26
+ const span = web.startSpan(
27
+ this.tracer,
28
+ {
29
+ ...this.config,
30
+ service: this.config.service || this.serviceName()
31
+ },
32
+ req,
33
+ res,
34
+ this.operationName()
35
+ )
28
36
  span.setTag(COMPONENT, this.constructor.id)
29
37
 
30
38
  this._parentStore = store
@@ -38,12 +38,12 @@ class Http2ClientPlugin extends ClientPlugin {
38
38
 
39
39
  const store = storage.getStore()
40
40
  const childOf = store && allowed ? store.span : null
41
- const span = this.startSpan('http.request', {
41
+ const span = this.startSpan(this.operationName(), {
42
42
  childOf,
43
43
  meta: {
44
44
  [COMPONENT]: this.constructor.id,
45
45
  [SPAN_KIND]: CLIENT,
46
- 'service.name': getServiceName(this.tracer, this.config, sessionDetails),
46
+ 'service.name': this.serviceName({ pluginConfig: this.config, sessionDetails }),
47
47
  'resource.name': method,
48
48
  'span.type': 'http',
49
49
  'http.method': method,
@@ -133,20 +133,6 @@ function extractSessionDetails (authority, options) {
133
133
  return { protocol, port, host }
134
134
  }
135
135
 
136
- function getFormattedHostString (host, port) {
137
- return [host, port].filter(val => val).join(':')
138
- }
139
-
140
- function getServiceName (tracer, config, sessionDetails) {
141
- if (config.splitByDomain) {
142
- return getFormattedHostString(sessionDetails.host, sessionDetails.port)
143
- } else if (config.service) {
144
- return config.service
145
- }
146
-
147
- return tracer._service
148
- }
149
-
150
136
  function hasAmazonSignature (headers, path) {
151
137
  if (headers) {
152
138
  headers = Object.keys(headers)
@@ -18,7 +18,16 @@ class Http2ServerPlugin extends ServerPlugin {
18
18
 
19
19
  start ({ req, res }) {
20
20
  const store = storage.getStore()
21
- const span = web.startSpan(this.tracer, this.config, req, res, 'web.request')
21
+ const span = web.startSpan(
22
+ this.tracer,
23
+ {
24
+ ...this.config,
25
+ service: this.config.service || this.serviceName()
26
+ },
27
+ req,
28
+ res,
29
+ this.operationName()
30
+ )
22
31
 
23
32
  span.setTag(COMPONENT, this.constructor.id)
24
33
 
@@ -10,7 +10,7 @@ class MemcachedPlugin extends CachePlugin {
10
10
  const address = getAddress(client, server, query)
11
11
 
12
12
  this.startSpan({
13
- service: this.serviceName(this.config, this.system),
13
+ service: this.serviceName({ pluginConfig: this.config, system: this.system }),
14
14
  resource: query.type,
15
15
  type: 'memcached',
16
16
  meta: {
@@ -12,7 +12,7 @@ class MongodbCorePlugin extends DatabasePlugin {
12
12
  const query = getQuery(ops)
13
13
  const resource = truncate(getResource(this, ns, query, name))
14
14
  this.startSpan(this.operationName(), {
15
- service: this.serviceName(this.config),
15
+ service: this.serviceName({ pluginConfig: this.config }),
16
16
  resource,
17
17
  type: 'mongodb',
18
18
  kind: 'client',
@@ -57,7 +57,7 @@ function truncate (input) {
57
57
  }
58
58
 
59
59
  function shouldSimplify (input) {
60
- return !isObject(input)
60
+ return !isObject(input) || typeof input.toJSON === 'function'
61
61
  }
62
62
 
63
63
  function shouldHide (input) {
@@ -8,7 +8,7 @@ class MySQLPlugin extends DatabasePlugin {
8
8
  static get system () { return 'mysql' }
9
9
 
10
10
  start (payload) {
11
- const service = this.serviceName(this.config, payload.conf, this.system)
11
+ const service = this.serviceName({ pluginConfig: this.config, dbConfig: payload.conf, system: this.system })
12
12
  this.startSpan(this.operationName(), {
13
13
  service,
14
14
  resource: payload.sql,
@@ -19,11 +19,11 @@ class NextPlugin extends ServerPlugin {
19
19
  start ({ req, res }) {
20
20
  const store = storage.getStore()
21
21
  const childOf = store ? store.span : store
22
- const span = this.tracer.startSpan('next.request', {
22
+ const span = this.tracer.startSpan(this.operationName(), {
23
23
  childOf,
24
24
  tags: {
25
25
  [COMPONENT]: this.constructor.id,
26
- 'service.name': this.config.service || this.tracer._service,
26
+ 'service.name': this.config.service || this.serviceName(),
27
27
  'resource.name': req.method,
28
28
  'span.type': 'web',
29
29
  'span.kind': 'server',
@@ -10,7 +10,7 @@ class OracledbPlugin extends DatabasePlugin {
10
10
  static get peerServicePrecursors () { return ['db.instance', 'db.hostname'] }
11
11
 
12
12
  start ({ query, connAttrs }) {
13
- const service = this.serviceName(this.config, connAttrs)
13
+ const service = this.serviceName({ pluginConfig: this.config, params: connAttrs })
14
14
  const url = getUrl(connAttrs.connectString)
15
15
 
16
16
  this.startSpan(this.operationName(), {
@@ -9,7 +9,7 @@ class PGPlugin extends DatabasePlugin {
9
9
  static get system () { return 'postgres' }
10
10
 
11
11
  start ({ params = {}, query, processId }) {
12
- const service = this.serviceName(this.config, params)
12
+ const service = this.serviceName({ pluginConfig: this.config, params })
13
13
  const originalStatement = query.text
14
14
 
15
15
  this.startSpan(this.operationName(), {
@@ -15,7 +15,7 @@ class RedisPlugin extends CachePlugin {
15
15
 
16
16
  this.startSpan({
17
17
  resource,
18
- service: this.serviceName(this.config, this.system, connectionName),
18
+ service: this.serviceName({ pluginConfig: this.config, system: this.system, connectionName }),
19
19
  type: 'redis',
20
20
  meta: {
21
21
  'db.type': 'redis',
@@ -10,7 +10,7 @@ class TediousPlugin extends DatabasePlugin {
10
10
 
11
11
  start ({ queryOrProcedure, connectionConfig }) {
12
12
  this.startSpan(this.operationName(), {
13
- service: this.serviceName(this.config, this.system),
13
+ service: this.serviceName({ pluginConfig: this.config, system: this.system }),
14
14
  resource: queryOrProcedure,
15
15
  type: 'sql',
16
16
  kind: 'client',
@@ -2,6 +2,7 @@
2
2
 
3
3
  const path = require('path')
4
4
 
5
+ const { getNodeModulesPaths } = require('../path-line')
5
6
  const Analyzer = require('./vulnerability-analyzer')
6
7
  const { WEAK_HASH } = require('../vulnerabilities')
7
8
 
@@ -11,13 +12,16 @@ const INSECURE_HASH_ALGORITHMS = new Set([
11
12
  'RSA-SHA1', 'RSA-SHA1-2', 'sha1', 'md5-sha1', 'sha1WithRSAEncryption', 'ssl3-sha1'
12
13
  ].map(algorithm => algorithm.toLowerCase()))
13
14
 
14
- const EXCLUDED_LOCATIONS = [
15
- path.join('node_modules', 'etag', 'index.js'),
16
- path.join('node_modules', 'redlock', 'dist', 'cjs'),
17
- path.join('node_modules', 'ws', 'lib', 'websocket-server.js'),
18
- path.join('node_modules', 'mysql2', 'lib', 'auth_41.js'),
19
- path.join('node_modules', '@mikro-orm', 'core', 'utils', 'Utils.js')
20
- ]
15
+ const EXCLUDED_LOCATIONS = getNodeModulesPaths(
16
+ 'etag/index.js',
17
+ '@mikro-orm/core/utils/Utils.js',
18
+ 'mongodb/lib/core/connection/connection.js',
19
+ 'mysql2/lib/auth_41.js',
20
+ 'pusher/lib/utils.js',
21
+ 'redlock/dist/cjs',
22
+ 'sqreen/lib/package-reader/index.js',
23
+ 'ws/lib/websocket-server.js'
24
+ )
21
25
 
22
26
  const EXCLUDED_PATHS_FROM_STACK = [
23
27
  path.join('node_modules', 'object-hash', path.sep)
@@ -69,7 +69,7 @@ function parseUser (login, passportUser, mode) {
69
69
  if (mode === 'safe') {
70
70
  // Remove PII in safe mode
71
71
  if (!regexUsername.test(user['usr.id'])) {
72
- user['usr.id'] = ' '
72
+ user['usr.id'] = ''
73
73
  }
74
74
  }
75
75
 
@@ -11,6 +11,7 @@ const tagger = require('./tagger')
11
11
  const { isTrue, isFalse } = require('./util')
12
12
  const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('./plugins/util/tags')
13
13
  const { getGitMetadataFromGitProperties } = require('./git_properties')
14
+ const { getIsGCPFunction, getIsAzureFunctionConsumptionPlan } = require('./serverless')
14
15
 
15
16
  const fromEntries = Object.fromEntries || (entries =>
16
17
  entries.reduce((obj, [k, v]) => Object.assign(obj, { [k]: v }), {}))
@@ -189,6 +190,7 @@ class Config {
189
190
  process.env.AWS_LAMBDA_FUNCTION_NAME ||
190
191
  process.env.FUNCTION_NAME || // Google Cloud Function Name set by deprecated runtimes
191
192
  process.env.K_SERVICE || // Google Cloud Function Name set by newer runtimes
193
+ process.env.WEBSITE_SITE_NAME || // set by Azure Functions
192
194
  pkg.name ||
193
195
  'node'
194
196
  const DD_SERVICE_MAPPING = coalesce(
@@ -227,11 +229,10 @@ class Config {
227
229
 
228
230
  const inAWSLambda = process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined
229
231
 
230
- const isDeprecatedGCPFunction = process.env.FUNCTION_NAME !== undefined && process.env.GCP_PROJECT !== undefined
231
- const isNewerGCPFunction = process.env.K_SERVICE !== undefined && process.env.FUNCTION_TARGET !== undefined
232
- const isGCPFunction = isDeprecatedGCPFunction || isNewerGCPFunction
232
+ const isGCPFunction = getIsGCPFunction()
233
+ const isAzureFunctionConsumptionPlan = getIsAzureFunctionConsumptionPlan()
233
234
 
234
- const inServerlessEnvironment = inAWSLambda || isGCPFunction
235
+ const inServerlessEnvironment = inAWSLambda || isGCPFunction || isAzureFunctionConsumptionPlan
235
236
 
236
237
  const DD_TRACE_TELEMETRY_ENABLED = coalesce(
237
238
  process.env.DD_TRACE_TELEMETRY_ENABLED,
@@ -362,7 +363,7 @@ class Config {
362
363
  const DD_TRACE_STATS_COMPUTATION_ENABLED = coalesce(
363
364
  options.stats,
364
365
  process.env.DD_TRACE_STATS_COMPUTATION_ENABLED,
365
- isGCPFunction
366
+ isGCPFunction || isAzureFunctionConsumptionPlan
366
367
  )
367
368
 
368
369
  const DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED = coalesce(
@@ -678,6 +679,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
678
679
  this.traceId128BitLoggingEnabled = isTrue(DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED)
679
680
 
680
681
  this.isGCPFunction = isGCPFunction
682
+ this.isAzureFunctionConsumptionPlan = isAzureFunctionConsumptionPlan
681
683
 
682
684
  tagger.add(this.tags, {
683
685
  service: this.service,
@@ -135,7 +135,8 @@ module.exports = class PluginManager {
135
135
  site,
136
136
  url,
137
137
  dbmPropagationMode,
138
- dsmEnabled
138
+ dsmEnabled,
139
+ clientIpEnabled
139
140
  } = this._tracerConfig
140
141
 
141
142
  const sharedConfig = {}
@@ -155,6 +156,10 @@ module.exports = class PluginManager {
155
156
  sharedConfig.service = serviceMapping[name]
156
157
  }
157
158
 
159
+ if (clientIpEnabled !== undefined) {
160
+ sharedConfig.clientIpEnabled = clientIpEnabled
161
+ }
162
+
158
163
  sharedConfig.site = site
159
164
  sharedConfig.url = url
160
165