dd-trace 3.0.0-pre.1 → 3.1.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 (71) hide show
  1. package/LICENSE-3rdparty.csv +2 -2
  2. package/MIGRATING.md +119 -0
  3. package/ci/init.js +0 -1
  4. package/ext/formats.js +3 -5
  5. package/index.d.ts +1 -11
  6. package/package.json +7 -7
  7. package/packages/datadog-core/src/storage/async_resource.js +19 -1
  8. package/packages/datadog-core/src/storage/index.js +1 -1
  9. package/packages/datadog-instrumentations/index.js +1 -52
  10. package/packages/datadog-instrumentations/src/connect.js +1 -1
  11. package/packages/datadog-instrumentations/src/cucumber.js +15 -0
  12. package/packages/datadog-instrumentations/src/grpc/client.js +2 -2
  13. package/packages/datadog-instrumentations/src/grpc/server.js +1 -1
  14. package/packages/datadog-instrumentations/src/hapi.js +3 -31
  15. package/packages/datadog-instrumentations/src/helpers/hooks.js +68 -0
  16. package/packages/datadog-instrumentations/src/helpers/instrument.js +5 -34
  17. package/packages/datadog-instrumentations/src/helpers/instrumentations.js +7 -0
  18. package/packages/datadog-instrumentations/src/helpers/register.js +59 -0
  19. package/packages/datadog-instrumentations/src/jest.js +33 -11
  20. package/packages/datadog-instrumentations/src/koa.js +1 -1
  21. package/packages/datadog-instrumentations/src/mocha.js +4 -1
  22. package/packages/datadog-instrumentations/src/pg.js +2 -2
  23. package/packages/datadog-instrumentations/src/restify.js +27 -5
  24. package/packages/datadog-instrumentations/src/router.js +1 -1
  25. package/packages/datadog-plugin-aws-sdk/src/base.js +1 -2
  26. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -2
  27. package/packages/datadog-plugin-cucumber/src/index.js +4 -0
  28. package/packages/datadog-plugin-jest/src/index.js +25 -4
  29. package/packages/datadog-plugin-mocha/src/index.js +2 -2
  30. package/packages/datadog-plugin-mongodb-core/src/index.js +21 -6
  31. package/packages/datadog-plugin-oracledb/src/index.js +12 -4
  32. package/packages/datadog-plugin-restify/src/index.js +7 -0
  33. package/packages/dd-trace/index.js +1 -1
  34. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +50 -0
  35. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +53 -8
  36. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +23 -24
  37. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +220 -0
  38. package/packages/dd-trace/src/config.js +13 -0
  39. package/packages/dd-trace/src/encode/0.4.js +51 -58
  40. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +13 -34
  41. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +84 -0
  42. package/packages/dd-trace/src/exporters/agent/index.js +13 -7
  43. package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
  44. package/packages/dd-trace/src/{profiling/exporters → exporters/common}/form-data.js +0 -0
  45. package/packages/dd-trace/src/exporters/common/request.js +23 -11
  46. package/packages/dd-trace/src/exporters/common/writer.js +9 -6
  47. package/packages/dd-trace/src/id.js +16 -13
  48. package/packages/dd-trace/src/iitm.js +1 -1
  49. package/packages/dd-trace/src/index.js +10 -0
  50. package/packages/dd-trace/src/noop/proxy.js +77 -0
  51. package/packages/dd-trace/src/noop/scope.js +2 -6
  52. package/packages/dd-trace/src/noop/span.js +12 -12
  53. package/packages/dd-trace/src/noop/tracer.js +8 -5
  54. package/packages/dd-trace/src/opentracing/propagation/text_map.js +6 -6
  55. package/packages/dd-trace/src/opentracing/span.js +63 -49
  56. package/packages/dd-trace/src/opentracing/span_context.js +1 -5
  57. package/packages/dd-trace/src/opentracing/tracer.js +31 -36
  58. package/packages/dd-trace/src/plugin_manager.js +101 -68
  59. package/packages/dd-trace/src/plugins/index.js +57 -44
  60. package/packages/dd-trace/src/plugins/util/ci.js +34 -9
  61. package/packages/dd-trace/src/plugins/util/git.js +52 -2
  62. package/packages/dd-trace/src/plugins/util/tags.js +4 -1
  63. package/packages/dd-trace/src/plugins/util/web.js +1 -1
  64. package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
  65. package/packages/dd-trace/src/profiling/profilers/cpu.js +3 -3
  66. package/packages/dd-trace/src/proxy.js +18 -71
  67. package/packages/dd-trace/src/scope.js +1 -58
  68. package/packages/dd-trace/src/startup-log.js +8 -19
  69. package/packages/dd-trace/src/telemetry.js +2 -15
  70. package/scripts/install_plugin_modules.js +17 -26
  71. package/ci/jest/env.js +0 -38
@@ -1,11 +1,7 @@
1
1
  'use strict'
2
2
 
3
- const opentracing = require('opentracing')
4
3
  const os = require('os')
5
- const Tracer = opentracing.Tracer
6
- const Reference = opentracing.Reference
7
4
  const Span = require('./span')
8
- const SpanContext = require('./span_context')
9
5
  const SpanProcessor = require('../span_processor')
10
6
  const PrioritySampler = require('../priority_sampler')
11
7
  const TextMapPropagator = require('./propagation/text_map')
@@ -17,14 +13,13 @@ const formats = require('../../../../ext/formats')
17
13
  const log = require('../log')
18
14
  const metrics = require('../metrics')
19
15
  const getExporter = require('../exporter')
16
+ const SpanContext = require('./span_context')
20
17
 
21
- const REFERENCE_CHILD_OF = opentracing.REFERENCE_CHILD_OF
22
- const REFERENCE_FOLLOWS_FROM = opentracing.REFERENCE_FOLLOWS_FROM
18
+ const REFERENCE_CHILD_OF = 'child_of'
19
+ const REFERENCE_FOLLOWS_FROM = 'follows_from'
23
20
 
24
- class DatadogTracer extends Tracer {
21
+ class DatadogTracer {
25
22
  constructor (config) {
26
- super()
27
-
28
23
  const Exporter = getExporter(config.experimental.exporter)
29
24
 
30
25
  this._service = config.service
@@ -49,32 +44,34 @@ class DatadogTracer extends Tracer {
49
44
  }
50
45
  }
51
46
 
52
- _startSpan (name, fields) {
53
- const reference = getParent(fields.references)
54
- const parent = reference && reference.referencedContext()
55
- return this._startSpanInternal(name, fields, parent)
56
- }
47
+ startSpan (name, options = {}) {
48
+ const parent = options.childOf
49
+ ? getContext(options.childOf)
50
+ : getParent(options.references)
57
51
 
58
- _startSpanInternal (name, fields = {}, parent) {
59
52
  const tags = {
60
53
  'service.name': this._service
61
54
  }
62
55
 
63
56
  const span = new Span(this, this._processor, this._prioritySampler, {
64
- operationName: fields.operationName || name,
57
+ operationName: options.operationName || name,
65
58
  parent,
66
59
  tags,
67
- startTime: fields.startTime,
60
+ startTime: options.startTime,
68
61
  hostname: this._hostname
69
62
  }, this._debug)
70
63
 
71
64
  span.addTags(this._tags)
72
- span.addTags(fields.tags)
65
+ span.addTags(options.tags)
73
66
 
74
67
  return span
75
68
  }
76
69
 
77
- _inject (spanContext, format, carrier) {
70
+ inject (spanContext, format, carrier) {
71
+ if (spanContext instanceof Span) {
72
+ spanContext = spanContext.context()
73
+ }
74
+
78
75
  try {
79
76
  this._prioritySampler.sample(spanContext)
80
77
  this._propagators[format].inject(spanContext, carrier)
@@ -82,11 +79,9 @@ class DatadogTracer extends Tracer {
82
79
  log.error(e)
83
80
  metrics.increment('datadog.tracer.node.inject.errors', true)
84
81
  }
85
-
86
- return this
87
82
  }
88
83
 
89
- _extract (format, carrier) {
84
+ extract (format, carrier) {
90
85
  try {
91
86
  return this._propagators[format].extract(carrier)
92
87
  } catch (e) {
@@ -97,31 +92,31 @@ class DatadogTracer extends Tracer {
97
92
  }
98
93
  }
99
94
 
95
+ function getContext (spanContext) {
96
+ if (spanContext instanceof Span) {
97
+ spanContext = spanContext.context()
98
+ }
99
+
100
+ if (!(spanContext instanceof SpanContext)) {
101
+ spanContext = null
102
+ }
103
+
104
+ return spanContext
105
+ }
106
+
100
107
  function getParent (references = []) {
101
108
  let parent = null
102
109
 
103
110
  for (let i = 0; i < references.length; i++) {
104
111
  const ref = references[i]
105
-
106
- if (!(ref instanceof Reference)) {
107
- log.error(() => `Expected ${ref} to be an instance of opentracing.Reference`)
108
- continue
109
- }
110
-
111
- const spanContext = ref.referencedContext()
112
112
  const type = ref.type()
113
113
 
114
- if (spanContext && !(spanContext instanceof SpanContext)) {
115
- log.error(() => `Expected ${spanContext} to be an instance of SpanContext`)
116
- continue
117
- }
118
-
119
114
  if (type === REFERENCE_CHILD_OF) {
120
- parent = ref
115
+ parent = ref.referencedContext()
121
116
  break
122
117
  } else if (type === REFERENCE_FOLLOWS_FROM) {
123
118
  if (!parent) {
124
- parent = ref
119
+ parent = ref.referencedContext()
125
120
  }
126
121
  }
127
122
  }
@@ -1,116 +1,149 @@
1
1
  'use strict'
2
2
 
3
- const { isTrue } = require('./util')
3
+ const { channel } = require('diagnostics_channel')
4
+ const { isFalse } = require('./util')
4
5
  const plugins = require('./plugins')
5
6
  const log = require('./log')
6
7
 
8
+ const loadChannel = channel('dd-trace:instrumentation:load')
9
+
7
10
  // instrument everything that needs Plugin System V2 instrumentation
8
11
  require('../../datadog-instrumentations')
9
12
 
10
- // TODO this is shared w/ instrumenter. DRY up.
11
- function getConfig (name, config = {}) {
12
- const enabled = process.env[`DD_TRACE_${name.toUpperCase()}_ENABLED`.replace(/[^a-z0-9_]/ig, '_')]
13
- if (enabled !== undefined) {
14
- config.enabled = isTrue(enabled)
15
- }
13
+ const { DD_TRACE_DISABLED_PLUGINS } = process.env
16
14
 
17
- // TODO is this the best/correct place for this default?
18
- if (!('enabled' in config)) {
19
- config.enabled = true
20
- }
15
+ const disabledPlugins = new Set(
16
+ DD_TRACE_DISABLED_PLUGINS && DD_TRACE_DISABLED_PLUGINS.split(',').map(plugin => plugin.trim())
17
+ )
21
18
 
22
- return config
23
- }
19
+ // TODO actually ... should we be looking at envrionment variables this deep down in the code?
24
20
 
25
- // TODO: maybe needs to DRY up as well, but depending on how the remaining old plugins
26
- // are migrated to the new system, can stay here for now, since this is the level
27
- // this check maybe should be happening on, even if it deals with env variabls
28
- const disabledPlugins = process.env.DD_TRACE_DISABLED_PLUGINS
21
+ const pluginClasses = {}
29
22
 
30
- const collectDisabledPlugins = () => {
31
- return new Set(disabledPlugins && disabledPlugins.split(',').map(plugin => plugin.trim()))
32
- }
23
+ loadChannel.subscribe(({ name }) => {
24
+ const Plugin = plugins[name]
33
25
 
34
- // TODO actually ... should we be looking at envrionment variables this deep down in the code?
26
+ if (!Plugin || typeof Plugin !== 'function') return
27
+ if (!pluginClasses[Plugin.name]) {
28
+ const envName = `DD_TRACE_${Plugin.name.toUpperCase()}_ENABLED`
29
+ const enabled = process.env[envName.replace(/[^a-z0-9_]/ig, '_')]
30
+
31
+ // TODO: remove the need to load the plugin class in order to disable the plugin
32
+ if (isFalse(enabled) || disabledPlugins.has(Plugin.name)) {
33
+ log.debug(`Plugin "${Plugin.name}" was disabled via configuration option.`)
34
+
35
+ pluginClasses[Plugin.name] = null
36
+ } else {
37
+ pluginClasses[Plugin.name] = Plugin
38
+ }
39
+ }
40
+ })
35
41
 
36
42
  // TODO this must always be a singleton.
37
43
  module.exports = class PluginManager {
38
44
  constructor (tracer) {
39
45
  this._tracer = tracer
46
+ this._tracerConfig = null
40
47
  this._pluginsByName = {}
41
48
  this._configsByName = {}
42
- this._disabledPlugins = collectDisabledPlugins()
49
+
50
+ this._loadedSubscriber = ({ name }) => {
51
+ const Plugin = plugins[name]
52
+
53
+ if (!Plugin || typeof Plugin !== 'function') return
54
+
55
+ this.loadPlugin(Plugin.name)
56
+ }
57
+
58
+ loadChannel.subscribe(this._loadedSubscriber)
43
59
  }
44
60
 
45
- // like instrumenter.use()
46
- configurePlugin (name, pluginConfig) {
47
- if (typeof pluginConfig === 'boolean') {
48
- pluginConfig = { enabled: pluginConfig }
61
+ loadPlugin (name) {
62
+ const Plugin = pluginClasses[name]
63
+
64
+ if (!Plugin) return
65
+ if (!this._pluginsByName[name]) {
66
+ this._pluginsByName[name] = new Plugin(this._tracer)
49
67
  }
50
- if (!pluginConfig) {
51
- pluginConfig = { enabled: true }
68
+ if (!this._tracerConfig) return // TODO: don't wait for tracer to be initialized
69
+
70
+ const pluginConfig = this._configsByName[name] || {
71
+ enabled: this._tracerConfig.plugins !== false
52
72
  }
53
73
 
54
- this._configsByName[name] = {
55
- ...this._configsByName[name],
74
+ this._pluginsByName[name].configure({
75
+ ...this._getSharedConfig(name),
56
76
  ...pluginConfig
57
- }
77
+ })
78
+ }
79
+
80
+ // TODO: merge config instead of replacing
81
+ configurePlugin (name, pluginConfig) {
82
+ const enabled = this._isEnabled(pluginConfig)
58
83
 
59
- if (this._pluginsByName[name]) {
60
- this._pluginsByName[name].configure(getConfig(name, this._configsByName[name]))
84
+ this._configsByName[name] = {
85
+ ...pluginConfig,
86
+ enabled
61
87
  }
88
+
89
+ this.loadPlugin(name)
62
90
  }
63
91
 
64
92
  // like instrumenter.enable()
65
93
  configure (config = {}) {
66
- const { logInjection, serviceMapping, experimental, queryStringObfuscation } = config
94
+ this._tracerConfig = config
67
95
 
68
- for (const PluginClass of Object.values(plugins)) {
69
- const name = PluginClass.name
70
-
71
- if (this._disabledPlugins.has(name)) {
72
- log.debug(`Plugin "${name}" was disabled via configuration option.`)
73
- continue
74
- }
96
+ for (const name in pluginClasses) {
97
+ this.loadPlugin(name)
98
+ }
99
+ }
75
100
 
76
- if (typeof PluginClass !== 'function') continue
101
+ // This is basically just for testing. like intrumenter.disable()
102
+ destroy () {
103
+ for (const name in this._pluginsByName) {
104
+ this._pluginsByName[name].configure({ enabled: false })
105
+ }
77
106
 
78
- this._pluginsByName[name] = new PluginClass(this._tracer)
107
+ loadChannel.unsubscribe(this._loadedSubscriber)
108
+ }
79
109
 
80
- if (config.plugins === false) continue
110
+ _isEnabled (pluginConfig) {
111
+ if (typeof pluginConfig === 'boolean') return pluginConfig
112
+ if (!pluginConfig) return true
81
113
 
82
- const pluginConfig = {
83
- ...this._configsByName[name]
84
- }
114
+ return pluginConfig.enabled !== false
115
+ }
85
116
 
86
- if (logInjection !== undefined) {
87
- pluginConfig.logInjection = logInjection
88
- }
117
+ // TODO: figure out a better way to handle this
118
+ _getSharedConfig (name) {
119
+ const {
120
+ logInjection,
121
+ serviceMapping,
122
+ experimental,
123
+ queryStringObfuscation,
124
+ isIntelligentTestRunnerEnabled
125
+ } = this._tracerConfig
89
126
 
90
- if (queryStringObfuscation !== undefined) {
91
- pluginConfig.queryStringObfuscation = queryStringObfuscation
92
- }
127
+ const sharedConfig = {}
93
128
 
94
- // TODO: update so that it's available for every CI Visibility's plugin
95
- if (name === 'mocha') {
96
- pluginConfig.isAgentlessEnabled = experimental && experimental.exporter === 'datadog'
97
- }
129
+ if (logInjection !== undefined) {
130
+ sharedConfig.logInjection = logInjection
131
+ }
98
132
 
99
- if (serviceMapping && serviceMapping[name]) {
100
- pluginConfig.service = serviceMapping[name]
101
- }
133
+ if (queryStringObfuscation !== undefined) {
134
+ sharedConfig.queryStringObfuscation = queryStringObfuscation
135
+ }
102
136
 
103
- this.configurePlugin(name, pluginConfig)
137
+ if (experimental) {
138
+ sharedConfig.isAgentlessEnabled = experimental.exporter === 'datadog'
104
139
  }
105
- }
106
140
 
107
- // This is basically just for testing. like intrumenter.disable()
108
- destroy () {
109
- for (const name in this._pluginsByName) {
110
- this._pluginsByName[name].configure({ enabled: false })
141
+ sharedConfig.isIntelligentTestRunnerEnabled = isIntelligentTestRunnerEnabled
142
+
143
+ if (serviceMapping && serviceMapping[name]) {
144
+ sharedConfig.service = serviceMapping[name]
111
145
  }
112
146
 
113
- this._pluginsByName = {}
114
- this._configsByName = {}
147
+ return sharedConfig
115
148
  }
116
149
  }
@@ -1,48 +1,61 @@
1
1
  'use strict'
2
2
 
3
3
  module.exports = {
4
- 'amqp10': require('../../../datadog-plugin-amqp10/src'),
5
- 'amqplib': require('../../../datadog-plugin-amqplib/src'),
6
- 'aws-sdk': require('../../../datadog-plugin-aws-sdk/src'),
7
- 'bunyan': require('../../../datadog-plugin-bunyan/src'),
8
- 'cassandra-driver': require('../../../datadog-plugin-cassandra-driver/src'),
9
- 'connect': require('../../../datadog-plugin-connect/src'),
10
- 'couchbase': require('../../../datadog-plugin-couchbase/src'),
11
- 'cucumber': require('../../../datadog-plugin-cucumber/src'),
12
- 'cypress': require('../../../datadog-plugin-cypress/src'),
13
- 'dns': require('../../../datadog-plugin-dns/src'),
14
- 'elasticsearch': require('../../../datadog-plugin-elasticsearch/src'),
15
- 'express': require('../../../datadog-plugin-express/src'),
16
- 'fastify': require('../../../datadog-plugin-fastify/src'),
17
- 'find-my-way': require('../../../datadog-plugin-find-my-way/src'),
18
- 'google-cloud-pubsub': require('../../../datadog-plugin-google-cloud-pubsub/src'),
19
- 'graphql': require('../../../datadog-plugin-graphql/src'),
20
- 'grpc': require('../../../datadog-plugin-grpc/src'),
21
- 'hapi': require('../../../datadog-plugin-hapi/src'),
22
- 'http': require('../../../datadog-plugin-http/src'),
23
- 'http2': require('../../../datadog-plugin-http2/src'),
24
- 'ioredis': require('../../../datadog-plugin-ioredis/src'),
25
- 'jest': require('../../../datadog-plugin-jest/src'),
26
- 'koa': require('../../../datadog-plugin-koa/src'),
27
- 'kafkajs': require('../../../datadog-plugin-kafkajs/src'),
28
- 'memcached': require('../../../datadog-plugin-memcached/src'),
29
- 'microgateway-core': require('../../../datadog-plugin-microgateway-core/src'),
30
- 'mocha': require('../../../datadog-plugin-mocha/src'),
31
- 'moleculer': require('../../../datadog-plugin-moleculer/src'),
32
- 'mongodb-core': require('../../../datadog-plugin-mongodb-core/src'),
33
- 'mysql': require('../../../datadog-plugin-mysql/src'),
34
- 'mysql2': require('../../../datadog-plugin-mysql2/src'),
35
- 'net': require('../../../datadog-plugin-net/src'),
36
- 'next': require('../../../datadog-plugin-next/src'),
37
- 'oracledb': require('../../../datadog-plugin-oracledb/src'),
38
- 'paperplane': require('../../../datadog-plugin-paperplane/src'),
39
- 'pg': require('../../../datadog-plugin-pg/src'),
40
- 'pino': require('../../../datadog-plugin-pino/src'),
41
- 'redis': require('../../../datadog-plugin-redis/src'),
42
- 'restify': require('../../../datadog-plugin-restify/src'),
43
- 'rhea': require('../../../datadog-plugin-rhea/src'),
44
- 'router': require('../../../datadog-plugin-router/src'),
45
- 'sharedb': require('../../../datadog-plugin-sharedb/src'),
46
- 'tedious': require('../../../datadog-plugin-tedious/src'),
47
- 'winston': require('../../../datadog-plugin-winston/src')
4
+ get '@cucumber/cucumber' () { return require('../../../datadog-plugin-cucumber/src') },
5
+ get '@elastic/elasticsearch' () { return require('../../../datadog-plugin-elasticsearch/src') },
6
+ get '@elastic/transport' () { return require('../../../datadog-plugin-elasticsearch/src') },
7
+ get '@google-cloud/pubsub' () { return require('../../../datadog-plugin-google-cloud-pubsub/src') },
8
+ get '@grpc/grpc-js' () { return require('../../../datadog-plugin-grpc/src') },
9
+ get '@hapi/hapi' () { return require('../../../datadog-plugin-hapi/src') },
10
+ get '@koa/router' () { return require('../../../datadog-plugin-koa/src') },
11
+ get '@node-redis/client' () { return require('../../../datadog-plugin-redis/src') },
12
+ get 'amqp10' () { return require('../../../datadog-plugin-amqp10/src') },
13
+ get 'amqplib' () { return require('../../../datadog-plugin-amqplib/src') },
14
+ get 'aws-sdk' () { return require('../../../datadog-plugin-aws-sdk/src') },
15
+ get 'bunyan' () { return require('../../../datadog-plugin-bunyan/src') },
16
+ get 'cassandra-driver' () { return require('../../../datadog-plugin-cassandra-driver/src') },
17
+ get 'connect' () { return require('../../../datadog-plugin-connect/src') },
18
+ get 'couchbase' () { return require('../../../datadog-plugin-couchbase/src') },
19
+ get 'cypress' () { return require('../../../datadog-plugin-cypress/src') },
20
+ get 'dns' () { return require('../../../datadog-plugin-dns/src') },
21
+ get 'elasticsearch' () { return require('../../../datadog-plugin-elasticsearch/src') },
22
+ get 'express' () { return require('../../../datadog-plugin-express/src') },
23
+ get 'fastify' () { return require('../../../datadog-plugin-fastify/src') },
24
+ get 'find-my-way' () { return require('../../../datadog-plugin-find-my-way/src') },
25
+ get 'graphql' () { return require('../../../datadog-plugin-graphql/src') },
26
+ get 'grpc' () { return require('../../../datadog-plugin-grpc/src') },
27
+ get 'hapi' () { return require('../../../datadog-plugin-hapi/src') },
28
+ get 'http' () { return require('../../../datadog-plugin-http/src') },
29
+ get 'http2' () { return require('../../../datadog-plugin-http2/src') },
30
+ get 'https' () { return require('../../../datadog-plugin-http/src') },
31
+ get 'ioredis' () { return require('../../../datadog-plugin-ioredis/src') },
32
+ get 'jest-environment-node' () { return require('../../../datadog-plugin-jest/src') },
33
+ get 'jest-environment-jsdom' () { return require('../../../datadog-plugin-jest/src') },
34
+ get 'jest-jasmine2' () { return require('../../../datadog-plugin-jest/src') },
35
+ get 'koa' () { return require('../../../datadog-plugin-koa/src') },
36
+ get 'koa-router' () { return require('../../../datadog-plugin-koa/src') },
37
+ get 'kafkajs' () { return require('../../../datadog-plugin-kafkajs/src') },
38
+ get 'memcached' () { return require('../../../datadog-plugin-memcached/src') },
39
+ get 'microgateway-core' () { return require('../../../datadog-plugin-microgateway-core/src') },
40
+ get 'mocha' () { return require('../../../datadog-plugin-mocha/src') },
41
+ get 'mocha-each' () { return require('../../../datadog-plugin-mocha/src') },
42
+ get 'moleculer' () { return require('../../../datadog-plugin-moleculer/src') },
43
+ get 'mongodb' () { return require('../../../datadog-plugin-mongodb-core/src') },
44
+ get 'mongodb-core' () { return require('../../../datadog-plugin-mongodb-core/src') },
45
+ get 'mysql' () { return require('../../../datadog-plugin-mysql/src') },
46
+ get 'mysql2' () { return require('../../../datadog-plugin-mysql2/src') },
47
+ get 'net' () { return require('../../../datadog-plugin-net/src') },
48
+ get 'next' () { return require('../../../datadog-plugin-next/src') },
49
+ get 'oracledb' () { return require('../../../datadog-plugin-oracledb/src') },
50
+ get 'paperplane' () { return require('../../../datadog-plugin-paperplane/src') },
51
+ get 'pg' () { return require('../../../datadog-plugin-pg/src') },
52
+ get 'pino' () { return require('../../../datadog-plugin-pino/src') },
53
+ get 'pino-pretty' () { return require('../../../datadog-plugin-pino/src') },
54
+ get 'redis' () { return require('../../../datadog-plugin-redis/src') },
55
+ get 'restify' () { return require('../../../datadog-plugin-restify/src') },
56
+ get 'rhea' () { return require('../../../datadog-plugin-rhea/src') },
57
+ get 'router' () { return require('../../../datadog-plugin-router/src') },
58
+ get 'sharedb' () { return require('../../../datadog-plugin-sharedb/src') },
59
+ get 'tedious' () { return require('../../../datadog-plugin-tedious/src') },
60
+ get 'winston' () { return require('../../../datadog-plugin-winston/src') }
48
61
  }
@@ -17,7 +17,8 @@ const {
17
17
  CI_WORKSPACE_PATH,
18
18
  CI_JOB_URL,
19
19
  CI_JOB_NAME,
20
- CI_STAGE_NAME
20
+ CI_STAGE_NAME,
21
+ CI_ENV_VARS
21
22
  } = require('./tags')
22
23
 
23
24
  // Receives a string with the form 'John Doe <john.doe@gmail.com>'
@@ -104,7 +105,8 @@ module.exports = {
104
105
  GIT_BRANCH: JENKINS_GIT_BRANCH,
105
106
  GIT_COMMIT: JENKINS_GIT_COMMIT,
106
107
  GIT_URL: JENKINS_GIT_REPOSITORY_URL,
107
- GIT_URL_1: JENKINS_GIT_REPOSITORY_URL_1
108
+ GIT_URL_1: JENKINS_GIT_REPOSITORY_URL_1,
109
+ DD_CUSTOM_TRACE_ID
108
110
  } = env
109
111
 
110
112
  tags = {
@@ -114,7 +116,8 @@ module.exports = {
114
116
  [CI_PROVIDER_NAME]: 'jenkins',
115
117
  [GIT_COMMIT_SHA]: JENKINS_GIT_COMMIT,
116
118
  [GIT_REPOSITORY_URL]: JENKINS_GIT_REPOSITORY_URL || JENKINS_GIT_REPOSITORY_URL_1,
117
- [CI_WORKSPACE_PATH]: WORKSPACE
119
+ [CI_WORKSPACE_PATH]: WORKSPACE,
120
+ [CI_ENV_VARS]: JSON.stringify({ DD_CUSTOM_TRACE_ID })
118
121
  }
119
122
 
120
123
  const isTag = JENKINS_GIT_BRANCH && JENKINS_GIT_BRANCH.includes('tags')
@@ -152,7 +155,9 @@ module.exports = {
152
155
  CI_JOB_NAME: GITLAB_CI_JOB_NAME,
153
156
  CI_COMMIT_MESSAGE,
154
157
  CI_COMMIT_TIMESTAMP,
155
- CI_COMMIT_AUTHOR
158
+ CI_COMMIT_AUTHOR,
159
+ CI_PROJECT_URL: GITLAB_PROJECT_URL,
160
+ CI_JOB_ID: GITLAB_CI_JOB_ID
156
161
  } = env
157
162
 
158
163
  const { name, email } = parseEmailAndName(CI_COMMIT_AUTHOR)
@@ -174,7 +179,12 @@ module.exports = {
174
179
  [GIT_COMMIT_MESSAGE]: CI_COMMIT_MESSAGE,
175
180
  [GIT_COMMIT_AUTHOR_NAME]: name,
176
181
  [GIT_COMMIT_AUTHOR_EMAIL]: email,
177
- [GIT_COMMIT_AUTHOR_DATE]: CI_COMMIT_TIMESTAMP
182
+ [GIT_COMMIT_AUTHOR_DATE]: CI_COMMIT_TIMESTAMP,
183
+ [CI_ENV_VARS]: JSON.stringify({
184
+ CI_PROJECT_URL: GITLAB_PROJECT_URL,
185
+ CI_PIPELINE_ID: GITLAB_PIPELINE_ID,
186
+ CI_JOB_ID: GITLAB_CI_JOB_ID
187
+ })
178
188
  }
179
189
  }
180
190
 
@@ -188,7 +198,8 @@ module.exports = {
188
198
  CIRCLE_TAG,
189
199
  CIRCLE_SHA1,
190
200
  CIRCLE_REPOSITORY_URL,
191
- CIRCLE_JOB
201
+ CIRCLE_JOB,
202
+ CIRCLE_BUILD_NUM
192
203
  } = env
193
204
 
194
205
  const pipelineUrl = `https://app.circleci.com/pipelines/workflows/${CIRCLE_WORKFLOW_ID}`
@@ -203,7 +214,11 @@ module.exports = {
203
214
  [GIT_REPOSITORY_URL]: CIRCLE_REPOSITORY_URL,
204
215
  [CI_JOB_URL]: CIRCLE_BUILD_URL,
205
216
  [CI_WORKSPACE_PATH]: CIRCLE_WORKING_DIRECTORY,
206
- [CIRCLE_TAG ? GIT_TAG : GIT_BRANCH]: CIRCLE_TAG || CIRCLE_BRANCH
217
+ [CIRCLE_TAG ? GIT_TAG : GIT_BRANCH]: CIRCLE_TAG || CIRCLE_BRANCH,
218
+ [CI_ENV_VARS]: JSON.stringify({
219
+ CIRCLE_WORKFLOW_ID,
220
+ CIRCLE_BUILD_NUM
221
+ })
207
222
  }
208
223
  }
209
224
 
@@ -243,7 +258,13 @@ module.exports = {
243
258
  [GIT_REPOSITORY_URL]: repositoryURL,
244
259
  [CI_JOB_URL]: jobUrl,
245
260
  [CI_WORKSPACE_PATH]: GITHUB_WORKSPACE,
246
- [refKey]: ref
261
+ [refKey]: ref,
262
+ [CI_ENV_VARS]: JSON.stringify({
263
+ GITHUB_SERVER_URL,
264
+ GITHUB_REPOSITORY,
265
+ GITHUB_RUN_ID,
266
+ GITHUB_RUN_ATTEMPT
267
+ })
247
268
  }
248
269
  }
249
270
 
@@ -443,7 +464,11 @@ module.exports = {
443
464
  [refKey]: ref,
444
465
  [GIT_COMMIT_AUTHOR_NAME]: BUILDKITE_BUILD_AUTHOR,
445
466
  [GIT_COMMIT_AUTHOR_EMAIL]: BUILDKITE_BUILD_AUTHOR_EMAIL,
446
- [GIT_COMMIT_MESSAGE]: BUILDKITE_MESSAGE
467
+ [GIT_COMMIT_MESSAGE]: BUILDKITE_MESSAGE,
468
+ [CI_ENV_VARS]: JSON.stringify({
469
+ BUILDKITE_BUILD_ID,
470
+ BUILDKITE_JOB_ID
471
+ })
447
472
  }
448
473
  }
449
474
 
@@ -1,5 +1,7 @@
1
- const { sanitizedExec } = require('./exec')
1
+ const { execSync } = require('child_process')
2
+ const os = require('os')
2
3
 
4
+ const { sanitizedExec } = require('./exec')
3
5
  const {
4
6
  GIT_COMMIT_SHA,
5
7
  GIT_BRANCH,
@@ -15,6 +17,48 @@ const {
15
17
  CI_WORKSPACE_PATH
16
18
  } = require('./tags')
17
19
 
20
+ function getRepositoryUrl () {
21
+ return sanitizedExec('git config --get remote.origin.url', { stdio: 'pipe' })
22
+ }
23
+
24
+ function getLatestCommits () {
25
+ return execSync('git log --format=%H -n 1000 --since="1 month ago"', { stdio: 'pipe' })
26
+ .toString()
27
+ .split('\n')
28
+ .filter(commit => !!commit)
29
+ }
30
+
31
+ function getCommitsToUpload (commitsToExclude) {
32
+ let gitCommandToGetCommitsToUpload =
33
+ 'git rev-list --objects --no-object-names --filter=blob:none --since="1 month ago" HEAD'
34
+
35
+ commitsToExclude.forEach(commit => {
36
+ gitCommandToGetCommitsToUpload = `${gitCommandToGetCommitsToUpload} ^${commit}`
37
+ })
38
+
39
+ return execSync(gitCommandToGetCommitsToUpload, { stdio: 'pipe' })
40
+ .toString()
41
+ .split('\n')
42
+ .filter(commit => !!commit)
43
+ }
44
+
45
+ // Generates pack files to upload and
46
+ // returns the ordered list of packfiles' paths
47
+ function generatePackFilesForCommits (commitsToUpload) {
48
+ const tmpFolder = os.tmpdir()
49
+
50
+ const prefix = Math.floor(Math.random() * 10000)
51
+ const path = `${tmpFolder}/${prefix}`
52
+
53
+ const orderedCommits =
54
+ execSync(
55
+ `git pack-objects --compression=9 --max-pack-size=3m ${path}`,
56
+ { input: commitsToUpload.join('\n') }
57
+ ).toString().split('\n').filter(commit => !!commit)
58
+
59
+ return orderedCommits.map(commit => `${path}-${commit}.pack`)
60
+ }
61
+
18
62
  // If there is ciMetadata, it takes precedence.
19
63
  function getGitMetadata (ciMetadata) {
20
64
  const {
@@ -57,4 +101,10 @@ function getGitMetadata (ciMetadata) {
57
101
  }
58
102
  }
59
103
 
60
- module.exports = { getGitMetadata }
104
+ module.exports = {
105
+ getGitMetadata,
106
+ getLatestCommits,
107
+ getRepositoryUrl,
108
+ generatePackFilesForCommits,
109
+ getCommitsToUpload
110
+ }
@@ -20,6 +20,8 @@ const CI_JOB_URL = 'ci.job.url'
20
20
  const CI_JOB_NAME = 'ci.job.name'
21
21
  const CI_STAGE_NAME = 'ci.stage.name'
22
22
 
23
+ const CI_ENV_VARS = '_dd.ci.env_vars'
24
+
23
25
  module.exports = {
24
26
  GIT_COMMIT_SHA,
25
27
  GIT_BRANCH,
@@ -40,5 +42,6 @@ module.exports = {
40
42
  CI_WORKSPACE_PATH,
41
43
  CI_JOB_URL,
42
44
  CI_JOB_NAME,
43
- CI_STAGE_NAME
45
+ CI_STAGE_NAME,
46
+ CI_ENV_VARS
44
47
  }