dd-trace 4.11.1 → 4.13.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 (34) hide show
  1. package/README.md +4 -9
  2. package/index.d.ts +43 -0
  3. package/package.json +3 -2
  4. package/packages/datadog-esbuild/index.js +29 -9
  5. package/packages/datadog-instrumentations/src/cucumber.js +30 -11
  6. package/packages/datadog-instrumentations/src/jest.js +22 -11
  7. package/packages/datadog-instrumentations/src/mocha.js +30 -8
  8. package/packages/datadog-instrumentations/src/next.js +102 -16
  9. package/packages/datadog-instrumentations/src/openai.js +1 -1
  10. package/packages/datadog-instrumentations/src/pg.js +46 -0
  11. package/packages/datadog-plugin-cucumber/src/index.js +14 -2
  12. package/packages/datadog-plugin-cypress/src/plugin.js +17 -8
  13. package/packages/datadog-plugin-graphql/src/index.js +3 -3
  14. package/packages/datadog-plugin-jest/src/index.js +10 -2
  15. package/packages/datadog-plugin-jest/src/util.js +10 -4
  16. package/packages/datadog-plugin-mocha/src/index.js +14 -2
  17. package/packages/datadog-plugin-next/src/index.js +11 -3
  18. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +19 -4
  19. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +1 -1
  20. package/packages/dd-trace/src/appsec/iast/telemetry/index.js +14 -5
  21. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +120 -10
  22. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +0 -1
  23. package/packages/dd-trace/src/dogstatsd.js +65 -5
  24. package/packages/dd-trace/src/exporters/agent/writer.js +9 -9
  25. package/packages/dd-trace/src/exporters/common/request.js +13 -4
  26. package/packages/dd-trace/src/opentracing/span.js +13 -13
  27. package/packages/dd-trace/src/opentracing/tracer.js +3 -3
  28. package/packages/dd-trace/src/plugins/ci_plugin.js +22 -1
  29. package/packages/dd-trace/src/plugins/util/test.js +18 -1
  30. package/packages/dd-trace/src/profiling/config.js +3 -1
  31. package/packages/dd-trace/src/profiling/profilers/wall.js +23 -7
  32. package/packages/dd-trace/src/proxy.js +23 -2
  33. package/packages/dd-trace/src/ritm.js +10 -2
  34. /package/packages/dd-trace/src/{metrics.js → runtime_metrics.js} +0 -0
@@ -2,7 +2,7 @@
2
2
 
3
3
  const request = require('../common/request')
4
4
  const { startupLog } = require('../../startup-log')
5
- const metrics = require('../../metrics')
5
+ const runtimeMetrics = require('../../runtime_metrics')
6
6
  const log = require('../../log')
7
7
  const tracerVersion = require('../../../../../package.json').version
8
8
  const BaseWriter = require('../common/writer')
@@ -22,19 +22,19 @@ class Writer extends BaseWriter {
22
22
  }
23
23
 
24
24
  _sendPayload (data, count, done) {
25
- metrics.increment(`${METRIC_PREFIX}.requests`, true)
25
+ runtimeMetrics.increment(`${METRIC_PREFIX}.requests`, true)
26
26
 
27
27
  const { _headers, _lookup, _protocolVersion, _url } = this
28
28
  makeRequest(_protocolVersion, data, count, _url, _headers, _lookup, true, (err, res, status) => {
29
29
  if (status) {
30
- metrics.increment(`${METRIC_PREFIX}.responses`, true)
31
- metrics.increment(`${METRIC_PREFIX}.responses.by.status`, `status:${status}`, true)
30
+ runtimeMetrics.increment(`${METRIC_PREFIX}.responses`, true)
31
+ runtimeMetrics.increment(`${METRIC_PREFIX}.responses.by.status`, `status:${status}`, true)
32
32
  } else if (err) {
33
- metrics.increment(`${METRIC_PREFIX}.errors`, true)
34
- metrics.increment(`${METRIC_PREFIX}.errors.by.name`, `name:${err.name}`, true)
33
+ runtimeMetrics.increment(`${METRIC_PREFIX}.errors`, true)
34
+ runtimeMetrics.increment(`${METRIC_PREFIX}.errors.by.name`, `name:${err.name}`, true)
35
35
 
36
36
  if (err.code) {
37
- metrics.increment(`${METRIC_PREFIX}.errors.by.code`, `code:${err.code}`, true)
37
+ runtimeMetrics.increment(`${METRIC_PREFIX}.errors.by.code`, `code:${err.code}`, true)
38
38
  }
39
39
  }
40
40
 
@@ -53,8 +53,8 @@ class Writer extends BaseWriter {
53
53
  } catch (e) {
54
54
  log.error(e)
55
55
 
56
- metrics.increment(`${METRIC_PREFIX}.errors`, true)
57
- metrics.increment(`${METRIC_PREFIX}.errors.by.name`, `name:${e.name}`, true)
56
+ runtimeMetrics.increment(`${METRIC_PREFIX}.errors`, true)
57
+ runtimeMetrics.increment(`${METRIC_PREFIX}.errors.by.name`, `name:${e.name}`, true)
58
58
  }
59
59
  done()
60
60
  })
@@ -42,10 +42,19 @@ function urlToOptions (url) {
42
42
  return options
43
43
  }
44
44
 
45
- function fromUrlString (url) {
46
- return typeof urlToHttpOptions === 'function'
47
- ? urlToOptions(new URL(url))
48
- : urlParse(url)
45
+ function fromUrlString (urlString) {
46
+ const url = typeof urlToHttpOptions === 'function'
47
+ ? urlToOptions(new URL(urlString))
48
+ : urlParse(urlString)
49
+
50
+ // Add the 'hostname' back if we're using named pipes
51
+ if (url.protocol === 'unix:' && url.host === '.') {
52
+ const udsPath = urlString.replace(/^unix:/, '')
53
+ url.path = udsPath
54
+ url.pathname = udsPath
55
+ }
56
+
57
+ return url
49
58
  }
50
59
 
51
60
  function request (data, options, callback) {
@@ -8,7 +8,7 @@ const semver = require('semver')
8
8
  const SpanContext = require('./span_context')
9
9
  const id = require('../id')
10
10
  const tagger = require('../tagger')
11
- const metrics = require('../metrics')
11
+ const runtimeMetrics = require('../runtime_metrics')
12
12
  const log = require('../log')
13
13
  const { storage } = require('../../../datadog-core')
14
14
  const telemetryMetrics = require('../telemetry/metrics')
@@ -79,11 +79,11 @@ class DatadogSpan {
79
79
  this._startTime = fields.startTime || this._getTime()
80
80
 
81
81
  if (DD_TRACE_EXPERIMENTAL_SPAN_COUNTS && finishedRegistry) {
82
- metrics.increment('runtime.node.spans.unfinished')
83
- metrics.increment('runtime.node.spans.unfinished.by.name', `span_name:${operationName}`)
82
+ runtimeMetrics.increment('runtime.node.spans.unfinished')
83
+ runtimeMetrics.increment('runtime.node.spans.unfinished.by.name', `span_name:${operationName}`)
84
84
 
85
- metrics.increment('runtime.node.spans.open') // unfinished for real
86
- metrics.increment('runtime.node.spans.open.by.name', `span_name:${operationName}`)
85
+ runtimeMetrics.increment('runtime.node.spans.open') // unfinished for real
86
+ runtimeMetrics.increment('runtime.node.spans.open.by.name', `span_name:${operationName}`)
87
87
 
88
88
  unfinishedRegistry.register(this, operationName, this)
89
89
  }
@@ -159,13 +159,13 @@ class DatadogSpan {
159
159
  getIntegrationCounter('span_finished', this._integrationName).inc()
160
160
 
161
161
  if (DD_TRACE_EXPERIMENTAL_SPAN_COUNTS && finishedRegistry) {
162
- metrics.decrement('runtime.node.spans.unfinished')
163
- metrics.decrement('runtime.node.spans.unfinished.by.name', `span_name:${this._name}`)
164
- metrics.increment('runtime.node.spans.finished')
165
- metrics.increment('runtime.node.spans.finished.by.name', `span_name:${this._name}`)
162
+ runtimeMetrics.decrement('runtime.node.spans.unfinished')
163
+ runtimeMetrics.decrement('runtime.node.spans.unfinished.by.name', `span_name:${this._name}`)
164
+ runtimeMetrics.increment('runtime.node.spans.finished')
165
+ runtimeMetrics.increment('runtime.node.spans.finished.by.name', `span_name:${this._name}`)
166
166
 
167
- metrics.decrement('runtime.node.spans.open') // unfinished for real
168
- metrics.decrement('runtime.node.spans.open.by.name', `span_name:${this._name}`)
167
+ runtimeMetrics.decrement('runtime.node.spans.open') // unfinished for real
168
+ runtimeMetrics.decrement('runtime.node.spans.open.by.name', `span_name:${this._name}`)
169
169
 
170
170
  unfinishedRegistry.unregister(this)
171
171
  finishedRegistry.register(this, this._name)
@@ -243,8 +243,8 @@ function createRegistry (type) {
243
243
  if (!semver.satisfies(process.version, '>=14.6')) return
244
244
 
245
245
  return new global.FinalizationRegistry(name => {
246
- metrics.decrement(`runtime.node.spans.${type}`)
247
- metrics.decrement(`runtime.node.spans.${type}.by.name`, [`span_name:${name}`])
246
+ runtimeMetrics.decrement(`runtime.node.spans.${type}`)
247
+ runtimeMetrics.decrement(`runtime.node.spans.${type}.by.name`, [`span_name:${name}`])
248
248
  })
249
249
  }
250
250
 
@@ -11,7 +11,7 @@ const LogPropagator = require('./propagation/log')
11
11
  const formats = require('../../../../ext/formats')
12
12
 
13
13
  const log = require('../log')
14
- const metrics = require('../metrics')
14
+ const runtimeMetrics = require('../runtime_metrics')
15
15
  const getExporter = require('../exporter')
16
16
  const SpanContext = require('./span_context')
17
17
 
@@ -82,7 +82,7 @@ class DatadogTracer {
82
82
  this._propagators[format].inject(spanContext, carrier)
83
83
  } catch (e) {
84
84
  log.error(e)
85
- metrics.increment('datadog.tracer.node.inject.errors', true)
85
+ runtimeMetrics.increment('datadog.tracer.node.inject.errors', true)
86
86
  }
87
87
  }
88
88
 
@@ -91,7 +91,7 @@ class DatadogTracer {
91
91
  return this._propagators[format].extract(carrier)
92
92
  } catch (e) {
93
93
  log.error(e)
94
- metrics.increment('datadog.tracer.node.extract.errors', true)
94
+ runtimeMetrics.increment('datadog.tracer.node.extract.errors', true)
95
95
  return null
96
96
  }
97
97
  }
@@ -12,7 +12,10 @@ const {
12
12
  TEST_MODULE_ID,
13
13
  TEST_SESSION_ID,
14
14
  TEST_COMMAND,
15
- TEST_MODULE
15
+ TEST_MODULE,
16
+ getTestSuiteCommonTags,
17
+ TEST_STATUS,
18
+ TEST_SKIPPED_BY_ITR
16
19
  } = require('./util/test')
17
20
  const Plugin = require('./plugin')
18
21
  const { COMPONENT } = require('../constants')
@@ -77,6 +80,24 @@ module.exports = class CiPlugin extends Plugin {
77
80
  }
78
81
  })
79
82
  })
83
+
84
+ this.addSub(`ci:${this.constructor.id}:itr:skipped-suites`, ({ skippedSuites, frameworkVersion }) => {
85
+ const testCommand = this.testSessionSpan.context()._tags[TEST_COMMAND]
86
+ skippedSuites.forEach((testSuite) => {
87
+ const testSuiteMetadata = getTestSuiteCommonTags(testCommand, frameworkVersion, testSuite, this.constructor.id)
88
+
89
+ this.tracer.startSpan(`${this.constructor.id}.test_suite`, {
90
+ childOf: this.testModuleSpan,
91
+ tags: {
92
+ [COMPONENT]: this.constructor.id,
93
+ ...this.testEnvironmentMetadata,
94
+ ...testSuiteMetadata,
95
+ [TEST_STATUS]: 'skip',
96
+ [TEST_SKIPPED_BY_ITR]: 'true'
97
+ }
98
+ }).finish()
99
+ })
100
+ })
80
101
  }
81
102
 
82
103
  configure (config) {
@@ -47,6 +47,7 @@ const TEST_SESSION_ID = 'test_session_id'
47
47
  const TEST_MODULE_ID = 'test_module_id'
48
48
  const TEST_SUITE_ID = 'test_suite_id'
49
49
  const TEST_TOOLCHAIN = 'test.toolchain'
50
+ const TEST_SKIPPED_BY_ITR = 'test.skipped_by_itr'
50
51
 
51
52
  const CI_APP_ORIGIN = 'ciapp-test'
52
53
 
@@ -54,6 +55,8 @@ const JEST_TEST_RUNNER = 'test.jest.test_runner'
54
55
 
55
56
  const TEST_ITR_TESTS_SKIPPED = '_dd.ci.itr.tests_skipped'
56
57
  const TEST_ITR_SKIPPING_ENABLED = 'test.itr.tests_skipping.enabled'
58
+ const TEST_ITR_SKIPPING_TYPE = 'test.itr.tests_skipping.type'
59
+ const TEST_ITR_SKIPPING_COUNT = 'test.itr.tests_skipping.count'
57
60
  const TEST_CODE_COVERAGE_ENABLED = 'test.code_coverage.enabled'
58
61
 
59
62
  const TEST_CODE_COVERAGE_LINES_PCT = 'test.code_coverage.lines_pct'
@@ -80,6 +83,7 @@ module.exports = {
80
83
  JEST_WORKER_TRACE_PAYLOAD_CODE,
81
84
  JEST_WORKER_COVERAGE_PAYLOAD_CODE,
82
85
  TEST_SOURCE_START,
86
+ TEST_SKIPPED_BY_ITR,
83
87
  getTestEnvironmentMetadata,
84
88
  getTestParametersString,
85
89
  finishAllTraceSpans,
@@ -99,6 +103,8 @@ module.exports = {
99
103
  TEST_ITR_TESTS_SKIPPED,
100
104
  TEST_MODULE,
101
105
  TEST_ITR_SKIPPING_ENABLED,
106
+ TEST_ITR_SKIPPING_TYPE,
107
+ TEST_ITR_SKIPPING_COUNT,
102
108
  TEST_CODE_COVERAGE_ENABLED,
103
109
  TEST_CODE_COVERAGE_LINES_PCT,
104
110
  addIntelligentTestRunnerSpanTags,
@@ -354,14 +360,25 @@ function getTestSuiteCommonTags (command, testFrameworkVersion, testSuite, testF
354
360
  function addIntelligentTestRunnerSpanTags (
355
361
  testSessionSpan,
356
362
  testModuleSpan,
357
- { isSuitesSkipped, isSuitesSkippingEnabled, isCodeCoverageEnabled, testCodeCoverageLinesTotal }
363
+ {
364
+ isSuitesSkipped,
365
+ isSuitesSkippingEnabled,
366
+ isCodeCoverageEnabled,
367
+ testCodeCoverageLinesTotal,
368
+ skippingCount,
369
+ skippingType = 'suite'
370
+ }
358
371
  ) {
359
372
  testSessionSpan.setTag(TEST_ITR_TESTS_SKIPPED, isSuitesSkipped ? 'true' : 'false')
360
373
  testSessionSpan.setTag(TEST_ITR_SKIPPING_ENABLED, isSuitesSkippingEnabled ? 'true' : 'false')
374
+ testSessionSpan.setTag(TEST_ITR_SKIPPING_TYPE, skippingType)
375
+ testSessionSpan.setTag(TEST_ITR_SKIPPING_COUNT, skippingCount)
361
376
  testSessionSpan.setTag(TEST_CODE_COVERAGE_ENABLED, isCodeCoverageEnabled ? 'true' : 'false')
362
377
 
363
378
  testModuleSpan.setTag(TEST_ITR_TESTS_SKIPPED, isSuitesSkipped ? 'true' : 'false')
364
379
  testModuleSpan.setTag(TEST_ITR_SKIPPING_ENABLED, isSuitesSkippingEnabled ? 'true' : 'false')
380
+ testModuleSpan.setTag(TEST_ITR_SKIPPING_TYPE, skippingType)
381
+ testModuleSpan.setTag(TEST_ITR_SKIPPING_COUNT, skippingCount)
365
382
  testModuleSpan.setTag(TEST_CODE_COVERAGE_ENABLED, isCodeCoverageEnabled ? 'true' : 'false')
366
383
 
367
384
  // If suites have been skipped we don't want to report the total coverage, as it will be wrong
@@ -31,6 +31,7 @@ class Config {
31
31
  DD_PROFILING_UPLOAD_PERIOD,
32
32
  DD_PROFILING_PPROF_PREFIX,
33
33
  DD_PROFILING_HEAP_ENABLED,
34
+ DD_PROFILING_V8_PROFILER_BUG_WORKAROUND,
34
35
  DD_PROFILING_WALLTIME_ENABLED,
35
36
  DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED,
36
37
  DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE,
@@ -76,7 +77,8 @@ class Config {
76
77
  this.debugSourceMaps = isTrue(coalesce(options.debugSourceMaps, DD_PROFILING_DEBUG_SOURCE_MAPS, false))
77
78
  this.endpointCollectionEnabled = endpointCollectionEnabled
78
79
  this.pprofPrefix = pprofPrefix
79
-
80
+ this.v8ProfilerBugWorkaroundEnabled = isTrue(coalesce(options.v8ProfilerBugWorkaround,
81
+ DD_PROFILING_V8_PROFILER_BUG_WORKAROUND, true))
80
82
  const hostname = coalesce(options.hostname, DD_AGENT_HOST) || 'localhost'
81
83
  const port = coalesce(options.port, DD_TRACE_AGENT_PORT) || 8126
82
84
  this.url = new URL(coalesce(options.url, DD_TRACE_AGENT_URL, format({
@@ -3,6 +3,9 @@
3
3
  const { storage } = require('../../../../datadog-core')
4
4
 
5
5
  const dc = require('../../../../diagnostics_channel')
6
+ const { HTTP_METHOD, HTTP_ROUTE, RESOURCE_NAME, SPAN_TYPE } = require('../../../../../ext/tags')
7
+ const { WEB } = require('../../../../../ext/types')
8
+ const runtimeMetrics = require('../../runtime_metrics')
6
9
 
7
10
  const beforeCh = dc.channel('dd-trace:storage:before')
8
11
  const enterCh = dc.channel('dd-trace:storage:enter')
@@ -41,13 +44,13 @@ function getSpanContextTags (span) {
41
44
  }
42
45
 
43
46
  function isWebServerSpan (tags) {
44
- return tags['span.type'] === 'web'
47
+ return tags[SPAN_TYPE] === WEB
45
48
  }
46
49
 
47
50
  function endpointNameFromTags (tags) {
48
- return tags['resource.name'] || [
49
- tags['http.method'],
50
- tags['http.route']
51
+ return tags[RESOURCE_NAME] || [
52
+ tags[HTTP_METHOD],
53
+ tags[HTTP_ROUTE]
51
54
  ].filter(v => v).join(' ')
52
55
  }
53
56
 
@@ -81,6 +84,7 @@ class NativeWallProfiler {
81
84
  this._flushIntervalMillis = options.flushInterval || 60 * 1e3 // 60 seconds
82
85
  this._codeHotspotsEnabled = !!options.codeHotspotsEnabled
83
86
  this._endpointCollectionEnabled = !!options.endpointCollectionEnabled
87
+ this._v8ProfilerBugWorkaroundEnabled = !!options.v8ProfilerBugWorkaroundEnabled
84
88
  this._mapper = undefined
85
89
  this._pprof = undefined
86
90
 
@@ -99,7 +103,7 @@ class NativeWallProfiler {
99
103
 
100
104
  if (this._codeHotspotsEnabled && !this._emittedFFMessage && this._logger) {
101
105
  this._logger.debug(
102
- `Wall profiler: Enable config_trace_show_breakdown_profiling_for_node feature flag to see code hotspots.`)
106
+ `Wall profiler: Enable trace_show_breakdown_profiling_for_node feature flag to see code hotspots.`)
103
107
  this._emittedFFMessage = true
104
108
  }
105
109
 
@@ -120,7 +124,8 @@ class NativeWallProfiler {
120
124
  durationMillis: this._flushIntervalMillis,
121
125
  sourceMapper: this._mapper,
122
126
  withContexts: this._codeHotspotsEnabled,
123
- lineNumbers: false
127
+ lineNumbers: false,
128
+ workaroundV8Bug: this._v8ProfilerBugWorkaroundEnabled
124
129
  })
125
130
 
126
131
  if (this._codeHotspotsEnabled) {
@@ -170,7 +175,18 @@ class NativeWallProfiler {
170
175
  this._enter()
171
176
  this._lastSampleCount = 0
172
177
  }
173
- return this._pprof.time.stop(restart, this._codeHotspotsEnabled ? generateLabels : undefined)
178
+ const profile = this._pprof.time.stop(restart, this._codeHotspotsEnabled ? generateLabels : undefined)
179
+ if (restart) {
180
+ const v8BugDetected = this._pprof.time.v8ProfilerStuckEventLoopDetected()
181
+ if (v8BugDetected === 1) {
182
+ this._logger?.warn('Wall profiler: possible v8 profiler stuck event loop detected.')
183
+ runtimeMetrics.increment('runtime.node.profiler.v8_cpu_profiler_maybe_stuck_event_loop', undefined, true)
184
+ } else if (v8BugDetected === 2) {
185
+ this._logger?.warn('Wall profiler: v8 profiler stuck event loop detected.')
186
+ runtimeMetrics.increment('runtime.node.profiler.v8_cpu_profiler_stuck_event_loop', undefined, true)
187
+ }
188
+ }
189
+ return profile
174
190
  }
175
191
 
176
192
  profile () {
@@ -2,13 +2,14 @@
2
2
  const NoopProxy = require('./noop/proxy')
3
3
  const DatadogTracer = require('./tracer')
4
4
  const Config = require('./config')
5
- const metrics = require('./metrics')
5
+ const runtimeMetrics = require('./runtime_metrics')
6
6
  const log = require('./log')
7
7
  const { setStartupLogPluginManager } = require('./startup-log')
8
8
  const telemetry = require('./telemetry')
9
9
  const PluginManager = require('./plugin_manager')
10
10
  const remoteConfig = require('./appsec/remote_config')
11
11
  const AppsecSdk = require('./appsec/sdk')
12
+ const dogstatsd = require('./dogstatsd')
12
13
 
13
14
  class Tracer extends NoopProxy {
14
15
  constructor () {
@@ -16,6 +17,7 @@ class Tracer extends NoopProxy {
16
17
 
17
18
  this._initialized = false
18
19
  this._pluginManager = new PluginManager(this)
20
+ this.dogstatsd = new dogstatsd.NoopDogStatsDClient()
19
21
  }
20
22
 
21
23
  init (options) {
@@ -26,6 +28,25 @@ class Tracer extends NoopProxy {
26
28
  try {
27
29
  const config = new Config(options) // TODO: support dynamic code config
28
30
 
31
+ if (config.dogstatsd) {
32
+ // Custom Metrics
33
+ this.dogstatsd = new dogstatsd.CustomMetrics({
34
+ host: config.dogstatsd.hostname,
35
+ port: config.dogstatsd.port,
36
+ tags: [
37
+ // these are the Runtime Metrics default tags
38
+ // Python also uses these as default Custom Metrics tags
39
+ `service:${config.tags.service}`,
40
+ `env:${config.tags.env}`,
41
+ `version:${config.tags.version}`
42
+ ]
43
+ })
44
+
45
+ setInterval(() => {
46
+ this.dogstatsd.flush()
47
+ }, 10 * 1000).unref()
48
+ }
49
+
29
50
  if (config.remoteConfig.enabled && !config.isCiVisibility) {
30
51
  const rc = remoteConfig.enable(config)
31
52
 
@@ -58,7 +79,7 @@ class Tracer extends NoopProxy {
58
79
  }
59
80
 
60
81
  if (config.runtimeMetrics) {
61
- metrics.start(config)
82
+ runtimeMetrics.start(config)
62
83
  }
63
84
 
64
85
  if (config.tracing) {
@@ -117,8 +117,16 @@ function Hook (modules, options, onrequire) {
117
117
  // abort if _resolveLookupPaths return null
118
118
  return exports
119
119
  }
120
- const res = Module._findPath(name, [basedir, ...paths])
121
- if (res !== filename) {
120
+
121
+ let res
122
+ try {
123
+ res = Module._findPath(name, [basedir, ...paths])
124
+ } catch (e) {
125
+ // case where the file specified in package.json "main" doesn't exist
126
+ // in this case, the file is treated as module-internal
127
+ }
128
+
129
+ if (!res || res !== filename) {
122
130
  // this is a module-internal file
123
131
  // use the module-relative path to the file, prefixed by original module name
124
132
  name = name + path.sep + path.relative(basedir, filename)