dd-trace 2.20.1 → 2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "2.20.1",
3
+ "version": "2.21.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -58,7 +58,7 @@
58
58
  "node": ">=12"
59
59
  },
60
60
  "dependencies": {
61
- "@datadog/native-appsec": "^1.2.1",
61
+ "@datadog/native-appsec": "1.3.0",
62
62
  "@datadog/native-metrics": "^1.5.0",
63
63
  "@datadog/pprof": "^1.1.1",
64
64
  "@datadog/sketches-js": "^2.1.0",
@@ -263,6 +263,9 @@ function jestAdapterWrapper (jestAdapter) {
263
263
  const adapter = jestAdapter.default ? jestAdapter.default : jestAdapter
264
264
  const newAdapter = shimmer.wrap(adapter, function () {
265
265
  const environment = arguments[2]
266
+ if (!environment) {
267
+ return adapter.apply(this, arguments)
268
+ }
266
269
  const asyncResource = new AsyncResource('bound-anonymous-fn')
267
270
  return asyncResource.runInAsyncScope(() => {
268
271
  testSuiteStartCh.publish({
@@ -280,7 +283,9 @@ function jestAdapterWrapper (jestAdapter) {
280
283
  testSuiteFinishCh.publish({ status, errorMessage })
281
284
  if (environment.global.__coverage__) {
282
285
  const coverageFiles = extractCoverageInformation(environment.global.__coverage__, environment.rootDir)
283
- if (coverageFiles.length) {
286
+ if (coverageFiles.length &&
287
+ environment.testEnvironmentOptions &&
288
+ environment.testEnvironmentOptions._ddTestCodeCoverageEnabled) {
284
289
  testSuiteCodeCoverageCh.publish([...coverageFiles, environment.testSuite])
285
290
  }
286
291
  }
@@ -314,6 +319,11 @@ function configureTestEnvironment (readConfigsResult) {
314
319
  sessionAsyncResource.runInAsyncScope(() => {
315
320
  testSessionConfigurationCh.publish(configs.map(config => config.testEnvironmentOptions))
316
321
  })
322
+ // We can't directly use isCodeCoverageEnabled when reporting coverage in `jestAdapterWrapper`
323
+ // because `jestAdapterWrapper` runs in a different process. We have to go through `testEnvironmentOptions`
324
+ configs.forEach(config => {
325
+ config.testEnvironmentOptions._ddTestCodeCoverageEnabled = isCodeCoverageEnabled
326
+ })
317
327
  if (isCodeCoverageEnabled) {
318
328
  const globalConfig = {
319
329
  ...readConfigsResult.globalConfig,
@@ -31,9 +31,10 @@ class HttpClientPlugin extends Plugin {
31
31
  const host = options.port ? `${hostname}:${options.port}` : hostname
32
32
  const path = options.path ? options.path.split(/[?#]/)[0] : '/'
33
33
  const uri = `${protocol}//${host}${path}`
34
+ const allowed = this.config.filter(uri)
34
35
 
35
36
  const method = (options.method || 'GET').toUpperCase()
36
- const childOf = store ? store.span : store
37
+ const childOf = store && allowed ? store.span : null
37
38
  const span = this.tracer.startSpan('http.request', {
38
39
  childOf,
39
40
  tags: {
@@ -46,6 +47,11 @@ class HttpClientPlugin extends Plugin {
46
47
  }
47
48
  })
48
49
 
50
+ // TODO: Figure out a better way to do this for any span.
51
+ if (!allowed) {
52
+ span._spanContext._trace.record = false
53
+ }
54
+
49
55
  if (!(hasAmazonSignature(options) || !this.config.propagationFilter(uri))) {
50
56
  this.tracer.inject(span, HTTP_HEADERS, options.headers)
51
57
  }
@@ -116,12 +122,14 @@ function addRequestHeaders (req, span, config) {
116
122
 
117
123
  function normalizeClientConfig (config) {
118
124
  const validateStatus = getStatusValidator(config)
125
+ const filter = getFilter(config)
119
126
  const propagationFilter = getFilter({ blocklist: config.propagationBlocklist })
120
127
  const headers = getHeaders(config)
121
128
  const hooks = getHooks(config)
122
129
 
123
130
  return Object.assign({}, config, {
124
131
  validateStatus,
132
+ filter,
125
133
  propagationFilter,
126
134
  headers,
127
135
  hooks
@@ -9,6 +9,7 @@ const tags = require('../../../ext/tags')
9
9
  const kinds = require('../../../ext/kinds')
10
10
  const formats = require('../../../ext/formats')
11
11
  const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
12
+ const urlFilter = require('../../dd-trace/src/plugins/util/urlfilter')
12
13
 
13
14
  const HTTP_HEADERS = formats.HTTP_HEADERS
14
15
  const HTTP_STATUS_CODE = tags.HTTP_STATUS_CODE
@@ -36,9 +37,10 @@ class Http2ClientPlugin extends Plugin {
36
37
  const pathname = path.split(/[?#]/)[0]
37
38
  const method = headers[HTTP2_HEADER_METHOD] || HTTP2_METHOD_GET
38
39
  const uri = `${sessionDetails.protocol}//${sessionDetails.host}:${sessionDetails.port}${pathname}`
40
+ const allowed = this.config.filter(uri)
39
41
 
40
42
  const store = storage.getStore()
41
- const childOf = store ? store.span : store
43
+ const childOf = store && allowed ? store.span : null
42
44
  const span = this.tracer.startSpan('http.request', {
43
45
  childOf,
44
46
  tags: {
@@ -51,6 +53,11 @@ class Http2ClientPlugin extends Plugin {
51
53
  }
52
54
  })
53
55
 
56
+ // TODO: Figure out a better way to do this for any span.
57
+ if (!allowed) {
58
+ span._spanContext._trace.record = false
59
+ }
60
+
54
61
  addHeaderTags(span, headers, HTTP_REQUEST_HEADERS, this.config)
55
62
 
56
63
  if (!hasAmazonSignature(headers, path)) {
@@ -155,14 +162,24 @@ function getStatusValidator (config) {
155
162
 
156
163
  function normalizeConfig (config) {
157
164
  const validateStatus = getStatusValidator(config)
165
+ const filter = getFilter(config)
158
166
  const headers = getHeaders(config)
159
167
 
160
168
  return Object.assign({}, config, {
161
169
  validateStatus,
170
+ filter,
162
171
  headers
163
172
  })
164
173
  }
165
174
 
175
+ function getFilter (config) {
176
+ config = Object.assign({}, config, {
177
+ blocklist: config.blocklist || []
178
+ })
179
+
180
+ return urlFilter.getFilter(config)
181
+ }
182
+
166
183
  function addHeaderTags (span, headers, prefix, config) {
167
184
  if (!headers) return
168
185
 
@@ -99,6 +99,7 @@ class JestPlugin extends Plugin {
99
99
  return
100
100
  }
101
101
  const testConfiguration = {
102
+ url: this.config.url,
102
103
  site: this.config.site,
103
104
  env: this.tracer._env,
104
105
  service: this.config.service || this.tracer._service,
@@ -130,6 +131,7 @@ class JestPlugin extends Plugin {
130
131
  return onError(gitUploadError)
131
132
  }
132
133
  const testConfiguration = {
134
+ url: this.config.url,
133
135
  site: this.config.site,
134
136
  env: this.tracer._env,
135
137
  service: this.config.service || this.tracer._service,
@@ -17,7 +17,6 @@ class OracledbPlugin extends DatabasePlugin {
17
17
  type: 'sql',
18
18
  kind: 'client',
19
19
  meta: {
20
- 'sql.query': query,
21
20
  'db.user': this.config.user,
22
21
  'db.instance': url.pathname && url.pathname.substring(1),
23
22
  'db.hostname': url.hostname,
@@ -2,6 +2,7 @@ const request = require('../../exporters/common/request')
2
2
  const id = require('../../id')
3
3
 
4
4
  function getItrConfiguration ({
5
+ url,
5
6
  site,
6
7
  env,
7
8
  service,
@@ -14,7 +15,7 @@ function getItrConfiguration ({
14
15
  runtimeVersion,
15
16
  branch
16
17
  }, done) {
17
- const url = new URL(`https://api.${site}`)
18
+ const intakeUrl = url || new URL(`https://api.${site}`)
18
19
 
19
20
  const apiKey = process.env.DATADOG_API_KEY || process.env.DD_API_KEY
20
21
  const appKey = process.env.DATADOG_APP_KEY ||
@@ -35,9 +36,9 @@ function getItrConfiguration ({
35
36
  'dd-application-key': appKey,
36
37
  'Content-Type': 'application/json'
37
38
  },
38
- protocol: url.protocol,
39
- hostname: url.hostname,
40
- port: url.port
39
+ protocol: intakeUrl.protocol,
40
+ hostname: intakeUrl.hostname,
41
+ port: intakeUrl.port
41
42
  }
42
43
 
43
44
  const data = JSON.stringify({
@@ -1,6 +1,7 @@
1
1
  const request = require('../../exporters/common/request')
2
2
 
3
3
  function getSkippableSuites ({
4
+ url,
4
5
  site,
5
6
  env,
6
7
  service,
@@ -12,7 +13,7 @@ function getSkippableSuites ({
12
13
  runtimeName,
13
14
  runtimeVersion
14
15
  }, done) {
15
- const url = new URL(`https://api.${site}`)
16
+ const intakeUrl = url || new URL(`https://api.${site}`)
16
17
 
17
18
  const apiKey = process.env.DATADOG_API_KEY || process.env.DD_API_KEY
18
19
  const appKey = process.env.DATADOG_APP_KEY ||
@@ -33,9 +34,9 @@ function getSkippableSuites ({
33
34
  'Content-Type': 'application/json'
34
35
  },
35
36
  timeout: 15000,
36
- protocol: url.protocol,
37
- hostname: url.hostname,
38
- port: url.port
37
+ protocol: intakeUrl.protocol,
38
+ hostname: intakeUrl.hostname,
39
+ port: intakeUrl.port
39
40
  }
40
41
 
41
42
  const data = JSON.stringify({
@@ -4,6 +4,7 @@ const fs = require('fs')
4
4
  const os = require('os')
5
5
  const URL = require('url').URL
6
6
  const path = require('path')
7
+ const log = require('./log')
7
8
  const pkg = require('./pkg')
8
9
  const coalesce = require('koalas')
9
10
  const tagger = require('./tagger')
@@ -44,6 +45,21 @@ class Config {
44
45
  constructor (options) {
45
46
  options = options || {}
46
47
 
48
+ // Configure the logger first so it can be used to warn about other configs
49
+ this.debug = isTrue(coalesce(
50
+ process.env.DD_TRACE_DEBUG,
51
+ false
52
+ ))
53
+ this.logger = options.logger
54
+ this.logLevel = coalesce(
55
+ options.logLevel,
56
+ process.env.DD_TRACE_LOG_LEVEL,
57
+ 'debug'
58
+ )
59
+
60
+ log.use(this.logger)
61
+ log.toggle(this.debug, this.logLevel, this)
62
+
47
63
  this.tags = {}
48
64
 
49
65
  tagger.add(this.tags, process.env.DD_TAGS)
@@ -128,10 +144,6 @@ class Config {
128
144
  process.env.DD_TRACE_TELEMETRY_ENABLED,
129
145
  !process.env.AWS_LAMBDA_FUNCTION_NAME
130
146
  )
131
- const DD_TRACE_DEBUG = coalesce(
132
- process.env.DD_TRACE_DEBUG,
133
- false
134
- )
135
147
  const DD_TRACE_AGENT_PROTOCOL_VERSION = coalesce(
136
148
  options.protocolVersion,
137
149
  process.env.DD_TRACE_AGENT_PROTOCOL_VERSION,
@@ -295,7 +307,6 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
295
307
  const defaultFlushInterval = inAWSLambda ? 0 : 2000
296
308
 
297
309
  this.tracing = !isFalse(DD_TRACING_ENABLED)
298
- this.debug = isTrue(DD_TRACE_DEBUG)
299
310
  this.logInjection = isTrue(DD_LOGS_INJECTION)
300
311
  this.env = DD_ENV
301
312
  this.url = DD_CIVISIBILITY_AGENTLESS_URL ? new URL(DD_CIVISIBILITY_AGENTLESS_URL)
@@ -309,7 +320,6 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
309
320
  this.clientIpHeaderDisabled = !isTrue(DD_APPSEC_ENABLED)
310
321
  this.clientIpHeader = DD_TRACE_CLIENT_IP_HEADER
311
322
  this.queryStringObfuscation = DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP
312
- this.logger = options.logger
313
323
  this.plugins = !!coalesce(options.plugins, true)
314
324
  this.service = DD_SERVICE
315
325
  this.serviceMapping = DD_SERVICE_MAPPING.length ? fromEntries(
@@ -331,11 +341,6 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
331
341
  this.sampler = sampler
332
342
  this.reportHostname = isTrue(coalesce(options.reportHostname, process.env.DD_TRACE_REPORT_HOSTNAME, false))
333
343
  this.scope = process.env.DD_TRACE_SCOPE
334
- this.logLevel = coalesce(
335
- options.logLevel,
336
- process.env.DD_TRACE_LOG_LEVEL,
337
- 'debug'
338
- )
339
344
  this.profiling = {
340
345
  enabled: isTrue(DD_PROFILING_ENABLED),
341
346
  sourceMap: !isFalse(DD_PROFILING_SOURCE_MAP),
@@ -124,7 +124,8 @@ module.exports = class PluginManager {
124
124
  isIntelligentTestRunnerEnabled,
125
125
  site,
126
126
  experimental,
127
- queryStringObfuscation
127
+ queryStringObfuscation,
128
+ url
128
129
  } = this._tracerConfig
129
130
 
130
131
  const sharedConfig = {}
@@ -156,6 +157,7 @@ module.exports = class PluginManager {
156
157
  }
157
158
 
158
159
  sharedConfig.site = site
160
+ sharedConfig.url = url
159
161
 
160
162
  return sharedConfig
161
163
  }
@@ -29,9 +29,6 @@ class Tracer extends NoopProxy {
29
29
  try {
30
30
  const config = new Config(options) // TODO: support dynamic config
31
31
 
32
- log.use(config.logger)
33
- log.toggle(config.debug, config.logLevel, this)
34
-
35
32
  if (config.profiling.enabled) {
36
33
  // do not stop tracer initialization if the profiler fails to be imported
37
34
  try {
@@ -27,6 +27,7 @@ class SpanProcessor {
27
27
  const { flushMinSpans } = this._config
28
28
  const { started, finished } = trace
29
29
 
30
+ if (trace.record === false) return
30
31
  if (started.length === finished.length || finished.length >= flushMinSpans) {
31
32
  this._prioritySampler.sample(spanContext)
32
33
  this._spanSampler.sample(spanContext)