dd-trace 3.3.1 → 3.12.1

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 (198) hide show
  1. package/LICENSE-3rdparty.csv +8 -0
  2. package/README.md +108 -43
  3. package/ci/init.js +6 -1
  4. package/ext/exporters.d.ts +2 -1
  5. package/ext/exporters.js +2 -1
  6. package/index.d.ts +129 -36
  7. package/package.json +18 -9
  8. package/packages/datadog-instrumentations/src/body-parser.js +26 -0
  9. package/packages/datadog-instrumentations/src/cassandra-driver.js +7 -7
  10. package/packages/datadog-instrumentations/src/child-process.js +30 -0
  11. package/packages/datadog-instrumentations/src/connect.js +15 -15
  12. package/packages/datadog-instrumentations/src/cucumber.js +1 -3
  13. package/packages/datadog-instrumentations/src/elasticsearch.js +51 -47
  14. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +1 -1
  15. package/packages/datadog-instrumentations/src/helpers/hooks.js +9 -0
  16. package/packages/datadog-instrumentations/src/helpers/register.js +5 -0
  17. package/packages/datadog-instrumentations/src/http/server.js +20 -12
  18. package/packages/datadog-instrumentations/src/http2/server.js +67 -1
  19. package/packages/datadog-instrumentations/src/jest.js +182 -25
  20. package/packages/datadog-instrumentations/src/koa.js +32 -32
  21. package/packages/datadog-instrumentations/src/ldapjs.js +91 -0
  22. package/packages/datadog-instrumentations/src/mariadb.js +63 -0
  23. package/packages/datadog-instrumentations/src/memcached.js +1 -4
  24. package/packages/datadog-instrumentations/src/mocha.js +135 -24
  25. package/packages/datadog-instrumentations/src/next.js +10 -2
  26. package/packages/datadog-instrumentations/src/opensearch.js +10 -0
  27. package/packages/datadog-instrumentations/src/oracledb.js +8 -8
  28. package/packages/datadog-instrumentations/src/pg.js +7 -3
  29. package/packages/datadog-instrumentations/src/qs.js +24 -0
  30. package/packages/datadog-instrumentations/src/redis.js +12 -3
  31. package/packages/datadog-instrumentations/src/restify.js +5 -1
  32. package/packages/datadog-instrumentations/src/rhea.js +29 -15
  33. package/packages/datadog-instrumentations/src/router.js +23 -23
  34. package/packages/datadog-plugin-amqp10/src/consumer.js +32 -0
  35. package/packages/datadog-plugin-amqp10/src/index.js +11 -101
  36. package/packages/datadog-plugin-amqp10/src/producer.js +34 -0
  37. package/packages/datadog-plugin-amqp10/src/util.js +15 -0
  38. package/packages/datadog-plugin-amqplib/src/client.js +38 -0
  39. package/packages/datadog-plugin-amqplib/src/consumer.js +40 -0
  40. package/packages/datadog-plugin-amqplib/src/index.js +14 -102
  41. package/packages/datadog-plugin-amqplib/src/producer.js +37 -0
  42. package/packages/datadog-plugin-amqplib/src/util.js +14 -0
  43. package/packages/datadog-plugin-cassandra-driver/src/index.js +22 -60
  44. package/packages/datadog-plugin-cucumber/src/index.js +14 -33
  45. package/packages/datadog-plugin-cypress/src/plugin.js +2 -1
  46. package/packages/datadog-plugin-dns/src/index.js +16 -91
  47. package/packages/datadog-plugin-dns/src/lookup.js +40 -0
  48. package/packages/datadog-plugin-dns/src/lookup_service.js +24 -0
  49. package/packages/datadog-plugin-dns/src/resolve.js +24 -0
  50. package/packages/datadog-plugin-dns/src/reverse.js +21 -0
  51. package/packages/datadog-plugin-elasticsearch/src/index.js +24 -60
  52. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +24 -0
  53. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +41 -0
  54. package/packages/datadog-plugin-google-cloud-pubsub/src/index.js +14 -99
  55. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +33 -0
  56. package/packages/datadog-plugin-graphql/src/execute.js +73 -0
  57. package/packages/datadog-plugin-graphql/src/index.js +14 -176
  58. package/packages/datadog-plugin-graphql/src/parse.js +32 -0
  59. package/packages/datadog-plugin-graphql/src/resolve.js +70 -76
  60. package/packages/datadog-plugin-graphql/src/validate.js +28 -0
  61. package/packages/datadog-plugin-grpc/src/client.js +46 -55
  62. package/packages/datadog-plugin-grpc/src/index.js +7 -24
  63. package/packages/datadog-plugin-grpc/src/server.js +50 -52
  64. package/packages/datadog-plugin-grpc/src/util.js +15 -14
  65. package/packages/datadog-plugin-http/src/client.js +15 -5
  66. package/packages/datadog-plugin-http/src/index.js +7 -22
  67. package/packages/datadog-plugin-http/src/server.js +19 -3
  68. package/packages/datadog-plugin-http2/src/client.js +20 -1
  69. package/packages/datadog-plugin-http2/src/index.js +8 -26
  70. package/packages/datadog-plugin-http2/src/server.js +44 -0
  71. package/packages/datadog-plugin-jest/src/index.js +41 -65
  72. package/packages/datadog-plugin-kafkajs/src/consumer.js +42 -0
  73. package/packages/datadog-plugin-kafkajs/src/index.js +11 -87
  74. package/packages/datadog-plugin-kafkajs/src/producer.js +31 -0
  75. package/packages/datadog-plugin-mariadb/src/index.js +10 -0
  76. package/packages/datadog-plugin-memcached/src/index.js +17 -52
  77. package/packages/datadog-plugin-mocha/src/index.js +40 -60
  78. package/packages/datadog-plugin-moleculer/src/client.js +22 -36
  79. package/packages/datadog-plugin-moleculer/src/index.js +8 -26
  80. package/packages/datadog-plugin-moleculer/src/server.js +18 -30
  81. package/packages/datadog-plugin-mongodb-core/src/index.js +23 -51
  82. package/packages/datadog-plugin-mysql/src/index.js +23 -52
  83. package/packages/datadog-plugin-mysql2/src/index.js +1 -3
  84. package/packages/datadog-plugin-net/src/index.js +4 -0
  85. package/packages/datadog-plugin-net/src/ipc.js +21 -0
  86. package/packages/datadog-plugin-net/src/tcp.js +46 -0
  87. package/packages/datadog-plugin-next/src/index.js +3 -0
  88. package/packages/datadog-plugin-opensearch/src/index.js +11 -0
  89. package/packages/datadog-plugin-oracledb/src/index.js +29 -55
  90. package/packages/datadog-plugin-pg/src/index.js +27 -51
  91. package/packages/datadog-plugin-redis/src/index.js +29 -60
  92. package/packages/datadog-plugin-rhea/src/consumer.js +55 -0
  93. package/packages/datadog-plugin-rhea/src/index.js +11 -96
  94. package/packages/datadog-plugin-rhea/src/producer.js +45 -0
  95. package/packages/datadog-plugin-router/src/index.js +13 -2
  96. package/packages/datadog-plugin-sharedb/src/index.js +22 -39
  97. package/packages/datadog-plugin-tedious/src/index.js +20 -41
  98. package/packages/dd-trace/src/appsec/addresses.js +3 -1
  99. package/packages/dd-trace/src/appsec/blocking.js +44 -0
  100. package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +8 -6
  101. package/packages/dd-trace/src/appsec/gateway/engine/engine.js +1 -1
  102. package/packages/dd-trace/src/appsec/gateway/engine/index.js +7 -2
  103. package/packages/dd-trace/src/appsec/gateway/engine/runner.js +0 -1
  104. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +4 -1
  105. package/packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js +11 -0
  106. package/packages/dd-trace/src/appsec/iast/analyzers/injection-analyzer.js +19 -0
  107. package/packages/dd-trace/src/appsec/iast/analyzers/ldap-injection-analyzer.js +11 -0
  108. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +13 -0
  109. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +43 -5
  110. package/packages/dd-trace/src/appsec/iast/iast-context.js +3 -1
  111. package/packages/dd-trace/src/appsec/iast/index.js +24 -8
  112. package/packages/dd-trace/src/appsec/iast/overhead-controller.js +20 -1
  113. package/packages/dd-trace/src/appsec/iast/path-line.js +17 -6
  114. package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +17 -0
  115. package/packages/dd-trace/src/appsec/iast/taint-tracking/filter.js +16 -0
  116. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +18 -0
  117. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +98 -0
  118. package/packages/dd-trace/src/appsec/iast/taint-tracking/origin-types.js +4 -0
  119. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +38 -0
  120. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +67 -0
  121. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +103 -0
  122. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +98 -30
  123. package/packages/dd-trace/src/appsec/index.js +79 -25
  124. package/packages/dd-trace/src/{plugins/util → appsec}/ip_blocklist.js +0 -0
  125. package/packages/dd-trace/src/appsec/ip_extractor.js +98 -0
  126. package/packages/dd-trace/src/appsec/recommended.json +134 -53
  127. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +7 -0
  128. package/packages/dd-trace/src/appsec/remote_config/index.js +56 -0
  129. package/packages/dd-trace/src/appsec/remote_config/manager.js +264 -0
  130. package/packages/dd-trace/src/{exporters → appsec/remote_config}/scheduler.js +9 -9
  131. package/packages/dd-trace/src/appsec/rule_manager.js +61 -1
  132. package/packages/dd-trace/src/appsec/templates/blocked.html +99 -0
  133. package/packages/dd-trace/src/appsec/templates/blocked.json +8 -0
  134. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +66 -0
  135. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +9 -5
  136. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +19 -51
  137. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +10 -5
  138. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +202 -0
  139. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +51 -62
  140. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +89 -0
  141. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +82 -0
  142. package/packages/dd-trace/src/config.js +119 -35
  143. package/packages/dd-trace/src/constants.js +9 -1
  144. package/packages/dd-trace/src/dogstatsd.js +42 -10
  145. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +10 -2
  146. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +0 -1
  147. package/packages/dd-trace/src/exporter.js +3 -0
  148. package/packages/dd-trace/src/exporters/agent/index.js +10 -2
  149. package/packages/dd-trace/src/exporters/agent/writer.js +2 -9
  150. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +82 -0
  151. package/packages/dd-trace/src/exporters/common/request.js +51 -1
  152. package/packages/dd-trace/src/exporters/span-stats/index.js +6 -2
  153. package/packages/dd-trace/src/format.js +29 -10
  154. package/packages/dd-trace/src/lambda/handler.js +72 -0
  155. package/packages/dd-trace/src/lambda/index.js +5 -0
  156. package/packages/dd-trace/src/lambda/runtime/errors.js +20 -0
  157. package/packages/dd-trace/src/lambda/runtime/patch.js +74 -0
  158. package/packages/dd-trace/src/lambda/runtime/ritm.js +138 -0
  159. package/packages/dd-trace/src/metrics.js +15 -2
  160. package/packages/dd-trace/src/opentracing/propagation/text_map.js +1 -5
  161. package/packages/dd-trace/src/opentracing/span.js +2 -1
  162. package/packages/dd-trace/src/opentracing/span_context.js +9 -0
  163. package/packages/dd-trace/src/plugin_manager.js +11 -17
  164. package/packages/dd-trace/src/plugins/cache.js +9 -0
  165. package/packages/dd-trace/src/plugins/ci_plugin.js +97 -0
  166. package/packages/dd-trace/src/plugins/client.js +9 -0
  167. package/packages/dd-trace/src/plugins/composite.js +26 -0
  168. package/packages/dd-trace/src/plugins/consumer.js +9 -0
  169. package/packages/dd-trace/src/plugins/database.js +55 -0
  170. package/packages/dd-trace/src/plugins/incoming.js +7 -0
  171. package/packages/dd-trace/src/plugins/index.js +3 -0
  172. package/packages/dd-trace/src/plugins/log_plugin.js +2 -2
  173. package/packages/dd-trace/src/plugins/outgoing.js +31 -0
  174. package/packages/dd-trace/src/plugins/plugin.js +3 -0
  175. package/packages/dd-trace/src/plugins/producer.js +9 -0
  176. package/packages/dd-trace/src/plugins/server.js +9 -0
  177. package/packages/dd-trace/src/plugins/storage.js +21 -0
  178. package/packages/dd-trace/src/plugins/tracing.js +94 -0
  179. package/packages/dd-trace/src/plugins/util/ci.js +40 -4
  180. package/packages/dd-trace/src/plugins/util/git.js +58 -18
  181. package/packages/dd-trace/src/plugins/util/test.js +71 -8
  182. package/packages/dd-trace/src/plugins/util/user-provided-git.js +14 -1
  183. package/packages/dd-trace/src/plugins/util/web.js +11 -114
  184. package/packages/dd-trace/src/priority_sampler.js +6 -2
  185. package/packages/dd-trace/src/profiling/config.js +11 -6
  186. package/packages/dd-trace/src/profiling/exporters/agent.js +4 -0
  187. package/packages/dd-trace/src/profiling/index.js +2 -2
  188. package/packages/dd-trace/src/profiling/profiler.js +43 -7
  189. package/packages/dd-trace/src/proxy.js +8 -16
  190. package/packages/dd-trace/src/ritm.js +25 -14
  191. package/packages/dd-trace/src/span_processor.js +17 -0
  192. package/packages/dd-trace/src/span_sampler.js +77 -0
  193. package/packages/dd-trace/src/span_stats.js +2 -2
  194. package/packages/dd-trace/src/telemetry/dependencies.js +21 -7
  195. package/packages/dd-trace/src/telemetry/index.js +7 -1
  196. package/packages/dd-trace/src/telemetry/send-data.js +3 -1
  197. package/packages/dd-trace/src/tracer.js +10 -5
  198. package/packages/dd-trace/src/util.js +43 -1
@@ -1,44 +1,30 @@
1
- const Plugin = require('../../dd-trace/src/plugins/plugin')
1
+ const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
2
2
  const { storage } = require('../../datadog-core')
3
3
 
4
4
  const {
5
- CI_APP_ORIGIN,
6
5
  TEST_STATUS,
7
6
  JEST_TEST_RUNNER,
8
7
  finishAllTraceSpans,
9
8
  getTestEnvironmentMetadata,
10
9
  getTestParentSpan,
11
- getTestCommonTags,
12
10
  getTestSessionCommonTags,
13
11
  getTestSuiteCommonTags,
14
12
  TEST_PARAMETERS,
15
13
  getCodeOwnersFileEntries,
16
- getCodeOwnersForFilename,
17
- TEST_CODE_OWNERS,
18
14
  TEST_SESSION_ID,
19
15
  TEST_SUITE_ID,
20
- TEST_COMMAND
16
+ TEST_COMMAND,
17
+ TEST_ITR_TESTS_SKIPPED,
18
+ TEST_SESSION_CODE_COVERAGE_ENABLED,
19
+ TEST_SESSION_ITR_SKIPPING_ENABLED,
20
+ TEST_CODE_COVERAGE_LINES_TOTAL
21
21
  } = require('../../dd-trace/src/plugins/util/test')
22
+ const { COMPONENT } = require('../../dd-trace/src/constants')
22
23
 
23
24
  // https://github.com/facebook/jest/blob/d6ad15b0f88a05816c2fe034dd6900d28315d570/packages/jest-worker/src/types.ts#L38
24
25
  const CHILD_MESSAGE_END = 2
25
26
 
26
- function getTestSpanMetadata (tracer, test) {
27
- const childOf = getTestParentSpan(tracer)
28
-
29
- const { suite, name, runner, testParameters } = test
30
-
31
- const commonTags = getTestCommonTags(name, suite, tracer._version)
32
-
33
- return {
34
- childOf,
35
- ...commonTags,
36
- [JEST_TEST_RUNNER]: runner,
37
- [TEST_PARAMETERS]: testParameters
38
- }
39
- }
40
-
41
- class JestPlugin extends Plugin {
27
+ class JestPlugin extends CiPlugin {
42
28
  static get name () {
43
29
  return 'jest'
44
30
  }
@@ -49,7 +35,7 @@ class JestPlugin extends Plugin {
49
35
  // Used to handle the end of a jest worker to be able to flush
50
36
  const handler = ([message]) => {
51
37
  if (message === CHILD_MESSAGE_END) {
52
- this.tracer._exporter._writer.flush(() => {
38
+ this.tracer._exporter.flush(() => {
53
39
  // eslint-disable-next-line
54
40
  // https://github.com/facebook/jest/blob/24ed3b5ecb419c023ee6fdbc838f07cc028fc007/packages/jest-worker/src/workers/processChild.ts#L118-L133
55
41
  // Only after the flush is done we clean up open handles
@@ -64,9 +50,6 @@ class JestPlugin extends Plugin {
64
50
  this.codeOwnersEntries = getCodeOwnersFileEntries()
65
51
 
66
52
  this.addSub('ci:jest:session:start', (command) => {
67
- if (!this.config.isAgentlessEnabled) {
68
- return
69
- }
70
53
  const store = storage.getStore()
71
54
  const childOf = getTestParentSpan(this.tracer)
72
55
  const testSessionSpanMetadata = getTestSessionCommonTags(command, this.tracer._version)
@@ -74,6 +57,7 @@ class JestPlugin extends Plugin {
74
57
  const testSessionSpan = this.tracer.startSpan('jest.test_session', {
75
58
  childOf,
76
59
  tags: {
60
+ [COMPONENT]: this.constructor.name,
77
61
  ...this.testEnvironmentMetadata,
78
62
  ...testSessionSpanMetadata
79
63
  }
@@ -81,24 +65,32 @@ class JestPlugin extends Plugin {
81
65
  this.enter(testSessionSpan, store)
82
66
  })
83
67
 
84
- this.addSub('ci:jest:session:finish', (status) => {
85
- if (!this.config.isAgentlessEnabled) {
86
- return
87
- }
68
+ this.addSub('ci:jest:session:finish', ({
69
+ status,
70
+ isSuitesSkipped,
71
+ isSuitesSkippingEnabled,
72
+ isCodeCoverageEnabled,
73
+ testCodeCoverageLinesTotal
74
+ }) => {
88
75
  const testSessionSpan = storage.getStore().span
76
+
89
77
  testSessionSpan.setTag(TEST_STATUS, status)
78
+ testSessionSpan.setTag(TEST_ITR_TESTS_SKIPPED, isSuitesSkipped ? 'true' : 'false')
79
+ testSessionSpan.setTag(TEST_SESSION_ITR_SKIPPING_ENABLED, isSuitesSkippingEnabled ? 'true' : 'false')
80
+ testSessionSpan.setTag(TEST_SESSION_CODE_COVERAGE_ENABLED, isCodeCoverageEnabled ? 'true' : 'false')
81
+
82
+ if (testCodeCoverageLinesTotal !== undefined) {
83
+ testSessionSpan.setTag(TEST_CODE_COVERAGE_LINES_TOTAL, testCodeCoverageLinesTotal)
84
+ }
90
85
  testSessionSpan.finish()
91
86
  finishAllTraceSpans(testSessionSpan)
92
- this.tracer._exporter._writer.flush()
87
+ this.tracer._exporter.flush()
93
88
  })
94
89
 
95
90
  // Test suites can be run in a different process from jest's main one.
96
91
  // This subscriber changes the configuration objects from jest to inject the trace id
97
92
  // of the test session to the processes that run the test suites.
98
93
  this.addSub('ci:jest:session:configuration', configs => {
99
- if (!this.config.isAgentlessEnabled) {
100
- return
101
- }
102
94
  const testSessionSpan = storage.getStore().span
103
95
  configs.forEach(config => {
104
96
  config._ddTestSessionId = testSessionSpan.context()._traceId.toString(10)
@@ -107,10 +99,6 @@ class JestPlugin extends Plugin {
107
99
  })
108
100
 
109
101
  this.addSub('ci:jest:test-suite:start', ({ testSuite, testEnvironmentOptions }) => {
110
- if (!this.config.isAgentlessEnabled) {
111
- return
112
- }
113
-
114
102
  const { _ddTestSessionId: testSessionId, _ddTestCommand: testCommand } = testEnvironmentOptions
115
103
 
116
104
  const store = storage.getStore()
@@ -125,6 +113,7 @@ class JestPlugin extends Plugin {
125
113
  const testSuiteSpan = this.tracer.startSpan('jest.test_suite', {
126
114
  childOf: testSessionSpanContext,
127
115
  tags: {
116
+ [COMPONENT]: this.constructor.name,
128
117
  ...this.testEnvironmentMetadata,
129
118
  ...testSuiteMetadata
130
119
  }
@@ -133,21 +122,23 @@ class JestPlugin extends Plugin {
133
122
  })
134
123
 
135
124
  this.addSub('ci:jest:test-suite:finish', ({ status, errorMessage }) => {
136
- if (!this.config.isAgentlessEnabled) {
137
- return
138
- }
139
125
  const testSuiteSpan = storage.getStore().span
140
126
  testSuiteSpan.setTag(TEST_STATUS, status)
141
127
  if (errorMessage) {
142
128
  testSuiteSpan.setTag('error', new Error(errorMessage))
143
129
  }
144
130
  testSuiteSpan.finish()
131
+ // Suites potentially run in a different process than the session,
132
+ // so calling finishAllTraceSpans on the session span is not enough
133
+ finishAllTraceSpans(testSuiteSpan)
145
134
  })
146
135
 
136
+ /**
137
+ * This can't use `this.itrConfig` like `ci:mocha:test-suite:code-coverage`
138
+ * because this subscription happens in a different process from the one
139
+ * fetching the ITR config.
140
+ */
147
141
  this.addSub('ci:jest:test-suite:code-coverage', (coverageFiles) => {
148
- if (!this.config.isAgentlessEnabled || !this.config.isIntelligentTestRunnerEnabled) {
149
- return
150
- }
151
142
  const testSuiteSpan = storage.getStore().span
152
143
  this.tracer._exporter.exportCoverage({ span: testSuiteSpan, coverageFiles })
153
144
  })
@@ -192,30 +183,15 @@ class JestPlugin extends Plugin {
192
183
  suiteTags[TEST_COMMAND] = testSuiteSpan.context()._tags[TEST_COMMAND]
193
184
  }
194
185
 
195
- const {
196
- childOf,
197
- ...testSpanMetadata
198
- } = getTestSpanMetadata(this.tracer, test)
199
-
200
- const codeOwners = getCodeOwnersForFilename(test.suite, this.codeOwnersEntries)
186
+ const { suite, name, runner, testParameters } = test
201
187
 
202
- if (codeOwners) {
203
- testSpanMetadata[TEST_CODE_OWNERS] = codeOwners
188
+ const extraTags = {
189
+ [JEST_TEST_RUNNER]: runner,
190
+ [TEST_PARAMETERS]: testParameters,
191
+ ...suiteTags
204
192
  }
205
193
 
206
- const testSpan = this.tracer
207
- .startSpan('jest.test', {
208
- childOf,
209
- tags: {
210
- ...this.testEnvironmentMetadata,
211
- ...testSpanMetadata,
212
- ...suiteTags
213
- }
214
- })
215
-
216
- testSpan.context()._trace.origin = CI_APP_ORIGIN
217
-
218
- return testSpan
194
+ return super.startTestSpan(name, suite, extraTags)
219
195
  }
220
196
  }
221
197
 
@@ -0,0 +1,42 @@
1
+ 'use strict'
2
+
3
+ const ConsumerPlugin = require('../../dd-trace/src/plugins/consumer')
4
+
5
+ class KafkajsConsumerPlugin extends ConsumerPlugin {
6
+ static get name () { return 'kafkajs' }
7
+ static get operation () { return 'consume' }
8
+
9
+ start ({ topic, partition, message }) {
10
+ const childOf = extract(this.tracer, message.headers)
11
+
12
+ this.startSpan('kafka.consume', {
13
+ childOf,
14
+ service: this.config.service || `${this.tracer._service}-kafka`,
15
+ resource: topic,
16
+ kind: 'consumer',
17
+ type: 'worker',
18
+ meta: {
19
+ 'component': 'kafkajs',
20
+ 'kafka.topic': topic,
21
+ 'kafka.message.offset': message.offset
22
+ },
23
+ metrics: {
24
+ 'kafka.partition': partition
25
+ }
26
+ })
27
+ }
28
+ }
29
+
30
+ function extract (tracer, bufferMap) {
31
+ if (!bufferMap) return null
32
+
33
+ const textMap = {}
34
+
35
+ for (const key of Object.keys(bufferMap)) {
36
+ textMap[key] = bufferMap[key].toString()
37
+ }
38
+
39
+ return tracer.extract('text_map', textMap)
40
+ }
41
+
42
+ module.exports = KafkajsConsumerPlugin
@@ -1,93 +1,17 @@
1
1
  'use strict'
2
2
 
3
- const Plugin = require('../../dd-trace/src/plugins/plugin')
4
- const { storage } = require('../../datadog-core')
5
- const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
6
-
7
- class KafkajsPlugin extends Plugin {
8
- static get name () {
9
- return 'kafkajs'
10
- }
11
-
12
- constructor (...args) {
13
- super(...args)
14
-
15
- this.addSub(`apm:kafkajs:produce:start`, ({ topic, messages }) => {
16
- const store = storage.getStore()
17
- const childOf = store ? store.span : store
18
- const span = this.tracer.startSpan('kafka.produce', {
19
- childOf,
20
- tags: {
21
- 'service.name': this.config.service || `${this.tracer._service}-kafka`,
22
- 'span.kind': 'producer',
23
- 'component': 'kafkajs'
24
- }
25
- })
26
-
27
- analyticsSampler.sample(span, this.config.measured)
28
- this.enter(span, store)
29
-
30
- span.addTags({
31
- 'resource.name': topic,
32
- 'kafka.topic': topic,
33
- 'kafka.batch_size': messages.length
34
- })
35
- for (const message of messages) {
36
- if (typeof message === 'object') {
37
- this.tracer.inject(span, 'text_map', message.headers)
38
- }
39
- }
40
- })
41
-
42
- this.addSub(`apm:kafkajs:consume:start`, ({ topic, partition, message }) => {
43
- const store = storage.getStore()
44
- const childOf = extract(this.tracer, message.headers)
45
- const span = this.tracer.startSpan('kafka.consume', {
46
- childOf,
47
- tags: {
48
- 'service.name': this.config.service || `${this.tracer._service}-kafka`,
49
- 'span.kind': 'consumer',
50
- 'span.type': 'worker',
51
- 'component': 'kafkajs',
52
- 'resource.name': topic,
53
- 'kafka.topic': topic,
54
- 'kafka.partition': partition,
55
- 'kafka.message.offset': message.offset
56
- }
57
- })
58
-
59
- analyticsSampler.sample(span, this.config.measured, true)
60
- this.enter(span, store)
61
- })
62
-
63
- this.addSub(`apm:kafkajs:consume:error`, errorHandler)
64
-
65
- this.addSub(`apm:kafkajs:consume:finish`, finishHandler)
66
-
67
- this.addSub(`apm:kafkajs:produce:error`, errorHandler)
68
-
69
- this.addSub(`apm:kafkajs:produce:finish`, finishHandler)
3
+ const ProducerPlugin = require('./producer')
4
+ const ConsumerPlugin = require('./consumer')
5
+ const CompositePlugin = require('../../dd-trace/src/plugins/composite')
6
+
7
+ class KafkajsPlugin extends CompositePlugin {
8
+ static get name () { return 'kafkajs' }
9
+ static get plugins () {
10
+ return {
11
+ producer: ProducerPlugin,
12
+ consumer: ConsumerPlugin
13
+ }
70
14
  }
71
15
  }
72
16
 
73
- function finishHandler () {
74
- storage.getStore().span.finish()
75
- }
76
-
77
- function errorHandler (error) {
78
- storage.getStore().span.setTag('error', error)
79
- }
80
-
81
- function extract (tracer, bufferMap) {
82
- if (!bufferMap) return null
83
-
84
- const textMap = {}
85
-
86
- for (const key of Object.keys(bufferMap)) {
87
- textMap[key] = bufferMap[key].toString()
88
- }
89
-
90
- return tracer.extract('text_map', textMap)
91
- }
92
-
93
17
  module.exports = KafkajsPlugin
@@ -0,0 +1,31 @@
1
+ 'use strict'
2
+
3
+ const ProducerPlugin = require('../../dd-trace/src/plugins/producer')
4
+
5
+ class KafkajsProducerPlugin extends ProducerPlugin {
6
+ static get name () { return 'kafkajs' }
7
+ static get operation () { return 'produce' }
8
+
9
+ start ({ topic, messages }) {
10
+ const span = this.startSpan('kafka.produce', {
11
+ service: this.config.service || `${this.tracer._service}-kafka`,
12
+ resource: topic,
13
+ kind: 'producer',
14
+ meta: {
15
+ 'component': 'kafkajs',
16
+ 'kafka.topic': topic
17
+ },
18
+ metrics: {
19
+ 'kafka.batch_size': messages.length
20
+ }
21
+ })
22
+
23
+ for (const message of messages) {
24
+ if (typeof message === 'object') {
25
+ this.tracer.inject(span, 'text_map', message.headers)
26
+ }
27
+ }
28
+ }
29
+ }
30
+
31
+ module.exports = KafkajsProducerPlugin
@@ -0,0 +1,10 @@
1
+ 'use strict'
2
+
3
+ const MySQLPlugin = require('../../datadog-plugin-mysql/src')
4
+
5
+ class MariadbPlugin extends MySQLPlugin {
6
+ static get name () { return 'mariadb' }
7
+ static get system () { return 'mariadb' }
8
+ }
9
+
10
+ module.exports = MariadbPlugin
@@ -1,59 +1,24 @@
1
1
  'use strict'
2
2
 
3
- const Plugin = require('../../dd-trace/src/plugins/plugin')
4
- const { storage } = require('../../datadog-core')
5
- const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
6
-
7
- class MemcachedPlugin extends Plugin {
8
- static get name () {
9
- return 'memcached'
10
- }
11
-
12
- constructor (...args) {
13
- super(...args)
14
-
15
- this.addSub('apm:memcached:command:start', () => {
16
- const store = storage.getStore()
17
- const childOf = store ? store.span : store
18
- const span = this.tracer.startSpan('memcached.command', {
19
- childOf,
20
- tags: {
21
- 'span.kind': 'client',
22
- 'span.type': 'memcached',
23
- 'service.name': this.config.service || `${this.tracer._service}-memcached`
24
- }
25
- })
26
-
27
- analyticsSampler.sample(span, this.config.measured)
28
- this.enter(span, store)
29
- })
30
-
31
- this.addSub('apm:memcached:command:start:with-args', ({ client, server, query }) => {
32
- const span = storage.getStore().span
33
- span.addTags({
34
- 'resource.name': query.type,
35
- 'memcached.command': query.command
36
- })
37
-
38
- const address = getAddress(client, server, query)
39
-
40
- if (address) {
41
- span.addTags({
42
- 'out.host': address[0],
43
- 'out.port': address[1]
44
- })
3
+ const CachePlugin = require('../../dd-trace/src/plugins/cache')
4
+
5
+ class MemcachedPlugin extends CachePlugin {
6
+ static get name () { return 'memcached' }
7
+
8
+ start ({ client, server, query }) {
9
+ const address = getAddress(client, server, query)
10
+
11
+ this.startSpan('memcached.command', {
12
+ service: this.config.service,
13
+ resource: query.type,
14
+ type: 'memcached',
15
+ kind: 'client',
16
+ meta: {
17
+ 'memcached.command': query.command,
18
+ 'out.host': address[0],
19
+ 'out.port': address[1]
45
20
  }
46
21
  })
47
-
48
- this.addSub('apm:memcached:command:error', err => {
49
- const span = storage.getStore().span
50
- span.setTag('error', err)
51
- })
52
-
53
- this.addSub('apm:memcached:command:finish', () => {
54
- const span = storage.getStore().span
55
- span.finish()
56
- })
57
22
  }
58
23
  }
59
24
 
@@ -1,45 +1,27 @@
1
1
  'use strict'
2
2
 
3
- const Plugin = require('../../dd-trace/src/plugins/plugin')
3
+ const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
4
4
  const { storage } = require('../../datadog-core')
5
5
 
6
6
  const {
7
- CI_APP_ORIGIN,
8
- TEST_CODE_OWNERS,
9
- TEST_SUITE,
10
7
  TEST_STATUS,
11
8
  TEST_PARAMETERS,
12
9
  finishAllTraceSpans,
13
- getTestEnvironmentMetadata,
14
10
  getTestSuitePath,
15
11
  getTestParentSpan,
16
12
  getTestParametersString,
17
- getCodeOwnersFileEntries,
18
- getCodeOwnersForFilename,
19
- getTestCommonTags,
20
13
  getTestSessionCommonTags,
21
14
  getTestSuiteCommonTags,
22
15
  TEST_SUITE_ID,
23
16
  TEST_SESSION_ID,
24
- TEST_COMMAND
17
+ TEST_COMMAND,
18
+ TEST_ITR_TESTS_SKIPPED,
19
+ TEST_SESSION_CODE_COVERAGE_ENABLED,
20
+ TEST_SESSION_ITR_SKIPPING_ENABLED
25
21
  } = require('../../dd-trace/src/plugins/util/test')
22
+ const { COMPONENT } = require('../../dd-trace/src/constants')
26
23
 
27
- function getTestSpanMetadata (tracer, test, sourceRoot) {
28
- const childOf = getTestParentSpan(tracer)
29
-
30
- const { file: testSuiteAbsolutePath } = test
31
- const fullTestName = test.fullTitle()
32
- const testSuite = getTestSuitePath(testSuiteAbsolutePath, sourceRoot)
33
-
34
- const commonTags = getTestCommonTags(fullTestName, testSuite, tracer._version)
35
-
36
- return {
37
- childOf,
38
- ...commonTags
39
- }
40
- }
41
-
42
- class MochaPlugin extends Plugin {
24
+ class MochaPlugin extends CiPlugin {
43
25
  static get name () {
44
26
  return 'mocha'
45
27
  }
@@ -49,14 +31,24 @@ class MochaPlugin extends Plugin {
49
31
 
50
32
  this._testSuites = new Map()
51
33
  this._testNameToParams = {}
52
- this.testEnvironmentMetadata = getTestEnvironmentMetadata('mocha', this.config)
53
34
  this.sourceRoot = process.cwd()
54
- this.codeOwnersEntries = getCodeOwnersFileEntries(this.sourceRoot)
55
35
 
56
- this.addSub('ci:mocha:run:start', (command) => {
57
- if (!this.config.isAgentlessEnabled) {
36
+ this.addSub('ci:mocha:test-suite:code-coverage', ({ coverageFiles, suiteFile }) => {
37
+ if (!this.itrConfig || !this.itrConfig.isCodeCoverageEnabled) {
58
38
  return
59
39
  }
40
+ const testSuiteSpan = this._testSuites.get(suiteFile)
41
+
42
+ const relativeCoverageFiles = [...coverageFiles, suiteFile]
43
+ .map(filename => getTestSuitePath(filename, this.sourceRoot))
44
+
45
+ this.tracer._exporter.exportCoverage({
46
+ span: testSuiteSpan,
47
+ coverageFiles: relativeCoverageFiles
48
+ })
49
+ })
50
+
51
+ this.addSub('ci:mocha:session:start', (command) => {
60
52
  const childOf = getTestParentSpan(this.tracer)
61
53
  const testSessionSpanMetadata = getTestSessionCommonTags(command, this.tracer._version)
62
54
 
@@ -64,6 +56,7 @@ class MochaPlugin extends Plugin {
64
56
  this.testSessionSpan = this.tracer.startSpan('mocha.test_session', {
65
57
  childOf,
66
58
  tags: {
59
+ [COMPONENT]: this.constructor.name,
67
60
  ...this.testEnvironmentMetadata,
68
61
  ...testSessionSpanMetadata
69
62
  }
@@ -71,9 +64,6 @@ class MochaPlugin extends Plugin {
71
64
  })
72
65
 
73
66
  this.addSub('ci:mocha:test-suite:start', (suite) => {
74
- if (!this.config.isAgentlessEnabled) {
75
- return
76
- }
77
67
  const store = storage.getStore()
78
68
  const testSuiteMetadata = getTestSuiteCommonTags(
79
69
  this.command,
@@ -83,6 +73,7 @@ class MochaPlugin extends Plugin {
83
73
  const testSuiteSpan = this.tracer.startSpan('mocha.test_suite', {
84
74
  childOf: this.testSessionSpan,
85
75
  tags: {
76
+ [COMPONENT]: this.constructor.name,
86
77
  ...this.testEnvironmentMetadata,
87
78
  ...testSuiteMetadata
88
79
  }
@@ -92,9 +83,6 @@ class MochaPlugin extends Plugin {
92
83
  })
93
84
 
94
85
  this.addSub('ci:mocha:test-suite:finish', (status) => {
95
- if (!this.config.isAgentlessEnabled) {
96
- return
97
- }
98
86
  const span = storage.getStore().span
99
87
  // the test status of the suite may have been set in ci:mocha:test-suite:error already
100
88
  if (!span.context()._tags[TEST_STATUS]) {
@@ -104,9 +92,6 @@ class MochaPlugin extends Plugin {
104
92
  })
105
93
 
106
94
  this.addSub('ci:mocha:test-suite:error', (err) => {
107
- if (!this.config.isAgentlessEnabled) {
108
- return
109
- }
110
95
  const span = storage.getStore().span
111
96
  span.setTag('error', err)
112
97
  span.setTag(TEST_STATUS, 'fail')
@@ -154,20 +139,25 @@ class MochaPlugin extends Plugin {
154
139
  this._testNameToParams[name] = params
155
140
  })
156
141
 
157
- this.addSub('ci:mocha:run:finish', (status) => {
142
+ this.addSub('ci:mocha:session:finish', ({ status, isSuitesSkipped }) => {
158
143
  if (this.testSessionSpan) {
144
+ const { isSuitesSkippingEnabled, isCodeCoverageEnabled } = this.itrConfig || {}
159
145
  this.testSessionSpan.setTag(TEST_STATUS, status)
146
+ this.testSessionSpan.setTag(TEST_ITR_TESTS_SKIPPED, isSuitesSkipped ? 'true' : 'false')
147
+ this.testSessionSpan.setTag(TEST_SESSION_ITR_SKIPPING_ENABLED, isSuitesSkippingEnabled ? 'true' : 'false')
148
+ this.testSessionSpan.setTag(TEST_SESSION_CODE_COVERAGE_ENABLED, isCodeCoverageEnabled ? 'true' : 'false')
149
+
160
150
  this.testSessionSpan.finish()
161
151
  finishAllTraceSpans(this.testSessionSpan)
162
152
  }
163
- this.tracer._exporter._writer.flush()
153
+ this.itrConfig = null
154
+ this.tracer._exporter.flush()
164
155
  })
165
156
  }
166
157
 
167
158
  startTestSpan (test) {
168
159
  const testSuiteTags = {}
169
160
  const testSuiteSpan = this._testSuites.get(test.parent.file)
170
-
171
161
  if (testSuiteSpan) {
172
162
  const testSuiteId = testSuiteSpan.context()._spanId.toString(10)
173
163
  testSuiteTags[TEST_SUITE_ID] = testSuiteId
@@ -179,30 +169,20 @@ class MochaPlugin extends Plugin {
179
169
  testSuiteTags[TEST_COMMAND] = this.command
180
170
  }
181
171
 
182
- const { childOf, ...testSpanMetadata } = getTestSpanMetadata(this.tracer, test, this.sourceRoot)
172
+ const { file: testSuiteAbsolutePath } = test
173
+ const fullTestName = test.fullTitle()
174
+ const testSuite = getTestSuitePath(testSuiteAbsolutePath, this.sourceRoot)
183
175
 
184
- const testParametersString = getTestParametersString(this._testNameToParams, test.title)
185
- if (testParametersString) {
186
- testSpanMetadata[TEST_PARAMETERS] = testParametersString
176
+ const extraTags = {
177
+ ...testSuiteTags
187
178
  }
188
- const codeOwners = getCodeOwnersForFilename(testSpanMetadata[TEST_SUITE], this.codeOwnersEntries)
189
179
 
190
- if (codeOwners) {
191
- testSpanMetadata[TEST_CODE_OWNERS] = codeOwners
180
+ const testParametersString = getTestParametersString(this._testNameToParams, test.title)
181
+ if (testParametersString) {
182
+ extraTags[TEST_PARAMETERS] = testParametersString
192
183
  }
193
184
 
194
- const testSpan = this.tracer
195
- .startSpan('mocha.test', {
196
- childOf,
197
- tags: {
198
- ...this.testEnvironmentMetadata,
199
- ...testSpanMetadata,
200
- ...testSuiteTags
201
- }
202
- })
203
- testSpan.context()._trace.origin = CI_APP_ORIGIN
204
-
205
- return testSpan
185
+ return super.startTestSpan(fullTestName, testSuite, extraTags)
206
186
  }
207
187
  }
208
188