dd-trace 5.0.0-pre-03f1a68 → 5.0.0-pre-e2df7ec

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "5.0.0-pre-03f1a68",
3
+ "version": "5.0.0-pre-e2df7ec",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -9,11 +9,10 @@ const shimmer = require('../../datadog-shimmer')
9
9
  const childProcessChannel = channel('datadog:child_process:execution:start')
10
10
  const execMethods = ['exec', 'execFile', 'fork', 'spawn', 'execFileSync', 'execSync', 'spawnSync']
11
11
  const names = ['child_process', 'node:child_process']
12
- names.forEach(name => {
13
- addHook({ name }, childProcess => {
14
- shimmer.massWrap(childProcess, execMethods, wrapChildProcessMethod())
15
- return childProcess
16
- })
12
+
13
+ addHook({ name: names }, childProcess => {
14
+ shimmer.massWrap(childProcess, execMethods, wrapChildProcessMethod())
15
+ return childProcess
17
16
  })
18
17
 
19
18
  function wrapChildProcessMethod () {
@@ -11,8 +11,9 @@ const cryptoCipherCh = channel('datadog:crypto:cipher:start')
11
11
 
12
12
  const hashMethods = ['createHash', 'createHmac', 'createSign', 'createVerify', 'sign', 'verify']
13
13
  const cipherMethods = ['createCipheriv', 'createDecipheriv']
14
+ const names = ['crypto', 'node:crypto']
14
15
 
15
- addHook({ name: 'crypto' }, crypto => {
16
+ addHook({ name: names }, crypto => {
16
17
  shimmer.massWrap(crypto, hashMethods, wrapCryptoMethod(cryptoHashCh))
17
18
  shimmer.massWrap(crypto, cipherMethods, wrapCryptoMethod(cryptoCipherCh))
18
19
  return crypto
@@ -18,8 +18,9 @@ const rrtypes = {
18
18
  }
19
19
 
20
20
  const rrtypeMap = new WeakMap()
21
+ const names = ['dns', 'node:dns']
21
22
 
22
- addHook({ name: 'dns' }, dns => {
23
+ addHook({ name: names }, dns => {
23
24
  dns.lookup = wrap('apm:dns:lookup', dns.lookup, 2)
24
25
  dns.lookupService = wrap('apm:dns:lookup_service', dns.lookupService, 3)
25
26
  dns.resolve = wrap('apm:dns:resolve', dns.resolve, 2)
@@ -31,7 +31,6 @@ module.exports = {
31
31
  'bunyan': () => require('../bunyan'),
32
32
  'cassandra-driver': () => require('../cassandra-driver'),
33
33
  'child_process': () => require('../child-process'),
34
- 'node:child_process': () => require('../child-process'),
35
34
  'connect': () => require('../connect'),
36
35
  'cookie': () => require('../cookie'),
37
36
  'cookie-parser': () => require('../cookie-parser'),
@@ -45,7 +44,6 @@ module.exports = {
45
44
  'fastify': () => require('../fastify'),
46
45
  'find-my-way': () => require('../find-my-way'),
47
46
  'fs': () => require('../fs'),
48
- 'node:fs': () => require('../fs'),
49
47
  'generic-pool': () => require('../generic-pool'),
50
48
  'graphql': () => require('../graphql'),
51
49
  'grpc': () => require('../grpc'),
@@ -79,6 +77,13 @@ module.exports = {
79
77
  'mysql2': () => require('../mysql2'),
80
78
  'net': () => require('../net'),
81
79
  'next': () => require('../next'),
80
+ 'node:child_process': () => require('../child-process'),
81
+ 'node:crypto': () => require('../crypto'),
82
+ 'node:dns': () => require('../dns'),
83
+ 'node:http': () => require('../http'),
84
+ 'node:http2': () => require('../http2'),
85
+ 'node:https': () => require('../http'),
86
+ 'node:net': () => require('../net'),
82
87
  'oracledb': () => require('../oracledb'),
83
88
  'openai': () => require('../openai'),
84
89
  'paperplane': () => require('../paperplane'),
@@ -21,11 +21,16 @@ exports.channel = function (name) {
21
21
  * @param Function hook
22
22
  */
23
23
  exports.addHook = function addHook ({ name, versions, file }, hook) {
24
- if (!instrumentations[name]) {
25
- instrumentations[name] = []
24
+ if (typeof name === 'string') {
25
+ name = [name]
26
26
  }
27
27
 
28
- instrumentations[name].push({ name, versions, file, hook })
28
+ for (const val of name) {
29
+ if (!instrumentations[val]) {
30
+ instrumentations[val] = []
31
+ }
32
+ instrumentations[val].push({ name: val, versions, file, hook })
33
+ }
29
34
  }
30
35
 
31
36
  // AsyncResource.bind exists and binds `this` properly only from 17.8.0 and up.
@@ -24,6 +24,7 @@ if (!disabledInstrumentations.has('fetch')) {
24
24
  require('../fetch')
25
25
  }
26
26
 
27
+ const HOOK_SYMBOL = Symbol('hookExportsMap')
27
28
  // TODO: make this more efficient
28
29
 
29
30
  for (const packageName of names) {
@@ -42,14 +43,29 @@ for (const packageName of names) {
42
43
  for (const { name, file, versions, hook } of instrumentations[packageName]) {
43
44
  const fullFilename = filename(name, file)
44
45
 
46
+ // Create a WeakMap associated with the hook function so that patches on the same moduleExport only happens once
47
+ // for example by instrumenting both dns and node:dns double the spans would be created
48
+ // since they both patch the same moduleExport, this WeakMap is used to mitigate that
49
+ if (!hook[HOOK_SYMBOL]) {
50
+ hook[HOOK_SYMBOL] = new WeakMap()
51
+ }
52
+
45
53
  if (moduleName === fullFilename) {
46
54
  const version = moduleVersion || getVersion(moduleBaseDir)
47
55
 
48
56
  if (matchVersion(version, versions)) {
57
+ // Check if the hook already has a set moduleExport
58
+ if (hook[HOOK_SYMBOL].has(moduleExports)) {
59
+ return moduleExports
60
+ }
61
+
49
62
  try {
50
63
  loadChannel.publish({ name, version, file })
51
-
52
- moduleExports = hook(moduleExports, version)
64
+ // Send the name and version of the module back to the callback because now addHook
65
+ // takes in an array of names so by passing the name the callback will know which module name is being used
66
+ moduleExports = hook(moduleExports, version, name)
67
+ // Set the moduleExports in the hooks weakmap
68
+ hook[HOOK_SYMBOL].set(moduleExports, name)
53
69
  } catch (e) {
54
70
  log.error(e)
55
71
  }
@@ -14,9 +14,9 @@ const endChannel = channel('apm:http:client:request:end')
14
14
  const asyncStartChannel = channel('apm:http:client:request:asyncStart')
15
15
  const errorChannel = channel('apm:http:client:request:error')
16
16
 
17
- addHook({ name: 'https' }, hookFn)
17
+ const names = ['http', 'https', 'node:http', 'node:https']
18
18
 
19
- addHook({ name: 'http' }, hookFn)
19
+ addHook({ name: names }, hookFn)
20
20
 
21
21
  function hookFn (http) {
22
22
  patch(http, 'request')
@@ -15,14 +15,17 @@ const finishSetHeaderCh = channel('datadog:http:server:response:set-header:finis
15
15
 
16
16
  const requestFinishedSet = new WeakSet()
17
17
 
18
- addHook({ name: 'https' }, http => {
19
- // http.ServerResponse not present on https
18
+ const httpNames = ['http', 'node:http']
19
+ const httpsNames = ['https', 'node:https']
20
+
21
+ addHook({ name: httpNames }, http => {
22
+ shimmer.wrap(http.ServerResponse.prototype, 'emit', wrapResponseEmit)
20
23
  shimmer.wrap(http.Server.prototype, 'emit', wrapEmit)
21
24
  return http
22
25
  })
23
26
 
24
- addHook({ name: 'http' }, http => {
25
- shimmer.wrap(http.ServerResponse.prototype, 'emit', wrapResponseEmit)
27
+ addHook({ name: httpsNames }, http => {
28
+ // http.ServerResponse not present on https
26
29
  shimmer.wrap(http.Server.prototype, 'emit', wrapEmit)
27
30
  return http
28
31
  })
@@ -10,6 +10,8 @@ const asyncStartChannel = channel('apm:http2:client:request:asyncStart')
10
10
  const asyncEndChannel = channel('apm:http2:client:request:asyncEnd')
11
11
  const errorChannel = channel('apm:http2:client:request:error')
12
12
 
13
+ const names = ['http2', 'node:http2']
14
+
13
15
  function createWrapEmit (ctx) {
14
16
  return function wrapEmit (emit) {
15
17
  return function (event, arg1) {
@@ -66,7 +68,7 @@ function wrapConnect (connect) {
66
68
  }
67
69
  }
68
70
 
69
- addHook({ name: 'http2' }, http2 => {
71
+ addHook({ name: names }, http2 => {
70
72
  shimmer.wrap(http2, 'connect', wrapConnect)
71
73
 
72
74
  return http2
@@ -14,7 +14,9 @@ const startServerCh = channel('apm:http2:server:request:start')
14
14
  const errorServerCh = channel('apm:http2:server:request:error')
15
15
  const finishServerCh = channel('apm:http2:server:request:finish')
16
16
 
17
- addHook({ name: 'http2' }, http2 => {
17
+ const names = ['http2', 'node:http2']
18
+
19
+ addHook({ name: names }, http2 => {
18
20
  shimmer.wrap(http2, 'createSecureServer', wrapCreateServer)
19
21
  shimmer.wrap(http2, 'createServer', wrapCreateServer)
20
22
  return http2
@@ -17,8 +17,16 @@ const errorTCPCh = channel('apm:net:tcp:error')
17
17
 
18
18
  const connectionCh = channel(`apm:net:tcp:connection`)
19
19
 
20
- addHook({ name: 'net' }, net => {
21
- require('dns')
20
+ const names = ['net', 'node:net']
21
+
22
+ addHook({ name: names }, (net, version, name) => {
23
+ // explicitly require dns so that net gets an instrumented instance
24
+ // so that we don't miss the dns calls
25
+ if (name === 'net') {
26
+ require('dns')
27
+ } else {
28
+ require('node:dns')
29
+ }
22
30
 
23
31
  shimmer.wrap(net.Socket.prototype, 'connect', connect => function () {
24
32
  if (!startICPCh.hasSubscribers || !startTCPCh.hasSubscribers) {
@@ -522,6 +522,19 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
522
522
  0
523
523
  )
524
524
 
525
+ const DD_INSTRUMENTATION_INSTALL_ID = coalesce(
526
+ process.env.DD_INSTRUMENTATION_INSTALL_ID,
527
+ null
528
+ )
529
+ const DD_INSTRUMENTATION_INSTALL_TIME = coalesce(
530
+ process.env.DD_INSTRUMENTATION_INSTALL_TIME,
531
+ null
532
+ )
533
+ const DD_INSTRUMENTATION_INSTALL_TYPE = coalesce(
534
+ process.env.DD_INSTRUMENTATION_INSTALL_TYPE,
535
+ null
536
+ )
537
+
525
538
  const ingestion = options.ingestion || {}
526
539
  const dogstatsd = coalesce(options.dogstatsd, {})
527
540
  const sampler = {
@@ -671,6 +684,12 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
671
684
 
672
685
  this.spanLeakDebug = Number(DD_TRACE_SPAN_LEAK_DEBUG)
673
686
 
687
+ this.installSignature = {
688
+ id: DD_INSTRUMENTATION_INSTALL_ID,
689
+ time: DD_INSTRUMENTATION_INSTALL_TIME,
690
+ type: DD_INSTRUMENTATION_INSTALL_TYPE
691
+ }
692
+
674
693
  this._applyDefaults()
675
694
  this._applyEnvironment()
676
695
  this._applyOptions(options)
@@ -59,6 +59,11 @@ module.exports = {
59
59
  get 'mysql2' () { return require('../../../datadog-plugin-mysql2/src') },
60
60
  get 'net' () { return require('../../../datadog-plugin-net/src') },
61
61
  get 'next' () { return require('../../../datadog-plugin-next/src') },
62
+ get 'node:dns' () { return require('../../../datadog-plugin-dns/src') },
63
+ get 'node:http' () { return require('../../../datadog-plugin-http/src') },
64
+ get 'node:http2' () { return require('../../../datadog-plugin-http2/src') },
65
+ get 'node:https' () { return require('../../../datadog-plugin-http/src') },
66
+ get 'node:net' () { return require('../../../datadog-plugin-net/src') },
62
67
  get 'oracledb' () { return require('../../../datadog-plugin-oracledb/src') },
63
68
  get 'openai' () { return require('../../../datadog-plugin-openai/src') },
64
69
  get 'paperplane' () { return require('../../../datadog-plugin-paperplane/src') },
@@ -75,6 +75,7 @@ class AgentExporter {
75
75
  ['tags[]', 'language:javascript'],
76
76
  ['tags[]', 'runtime:nodejs'],
77
77
  ['tags[]', `runtime_version:${process.version}`],
78
+ ['tags[]', `process_id:${process.pid}`],
78
79
  ['tags[]', `profiler_version:${version}`],
79
80
  ['tags[]', 'format:pprof'],
80
81
  ...Object.entries(tags).map(([key, value]) => ['tags[]', `${key}:${value}`])
@@ -1,4 +1,4 @@
1
- const { performance, constants, PerformanceObserver } = require('node:perf_hooks')
1
+ const { performance, constants, PerformanceObserver } = require('perf_hooks')
2
2
  const { END_TIMESTAMP_LABEL } = require('./shared')
3
3
  const semver = require('semver')
4
4
  const { Function, Label, Line, Location, Profile, Sample, StringTable, ValueType } = require('pprof-format')
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const { isMainThread, threadId } = require('node:worker_threads')
3
+ const { isMainThread, threadId } = require('worker_threads')
4
4
 
5
5
  const END_TIMESTAMP_LABEL = 'end_timestamp_ns'
6
6
  const THREAD_NAME_LABEL = 'thread name'
@@ -112,11 +112,26 @@ function flatten (input, result = [], prefix = [], traversedObjects = null) {
112
112
  return result
113
113
  }
114
114
 
115
+ function getInstallSignature (config) {
116
+ const { installSignature: sig } = config
117
+ if (sig && (sig.id || sig.time || sig.type)) {
118
+ return {
119
+ install_id: sig.id,
120
+ install_time: sig.time,
121
+ install_type: sig.type
122
+ }
123
+ }
124
+ }
125
+
115
126
  function appStarted (config) {
116
127
  const app = {
117
128
  products: getProducts(config),
118
129
  configuration: flatten(config)
119
130
  }
131
+ const installSignature = getInstallSignature(config)
132
+ if (installSignature) {
133
+ app.install_signature = installSignature
134
+ }
120
135
  // TODO: add app.error with correct error codes
121
136
  // if (errors.agentError) {
122
137
  // app.error = errors.agentError