dd-trace 5.105.0 → 5.106.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.
@@ -5,6 +5,7 @@ const { pathToFileURL } = require('url')
5
5
 
6
6
  const satisfies = require('../../../../vendor/dist/semifies')
7
7
  const getGitMetadata = require('../git_metadata')
8
+ const log = require('../log')
8
9
  const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('../plugins/util/tags')
9
10
  const { getIsAzureFunction } = require('../serverless')
10
11
  const { getAzureTagsFromMetadata, getAzureAppMetadata, getAzureFunctionMetadata } = require('../azure_metadata')
@@ -14,7 +15,6 @@ const { isACFActive } = require('../../../datadog-core/src/storage')
14
15
 
15
16
  const { AgentExporter } = require('./exporters/agent')
16
17
  const { FileExporter } = require('./exporters/file')
17
- const { ConsoleLogger } = require('./loggers/console')
18
18
  const WallProfiler = require('./profilers/wall')
19
19
  const SpaceProfiler = require('./profilers/space')
20
20
  const EventsProfiler = require('./profilers/events')
@@ -54,7 +54,6 @@ class Config {
54
54
  this.pprofPrefix = options.DD_PROFILING_PPROF_PREFIX
55
55
  this.v8ProfilerBugWorkaroundEnabled = options.DD_PROFILING_V8_PROFILER_BUG_WORKAROUND
56
56
 
57
- this.logger = ensureLogger(options.logger)
58
57
  this.url = getAgentUrl(options)
59
58
 
60
59
  this.libraryInjected = !!options.DD_INJECTION_ENABLED
@@ -73,7 +72,7 @@ class Config {
73
72
  const heapLimitExtensionSize = options.DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE
74
73
  const maxHeapExtensionCount = options.DD_PROFILING_EXPERIMENTAL_OOM_MAX_HEAP_EXTENSION_COUNT
75
74
  const exportStrategies = oomMonitoringEnabled
76
- ? ensureOOMExportStrategies(options.DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES, this)
75
+ ? ensureOOMExportStrategies(options.DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES)
77
76
  : []
78
77
  const exportCommand = oomMonitoringEnabled ? buildExportCommand(this) : undefined
79
78
  this.oomMonitoring = {
@@ -102,7 +101,7 @@ class Config {
102
101
  if (level !== undefined) {
103
102
  const maxLevel = { gzip: 9, zstd: 22 }[uploadCompression]
104
103
  if (level > maxLevel) {
105
- this.logger.warn(`Invalid compression level ${level}. Will use ${maxLevel}.`)
104
+ log.warn('Invalid compression level %d. Will use %d.', level, maxLevel)
106
105
  level = maxLevel
107
106
  }
108
107
  }
@@ -119,8 +118,7 @@ class Config {
119
118
 
120
119
  const that = this
121
120
  function turnOffAsyncContextFrame (msg) {
122
- that.logger.warn(
123
- `DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED was set ${msg}, it will have no effect.`)
121
+ log.warn('DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED was set %s, it will have no effect.', msg)
124
122
  that.asyncContextFrameEnabled = false
125
123
  }
126
124
 
@@ -215,18 +213,18 @@ function getProfilers ({
215
213
  return profilersArray
216
214
  }
217
215
 
218
- function getExportStrategy (name, options) {
216
+ function getExportStrategy (name) {
219
217
  const strategy = Object.values(oomExportStrategies).find(value => value === name)
220
218
  if (strategy === undefined) {
221
- options.logger.error(`Unknown oom export strategy "${name}"`)
219
+ log.error('Unknown oom export strategy "%s"', name)
222
220
  }
223
221
  return strategy
224
222
  }
225
223
 
226
- function ensureOOMExportStrategies (strategies, options) {
224
+ function ensureOOMExportStrategies (strategies) {
227
225
  const set = new Set()
228
226
  for (const strategy of strategies) {
229
- set.add(getExportStrategy(strategy, options))
227
+ set.add(getExportStrategy(strategy))
230
228
  }
231
229
 
232
230
  return [...set]
@@ -239,7 +237,7 @@ function getExporter (name, options) {
239
237
  case 'file':
240
238
  return new FileExporter(options)
241
239
  default:
242
- options.logger.error(`Unknown exporter "${name}"`)
240
+ log.error('Unknown exporter "%s"', name)
243
241
  }
244
242
  }
245
243
 
@@ -255,7 +253,7 @@ function getProfiler (name, options) {
255
253
  case 'space':
256
254
  return new SpaceProfiler(options)
257
255
  default:
258
- options.logger.error(`Unknown profiler "${name}"`)
256
+ log.error('Unknown profiler "%s"', name)
259
257
  }
260
258
  }
261
259
 
@@ -278,17 +276,6 @@ function ensureProfilers (profilers, options) {
278
276
  return filteredProfilers
279
277
  }
280
278
 
281
- function ensureLogger (logger) {
282
- if (typeof logger?.debug !== 'function' ||
283
- typeof logger.info !== 'function' ||
284
- typeof logger.warn !== 'function' ||
285
- typeof logger.error !== 'function') {
286
- return new ConsoleLogger()
287
- }
288
-
289
- return logger
290
- }
291
-
292
279
  function buildExportCommand (options) {
293
280
  const tags = [...Object.entries(options.tags),
294
281
  ['snapshot', snapshotKinds.ON_OUT_OF_MEMORY]].map(([key, value]) => `${key}:${value}`).join(',')
@@ -9,6 +9,7 @@ const retry = require('../../../../../vendor/dist/retry')
9
9
  // TODO: avoid using dd-trace internals. Make this a separate module?
10
10
  const docker = require('../../exporters/common/docker')
11
11
  const FormData = require('../../exporters/common/form-data')
12
+ const log = require('../../log')
12
13
  const { storage } = require('../../../../datadog-core')
13
14
  const version = require('../../../../../package.json').version
14
15
  const telemetryMetrics = require('../../telemetry/metrics')
@@ -89,9 +90,8 @@ function computeRetries (uploadTimeout) {
89
90
  class AgentExporter extends EventSerializer {
90
91
  constructor (config = {}) {
91
92
  super(config)
92
- const { url, logger, uploadTimeout } = config
93
+ const { url, uploadTimeout } = config
93
94
  this._url = url
94
- this._logger = logger
95
95
 
96
96
  const [backoffTries, backoffTime] = computeRetries(uploadTimeout)
97
97
 
@@ -109,12 +109,11 @@ class AgentExporter extends EventSerializer {
109
109
  contentType: 'application/json',
110
110
  }])
111
111
 
112
- this._logger.debug(() => {
113
- return `Building agent export report:\n${event}`
114
- })
112
+ log.debug('Building agent export report:\n%s', event)
115
113
 
116
114
  for (const [type, buffer] of Object.entries(profiles)) {
117
- this._logger.debug(() => {
115
+ // eslint-disable-next-line eslint-rules/eslint-log-printf-style
116
+ log.debug(() => {
118
117
  const bytes = buffer.toString('hex').match(/../g).join(' ')
119
118
  return `Adding ${type} profile to agent export: ` + bytes
120
119
  })
@@ -163,7 +162,8 @@ class AgentExporter extends EventSerializer {
163
162
  options.port = httpOptions.port
164
163
  }
165
164
 
166
- this._logger.debug(() => {
165
+ // eslint-disable-next-line eslint-rules/eslint-log-printf-style
166
+ log.debug(() => {
167
167
  return `Submitting profiler agent report attempt #${attempt} to: ${JSON.stringify(options)}`
168
168
  })
169
169
 
@@ -171,7 +171,7 @@ class AgentExporter extends EventSerializer {
171
171
  if (err) {
172
172
  const { status } = err
173
173
  if ((typeof status !== 'number' || status >= 500 || status === 429) && operation.retry(err)) {
174
- this._logger.warn(`Error from the agent: ${err.message}`)
174
+ log.warn('Error from the agent: %s', err.message)
175
175
  } else {
176
176
  reject(err)
177
177
  }
@@ -180,9 +180,10 @@ class AgentExporter extends EventSerializer {
180
180
 
181
181
  getBody(response, (err, body) => {
182
182
  if (err) {
183
- this._logger.warn(`Error reading agent response: ${err.message}`)
183
+ log.warn('Error reading agent response: %s', err.message)
184
184
  } else {
185
- this._logger.debug(() => {
185
+ // eslint-disable-next-line eslint-rules/eslint-log-printf-style
186
+ log.debug(() => {
186
187
  const bytes = (body.toString('hex').match(/../g) || []).join(' ')
187
188
  return `Agent export response: ${bytes}`
188
189
  })
@@ -40,6 +40,16 @@ function processInfo (infos, info, type) {
40
40
  }
41
41
  }
42
42
 
43
+ // Route pprof through the central log module so logLevel applies.
44
+ const pprofLogger = {
45
+ trace: (...args) => log.trace(...args),
46
+ debug: (...args) => log.debug(...args),
47
+ info: (...args) => log.info(...args),
48
+ warn: (...args) => log.warn(...args),
49
+ error: (...args) => log.error(...args),
50
+ fatal: (...args) => log.error(...args),
51
+ }
52
+
43
53
  class Profiler extends EventEmitter {
44
54
  #compressionFn
45
55
  #compressionFnInitialized = false
@@ -49,7 +59,6 @@ class Profiler extends EventEmitter {
49
59
  #enabled = false
50
60
  #endpointCounts = new Map()
51
61
  #lastStart
52
- #logger
53
62
  #profileSeq = 0
54
63
  #spanFinishListener
55
64
  #timer
@@ -159,14 +168,13 @@ class Profiler extends EventEmitter {
159
168
  this.#enabled = true
160
169
 
161
170
  const config = this.#config = new Config(options)
162
- this.#logger = config.logger
163
171
 
164
172
  this._setInterval()
165
173
  // Log errors if the source map finder fails, but don't prevent the rest
166
174
  // of the profiler from running without source maps.
167
175
  let mapper
168
176
  const { setLogger, SourceMapper } = require('@datadog/pprof')
169
- setLogger(config.logger)
177
+ setLogger(pprofLogger)
170
178
 
171
179
  if (config.sourceMap) {
172
180
  mapper = new SourceMapper(config.debugSourceMaps)
@@ -174,7 +182,8 @@ class Profiler extends EventEmitter {
174
182
  .then(() => {
175
183
  if (config.debugSourceMaps) {
176
184
  const count = mapper.infoMap.size
177
- this.#logger.debug(() => {
185
+ // eslint-disable-next-line eslint-rules/eslint-log-printf-style
186
+ log.debug(() => {
178
187
  return count === 0
179
188
  ? 'Found no source maps'
180
189
  : `Found source maps for following files: [${[...mapper.infoMap.keys()].join(', ')}]`
@@ -195,7 +204,7 @@ class Profiler extends EventEmitter {
195
204
  mapper,
196
205
  nearOOMCallback,
197
206
  })
198
- this.#logger.debug(`Started ${profiler.type} profiler in ${threadNamePrefix} thread`)
207
+ log.debug('Started %s profiler in %s thread', profiler.type, threadNamePrefix)
199
208
  }
200
209
 
201
210
  if (config.endpointCollectionEnabled) {
@@ -248,7 +257,7 @@ class Profiler extends EventEmitter {
248
257
 
249
258
  for (const profiler of this.#config.profilers) {
250
259
  profiler.stop()
251
- this.#logger.debug(`Stopped ${profiler.type} profiler in ${threadNamePrefix} thread`)
260
+ log.debug('Stopped %s profiler in %s thread', profiler.type, threadNamePrefix)
252
261
  }
253
262
 
254
263
  clearTimeout(this.#timer)
@@ -312,7 +321,7 @@ class Profiler extends EventEmitter {
312
321
  const info = profiler.getInfo()
313
322
  const profile = profiler.profile(restart, startDate, endDate)
314
323
  if (!restart) {
315
- this.#logger.debug(`Stopped ${profiler.type} profiler in ${threadNamePrefix} thread`)
324
+ log.debug('Stopped %s profiler in %s thread', profiler.type, threadNamePrefix)
316
325
  }
317
326
  if (!profile) continue
318
327
  profiles.push({ profiler, profile, info })
@@ -341,7 +350,8 @@ class Profiler extends EventEmitter {
341
350
  infos.hasMissingSourceMaps = true
342
351
  }
343
352
  processInfo(infos, info, profiler.type)
344
- this.#logger.debug(() => {
353
+ // eslint-disable-next-line eslint-rules/eslint-log-printf-style
354
+ log.debug(() => {
345
355
  const profileJson = JSON.stringify(profile, (_, value) => {
346
356
  return typeof value === 'bigint' ? value.toString() : value
347
357
  })
@@ -358,7 +368,7 @@ class Profiler extends EventEmitter {
358
368
  if (hasEncoded) {
359
369
  await this.#submit(encodedProfiles, infos, startDate, endDate, snapshotKind)
360
370
  profileSubmittedChannel.publish()
361
- this.#logger.debug('Submitted profiles')
371
+ log.debug('Submitted profiles')
362
372
  }
363
373
  } catch (error) {
364
374
  log.error(error)
@@ -3,6 +3,7 @@
3
3
  const dc = require('dc-polyfill')
4
4
 
5
5
  const { storage } = require('../../../../datadog-core')
6
+ const log = require('../../log')
6
7
  const runtimeMetrics = require('../../runtime_metrics')
7
8
  const telemetryMetrics = require('../../telemetry/metrics')
8
9
  const { isWebServerSpan, endpointNameFromTags, getStartedSpans } = require('../webspan-utils')
@@ -112,7 +113,6 @@ class NativeWallProfiler {
112
113
  #customLabelKeys
113
114
  #endpointCollectionEnabled = false
114
115
  #flushIntervalMillis = 0
115
- #logger
116
116
  #mapper
117
117
  #pprof
118
118
  #samplingIntervalMicros = 0
@@ -136,7 +136,6 @@ class NativeWallProfiler {
136
136
  this.#cpuProfilingEnabled = !!options.cpuProfilingEnabled
137
137
  this.#endpointCollectionEnabled = !!options.endpointCollectionEnabled
138
138
  this.#flushIntervalMillis = options.flushInterval || 60 * 1e3 // 60 seconds
139
- this.#logger = options.logger
140
139
  // TODO: Remove default value. It is only used in testing.
141
140
  this.#samplingIntervalMicros = (options.samplingInterval || 1e3 / 99) * 1000
142
141
  this.#telemetryHeartbeatIntervalMillis = options.heartbeatInterval || 60 * 1e3 // 60 seconds
@@ -348,7 +347,7 @@ class NativeWallProfiler {
348
347
  #reportV8bug (maybeBug) {
349
348
  const tag = `v8_profiler_bug_workaround_enabled:${this.#v8ProfilerBugWorkaroundEnabled}`
350
349
  const metric = `v8_cpu_profiler${maybeBug ? '_maybe' : ''}_stuck_event_loop`
351
- this.#logger?.warn(`Wall profiler: ${maybeBug ? 'possible ' : ''}v8 profiler stuck event loop detected.`)
350
+ log.warn('Wall profiler: %sv8 profiler stuck event loop detected.', maybeBug ? 'possible ' : '')
352
351
  // report as runtime metric (can be removed in the future when telemetry is mature)
353
352
  runtimeMetrics.increment(`runtime.node.profiler.${metric}`, tag, true)
354
353
  // report as telemetry metric