dd-trace 4.0.0 → 4.1.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 (98) hide show
  1. package/LICENSE-3rdparty.csv +1 -0
  2. package/MIGRATING.md +39 -0
  3. package/README.md +18 -11
  4. package/package.json +3 -2
  5. package/packages/datadog-esbuild/index.js +13 -1
  6. package/packages/datadog-instrumentations/src/cucumber.js +13 -0
  7. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  8. package/packages/datadog-instrumentations/src/http/client.js +2 -1
  9. package/packages/datadog-instrumentations/src/http/server.js +14 -0
  10. package/packages/datadog-instrumentations/src/http2/client.js +4 -0
  11. package/packages/datadog-instrumentations/src/jest.js +2 -3
  12. package/packages/datadog-instrumentations/src/next.js +2 -2
  13. package/packages/datadog-instrumentations/src/pg.js +14 -11
  14. package/packages/datadog-instrumentations/src/playwright.js +1 -1
  15. package/packages/datadog-instrumentations/src/sequelize.js +51 -0
  16. package/packages/datadog-plugin-amqp10/src/consumer.js +1 -3
  17. package/packages/datadog-plugin-amqp10/src/producer.js +1 -3
  18. package/packages/datadog-plugin-amqplib/src/client.js +4 -3
  19. package/packages/datadog-plugin-amqplib/src/consumer.js +1 -3
  20. package/packages/datadog-plugin-amqplib/src/producer.js +1 -3
  21. package/packages/datadog-plugin-cucumber/src/index.js +2 -2
  22. package/packages/datadog-plugin-cypress/src/plugin.js +150 -30
  23. package/packages/datadog-plugin-cypress/src/support.js +6 -3
  24. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +4 -3
  25. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -3
  26. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +1 -3
  27. package/packages/datadog-plugin-http/src/client.js +70 -68
  28. package/packages/datadog-plugin-http2/src/client.js +50 -47
  29. package/packages/datadog-plugin-jest/src/index.js +5 -4
  30. package/packages/datadog-plugin-kafkajs/src/consumer.js +1 -4
  31. package/packages/datadog-plugin-kafkajs/src/producer.js +1 -3
  32. package/packages/datadog-plugin-memcached/src/index.js +2 -3
  33. package/packages/datadog-plugin-mocha/src/index.js +4 -2
  34. package/packages/datadog-plugin-pg/src/index.js +1 -1
  35. package/packages/datadog-plugin-redis/src/index.js +2 -13
  36. package/packages/datadog-plugin-rhea/src/consumer.js +1 -3
  37. package/packages/datadog-plugin-rhea/src/producer.js +1 -5
  38. package/packages/datadog-plugin-router/src/index.js +12 -1
  39. package/packages/dd-trace/src/appsec/blocked_templates.js +2 -101
  40. package/packages/dd-trace/src/appsec/blocking.js +60 -11
  41. package/packages/dd-trace/src/appsec/channels.js +3 -2
  42. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +7 -5
  43. package/packages/dd-trace/src/appsec/iast/analyzers/index.js +3 -0
  44. package/packages/dd-trace/src/appsec/iast/analyzers/insecure-cookie-analyzer.js +31 -0
  45. package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +4 -0
  46. package/packages/dd-trace/src/appsec/iast/analyzers/set-cookies-header-interceptor.js +47 -0
  47. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +30 -5
  48. package/packages/dd-trace/src/appsec/iast/analyzers/ssrf-analyzer.js +26 -0
  49. package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +35 -3
  50. package/packages/dd-trace/src/appsec/iast/path-line.js +14 -7
  51. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +19 -4
  52. package/packages/dd-trace/src/appsec/iast/telemetry/logs.js +1 -1
  53. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +25 -2
  54. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +49 -0
  55. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +3 -1
  56. package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +7 -5
  57. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +0 -33
  58. package/packages/dd-trace/src/appsec/recommended.json +45 -46
  59. package/packages/dd-trace/src/appsec/remote_config/capabilities.js +3 -1
  60. package/packages/dd-trace/src/appsec/remote_config/index.js +4 -0
  61. package/packages/dd-trace/src/appsec/rule_manager.js +49 -6
  62. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -7
  63. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +1 -1
  64. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +1 -6
  65. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +10 -4
  66. package/packages/dd-trace/src/config.js +36 -5
  67. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +11 -3
  68. package/packages/dd-trace/src/exporters/common/util.js +9 -0
  69. package/packages/dd-trace/src/exporters/common/writer.js +3 -2
  70. package/packages/dd-trace/src/plugin_manager.js +2 -0
  71. package/packages/dd-trace/src/plugins/cache.js +7 -0
  72. package/packages/dd-trace/src/plugins/ci_plugin.js +2 -0
  73. package/packages/dd-trace/src/plugins/client.js +3 -2
  74. package/packages/dd-trace/src/plugins/consumer.js +14 -2
  75. package/packages/dd-trace/src/plugins/database.js +2 -2
  76. package/packages/dd-trace/src/plugins/inbound.js +7 -0
  77. package/packages/dd-trace/src/plugins/{outgoing.js → outbound.js} +2 -2
  78. package/packages/dd-trace/src/plugins/producer.js +19 -2
  79. package/packages/dd-trace/src/plugins/server.js +2 -2
  80. package/packages/dd-trace/src/plugins/storage.js +2 -0
  81. package/packages/dd-trace/src/plugins/tracing.js +11 -0
  82. package/packages/dd-trace/src/plugins/util/ci.js +1 -1
  83. package/packages/dd-trace/src/profiling/config.js +4 -2
  84. package/packages/dd-trace/src/service-naming/index.js +30 -0
  85. package/packages/dd-trace/src/service-naming/schemas/definition.js +24 -0
  86. package/packages/dd-trace/src/service-naming/schemas/index.js +6 -0
  87. package/packages/dd-trace/src/service-naming/schemas/util.js +5 -0
  88. package/packages/dd-trace/src/service-naming/schemas/v0/index.js +5 -0
  89. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +64 -0
  90. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +33 -0
  91. package/packages/dd-trace/src/service-naming/schemas/v1/index.js +5 -0
  92. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +52 -0
  93. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +21 -0
  94. package/packages/dd-trace/src/telemetry/index.js +5 -6
  95. package/packages/dd-trace/src/telemetry/send-data.js +17 -5
  96. package/packages/dd-trace/src/tracer.js +3 -3
  97. package/version.js +8 -4
  98. package/packages/dd-trace/src/plugins/incoming.js +0 -7
@@ -36,6 +36,22 @@ function safeJsonParse (input) {
36
36
  }
37
37
  }
38
38
 
39
+ const namingVersions = ['v0', 'v1']
40
+ const defaultNamingVersion = 'v0'
41
+
42
+ function validateNamingVersion (versionString) {
43
+ if (!versionString) {
44
+ return defaultNamingVersion
45
+ }
46
+ if (!namingVersions.includes(versionString)) {
47
+ log.warn(
48
+ `Unexpected input for config.spanAttributeSchema, picked default ${defaultNamingVersion}`
49
+ )
50
+ return defaultNamingVersion
51
+ }
52
+ return versionString
53
+ }
54
+
39
55
  // Shallow clone with property name remapping
40
56
  function remapify (input, mappings) {
41
57
  if (!input) return
@@ -200,8 +216,11 @@ class Config {
200
216
  process.env.DD_TRACE_TELEMETRY_ENABLED,
201
217
  !inServerlessEnvironment
202
218
  )
203
- const DD_TELEMETRY_DEBUG_ENABLED = coalesce(
204
- process.env.DD_TELEMETRY_DEBUG_ENABLED,
219
+ const DD_TELEMETRY_HEARTBEAT_INTERVAL = process.env.DD_TELEMETRY_HEARTBEAT_INTERVAL
220
+ ? parseInt(process.env.DD_TELEMETRY_HEARTBEAT_INTERVAL) * 1000
221
+ : 60000
222
+ const DD_TELEMETRY_DEBUG = coalesce(
223
+ process.env.DD_TELEMETRY_DEBUG,
205
224
  false
206
225
  )
207
226
  const DD_TRACE_AGENT_PROTOCOL_VERSION = coalesce(
@@ -273,7 +292,9 @@ class Config {
273
292
  process.env.DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED,
274
293
  false
275
294
  )
276
-
295
+ const DD_TRACE_SPAN_ATTRIBUTE_SCHEMA = validateNamingVersion(
296
+ process.env.DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
297
+ )
277
298
  const DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH = coalesce(
278
299
  process.env.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH,
279
300
  '512'
@@ -489,13 +510,15 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
489
510
  sourceMap: !isFalse(DD_PROFILING_SOURCE_MAP),
490
511
  exporters: DD_PROFILING_EXPORTERS
491
512
  }
513
+ this.spanAttributeSchema = DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
492
514
  this.lookup = options.lookup
493
515
  this.startupLogs = isTrue(DD_TRACE_STARTUP_LOGS)
494
516
  // Disabled for CI Visibility's agentless
495
517
  this.telemetry = {
496
518
  enabled: DD_TRACE_EXPORTER !== 'datadog' && isTrue(DD_TRACE_TELEMETRY_ENABLED),
519
+ heartbeatInterval: DD_TELEMETRY_HEARTBEAT_INTERVAL,
497
520
  logCollection: isTrue(DD_TELEMETRY_LOG_COLLECTION_ENABLED),
498
- debug: isTrue(DD_TELEMETRY_DEBUG_ENABLED)
521
+ debug: isTrue(DD_TELEMETRY_DEBUG)
499
522
  }
500
523
  this.protocolVersion = DD_TRACE_AGENT_PROTOCOL_VERSION
501
524
  this.tagsHeaderMaxLength = parseInt(DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH)
@@ -545,7 +568,15 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
545
568
  process.env.DD_GIT_PROPERTIES_FILE,
546
569
  `${process.cwd()}/git.properties`
547
570
  )
548
- const gitPropertiesString = maybeFile(DD_GIT_PROPERTIES_FILE)
571
+ let gitPropertiesString
572
+ try {
573
+ gitPropertiesString = fs.readFileSync(DD_GIT_PROPERTIES_FILE, 'utf8')
574
+ } catch (e) {
575
+ // Only log error if the user has set a git.properties path
576
+ if (process.env.DD_GIT_PROPERTIES_FILE) {
577
+ log.error(e)
578
+ }
579
+ }
549
580
  if (gitPropertiesString) {
550
581
  const { commitSHA, repositoryUrl } = getGitMetadataFromGitProperties(gitPropertiesString)
551
582
  this.commitSHA = this.commitSHA || commitSHA
@@ -26,11 +26,19 @@ class CoverageCIVisibilityEncoder extends AgentEncoder {
26
26
  }
27
27
 
28
28
  encodeCodeCoverage (bytes, coverage) {
29
- this._encodeMapPrefix(bytes, 3)
29
+ if (coverage.testId) {
30
+ this._encodeMapPrefix(bytes, 4)
31
+ } else {
32
+ this._encodeMapPrefix(bytes, 3)
33
+ }
30
34
  this._encodeString(bytes, 'test_session_id')
31
- this._encodeId(bytes, coverage.traceId)
35
+ this._encodeId(bytes, coverage.sessionId)
32
36
  this._encodeString(bytes, 'test_suite_id')
33
- this._encodeId(bytes, coverage.spanId)
37
+ this._encodeId(bytes, coverage.suiteId)
38
+ if (coverage.testId) {
39
+ this._encodeString(bytes, 'span_id')
40
+ this._encodeId(bytes, coverage.testId)
41
+ }
34
42
  this._encodeString(bytes, 'files')
35
43
  this._encodeArrayPrefix(bytes, coverage.files)
36
44
  for (const filename of coverage.files) {
@@ -0,0 +1,9 @@
1
+ function safeJSONStringify (value) {
2
+ return JSON.stringify(
3
+ value,
4
+ (key, value) => key !== 'dd-api-key' ? value : undefined,
5
+ process.env.DD_TRACE_BEAUTIFUL_LOGS ? 2 : undefined
6
+ )
7
+ }
8
+
9
+ module.exports = { safeJSONStringify }
@@ -2,6 +2,7 @@
2
2
 
3
3
  const request = require('./request')
4
4
  const log = require('../../log')
5
+ const { safeJSONStringify } = require('./util')
5
6
 
6
7
  class Writer {
7
8
  constructor ({ url }) {
@@ -25,11 +26,11 @@ class Writer {
25
26
 
26
27
  append (payload) {
27
28
  if (!request.writable) {
28
- log.debug(() => `Maximum number of active requests reached. Payload discarded: ${JSON.stringify(payload)}`)
29
+ log.debug(() => `Maximum number of active requests reached. Payload discarded: ${safeJSONStringify(payload)}`)
29
30
  return
30
31
  }
31
32
 
32
- log.debug(() => `Encoding payload: ${JSON.stringify(payload)}`)
33
+ log.debug(() => `Encoding payload: ${safeJSONStringify(payload)}`)
33
34
 
34
35
  this._encode(payload)
35
36
  }
@@ -4,6 +4,7 @@ const { channel } = require('../../diagnostics_channel')
4
4
  const { isFalse } = require('./util')
5
5
  const plugins = require('./plugins')
6
6
  const log = require('./log')
7
+ const Nomenclature = require('./service-naming')
7
8
 
8
9
  const loadChannel = channel('dd-trace:instrumentation:load')
9
10
 
@@ -96,6 +97,7 @@ module.exports = class PluginManager {
96
97
  // like instrumenter.enable()
97
98
  configure (config = {}) {
98
99
  this._tracerConfig = config
100
+ Nomenclature.configure(config)
99
101
 
100
102
  for (const name in pluginClasses) {
101
103
  this.loadPlugin(name)
@@ -4,6 +4,13 @@ const StoragePlugin = require('./storage')
4
4
 
5
5
  class CachePlugin extends StoragePlugin {
6
6
  static get operation () { return 'command' }
7
+
8
+ startSpan (options) {
9
+ if (!options.kind) {
10
+ options.kind = this.constructor.kind
11
+ }
12
+ return super.startSpan(this.operationName(), options)
13
+ }
7
14
  }
8
15
 
9
16
  module.exports = CachePlugin
@@ -22,6 +22,8 @@ module.exports = class CiPlugin extends Plugin {
22
22
  constructor (...args) {
23
23
  super(...args)
24
24
 
25
+ this.rootDir = process.cwd() // fallback in case :session:start events are not emitted
26
+
25
27
  this.addSub(`ci:${this.constructor.id}:itr-configuration`, ({ onDone }) => {
26
28
  if (!this.tracer._exporter || !this.tracer._exporter.getItrConfiguration) {
27
29
  return onDone({ err: new Error('CI Visibility was not initialized correctly') })
@@ -1,9 +1,10 @@
1
1
  'use strict'
2
2
 
3
- const OutgoingPlugin = require('./outgoing')
3
+ const OutboundPlugin = require('./outbound')
4
4
 
5
- class ClientPlugin extends OutgoingPlugin {
5
+ class ClientPlugin extends OutboundPlugin {
6
6
  static get operation () { return 'request' }
7
+ static get kind () { return 'client' }
7
8
  }
8
9
 
9
10
  module.exports = ClientPlugin
@@ -1,9 +1,21 @@
1
1
  'use strict'
2
2
 
3
- const IncomingPlugin = require('./incoming')
3
+ const InboundPlugin = require('./inbound')
4
4
 
5
- class ConsumerPlugin extends IncomingPlugin {
5
+ class ConsumerPlugin extends InboundPlugin {
6
6
  static get operation () { return 'receive' }
7
+ static get kind () { return 'consumer' }
8
+ static get type () { return 'messaging' }
9
+
10
+ startSpan (options) {
11
+ if (!options.service) {
12
+ options.service = this.config.service || this.serviceName()
13
+ }
14
+ if (!options.kind) {
15
+ options.kind = this.constructor.kind
16
+ }
17
+ return super.startSpan(this.operationName(), options)
18
+ }
7
19
  }
8
20
 
9
21
  module.exports = ConsumerPlugin
@@ -37,12 +37,12 @@ class DatabasePlugin extends StoragePlugin {
37
37
  `ddps='${encodedDdps}',ddpv='${encodedDdpv}'`
38
38
  }
39
39
 
40
- injectDbmQuery (query, serviceName) {
40
+ injectDbmQuery (query, serviceName, isPreparedStatement = false) {
41
41
  if (this.config.dbmPropagationMode === 'disabled') {
42
42
  return query
43
43
  }
44
44
  const servicePropagation = this.createDBMPropagationCommentService(serviceName)
45
- if (this.config.dbmPropagationMode === 'service') {
45
+ if (isPreparedStatement || this.config.dbmPropagationMode === 'service') {
46
46
  return `/*${servicePropagation}*/ ${query}`
47
47
  } else if (this.config.dbmPropagationMode === 'full') {
48
48
  this.activeSpan.setTag('_dd.dbm_trace_injected', 'true')
@@ -0,0 +1,7 @@
1
+ 'use strict'
2
+
3
+ const TracingPlugin = require('./tracing')
4
+
5
+ class InboundPlugin extends TracingPlugin {}
6
+
7
+ module.exports = InboundPlugin
@@ -4,7 +4,7 @@ const { CLIENT_PORT_KEY } = require('../constants')
4
4
  const TracingPlugin = require('./tracing')
5
5
 
6
6
  // TODO: Exit span on finish when AsyncResource instances are removed.
7
- class OutgoingPlugin extends TracingPlugin {
7
+ class OutboundPlugin extends TracingPlugin {
8
8
  constructor (...args) {
9
9
  super(...args)
10
10
 
@@ -29,4 +29,4 @@ class OutgoingPlugin extends TracingPlugin {
29
29
  }
30
30
  }
31
31
 
32
- module.exports = OutgoingPlugin
32
+ module.exports = OutboundPlugin
@@ -1,9 +1,26 @@
1
1
  'use strict'
2
2
 
3
- const OutgoingPlugin = require('./outgoing')
3
+ const OutboundPlugin = require('./outbound')
4
4
 
5
- class ProducerPlugin extends OutgoingPlugin {
5
+ class ProducerPlugin extends OutboundPlugin {
6
6
  static get operation () { return 'publish' }
7
+ static get kind () { return 'producer' }
8
+ static get type () { return 'messaging' }
9
+
10
+ startSpan (options) {
11
+ const spanDefaults = {
12
+ kind: this.constructor.kind
13
+ }
14
+ if (!options.service) {
15
+ options.service = this.config.service || this.serviceName()
16
+ }
17
+ Object.keys(spanDefaults).forEach(
18
+ key => {
19
+ if (!options[key]) options[key] = spanDefaults[key]
20
+ }
21
+ )
22
+ return super.startSpan(this.operationName(), options)
23
+ }
7
24
  }
8
25
 
9
26
  module.exports = ProducerPlugin
@@ -1,8 +1,8 @@
1
1
  'use strict'
2
2
 
3
- const IncomingPlugin = require('./incoming')
3
+ const InboundPlugin = require('./inbound')
4
4
 
5
- class ServerPlugin extends IncomingPlugin {
5
+ class ServerPlugin extends InboundPlugin {
6
6
  static get operation () { return 'request' }
7
7
  }
8
8
 
@@ -3,6 +3,8 @@
3
3
  const ClientPlugin = require('./client')
4
4
 
5
5
  class StoragePlugin extends ClientPlugin {
6
+ static get type () { return 'storage' }
7
+
6
8
  constructor (...args) {
7
9
  super(...args)
8
10
 
@@ -4,6 +4,7 @@ const Plugin = require('./plugin')
4
4
  const { storage } = require('../../../datadog-core')
5
5
  const analyticsSampler = require('../analytics_sampler')
6
6
  const { COMPONENT } = require('../constants')
7
+ const Nomenclature = require('../service-naming')
7
8
 
8
9
  class TracingPlugin extends Plugin {
9
10
  constructor (...args) {
@@ -31,6 +32,16 @@ class TracingPlugin extends Plugin {
31
32
  return store && store.span
32
33
  }
33
34
 
35
+ serviceName (...serviceArgs) {
36
+ const { type, id, kind } = this.constructor
37
+ return Nomenclature.serviceName(type, kind, id, ...serviceArgs)
38
+ }
39
+
40
+ operationName (...opNameArgs) {
41
+ const { type, id, kind } = this.constructor
42
+ return Nomenclature.opName(type, kind, id, ...opNameArgs)
43
+ }
44
+
34
45
  configure (config) {
35
46
  return super.configure({
36
47
  ...config,
@@ -192,7 +192,7 @@ module.exports = {
192
192
  [GIT_TAG]: CI_COMMIT_TAG,
193
193
  [GIT_BRANCH]: CI_COMMIT_REF_NAME,
194
194
  [CI_WORKSPACE_PATH]: CI_PROJECT_DIR,
195
- [CI_PIPELINE_URL]: GITLAB_PIPELINE_URL && GITLAB_PIPELINE_URL.replace('/-/pipelines/', '/pipelines/'),
195
+ [CI_PIPELINE_URL]: GITLAB_PIPELINE_URL,
196
196
  [CI_STAGE_NAME]: CI_JOB_STAGE,
197
197
  [CI_JOB_NAME]: GITLAB_CI_JOB_NAME,
198
198
  [GIT_COMMIT_MESSAGE]: CI_COMMIT_MESSAGE,
@@ -91,8 +91,10 @@ class Config {
91
91
  Number(DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE), 0)
92
92
  const maxHeapExtensionCount = coalesce(options.oomMaxHeapExtensionCount,
93
93
  Number(DD_PROFILING_EXPERIMENTAL_OOM_MAX_HEAP_EXTENSION_COUNT), 0)
94
- const exportStrategies = ensureOOMExportStrategies(coalesce(options.oomExportStrategies,
95
- DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES), this)
94
+ const exportStrategies = oomMonitoringEnabled
95
+ ? ensureOOMExportStrategies(coalesce(options.oomExportStrategies, DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES,
96
+ [oomExportStrategies.PROCESS]), this)
97
+ : []
96
98
  const exportCommand = oomMonitoringEnabled ? buildExportCommand(this) : undefined
97
99
  this.oomMonitoring = {
98
100
  enabled: oomMonitoringEnabled,
@@ -0,0 +1,30 @@
1
+ const { schemaDefinitions } = require('./schemas')
2
+
3
+ class SchemaManager {
4
+ constructor () {
5
+ this.schemas = schemaDefinitions
6
+ this.config = { spanAttributeSchema: 'v0' }
7
+ }
8
+
9
+ get schema () {
10
+ return this.schemas[this.version]
11
+ }
12
+
13
+ get version () {
14
+ return this.config.spanAttributeSchema
15
+ }
16
+
17
+ opName (type, kind, plugin, ...opNameArgs) {
18
+ return this.schema.getOpName(type, kind, plugin, ...opNameArgs)
19
+ }
20
+
21
+ serviceName (type, kind, plugin, ...serviceNameArgs) {
22
+ return this.schema.getServiceName(type, kind, plugin, this.config.service, ...serviceNameArgs)
23
+ }
24
+
25
+ configure (config = {}) {
26
+ this.config = config
27
+ }
28
+ }
29
+
30
+ module.exports = new SchemaManager()
@@ -0,0 +1,24 @@
1
+ class SchemaDefinition {
2
+ constructor (schema) {
3
+ this.schema = schema
4
+ }
5
+
6
+ getSchemaItem (type, kind, plugin) {
7
+ const schema = this.schema
8
+ if (schema && schema[type] && schema[type][kind] && schema[type][kind][plugin]) {
9
+ return schema[type][kind][plugin]
10
+ }
11
+ }
12
+
13
+ getOpName (type, kind, plugin, ...opNameArgs) {
14
+ const item = this.getSchemaItem(type, kind, plugin)
15
+ return item.opName(...opNameArgs)
16
+ }
17
+
18
+ getServiceName (type, kind, plugin, service, ...serviceNameArgs) {
19
+ const item = this.getSchemaItem(type, kind, plugin)
20
+ return item.serviceName(service, ...serviceNameArgs)
21
+ }
22
+ }
23
+
24
+ module.exports = SchemaDefinition
@@ -0,0 +1,6 @@
1
+ const v0 = require('./v0')
2
+ const v1 = require('./v1')
3
+
4
+ module.exports = {
5
+ schemaDefinitions: { v0, v1 }
6
+ }
@@ -0,0 +1,5 @@
1
+ function identityService (service) {
2
+ return service
3
+ }
4
+
5
+ module.exports = { identityService }
@@ -0,0 +1,5 @@
1
+ const SchemaDefinition = require('../definition')
2
+ const messaging = require('./messaging')
3
+ const storage = require('./storage')
4
+
5
+ module.exports = new SchemaDefinition({ messaging, storage })
@@ -0,0 +1,64 @@
1
+ const { identityService } = require('../util')
2
+
3
+ function amqpServiceName (service) {
4
+ return `${service}-amqp`
5
+ }
6
+
7
+ const messaging = {
8
+ producer: {
9
+ amqplib: {
10
+ opName: () => 'amqp.command',
11
+ serviceName: amqpServiceName
12
+ },
13
+ amqp10: {
14
+ opName: () => 'amqp.send',
15
+ serviceName: amqpServiceName
16
+ },
17
+ 'google-cloud-pubsub': {
18
+ opName: () => 'pubsub.request',
19
+ serviceName: service => `${service}-pubsub`
20
+ },
21
+ kafkajs: {
22
+ opName: () => 'kafka.produce',
23
+ serviceName: service => `${service}-kafka`
24
+ },
25
+ rhea: {
26
+ opName: () => 'amqp.send',
27
+ serviceName: service => `${service}-amqp-producer`
28
+ }
29
+ },
30
+ consumer: {
31
+ amqplib: {
32
+ opName: () => 'amqp.command',
33
+ serviceName: amqpServiceName
34
+ },
35
+ amqp10: {
36
+ opName: () => 'amqp.receive',
37
+ serviceName: amqpServiceName
38
+ },
39
+ 'google-cloud-pubsub': {
40
+ opName: () => 'pubsub.receive',
41
+ serviceName: identityService
42
+ },
43
+ kafkajs: {
44
+ opName: () => 'kafka.consume',
45
+ serviceName: service => `${service}-kafka`
46
+ },
47
+ rhea: {
48
+ opName: () => 'amqp.receive',
49
+ serviceName: identityService
50
+ }
51
+ },
52
+ client: {
53
+ amqplib: {
54
+ opName: () => 'amqp.command',
55
+ serviceName: amqpServiceName
56
+ },
57
+ 'google-cloud-pubsub': {
58
+ opName: () => 'pubsub.request',
59
+ serviceName: service => `${service}-pubsub`
60
+ }
61
+ }
62
+ }
63
+
64
+ module.exports = messaging
@@ -0,0 +1,33 @@
1
+ function getRedisService (config, connectionName) {
2
+ if (config.splitByInstance && connectionName) {
3
+ return config.service
4
+ ? `${config.service}-${connectionName}`
5
+ : connectionName
6
+ }
7
+
8
+ return config.service
9
+ }
10
+
11
+ function fromSystem (service, system) {
12
+ return system ? `${service}-${system}` : undefined
13
+ }
14
+
15
+ const redisConfig = {
16
+ opName: () => 'redis.command',
17
+ serviceName: (service, config, system, connectionName) => {
18
+ return getRedisService(config, connectionName) || fromSystem(service, system)
19
+ }
20
+ }
21
+
22
+ const storage = {
23
+ client: {
24
+ ioredis: redisConfig,
25
+ memcached: {
26
+ opName: () => 'memcached.command',
27
+ serviceName: (service, config, system) => config.service || fromSystem(service, system)
28
+ },
29
+ redis: redisConfig
30
+ }
31
+ }
32
+
33
+ module.exports = storage
@@ -0,0 +1,5 @@
1
+ const SchemaDefinition = require('../definition')
2
+ const messaging = require('./messaging')
3
+ const storage = require('./storage')
4
+
5
+ module.exports = new SchemaDefinition({ messaging, storage })
@@ -0,0 +1,52 @@
1
+ const { identityService } = require('../util')
2
+
3
+ const amqpInbound = {
4
+ opName: () => 'amqp.process',
5
+ serviceName: identityService
6
+ }
7
+
8
+ const amqpOutbound = {
9
+ opName: () => 'amqp.send',
10
+ serviceName: identityService
11
+ }
12
+
13
+ const messaging = {
14
+ producer: {
15
+ amqplib: amqpOutbound,
16
+ amqp10: amqpOutbound,
17
+ 'google-cloud-pubsub': {
18
+ opName: () => 'gcp.pubsub.send',
19
+ serviceName: identityService
20
+ },
21
+ kafkajs: {
22
+ opName: () => 'kafka.send',
23
+ serviceName: identityService
24
+ },
25
+ rhea: amqpOutbound
26
+ },
27
+ consumer: {
28
+ amqplib: amqpInbound,
29
+ amqp10: amqpInbound,
30
+ 'google-cloud-pubsub': {
31
+ opName: () => 'gcp.pubsub.process',
32
+ serviceName: identityService
33
+ },
34
+ kafkajs: {
35
+ opName: () => 'kafka.process',
36
+ serviceName: identityService
37
+ },
38
+ rhea: amqpInbound
39
+ },
40
+ client: {
41
+ amqplib: {
42
+ opName: () => 'amqp.command',
43
+ serviceName: identityService
44
+ },
45
+ 'google-cloud-pubsub': {
46
+ opName: () => 'gcp.pubsub.request',
47
+ serviceName: identityService
48
+ }
49
+ }
50
+ }
51
+
52
+ module.exports = messaging
@@ -0,0 +1,21 @@
1
+ function configWithFallback (service, config) {
2
+ return config.service || service
3
+ }
4
+
5
+ const redisNaming = {
6
+ opName: () => 'redis.command',
7
+ serviceName: configWithFallback
8
+ }
9
+
10
+ const storage = {
11
+ client: {
12
+ ioredis: redisNaming,
13
+ memcached: {
14
+ opName: () => 'memcached.command',
15
+ serviceName: configWithFallback
16
+ },
17
+ redis: redisNaming
18
+ }
19
+ }
20
+
21
+ module.exports = storage
@@ -6,10 +6,6 @@ const os = require('os')
6
6
  const dependencies = require('./dependencies')
7
7
  const { sendData } = require('./send-data')
8
8
 
9
- const HEARTBEAT_INTERVAL = process.env.DD_TELEMETRY_HEARTBEAT_INTERVAL
10
- ? Number(process.env.DD_TELEMETRY_HEARTBEAT_INTERVAL) * 1000
11
- : 60000
12
-
13
9
  const telemetryStartChannel = dc.channel('datadog:telemetry:start')
14
10
  const telemetryStopChannel = dc.channel('datadog:telemetry:stop')
15
11
 
@@ -19,6 +15,7 @@ let pluginManager
19
15
  let application
20
16
  let host
21
17
  let interval
18
+ let heartbeatInterval
22
19
  const sentIntegrations = new Set()
23
20
 
24
21
  function getIntegrations () {
@@ -108,7 +105,7 @@ function createHostObject () {
108
105
  }
109
106
 
110
107
  function getTelemetryData () {
111
- return { config, application, host, heartbeatInterval: HEARTBEAT_INTERVAL }
108
+ return { config, application, host, heartbeatInterval }
112
109
  }
113
110
 
114
111
  function start (aConfig, thePluginManager) {
@@ -119,11 +116,13 @@ function start (aConfig, thePluginManager) {
119
116
  pluginManager = thePluginManager
120
117
  application = createAppObject()
121
118
  host = createHostObject()
119
+ heartbeatInterval = config.telemetry.heartbeatInterval
120
+
122
121
  dependencies.start(config, application, host)
123
122
  sendData(config, application, host, 'app-started', appStarted())
124
123
  interval = setInterval(() => {
125
124
  sendData(config, application, host, 'app-heartbeat')
126
- }, HEARTBEAT_INTERVAL)
125
+ }, heartbeatInterval)
127
126
  interval.unref()
128
127
  process.on('beforeExit', onBeforeExit)
129
128