dd-trace 5.20.0 → 5.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/index.d.ts +2 -1
  2. package/package.json +6 -6
  3. package/packages/datadog-instrumentations/src/aerospike.js +1 -1
  4. package/packages/datadog-instrumentations/src/apollo-server.js +1 -1
  5. package/packages/datadog-instrumentations/src/aws-sdk.js +4 -4
  6. package/packages/datadog-instrumentations/src/body-parser.js +17 -5
  7. package/packages/datadog-instrumentations/src/cassandra-driver.js +2 -2
  8. package/packages/datadog-instrumentations/src/child_process.js +2 -2
  9. package/packages/datadog-instrumentations/src/connect.js +4 -4
  10. package/packages/datadog-instrumentations/src/cookie-parser.js +4 -4
  11. package/packages/datadog-instrumentations/src/couchbase.js +12 -12
  12. package/packages/datadog-instrumentations/src/cucumber.js +16 -5
  13. package/packages/datadog-instrumentations/src/dns.js +10 -10
  14. package/packages/datadog-instrumentations/src/elasticsearch.js +4 -4
  15. package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +3 -3
  16. package/packages/datadog-instrumentations/src/express.js +4 -4
  17. package/packages/datadog-instrumentations/src/fastify.js +6 -6
  18. package/packages/datadog-instrumentations/src/fetch.js +1 -1
  19. package/packages/datadog-instrumentations/src/find-my-way.js +2 -2
  20. package/packages/datadog-instrumentations/src/fs.js +2 -2
  21. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +2 -2
  22. package/packages/datadog-instrumentations/src/grpc/client.js +4 -6
  23. package/packages/datadog-instrumentations/src/grpc/server.js +2 -2
  24. package/packages/datadog-instrumentations/src/hapi.js +10 -13
  25. package/packages/datadog-instrumentations/src/helpers/hooks.js +3 -2
  26. package/packages/datadog-instrumentations/src/helpers/register.js +9 -2
  27. package/packages/datadog-instrumentations/src/http/client.js +3 -3
  28. package/packages/datadog-instrumentations/src/jest.js +5 -4
  29. package/packages/datadog-instrumentations/src/knex.js +2 -2
  30. package/packages/datadog-instrumentations/src/koa.js +5 -5
  31. package/packages/datadog-instrumentations/src/ldapjs.js +1 -1
  32. package/packages/datadog-instrumentations/src/mariadb.js +8 -8
  33. package/packages/datadog-instrumentations/src/memcached.js +2 -2
  34. package/packages/datadog-instrumentations/src/microgateway-core.js +4 -4
  35. package/packages/datadog-instrumentations/src/mocha/common.js +1 -1
  36. package/packages/datadog-instrumentations/src/mocha/main.js +91 -70
  37. package/packages/datadog-instrumentations/src/mocha/utils.js +2 -3
  38. package/packages/datadog-instrumentations/src/mocha.js +4 -0
  39. package/packages/datadog-instrumentations/src/moleculer/server.js +2 -2
  40. package/packages/datadog-instrumentations/src/mongodb-core.js +7 -7
  41. package/packages/datadog-instrumentations/src/mongoose.js +5 -6
  42. package/packages/datadog-instrumentations/src/mysql.js +3 -3
  43. package/packages/datadog-instrumentations/src/mysql2.js +6 -6
  44. package/packages/datadog-instrumentations/src/net.js +2 -2
  45. package/packages/datadog-instrumentations/src/next.js +5 -5
  46. package/packages/datadog-instrumentations/src/nyc.js +23 -0
  47. package/packages/datadog-instrumentations/src/openai.js +58 -69
  48. package/packages/datadog-instrumentations/src/oracledb.js +8 -8
  49. package/packages/datadog-instrumentations/src/passport-http.js +1 -1
  50. package/packages/datadog-instrumentations/src/passport-local.js +1 -1
  51. package/packages/datadog-instrumentations/src/passport-utils.js +1 -1
  52. package/packages/datadog-instrumentations/src/pg.js +1 -1
  53. package/packages/datadog-instrumentations/src/pino.js +4 -4
  54. package/packages/datadog-instrumentations/src/playwright.js +6 -4
  55. package/packages/datadog-instrumentations/src/redis.js +2 -2
  56. package/packages/datadog-instrumentations/src/restify.js +4 -4
  57. package/packages/datadog-instrumentations/src/rhea.js +4 -4
  58. package/packages/datadog-instrumentations/src/router.js +5 -5
  59. package/packages/datadog-instrumentations/src/sharedb.js +2 -2
  60. package/packages/datadog-instrumentations/src/vitest.js +22 -5
  61. package/packages/datadog-instrumentations/src/winston.js +2 -3
  62. package/packages/datadog-plugin-cucumber/src/index.js +12 -2
  63. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +21 -10
  64. package/packages/datadog-plugin-hapi/src/index.js +2 -2
  65. package/packages/datadog-plugin-jest/src/index.js +18 -4
  66. package/packages/datadog-plugin-mocha/src/index.js +25 -6
  67. package/packages/datadog-plugin-nyc/src/index.js +35 -0
  68. package/packages/datadog-plugin-openai/src/index.js +58 -47
  69. package/packages/datadog-plugin-playwright/src/index.js +9 -4
  70. package/packages/datadog-plugin-vitest/src/index.js +30 -4
  71. package/packages/datadog-shimmer/src/shimmer.js +144 -10
  72. package/packages/dd-trace/src/appsec/blocking.js +23 -17
  73. package/packages/dd-trace/src/appsec/graphql.js +3 -1
  74. package/packages/dd-trace/src/appsec/iast/iast-log.js +2 -1
  75. package/packages/dd-trace/src/appsec/remote_config/manager.js +4 -1
  76. package/packages/dd-trace/src/appsec/rule_manager.js +8 -0
  77. package/packages/dd-trace/src/appsec/telemetry.js +3 -3
  78. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +40 -1
  79. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -4
  80. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -4
  81. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +2 -1
  82. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +8 -7
  83. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -4
  84. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +2 -4
  85. package/packages/dd-trace/src/ci-visibility/telemetry.js +29 -2
  86. package/packages/dd-trace/src/config.js +157 -142
  87. package/packages/dd-trace/src/lambda/handler.js +1 -0
  88. package/packages/dd-trace/src/lambda/index.js +12 -1
  89. package/packages/dd-trace/src/opentelemetry/context_manager.js +22 -39
  90. package/packages/dd-trace/src/opentelemetry/span_context.js +2 -2
  91. package/packages/dd-trace/src/opentelemetry/tracer.js +23 -14
  92. package/packages/dd-trace/src/opentelemetry/tracer_provider.js +9 -1
  93. package/packages/dd-trace/src/opentracing/propagation/log.js +1 -1
  94. package/packages/dd-trace/src/opentracing/propagation/text_map.js +61 -6
  95. package/packages/dd-trace/src/opentracing/span_context.js +1 -0
  96. package/packages/dd-trace/src/plugins/ci_plugin.js +2 -2
  97. package/packages/dd-trace/src/plugins/index.js +1 -0
  98. package/packages/dd-trace/src/plugins/util/git.js +14 -1
  99. package/packages/dd-trace/src/plugins/util/test.js +1 -5
  100. package/packages/dd-trace/src/profiler.js +15 -5
  101. package/packages/dd-trace/src/profiling/config.js +2 -4
  102. package/packages/dd-trace/src/profiling/exporter_cli.js +13 -1
  103. package/packages/dd-trace/src/profiling/exporters/agent.js +7 -1
  104. package/packages/dd-trace/src/profiling/profiler.js +0 -9
  105. package/packages/dd-trace/src/profiling/ssi-heuristics.js +49 -58
  106. package/packages/dd-trace/src/proxy.js +21 -21
  107. package/packages/dd-trace/src/telemetry/index.js +24 -7
  108. package/packages/dd-trace/src/telemetry/logs/index.js +20 -0
@@ -2,61 +2,46 @@
2
2
 
3
3
  const { AsyncLocalStorage } = require('async_hooks')
4
4
  const { trace, ROOT_CONTEXT } = require('@opentelemetry/api')
5
+ const DataDogSpanContext = require('../opentracing/span_context')
5
6
 
6
7
  const SpanContext = require('./span_context')
7
8
  const tracer = require('../../')
8
9
 
9
- // Horrible hack to acquire the otherwise inaccessible SPAN_KEY so we can redirect it...
10
- // This is used for getting the current span context in OpenTelemetry, but the SPAN_KEY value is
11
- // not exposed as it's meant to be read-only from outside the module. We want to hijack this logic
12
- // so we can instead get the span context from the datadog context manager instead.
13
- let SPAN_KEY
14
- trace.getSpan({
15
- getValue (key) {
16
- SPAN_KEY = key
17
- }
18
- })
19
-
20
- // Whenever a value is acquired from the context map we should mostly delegate to the real getter,
21
- // but when accessing the current span we should hijack that access to instead provide a fake span
22
- // which we can use to get an OTel span context wrapping the datadog active scope span context.
23
- function wrappedGetValue (target) {
24
- return (key) => {
25
- if (key === SPAN_KEY) {
26
- return {
27
- spanContext () {
28
- const activeSpan = tracer.scope().active()
29
- const context = activeSpan && activeSpan.context()
30
- return new SpanContext(context)
31
- }
32
- }
33
- }
34
- return target.getValue(key)
35
- }
36
- }
37
-
38
10
  class ContextManager {
39
11
  constructor () {
40
12
  this._store = new AsyncLocalStorage()
41
13
  }
42
14
 
43
15
  active () {
44
- const active = this._store.getStore() || ROOT_CONTEXT
16
+ const activeSpan = tracer.scope().active()
17
+ const store = this._store.getStore()
18
+ const context = (activeSpan && activeSpan.context()) || store || ROOT_CONTEXT
45
19
 
46
- return new Proxy(active, {
47
- get (target, key) {
48
- return key === 'getValue' ? wrappedGetValue(target) : target[key]
49
- }
50
- })
20
+ if (!(context instanceof DataDogSpanContext)) {
21
+ return context
22
+ }
23
+
24
+ if (!context._otelSpanContext) {
25
+ const newSpanContext = new SpanContext(context)
26
+ context._otelSpanContext = newSpanContext
27
+ }
28
+ if (store && trace.getSpanContext(store) === context._otelSpanContext) {
29
+ return store
30
+ }
31
+ return trace.setSpanContext(store || ROOT_CONTEXT, context._otelSpanContext)
51
32
  }
52
33
 
53
34
  with (context, fn, thisArg, ...args) {
54
35
  const span = trace.getSpan(context)
55
36
  const ddScope = tracer.scope()
56
- return ddScope.activate(span._ddSpan, () => {
37
+ const run = () => {
57
38
  const cb = thisArg == null ? fn : fn.bind(thisArg)
58
39
  return this._store.run(context, cb, ...args)
59
- })
40
+ }
41
+ if (span && span._ddSpan) {
42
+ return ddScope.activate(span._ddSpan, run)
43
+ }
44
+ return run()
60
45
  }
61
46
 
62
47
  bind (context, target) {
@@ -66,9 +51,7 @@ class ContextManager {
66
51
  }
67
52
  }
68
53
 
69
- // Not part of the spec but the Node.js API expects these
70
54
  enable () {}
71
55
  disable () {}
72
56
  }
73
-
74
57
  module.exports = ContextManager
@@ -24,11 +24,11 @@ class SpanContext {
24
24
  }
25
25
 
26
26
  get traceId () {
27
- return this._ddContext._traceId.toString(16)
27
+ return this._ddContext.toTraceId(true)
28
28
  }
29
29
 
30
30
  get spanId () {
31
- return this._ddContext._spanId.toString(16)
31
+ return this._ddContext.toSpanId(true)
32
32
  }
33
33
 
34
34
  get traceFlags () {
@@ -7,6 +7,7 @@ const Sampler = require('./sampler')
7
7
  const Span = require('./span')
8
8
  const id = require('../id')
9
9
  const SpanContext = require('./span_context')
10
+ const TextMapPropagator = require('../opentracing/propagation/text_map')
10
11
 
11
12
  class Tracer {
12
13
  constructor (library, config, tracerProvider) {
@@ -22,6 +23,24 @@ class Tracer {
22
23
  return this._tracerProvider.resource
23
24
  }
24
25
 
26
+ _createSpanContextFromParent (parentSpanContext) {
27
+ return new SpanContext({
28
+ traceId: parentSpanContext._traceId,
29
+ spanId: id(),
30
+ parentId: parentSpanContext._spanId,
31
+ sampling: parentSpanContext._sampling,
32
+ baggageItems: Object.assign({}, parentSpanContext._baggageItems),
33
+ trace: parentSpanContext._trace,
34
+ tracestate: parentSpanContext._tracestate
35
+ })
36
+ }
37
+
38
+ // Extracted method to create span context for a new span
39
+ _createSpanContextForNewSpan (context) {
40
+ const { traceId, spanId, traceFlags, traceState } = context
41
+ return TextMapPropagator._convertOtelContextToDatadog(traceId, spanId, traceFlags, traceState)
42
+ }
43
+
25
44
  startSpan (name, options = {}, context = api.context.active()) {
26
45
  // remove span from context in case a root span is requested via options
27
46
  if (options.root) {
@@ -29,21 +48,11 @@ class Tracer {
29
48
  }
30
49
  const parentSpan = api.trace.getSpan(context)
31
50
  const parentSpanContext = parentSpan && parentSpan.spanContext()
32
-
33
51
  let spanContext
34
- // TODO: Need a way to get 128-bit trace IDs for the validity check API to work...
35
- // if (parent && api.trace.isSpanContextValid(parent)) {
36
- if (parentSpanContext && parentSpanContext.traceId) {
37
- const parent = parentSpanContext._ddContext
38
- spanContext = new SpanContext({
39
- traceId: parent._traceId,
40
- spanId: id(),
41
- parentId: parent._spanId,
42
- sampling: parent._sampling,
43
- baggageItems: Object.assign({}, parent._baggageItems),
44
- trace: parent._trace,
45
- tracestate: parent._tracestate
46
- })
52
+ if (parentSpanContext && api.trace.isSpanContextValid(parentSpanContext)) {
53
+ spanContext = parentSpanContext._ddContext
54
+ ? this._createSpanContextFromParent(parentSpanContext._ddContext)
55
+ : this._createSpanContextForNewSpan(parentSpanContext)
47
56
  } else {
48
57
  spanContext = new SpanContext()
49
58
  }
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
- const { trace, context } = require('@opentelemetry/api')
3
+ const { trace, context, propagation } = require('@opentelemetry/api')
4
+ const { W3CTraceContextPropagator } = require('@opentelemetry/core')
4
5
 
5
6
  const tracer = require('../../')
6
7
 
@@ -52,6 +53,13 @@ class TracerProvider {
52
53
  if (!trace.setGlobalTracerProvider(this)) {
53
54
  trace.getTracerProvider().setDelegate(this)
54
55
  }
56
+ // The default propagator used is the W3C Trace Context propagator, users should be able to pass in others
57
+ // as needed
58
+ if (config.propagator) {
59
+ propagation.setGlobalPropagator(config.propagator)
60
+ } else {
61
+ propagation.setGlobalPropagator(new W3CTraceContextPropagator())
62
+ }
55
63
  }
56
64
 
57
65
  forceFlush () {
@@ -15,7 +15,7 @@ class LogPropagator {
15
15
 
16
16
  if (spanContext) {
17
17
  if (this._config.traceId128BitLoggingEnabled && spanContext._trace.tags['_dd.p.tid']) {
18
- carrier.dd.trace_id = spanContext._trace.tags['_dd.p.tid'] + spanContext._traceId.toString(16)
18
+ carrier.dd.trace_id = spanContext.toTraceId(true)
19
19
  } else {
20
20
  carrier.dd.trace_id = spanContext.toTraceId()
21
21
  }
@@ -3,6 +3,7 @@
3
3
  const pick = require('../../../../datadog-core/src/utils/src/pick')
4
4
  const id = require('../../id')
5
5
  const DatadogSpanContext = require('../span_context')
6
+ const OtelSpanContext = require('../../opentelemetry/span_context')
6
7
  const log = require('../../log')
7
8
  const TraceState = require('./tracestate')
8
9
  const tags = require('../../../../../ext/tags')
@@ -235,8 +236,7 @@ class TextMapPropagator {
235
236
  }
236
237
 
237
238
  _hasParentIdInTags (spanContext) {
238
- return tags.DD_PARENT_ID in spanContext._trace.tags &&
239
- spanContext._trace.tags[tags.DD_PARENT_ID] !== zeroTraceId
239
+ return tags.DD_PARENT_ID in spanContext._trace.tags
240
240
  }
241
241
 
242
242
  _updateParentIdFromDdHeaders (carrier, firstSpanContext) {
@@ -444,10 +444,6 @@ class TextMapPropagator {
444
444
  }
445
445
  })
446
446
 
447
- if (!spanContext._trace.tags[tags.DD_PARENT_ID]) {
448
- spanContext._trace.tags[tags.DD_PARENT_ID] = zeroTraceId
449
- }
450
-
451
447
  this._extractBaggageItems(carrier, spanContext)
452
448
  return spanContext
453
449
  }
@@ -618,6 +614,65 @@ class TextMapPropagator {
618
614
 
619
615
  return spanContext._traceId.toString(16)
620
616
  }
617
+
618
+ static _convertOtelContextToDatadog (traceId, spanId, traceFlag, ts, meta = {}) {
619
+ const origin = null
620
+ let samplingPriority = traceFlag
621
+
622
+ ts = ts?.traceparent || null
623
+
624
+ if (ts) {
625
+ // Use TraceState.fromString to parse the tracestate header
626
+ const traceState = TraceState.fromString(ts)
627
+ let ddTraceStateData = null
628
+
629
+ // Extract Datadog specific trace state data
630
+ traceState.forVendor('dd', (state) => {
631
+ ddTraceStateData = state
632
+ return state // You might need to adjust this part based on actual logic needed
633
+ })
634
+
635
+ if (ddTraceStateData) {
636
+ // Assuming ddTraceStateData is now a Map or similar structure containing Datadog trace state data
637
+ // Extract values as needed, similar to the original logic
638
+ const samplingPriorityTs = ddTraceStateData.get('s')
639
+ const origin = ddTraceStateData.get('o')
640
+ // Convert Map to object for meta
641
+ const otherPropagatedTags = Object.fromEntries(ddTraceStateData.entries())
642
+
643
+ // Update meta and samplingPriority based on extracted values
644
+ Object.assign(meta, otherPropagatedTags)
645
+ samplingPriority = TextMapPropagator._getSamplingPriority(traceFlag, parseInt(samplingPriorityTs, 10), origin)
646
+ } else {
647
+ log.debug(`no dd list member in tracestate from incoming request: ${ts}`)
648
+ }
649
+ }
650
+
651
+ const spanContext = new OtelSpanContext({
652
+ traceId: id(traceId, 16), spanId: id(), tags: meta, parentId: id(spanId, 16)
653
+ })
654
+
655
+ spanContext._sampling = { priority: samplingPriority }
656
+ spanContext._trace = { origin }
657
+ return spanContext
658
+ }
659
+
660
+ static _getSamplingPriority (traceparentSampled, tracestateSamplingPriority, origin = null) {
661
+ const fromRumWithoutPriority = !tracestateSamplingPriority && origin === 'rum'
662
+
663
+ let samplingPriority
664
+ if (!fromRumWithoutPriority && traceparentSampled === 0 &&
665
+ (!tracestateSamplingPriority || tracestateSamplingPriority >= 0)) {
666
+ samplingPriority = 0
667
+ } else if (!fromRumWithoutPriority && traceparentSampled === 1 &&
668
+ (!tracestateSamplingPriority || tracestateSamplingPriority < 0)) {
669
+ samplingPriority = 1
670
+ } else {
671
+ samplingPriority = tracestateSamplingPriority
672
+ }
673
+
674
+ return samplingPriority
675
+ }
621
676
  }
622
677
 
623
678
  module.exports = TextMapPropagator
@@ -27,6 +27,7 @@ class DatadogSpanContext {
27
27
  finished: [],
28
28
  tags: {}
29
29
  }
30
+ this._otelSpanContext = undefined
30
31
  }
31
32
 
32
33
  toTraceId (get128bitId = false) {
@@ -145,7 +145,7 @@ module.exports = class CiPlugin extends Plugin {
145
145
  incrementCountMetric(name, {
146
146
  testLevel,
147
147
  testFramework,
148
- isUnsupportedCIProvider: this.isUnsupportedCIProvider,
148
+ isUnsupportedCIProvider: !this.ciProviderName,
149
149
  ...tags
150
150
  })
151
151
  },
@@ -179,7 +179,7 @@ module.exports = class CiPlugin extends Plugin {
179
179
 
180
180
  this.codeOwnersEntries = getCodeOwnersFileEntries(repositoryRoot)
181
181
 
182
- this.isUnsupportedCIProvider = !ciProviderName
182
+ this.ciProviderName = ciProviderName
183
183
 
184
184
  this.testConfiguration = {
185
185
  repositoryUrl,
@@ -69,6 +69,7 @@ module.exports = {
69
69
  get 'node:http2' () { return require('../../../datadog-plugin-http2/src') },
70
70
  get 'node:https' () { return require('../../../datadog-plugin-http/src') },
71
71
  get 'node:net' () { return require('../../../datadog-plugin-net/src') },
72
+ get nyc () { return require('../../../datadog-plugin-nyc/src') },
72
73
  get oracledb () { return require('../../../datadog-plugin-oracledb/src') },
73
74
  get openai () { return require('../../../datadog-plugin-openai/src') },
74
75
  get paperplane () { return require('../../../datadog-plugin-paperplane/src') },
@@ -77,6 +77,18 @@ function isDirectory (path) {
77
77
  }
78
78
  }
79
79
 
80
+ function isGitAvailable () {
81
+ const isWindows = os.platform() === 'win32'
82
+ const command = isWindows ? 'where' : 'which'
83
+ try {
84
+ cp.execFileSync(command, ['git'], { stdio: 'pipe' })
85
+ return true
86
+ } catch (e) {
87
+ incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'check_git', exitCode: 'missing' })
88
+ return false
89
+ }
90
+ }
91
+
80
92
  function isShallowRepository () {
81
93
  return sanitizedExec(
82
94
  'git',
@@ -342,5 +354,6 @@ module.exports = {
342
354
  getCommitsRevList,
343
355
  GIT_REV_LIST_MAX_BUFFER,
344
356
  isShallowRepository,
345
- unshallowRepository
357
+ unshallowRepository,
358
+ isGitAvailable
346
359
  }
@@ -95,9 +95,6 @@ const MOCHA_WORKER_TRACE_PAYLOAD_CODE = 80
95
95
  const EFD_STRING = "Retried by Datadog's Early Flake Detection"
96
96
  const EFD_TEST_NAME_REGEX = new RegExp(EFD_STRING + ' \\(#\\d+\\): ', 'g')
97
97
 
98
- // Flaky test retries
99
- const NUM_FAILED_TEST_RETRIES = 5
100
-
101
98
  module.exports = {
102
99
  TEST_CODE_OWNERS,
103
100
  TEST_FRAMEWORK,
@@ -170,8 +167,7 @@ module.exports = {
170
167
  TEST_BROWSER_DRIVER,
171
168
  TEST_BROWSER_DRIVER_VERSION,
172
169
  TEST_BROWSER_NAME,
173
- TEST_BROWSER_VERSION,
174
- NUM_FAILED_TEST_RETRIES
170
+ TEST_BROWSER_VERSION
175
171
  }
176
172
 
177
173
  // Returns pkg manager and its version, separated by '-', e.g. npm-8.15.0 or yarn-1.22.19
@@ -8,8 +8,8 @@ process.once('beforeExit', () => { profiler.stop() })
8
8
 
9
9
  module.exports = {
10
10
  start: config => {
11
- const { service, version, env, url, hostname, port, tags, repositoryUrl, commitSHA } = config
12
- const { enabled, sourceMap, exporters, heuristicsEnabled } = config.profiling
11
+ const { service, version, env, url, hostname, port, tags, repositoryUrl, commitSHA, injectionEnabled } = config
12
+ const { enabled, sourceMap, exporters } = config.profiling
13
13
  const logger = {
14
14
  debug: (message) => log.debug(message),
15
15
  info: (message) => log.info(message),
@@ -17,9 +17,17 @@ module.exports = {
17
17
  error: (message) => log.error(message)
18
18
  }
19
19
 
20
+ const libraryInjected = injectionEnabled.length > 0
21
+ let activation
22
+ if (enabled === 'auto') {
23
+ activation = 'auto'
24
+ } else if (enabled === 'true') {
25
+ activation = 'manual'
26
+ } else if (injectionEnabled.includes('profiler')) {
27
+ activation = 'injection'
28
+ } // else activation = undefined
29
+
20
30
  return profiler.start({
21
- enabled,
22
- heuristicsEnabled,
23
31
  service,
24
32
  version,
25
33
  env,
@@ -31,7 +39,9 @@ module.exports = {
31
39
  port,
32
40
  tags,
33
41
  repositoryUrl,
34
- commitSHA
42
+ commitSHA,
43
+ libraryInjected,
44
+ activation
35
45
  })
36
46
  },
37
47
 
@@ -23,7 +23,6 @@ class Config {
23
23
  DD_PROFILING_CODEHOTSPOTS_ENABLED,
24
24
  DD_PROFILING_CPU_ENABLED,
25
25
  DD_PROFILING_DEBUG_SOURCE_MAPS,
26
- DD_PROFILING_ENABLED,
27
26
  DD_PROFILING_ENDPOINT_COLLECTION_ENABLED,
28
27
  DD_PROFILING_EXPERIMENTAL_CODEHOTSPOTS_ENABLED,
29
28
  DD_PROFILING_EXPERIMENTAL_CPU_ENABLED,
@@ -49,7 +48,6 @@ class Config {
49
48
  DD_VERSION
50
49
  } = process.env
51
50
 
52
- const enabled = isTrue(coalesce(options.enabled, DD_PROFILING_ENABLED, true))
53
51
  const env = coalesce(options.env, DD_ENV)
54
52
  const service = options.service || DD_SERVICE || 'node'
55
53
  const host = os.hostname()
@@ -64,8 +62,6 @@ class Config {
64
62
  const pprofPrefix = coalesce(options.pprofPrefix,
65
63
  DD_PROFILING_PPROF_PREFIX, '')
66
64
 
67
- this.enabled = enabled
68
- this.heuristicsEnabled = options.heuristicsEnabled
69
65
  this.service = service
70
66
  this.env = env
71
67
  this.host = host
@@ -129,6 +125,8 @@ class Config {
129
125
  port
130
126
  })))
131
127
 
128
+ this.libraryInjected = options.libraryInjected
129
+ this.activation = options.activation
132
130
  this.exporters = ensureExporters(options.exporters || [
133
131
  new AgentExporter(this)
134
132
  ], this)
@@ -16,10 +16,22 @@ function exporterFromURL (url) {
16
16
  if (url.protocol === 'file:') {
17
17
  return new FileExporter({ pprofPrefix: fileURLToPath(url) })
18
18
  } else {
19
+ const injectionEnabled = (process.env.DD_INJECTION_ENABLED || '').split(',')
20
+ const libraryInjected = injectionEnabled.length > 0
21
+ const profilingEnabled = (process.env.DD_PROFILING_ENABLED || '').toLowerCase()
22
+ const activation = ['true', '1'].includes(profilingEnabled)
23
+ ? 'manual'
24
+ : profilingEnabled === 'auto'
25
+ ? 'auto'
26
+ : injectionEnabled.includes('profiling')
27
+ ? 'injection'
28
+ : 'unknown'
19
29
  return new AgentExporter({
20
30
  url,
21
31
  logger,
22
- uploadTimeout: timeoutMs
32
+ uploadTimeout: timeoutMs,
33
+ libraryInjected,
34
+ activation
23
35
  })
24
36
  }
25
37
  }
@@ -53,7 +53,7 @@ function computeRetries (uploadTimeout) {
53
53
  }
54
54
 
55
55
  class AgentExporter {
56
- constructor ({ url, logger, uploadTimeout, env, host, service, version } = {}) {
56
+ constructor ({ url, logger, uploadTimeout, env, host, service, version, libraryInjected, activation } = {}) {
57
57
  this._url = url
58
58
  this._logger = logger
59
59
 
@@ -65,6 +65,8 @@ class AgentExporter {
65
65
  this._host = host
66
66
  this._service = service
67
67
  this._appVersion = version
68
+ this._libraryInjected = !!libraryInjected
69
+ this._activation = activation || 'unknown'
68
70
  }
69
71
 
70
72
  export ({ profiles, start, end, tags }) {
@@ -105,6 +107,10 @@ class AgentExporter {
105
107
  kernel_version: os.version()
106
108
  },
107
109
  profiler: {
110
+ activation: this._activation,
111
+ ssi: {
112
+ mechanism: this._libraryInjected ? 'injected_agent' : 'none'
113
+ },
108
114
  version
109
115
  },
110
116
  runtime: {
@@ -5,7 +5,6 @@ const { Config } = require('./config')
5
5
  const { snapshotKinds } = require('./constants')
6
6
  const { threadNamePrefix } = require('./profilers/shared')
7
7
  const dc = require('dc-polyfill')
8
- const telemetryLog = dc.channel('datadog:telemetry:log')
9
8
 
10
9
  const profileSubmittedChannel = dc.channel('datadog:profiling:profile-submitted')
11
10
 
@@ -20,13 +19,6 @@ function logError (logger, err) {
20
19
  if (logger) {
21
20
  logger.error(err)
22
21
  }
23
- if (telemetryLog.hasSubscribers) {
24
- telemetryLog.publish({
25
- message: err.message,
26
- level: 'ERROR',
27
- stack_trace: err.stack
28
- })
29
- }
30
22
  }
31
23
 
32
24
  class Profiler extends EventEmitter {
@@ -55,7 +47,6 @@ class Profiler extends EventEmitter {
55
47
  if (this._enabled) return true
56
48
 
57
49
  const config = this._config = new Config(options)
58
- if (!config.enabled && !config.heuristicsEnabled) return false
59
50
 
60
51
  this._logger = config.logger
61
52
  this._enabled = true