dd-trace 4.20.0 → 4.22.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 (76) hide show
  1. package/LICENSE-3rdparty.csv +1 -0
  2. package/index.d.ts +29 -0
  3. package/package.json +8 -7
  4. package/packages/datadog-instrumentations/src/aerospike.js +47 -0
  5. package/packages/datadog-instrumentations/src/apollo-server-core.js +41 -0
  6. package/packages/datadog-instrumentations/src/apollo-server.js +83 -0
  7. package/packages/datadog-instrumentations/src/graphql.js +18 -4
  8. package/packages/datadog-instrumentations/src/helpers/hooks.js +3 -0
  9. package/packages/datadog-instrumentations/src/http/client.js +10 -0
  10. package/packages/datadog-instrumentations/src/jest.js +11 -5
  11. package/packages/datadog-instrumentations/src/kafkajs.js +27 -0
  12. package/packages/datadog-instrumentations/src/next.js +18 -6
  13. package/packages/datadog-instrumentations/src/restify.js +1 -1
  14. package/packages/datadog-instrumentations/src/rhea.js +15 -9
  15. package/packages/datadog-plugin-aerospike/src/index.js +113 -0
  16. package/packages/datadog-plugin-graphql/src/resolve.js +26 -18
  17. package/packages/datadog-plugin-http/src/client.js +19 -2
  18. package/packages/datadog-plugin-kafkajs/src/consumer.js +51 -0
  19. package/packages/datadog-plugin-kafkajs/src/producer.js +55 -0
  20. package/packages/datadog-plugin-next/src/index.js +40 -14
  21. package/packages/dd-trace/src/appsec/activation.js +29 -0
  22. package/packages/dd-trace/src/appsec/addresses.js +3 -1
  23. package/packages/dd-trace/src/appsec/api_security_sampler.js +48 -0
  24. package/packages/dd-trace/src/appsec/blocked_templates.js +4 -1
  25. package/packages/dd-trace/src/appsec/blocking.js +95 -43
  26. package/packages/dd-trace/src/appsec/channels.js +4 -1
  27. package/packages/dd-trace/src/appsec/graphql.js +146 -0
  28. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
  29. package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +105 -0
  30. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/constants.js +7 -0
  31. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +12 -19
  32. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/header-sensitive-analyzer.js +20 -0
  33. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/json-sensitive-analyzer.js +6 -10
  34. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js +18 -25
  35. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +79 -85
  36. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +27 -36
  37. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +14 -11
  38. package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +1 -0
  39. package/packages/dd-trace/src/appsec/index.js +32 -31
  40. package/packages/dd-trace/src/appsec/recommended.json +1395 -2
  41. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -1
  42. package/packages/dd-trace/src/appsec/remote_config/index.js +36 -15
  43. package/packages/dd-trace/src/appsec/reporter.js +19 -0
  44. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
  45. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +28 -13
  46. package/packages/dd-trace/src/appsec/waf/waf_manager.js +0 -1
  47. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +17 -1
  48. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +75 -56
  49. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +15 -9
  50. package/packages/dd-trace/src/config.js +36 -2
  51. package/packages/dd-trace/src/datastreams/processor.js +107 -12
  52. package/packages/dd-trace/src/noop/proxy.js +4 -0
  53. package/packages/dd-trace/src/opentracing/span.js +2 -0
  54. package/packages/dd-trace/src/plugins/ci_plugin.js +2 -1
  55. package/packages/dd-trace/src/plugins/index.js +1 -0
  56. package/packages/dd-trace/src/plugins/util/git.js +2 -2
  57. package/packages/dd-trace/src/plugins/util/test.js +3 -2
  58. package/packages/dd-trace/src/plugins/util/user-provided-git.js +3 -2
  59. package/packages/dd-trace/src/profiler.js +5 -3
  60. package/packages/dd-trace/src/profiling/config.js +8 -0
  61. package/packages/dd-trace/src/profiling/profiler.js +17 -10
  62. package/packages/dd-trace/src/profiling/profilers/events.js +181 -83
  63. package/packages/dd-trace/src/profiling/profilers/shared.js +33 -3
  64. package/packages/dd-trace/src/profiling/profilers/space.js +2 -1
  65. package/packages/dd-trace/src/profiling/profilers/wall.js +17 -12
  66. package/packages/dd-trace/src/proxy.js +25 -1
  67. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +5 -0
  68. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
  69. package/packages/dd-trace/src/spanleak.js +98 -0
  70. package/packages/dd-trace/src/startup-log.js +7 -1
  71. package/packages/dd-trace/src/telemetry/dependencies.js +55 -9
  72. package/packages/dd-trace/src/telemetry/index.js +135 -43
  73. package/packages/dd-trace/src/telemetry/logs/index.js +1 -1
  74. package/packages/dd-trace/src/telemetry/send-data.js +47 -5
  75. package/packages/dd-trace/src/tracer.js +4 -0
  76. package/scripts/install_plugin_modules.js +11 -3
@@ -6,6 +6,7 @@ const requirePackageJson = require('../require-package-json')
6
6
  const { sendData } = require('./send-data')
7
7
  const dc = require('dc-polyfill')
8
8
  const { fileURLToPath } = require('url')
9
+ const { isTrue } = require('../../src/util')
9
10
 
10
11
  const savedDependenciesToSend = new Set()
11
12
  const detectedDependencyKeys = new Set()
@@ -14,20 +15,57 @@ const detectedDependencyVersions = new Set()
14
15
  const FILE_URI_START = `file://`
15
16
  const moduleLoadStartChannel = dc.channel('dd-trace:moduleLoadStart')
16
17
 
17
- let immediate, config, application, host
18
+ let immediate, config, application, host, initialLoad
18
19
  let isFirstModule = true
20
+ let getRetryData
21
+ let updateRetryData
19
22
 
23
+ function createBatchPayload (payload) {
24
+ const batchPayload = []
25
+ payload.map(item => {
26
+ batchPayload.push({
27
+ request_type: item.reqType,
28
+ payload: item.payload
29
+ })
30
+ })
31
+
32
+ return batchPayload
33
+ }
20
34
  function waitAndSend (config, application, host) {
21
35
  if (!immediate) {
22
36
  immediate = setImmediate(() => {
23
37
  immediate = null
24
38
  if (savedDependenciesToSend.size > 0) {
25
- const dependencies = Array.from(savedDependenciesToSend.values()).splice(0, 1000).map(pair => {
26
- savedDependenciesToSend.delete(pair)
27
- const [name, version] = pair.split(' ')
28
- return { name, version }
29
- })
30
- sendData(config, application, host, 'app-dependencies-loaded', { dependencies })
39
+ const dependencies = Array.from(savedDependenciesToSend.values())
40
+ // if a depencdency is from the initial load, *always* send the event
41
+ // Otherwise, only send if dependencyCollection is enabled
42
+ .filter(dep => {
43
+ const initialLoadModule = isTrue(dep.split(' ')[2])
44
+ const sendModule = initialLoadModule || (config.telemetry?.dependencyCollection)
45
+
46
+ if (!sendModule) savedDependenciesToSend.delete(dep) // we'll never send it
47
+ return sendModule
48
+ })
49
+ .splice(0, 2000) // v2 documentation specifies up to 2000 dependencies can be sent at once
50
+ .map(pair => {
51
+ savedDependenciesToSend.delete(pair)
52
+ const [name, version] = pair.split(' ')
53
+ return { name, version }
54
+ })
55
+ let currPayload
56
+ const retryData = getRetryData()
57
+ if (retryData) {
58
+ currPayload = { reqType: 'app-dependencies-loaded', payload: { dependencies } }
59
+ } else {
60
+ if (!dependencies.length) return // no retry data and no dependencies, nothing to send
61
+ currPayload = { dependencies }
62
+ }
63
+
64
+ const payload = retryData ? createBatchPayload([currPayload, retryData]) : currPayload
65
+ const reqType = retryData ? 'message-batch' : 'app-dependencies-loaded'
66
+
67
+ sendData(config, application, host, reqType, payload, updateRetryData)
68
+
31
69
  if (savedDependenciesToSend.size > 0) {
32
70
  waitAndSend(config, application, host)
33
71
  }
@@ -76,7 +114,7 @@ function onModuleLoad (data) {
76
114
  const dependencyAndVersion = `${name} ${version}`
77
115
 
78
116
  if (!detectedDependencyVersions.has(dependencyAndVersion)) {
79
- savedDependenciesToSend.add(dependencyAndVersion)
117
+ savedDependenciesToSend.add(`${dependencyAndVersion} ${initialLoad}`)
80
118
  detectedDependencyVersions.add(dependencyAndVersion)
81
119
 
82
120
  waitAndSend(config, application, host)
@@ -89,11 +127,19 @@ function onModuleLoad (data) {
89
127
  }
90
128
  }
91
129
  }
92
- function start (_config, _application, _host) {
130
+ function start (_config = {}, _application, _host, getRetryDataFunction, updateRetryDatafunction) {
93
131
  config = _config
94
132
  application = _application
95
133
  host = _host
134
+ initialLoad = true
135
+ getRetryData = getRetryDataFunction
136
+ updateRetryData = updateRetryDatafunction
96
137
  moduleLoadStartChannel.subscribe(onModuleLoad)
138
+
139
+ // try and capture intially loaded modules in the first tick
140
+ // since, ideally, the tracer (and this module) should be loaded first,
141
+ // this should capture any first-tick dependencies
142
+ queueMicrotask(() => { initialLoad = false })
97
143
  }
98
144
 
99
145
  function isDependency (filename, request) {
@@ -1,13 +1,11 @@
1
1
  'use strict'
2
-
3
2
  const tracerVersion = require('../../../../package.json').version
4
3
  const dc = require('dc-polyfill')
5
4
  const os = require('os')
6
5
  const dependencies = require('./dependencies')
7
6
  const { sendData } = require('./send-data')
8
-
7
+ const { errors } = require('../startup-log')
9
8
  const { manager: metricsManager } = require('./metrics')
10
- const logs = require('./logs')
11
9
 
12
10
  const telemetryStartChannel = dc.channel('datadog:telemetry:start')
13
11
  const telemetryStopChannel = dc.channel('datadog:telemetry:stop')
@@ -17,11 +15,53 @@ let pluginManager
17
15
 
18
16
  let application
19
17
  let host
20
- let interval
21
18
  let heartbeatTimeout
22
19
  let heartbeatInterval
20
+ let extendedInterval
21
+ let integrations
22
+ let retryData = null
23
+ const extendedHeartbeatPayload = {}
24
+
23
25
  const sentIntegrations = new Set()
24
26
 
27
+ function getRetryData () {
28
+ return retryData
29
+ }
30
+
31
+ function updateRetryData (error, retryObj) {
32
+ if (error) {
33
+ if (retryObj.reqType === 'message-batch') {
34
+ const payload = retryObj.payload[0].payload
35
+ const reqType = retryObj.payload[0].request_type
36
+ retryData = { payload: payload, reqType: reqType }
37
+
38
+ // Since this payload failed twice it now gets save in to the extended heartbeat
39
+ const failedPayload = retryObj.payload[1].payload
40
+ const failedReqType = retryObj.payload[1].request_type
41
+
42
+ // save away the dependencies and integration request for extended heartbeat.
43
+ if (failedReqType === 'app-integrations-change') {
44
+ if (extendedHeartbeatPayload['integrations']) {
45
+ extendedHeartbeatPayload['integrations'].push(failedPayload)
46
+ } else {
47
+ extendedHeartbeatPayload['integrations'] = [failedPayload]
48
+ }
49
+ }
50
+ if (failedReqType === 'app-dependencies-loaded') {
51
+ if (extendedHeartbeatPayload['dependencies']) {
52
+ extendedHeartbeatPayload['dependencies'].push(failedPayload)
53
+ } else {
54
+ extendedHeartbeatPayload['dependencies'] = [failedPayload]
55
+ }
56
+ }
57
+ } else {
58
+ retryData = retryObj
59
+ }
60
+ } else {
61
+ retryData = null
62
+ }
63
+ }
64
+
25
65
  function getIntegrations () {
26
66
  const newIntegrations = []
27
67
  for (const pluginName in pluginManager._pluginsByName) {
@@ -38,6 +78,23 @@ function getIntegrations () {
38
78
  return newIntegrations
39
79
  }
40
80
 
81
+ function getProducts (config) {
82
+ const products = {
83
+ appsec: {
84
+ enabled: config.appsec.enabled
85
+ },
86
+ profiler: {
87
+ version: tracerVersion,
88
+ enabled: config.profiling.enabled
89
+ }
90
+ }
91
+ if (errors.profilingError) {
92
+ products.profiler.error = errors.profilingError
93
+ errors.profilingError = {}
94
+ }
95
+ return products
96
+ }
97
+
41
98
  function flatten (input, result = [], prefix = [], traversedObjects = null) {
42
99
  traversedObjects = traversedObjects || new WeakSet()
43
100
  if (traversedObjects.has(input)) {
@@ -48,33 +105,30 @@ function flatten (input, result = [], prefix = [], traversedObjects = null) {
48
105
  if (typeof value === 'object' && value !== null) {
49
106
  flatten(value, result, [...prefix, key], traversedObjects)
50
107
  } else {
51
- result.push({ name: [...prefix, key].join('.'), value })
108
+ // TODO: add correct origin value
109
+ result.push({ name: [...prefix, key].join('.'), value, origin: 'unknown' })
52
110
  }
53
111
  }
54
112
  return result
55
113
  }
56
114
 
57
- function appStarted () {
58
- return {
59
- integrations: getIntegrations(),
60
- dependencies: [],
61
- configuration: flatten(formatConfig(config)),
62
- additional_payload: []
115
+ function appStarted (config) {
116
+ const app = {
117
+ products: getProducts(config),
118
+ configuration: flatten(config)
63
119
  }
64
- }
65
-
66
- function formatConfig (config) {
67
- // format peerServiceMapping from an object to a string map in order for
68
- // telemetry intake to accept the configuration
69
- config.peerServiceMapping = config.peerServiceMapping
70
- ? Object.entries(config.peerServiceMapping).map(([key, value]) => `${key}:${value}`).join(',')
71
- : ''
72
- return config
120
+ // TODO: add app.error with correct error codes
121
+ // if (errors.agentError) {
122
+ // app.error = errors.agentError
123
+ // errors.agentError = {}
124
+ // }
125
+ return app
73
126
  }
74
127
 
75
128
  function onBeforeExit () {
76
129
  process.removeListener('beforeExit', onBeforeExit)
77
- sendData(config, application, host, 'app-closing')
130
+ const { reqType, payload } = createPayload('app-closing')
131
+ sendData(config, application, host, reqType, payload)
78
132
  }
79
133
 
80
134
  function createAppObject (config) {
@@ -121,14 +175,52 @@ function getTelemetryData () {
121
175
  return { config, application, host, heartbeatInterval }
122
176
  }
123
177
 
178
+ function createBatchPayload (payload) {
179
+ const batchPayload = []
180
+ payload.map(item => {
181
+ batchPayload.push({
182
+ request_type: item.reqType,
183
+ payload: item.payload
184
+ })
185
+ })
186
+
187
+ return batchPayload
188
+ }
189
+
190
+ function createPayload (currReqType, currPayload = {}) {
191
+ if (getRetryData()) {
192
+ const payload = { reqType: currReqType, payload: currPayload }
193
+ const batchPayload = createBatchPayload([payload, retryData])
194
+ return { 'reqType': 'message-batch', 'payload': batchPayload }
195
+ }
196
+
197
+ return { 'reqType': currReqType, 'payload': currPayload }
198
+ }
199
+
124
200
  function heartbeat (config, application, host) {
125
201
  heartbeatTimeout = setTimeout(() => {
126
- sendData(config, application, host, 'app-heartbeat')
202
+ metricsManager.send(config, application, host)
203
+
204
+ const { reqType, payload } = createPayload('app-heartbeat')
205
+ sendData(config, application, host, reqType, payload, updateRetryData)
127
206
  heartbeat(config, application, host)
128
207
  }, heartbeatInterval).unref()
129
208
  return heartbeatTimeout
130
209
  }
131
210
 
211
+ function extendedHeartbeat (config) {
212
+ extendedInterval = setInterval(() => {
213
+ const appPayload = appStarted(config)
214
+ const payload = {
215
+ ...appPayload,
216
+ ...extendedHeartbeatPayload
217
+ }
218
+ sendData(config, application, host, 'app-extended-heartbeat', payload)
219
+ Object.keys(extendedHeartbeatPayload).forEach(key => delete extendedHeartbeatPayload[key])
220
+ }, 1000 * 60 * 60 * 24).unref()
221
+ return extendedInterval
222
+ }
223
+
132
224
  function start (aConfig, thePluginManager) {
133
225
  if (!aConfig.telemetry.enabled) {
134
226
  return
@@ -138,19 +230,22 @@ function start (aConfig, thePluginManager) {
138
230
  application = createAppObject(config)
139
231
  host = createHostObject()
140
232
  heartbeatInterval = config.telemetry.heartbeatInterval
233
+ integrations = getIntegrations()
234
+
235
+ dependencies.start(config, application, host, getRetryData, updateRetryData)
236
+
237
+ sendData(config, application, host, 'app-started', appStarted(config))
141
238
 
142
- dependencies.start(config, application, host)
143
- logs.start(config)
239
+ if (integrations.length > 0) {
240
+ sendData(config, application, host, 'app-integrations-change',
241
+ { integrations }, updateRetryData)
242
+ }
144
243
 
145
- sendData(config, application, host, 'app-started', appStarted())
146
244
  heartbeat(config, application, host)
147
- interval = setInterval(() => {
148
- metricsManager.send(config, application, host)
149
- logs.send(config, application, host)
150
- }, heartbeatInterval)
151
- interval.unref()
152
- process.on('beforeExit', onBeforeExit)
153
245
 
246
+ extendedHeartbeat(config)
247
+
248
+ process.on('beforeExit', onBeforeExit)
154
249
  telemetryStartChannel.publish(getTelemetryData())
155
250
  }
156
251
 
@@ -158,7 +253,7 @@ function stop () {
158
253
  if (!config) {
159
254
  return
160
255
  }
161
- clearInterval(interval)
256
+ clearInterval(extendedInterval)
162
257
  clearTimeout(heartbeatTimeout)
163
258
  process.removeListener('beforeExit', onBeforeExit)
164
259
 
@@ -175,7 +270,10 @@ function updateIntegrations () {
175
270
  if (integrations.length === 0) {
176
271
  return
177
272
  }
178
- sendData(config, application, host, 'app-integrations-change', { integrations })
273
+
274
+ const { reqType, payload } = createPayload('app-integrations-change', { integrations })
275
+
276
+ sendData(config, application, host, reqType, payload, updateRetryData)
179
277
  }
180
278
 
181
279
  function updateConfig (changes, config) {
@@ -188,21 +286,15 @@ function updateConfig (changes, config) {
188
286
  const application = createAppObject(config)
189
287
  const host = createHostObject()
190
288
 
191
- const names = {
192
- sampleRate: 'DD_TRACE_SAMPLE_RATE',
193
- logInjection: 'DD_LOG_INJECTION',
194
- headerTags: 'DD_TRACE_HEADER_TAGS'
195
- }
196
-
197
289
  const configuration = changes.map(change => ({
198
- name: names[change.name],
290
+ name: change.name,
199
291
  value: Array.isArray(change.value) ? change.value.join(',') : change.value,
200
292
  origin: change.origin
201
293
  }))
202
294
 
203
- sendData(config, application, host, 'app-client-configuration-change', {
204
- configuration
205
- })
295
+ const { reqType, payload } = createPayload('app-client-configuration-change', { configuration })
296
+
297
+ sendData(config, application, host, reqType, payload, updateRetryData)
206
298
  }
207
299
 
208
300
  module.exports = {
@@ -52,7 +52,7 @@ function stop () {
52
52
  function send (config, application, host) {
53
53
  if (!enabled) return
54
54
 
55
- const logs = logCollector.drain()
55
+ const logs = { 'logs': logCollector.drain() }
56
56
  if (logs) {
57
57
  sendData(config, application, host, 'logs', logs)
58
58
  }
@@ -1,9 +1,12 @@
1
+
1
2
  const request = require('../exporters/common/request')
3
+ const log = require('../log')
4
+ let agentTelemetry = true
2
5
 
3
6
  function getHeaders (config, application, reqType) {
4
7
  const headers = {
5
8
  'content-type': 'application/json',
6
- 'dd-telemetry-api-version': 'v1',
9
+ 'dd-telemetry-api-version': 'v2',
7
10
  'dd-telemetry-request-type': reqType,
8
11
  'dd-client-library-language': application.language_name,
9
12
  'dd-client-library-version': application.tracer_version
@@ -28,7 +31,7 @@ function getPayload (payload) {
28
31
  }
29
32
  }
30
33
 
31
- function sendData (config, application, host, reqType, payload = {}) {
34
+ function sendData (config, application, host, reqType, payload = {}, cb = () => {}) {
32
35
  const {
33
36
  hostname,
34
37
  port,
@@ -44,7 +47,8 @@ function sendData (config, application, host, reqType, payload = {}) {
44
47
  headers: getHeaders(config, application, reqType)
45
48
  }
46
49
  const data = JSON.stringify({
47
- api_version: 'v1',
50
+ api_version: 'v2',
51
+ naming_schema_version: config.spanAttributeSchema ? config.spanAttributeSchema : '',
48
52
  request_type: reqType,
49
53
  tracer_time: Math.floor(Date.now() / 1000),
50
54
  runtime_id: config.tags['runtime-id'],
@@ -54,8 +58,46 @@ function sendData (config, application, host, reqType, payload = {}) {
54
58
  host
55
59
  })
56
60
 
57
- request(data, options, () => {
58
- // ignore errors
61
+ request(data, options, (error) => {
62
+ if (error && process.env.DD_API_KEY && config.site) {
63
+ if (agentTelemetry) {
64
+ log.warn('Agent telemetry failed, started agentless telemetry')
65
+ agentTelemetry = false
66
+ }
67
+ // figure out which data center to send to
68
+ let backendUrl
69
+ const dataCenters = [
70
+ 'datadoghq.com',
71
+ 'us3.datadoghq.com',
72
+ 'us5.datadoghq.com',
73
+ 'ap1.datadoghq.com',
74
+ 'eu1.datadoghq.com'
75
+ ]
76
+ if (config.site === 'datad0g.com') { // staging
77
+ backendUrl = 'https://all-http-intake.logs.datad0g.com/api/v2/apmtelemetry'
78
+ } else if (dataCenters.includes(config.site)) {
79
+ backendUrl = 'https://instrumentation-telemetry-intake.' + config.site + '/api/v2/apmtelemetry'
80
+ }
81
+ const backendHeader = { ...options.headers, 'DD-API-KEY': process.env.DD_API_KEY }
82
+ const backendOptions = {
83
+ ...options,
84
+ url: backendUrl,
85
+ headers: backendHeader
86
+ }
87
+ if (backendUrl) {
88
+ request(data, backendOptions, (error) => { log.error(error) })
89
+ } else {
90
+ log.error('Invalid Telemetry URL')
91
+ }
92
+ }
93
+
94
+ if (!error && !agentTelemetry) {
95
+ agentTelemetry = true
96
+ log.info('Started agent telemetry')
97
+ }
98
+
99
+ // call the callback function so that we can track the error and payload
100
+ cb(error, { payload, reqType })
59
101
  })
60
102
  }
61
103
 
@@ -46,6 +46,10 @@ class DatadogTracer extends Tracer {
46
46
  return ctx
47
47
  }
48
48
 
49
+ setOffset (offsetData) {
50
+ return this._dataStreamsProcessor.setOffset(offsetData)
51
+ }
52
+
49
53
  trace (name, options, fn) {
50
54
  options = Object.assign({
51
55
  childOf: this.scope().active()
@@ -80,7 +80,9 @@ async function assertVersions () {
80
80
  }
81
81
 
82
82
  async function assertInstrumentation (instrumentation, external) {
83
- const versions = [].concat(instrumentation.versions || [])
83
+ const versions = process.env.PACKAGE_VERSION_RANGE ? [process.env.PACKAGE_VERSION_RANGE]
84
+ : [].concat(instrumentation.versions || [])
85
+
84
86
  for (const version of versions) {
85
87
  if (version) {
86
88
  await assertModules(instrumentation.name, semver.coerce(version).version, external)
@@ -130,8 +132,14 @@ async function assertPackage (name, version, dependency, external) {
130
132
  }
131
133
 
132
134
  if (!external) {
133
- pkg.workspaces = {
134
- nohoist: ['**/**']
135
+ if (name === 'aerospike') {
136
+ pkg.installConfig = {
137
+ 'hoistingLimits': 'workspaces'
138
+ }
139
+ } else {
140
+ pkg.workspaces = {
141
+ nohoist: ['**/**']
142
+ }
135
143
  }
136
144
  }
137
145
  fs.writeFileSync(filename(name, version, 'package.json'), JSON.stringify(pkg, null, 2) + '\n')