newrelic 10.6.2 → 11.1.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.
package/esm-loader.mjs CHANGED
@@ -3,228 +3,4 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
 
6
- import newrelic from './index.js'
7
- import shimmer from './lib/shimmer.js'
8
- import loggingModule from './lib/logger.js'
9
- import NAMES from './lib/metrics/names.js'
10
- import semver from 'semver'
11
- import path from 'node:path'
12
- import { fileURLToPath } from 'node:url'
13
-
14
- const isSupportedVersion = () => semver.gte(process.version, 'v16.12.0')
15
- // This check will prevent resolve hooks executing from within this file
16
- // If I do `import('foo')` in here it'll hit the resolve hook multiple times
17
- const isFromEsmLoader = (context) =>
18
- context && context.parentURL && context.parentURL.includes('newrelic/esm-loader.mjs')
19
-
20
- const logger = loggingModule.child({ component: 'esm-loader' })
21
- const esmShimPath = new URL('./lib/esm-shim.mjs', import.meta.url)
22
- const customEntryPoint = newrelic?.agent?.config?.api.esm.custom_instrumentation_entrypoint
23
-
24
- // Hook point within agent for customers to register their custom instrumentation.
25
- if (customEntryPoint) {
26
- const resolvedEntryPoint = path.resolve(customEntryPoint)
27
- logger.debug('Registering custom ESM instrumentation at %s', resolvedEntryPoint)
28
- await import(resolvedEntryPoint)
29
- }
30
-
31
- addESMSupportabilityMetrics(newrelic.agent)
32
-
33
- // exporting for testing purposes
34
- export const registeredSpecifiers = new Map()
35
-
36
- /**
37
- * Hook chain responsible for resolving a file URL for a given module specifier
38
- *
39
- * Our loader has to be the last user-supplied loader if chaining is happening,
40
- * as we rely on `nextResolve` being the default Node.js resolve hook to get our URL
41
- *
42
- * Docs: https://nodejs.org/api/esm.html#resolvespecifier-context-nextresolve
43
- *
44
- * @param {string} specifier string identifier in an import statement or import() expression
45
- * @param {object} context metadata about the specifier, including url of the parent module and any import assertions
46
- * Optional argument that only needs to be passed when changed
47
- * @param {Function} nextResolve The subsequent resolve hook in the chain, or the Node.js default resolve hook after the last user-supplied resolve hook
48
- * @returns {Promise} Promise object representing the resolution of a given specifier
49
- */
50
- export async function resolve(specifier, context, nextResolve) {
51
- if (!newrelic.agent || !isSupportedVersion() || isFromEsmLoader(context)) {
52
- return nextResolve(specifier, context, nextResolve)
53
- }
54
-
55
- /**
56
- * We manually call the default Node.js resolve hook so
57
- * that we can get the fully qualified URL path and the
58
- * package type (commonjs/module/builtin) without
59
- * duplicating the logic of the Node.js hook
60
- */
61
- const resolvedModule = await nextResolve(specifier, context, nextResolve)
62
- const instrumentationName = shimmer.getInstrumentationNameFromModuleName(specifier)
63
- const instrumentationDefinition = shimmer.registeredInstrumentations[instrumentationName]
64
-
65
- if (instrumentationDefinition) {
66
- const { url, format } = resolvedModule
67
- logger.debug(`Instrumentation exists for ${specifier} ${format} package.`)
68
-
69
- if (registeredSpecifiers.get(url)) {
70
- logger.debug(
71
- `Instrumentation already registered for ${specifier} under ${fileURLToPath(
72
- url
73
- )}, skipping resolve hook...`
74
- )
75
- } else if (format === 'commonjs') {
76
- // ES Modules translate import statements into fully qualified filepaths, so we create a copy of our instrumentation under this filepath
77
- const instrumentationDefinitionCopy = [...instrumentationDefinition]
78
-
79
- instrumentationDefinitionCopy.forEach((copy) => {
80
- // Stripping the prefix is necessary because the code downstream gets this url without it
81
- copy.moduleName = fileURLToPath(url)
82
-
83
- // Added to keep our Supportability metrics from exploding/including customer info via full filepath
84
- copy.specifier = specifier
85
- shimmer.registerInstrumentation(copy)
86
- logger.debug(
87
- `Registered CommonJS instrumentation for ${specifier} under ${copy.moduleName}`
88
- )
89
- })
90
-
91
- // Keep track of what we've registered so we don't double register (see: https://github.com/newrelic/node-newrelic/issues/1646)
92
- registeredSpecifiers.set(url, { specifier })
93
- } else if (format === 'module') {
94
- addNrInstrumentation(resolvedModule)
95
- registeredSpecifiers.set(url, { specifier, hasNrInstrumentation: true })
96
- } else {
97
- logger.debug(`${specifier} is not a CommonJS nor ESM package, skipping for now.`)
98
- }
99
- }
100
-
101
- return resolvedModule
102
- }
103
-
104
- /**
105
- * This is purely done so that we can import the incoming specifier
106
- * in the load hook. It used to be used to determine if instrumentation existed
107
- * for specifier but we found a RCE with that solution.
108
- *
109
- * @param {object} resolvedModule the result of call resolve on a specifier
110
- */
111
- function addNrInstrumentation(resolvedModule) {
112
- const modifiedUrl = new URL(resolvedModule.url)
113
- modifiedUrl.searchParams.set('hasNrInstrumentation', 'true')
114
- resolvedModule.url = modifiedUrl.href
115
- }
116
-
117
- /**
118
- * Extracts the href without query params
119
- *
120
- * @param {string} url url of specifier
121
- * @returns {string} new url without hasNrInstrumentation query param
122
- */
123
- function removeNrInstrumentation(url) {
124
- let parsedUrl
125
-
126
- try {
127
- parsedUrl = new URL(url)
128
- url = parsedUrl.href.split('?')[0]
129
- } catch (err) {
130
- logger.error('Unable to parse url: %s, msg: %s', url, err.message)
131
- }
132
-
133
- return url
134
- }
135
-
136
- /**
137
- * Hook chain responsible for determining how a URL should be interpreted, retrieved, and parsed.
138
- *
139
- * Our loader has to be the last user-supplied loader if chaining is happening,
140
- * as we rely on `nextLoad` being the default Node.js resolve hook to load the ESM.
141
- *
142
- * Docs: https://nodejs.org/dist/latest-v18.x/docs/api/esm.html#loadurl-context-nextload
143
- *
144
- * @param {string} url the URL returned by the resolve chain
145
- * @param {object} context metadata about the url, including conditions, format and import assertions
146
- * @param {Function} nextLoad the subsequent load hook in the chain, or the Node.js default load hook after the last user-supplied load hook
147
- * @returns {Promise} Promise object representing the load of a given url
148
- */
149
- export async function load(url, context, nextLoad) {
150
- if (!newrelic.agent || !isSupportedVersion()) {
151
- return nextLoad(url, context, nextLoad)
152
- }
153
-
154
- url = removeNrInstrumentation(url)
155
-
156
- const pkg = registeredSpecifiers.get(url)
157
-
158
- if (!pkg?.hasNrInstrumentation) {
159
- return nextLoad(url, context, nextLoad)
160
- }
161
-
162
- const { specifier } = pkg
163
-
164
- const rewrittenSource = await wrapEsmSource(url, specifier)
165
- logger.debug(`Registered module instrumentation for ${specifier}.`)
166
-
167
- return {
168
- format: 'module',
169
- source: rewrittenSource,
170
- shortCircuit: true
171
- }
172
- }
173
-
174
- /**
175
- * Helper function for determining which of our Supportability metrics to use for the current loader invocation
176
- *
177
- * @param {object} agent
178
- * instantiation of the New Relic agent
179
- * @returns {void}
180
- */
181
- function addESMSupportabilityMetrics(agent) {
182
- if (!agent) {
183
- return
184
- }
185
-
186
- if (isSupportedVersion()) {
187
- agent.metrics.getOrCreateMetric(NAMES.FEATURES.ESM.LOADER).incrementCallCount()
188
- } else {
189
- logger.warn(
190
- 'New Relic for Node.js ESM loader requires a version of Node >= v16.12.0; your version is %s. Instrumentation will not be registered.',
191
- process.version
192
- )
193
- agent.metrics.getOrCreateMetric(NAMES.FEATURES.ESM.UNSUPPORTED_LOADER).incrementCallCount()
194
- }
195
-
196
- if (customEntryPoint) {
197
- agent.metrics.getOrCreateMetric(NAMES.FEATURES.ESM.CUSTOM_INSTRUMENTATION).incrementCallCount()
198
- }
199
- }
200
-
201
- /**
202
- * Rewrites the source code of a ES module we want to instrument.
203
- * This is done by injecting the ESM shim which proxies every property on the exported
204
- * module and registers the module with shimmer so instrumentation can be registered properly.
205
- *
206
- * Note: this autogenerated code _requires_ that the import have the file:// prefix!
207
- * Without it, Node.js throws an ERR_INVALID_URL error: you've been warned.
208
- *
209
- * @param {string} url the URL returned by the resolve chain
210
- * @param {string} specifier string identifier in an import statement or import() expression
211
- * @returns {string} source code rewritten to wrap with our esm-shim
212
- */
213
- async function wrapEsmSource(url, specifier) {
214
- const pkg = await import(url)
215
- const props = Object.keys(pkg)
216
- const trimmedUrl = fileURLToPath(url)
217
-
218
- return `
219
- import wrapModule from '${esmShimPath.href}'
220
- import * as _originalModule from '${url}'
221
- const _wrappedModule = wrapModule(_originalModule, '${specifier}', '${trimmedUrl}')
222
- ${props
223
- .map((propName) => {
224
- return `
225
- let _${propName} = _wrappedModule.${propName}
226
- export { _${propName} as ${propName} }`
227
- })
228
- .join('\n')}
229
- `
230
- }
6
+ export * from 'import-in-the-middle/hook.mjs'
package/index.js CHANGED
@@ -8,6 +8,7 @@
8
8
  // Record opening times before loading any other files.
9
9
  const preAgentTime = process.uptime()
10
10
  const agentStart = Date.now()
11
+ const { isMainThread } = require('worker_threads')
11
12
 
12
13
  // Load unwrapped core now to ensure it gets the freshest properties.
13
14
  require('./lib/util/unwrapped-core')
@@ -16,8 +17,14 @@ const featureFlags = require('./lib/feature_flags').prerelease
16
17
  const psemver = require('./lib/util/process-version')
17
18
  let logger = require('./lib/logger') // Gets re-loaded after initialization.
18
19
  const NAMES = require('./lib/metrics/names')
20
+ const isESMSupported = psemver.satisfies('>=16.2.0')
19
21
 
20
22
  const pkgJSON = require('./package.json')
23
+ if (!isMainThread) {
24
+ logger.warn('Using New Relic for Node.js in worker_threads is not supported. Not starting!')
25
+ return
26
+ }
27
+
21
28
  logger.info(
22
29
  'Using New Relic for Node.js. Agent version: %s; Node version: %s.',
23
30
  pkgJSON.version,
@@ -150,12 +157,12 @@ function createAgent(config) {
150
157
  }
151
158
 
152
159
  const shimmer = require('./lib/shimmer')
153
- shimmer.patchModule(agent)
154
160
  shimmer.bootstrapInstrumentation(agent)
155
161
 
156
162
  // Check for already loaded modules and warn about them.
157
163
  const uninstrumented = require('./lib/uninstrumented')
158
164
  uninstrumented.check(shimmer.registeredInstrumentations)
165
+ shimmer.registerHooks(agent)
159
166
 
160
167
  agent.start(function afterStart(error) {
161
168
  if (error) {
@@ -221,22 +228,33 @@ function recordFeatureFlagMetrics(agent) {
221
228
  * 3. require('newrelic')
222
229
  *
223
230
  * Then a supportability metric is loaded to decide.
224
- * Note: We already take care of scenario #2 in newrelic/esm-loader.mjs
225
231
  *
226
232
  * @param {Agent} agent active NR agent
227
233
  */
228
234
  function recordLoaderMetric(agent) {
229
- const isESM = agent.metrics.getMetric(NAMES.FEATURES.ESM.LOADER)
230
235
  let isDashR = false
231
236
 
232
237
  process.execArgv.forEach((arg, index) => {
233
238
  if (arg === '-r' && process.execArgv[index + 1] === 'newrelic') {
234
239
  agent.metrics.getOrCreateMetric(NAMES.FEATURES.CJS.PRELOAD).incrementCallCount()
235
240
  isDashR = true
241
+ } else if (
242
+ (arg === '--loader' || arg === '--experimental-loader') &&
243
+ process.execArgv[index + 1] === 'newrelic/esm-loader.mjs'
244
+ ) {
245
+ if (isESMSupported) {
246
+ agent.metrics.getOrCreateMetric(NAMES.FEATURES.ESM.LOADER).incrementCallCount()
247
+ } else {
248
+ agent.metrics.getOrCreateMetric(NAMES.FEATURES.ESM.UNSUPPORTED_LOADER)
249
+ logger.warn(
250
+ 'New Relic for Node.js ESM loader requires a version of Node >= v16.12.0; your version is %s. Instrumentation will not be registered.',
251
+ process.version
252
+ )
253
+ }
236
254
  }
237
255
  })
238
256
 
239
- if (!isESM && !isDashR) {
257
+ if (!isDashR) {
240
258
  agent.metrics.getOrCreateMetric(NAMES.FEATURES.CJS.REQUIRE).incrementCallCount()
241
259
  }
242
260
  }
@@ -738,14 +738,6 @@ defaultConfig.definition = () => ({
738
738
  formatter: boolean,
739
739
  default: true,
740
740
  env: 'NEW_RELIC_API_NOTICE_ERROR'
741
- },
742
- /**
743
- * Sets the path to custom ESM instrumentation
744
- */
745
- esm: {
746
- custom_instrumentation_entrypoint: {
747
- default: null
748
- }
749
741
  }
750
742
  },
751
743
  /**
@@ -5,8 +5,6 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- const semver = require('semver')
9
-
10
8
  const logger = require('../logger')
11
9
 
12
10
  /**
@@ -18,16 +16,11 @@ const logger = require('../logger')
18
16
  * the current configuration.
19
17
  */
20
18
  function createContextManager(config) {
21
- if (config.feature_flag.async_local_context) {
22
- // TODO: Remove >=16 check when only support 16+. AsyncLocal became stable in 16.4.0
23
- if (semver.satisfies(process.version, '>=16.4.0')) {
24
- return createAsyncLocalContextManager(config)
25
- }
26
-
27
- logger.warn('The AsyncLocalContextManager is only supported on Node version 16.4.0 and later.')
19
+ if (config.feature_flag.legacy_context_manager) {
20
+ return createLegacyContextManager(config)
28
21
  }
29
22
 
30
- return createLegacyContextManager(config)
23
+ return createAsyncLocalContextManager(config)
31
24
  }
32
25
 
33
26
  function createAsyncLocalContextManager(config) {
@@ -38,13 +31,6 @@ function createAsyncLocalContextManager(config) {
38
31
  }
39
32
 
40
33
  function createLegacyContextManager(config) {
41
- if (config.logging.diagnostics) {
42
- logger.info('Using LegacyDiagnosticContextManager')
43
-
44
- const LegacyDiagnosticContextManager = require('./diagnostics/legacy-diagnostic-context-manager')
45
- return new LegacyDiagnosticContextManager(config)
46
- }
47
-
48
34
  logger.info('Using LegacyContextManager')
49
35
 
50
36
  const LegacyContextManager = require('./legacy-context-manager')
@@ -10,10 +10,9 @@ exports.prerelease = {
10
10
  express5: false,
11
11
  promise_segments: false,
12
12
  reverse_naming_rules: false,
13
- undici_instrumentation: false,
14
13
  undici_async_tracking: true,
15
14
  unresolved_promise_cleanup: true,
16
- async_local_context: false
15
+ legacy_context_manager: false
17
16
  }
18
17
 
19
18
  // flags that are no longer used for released features
@@ -32,7 +31,9 @@ exports.released = [
32
31
  'dt_format_w3c',
33
32
  'fastify_instrumentation',
34
33
  'await_support',
35
- 'certificate_bundle'
34
+ 'certificate_bundle',
35
+ 'async_local_context',
36
+ 'undici_instrumentation'
36
37
  ]
37
38
 
38
39
  // flags that are no longer used for unreleased features
@@ -13,41 +13,6 @@ const parseSql = require('../../db/query-parsers/sql')
13
13
  const RAW_COMMANDS = ['executeRaw', 'queryRaw']
14
14
 
15
15
  const semver = require('semver')
16
- const { getSchema } = require('@mrleebo/prisma-ast')
17
-
18
- /**
19
- * The library we use to parse the prisma schema retains double quotes around
20
- * strings, and they need to be stripped
21
- *
22
- * @param {string} [str=''] string to strip double-quotes from
23
- * @returns {string} stripped string
24
- */
25
- function trimQuotes(str = '') {
26
- return str.match(/"(.*)"/)[1]
27
- }
28
-
29
- /**
30
- * You can set the connection string in schema as raw string,
31
- * env var mapping, or an override at client instantiation time.
32
- *
33
- * @param {*} url string/object value of url in datsource stanza of schema
34
- * @param {string} overrideUrl value of url in overrides at client instantiation
35
- * @returns {string} properly parsed connection url
36
- */
37
- function parseDataModelUrl(url, overrideUrl) {
38
- let parsedUrl = ''
39
-
40
- if (overrideUrl) {
41
- parsedUrl = overrideUrl
42
- } else if (typeof url === 'string') {
43
- parsedUrl = trimQuotes(url)
44
- } else if (url.name && url.name === 'env') {
45
- const envVar = trimQuotes(url.params[0])
46
- parsedUrl = process.env[envVar]
47
- }
48
-
49
- return parsedUrl
50
- }
51
16
 
52
17
  /**
53
18
  * Parses a connection string. Most database engines in prisma are SQL and all
@@ -148,22 +113,34 @@ function queryParser(query) {
148
113
  }
149
114
 
150
115
  /**
151
- * Extracts the prisma connection information from the engine. This used to use
152
- * prisma functions available on engine `getConfig` but that's no longer accessible.
153
- * Instead we went the route of parsing the schema DSL.
116
+ * Extracts connection string from parse datasource config
117
+ *
118
+ * @param {object} datasource active datasource
119
+ * @returns {string} connection string
120
+ */
121
+ function extractConnectionString(datasource = {}) {
122
+ return process.env[datasource?.url?.fromEnvVar] || datasource?.url?.value
123
+ }
124
+
125
+ /**
126
+ * Extracts the prisma connection information from the engine. This calls an internal
127
+ * package used to parse the prisma schema config.
154
128
  *
155
129
  * @param {object} client prisma client instance
156
- * @returns {Promise} returns prisma datasource connection configuration { provider, url }
130
+ * @returns {object} returns prisma datasource connection configuration { provider, url }
157
131
  */
158
132
  function extractPrismaDatasource(client) {
159
- const { datamodel, datasourceOverrides: overrides } = client._engine
160
- const schema = getSchema(datamodel)
161
- const datasource = schema.list.filter(({ type }) => type === 'datasource')[0]
162
- const urlData = datasource.assignments.filter(({ key }) => key === 'url')[0].value
163
- const url = parseDataModelUrl(urlData, overrides[datasource.name])
133
+ const { get_config: getConfig } = require('@prisma/prisma-fmt-wasm')
134
+ const options = JSON.stringify({
135
+ prismaSchema: client?._engine?.datamodel,
136
+ ignoreEnvVarErrors: true
137
+ })
138
+ const config = JSON.parse(getConfig(options))
139
+ const activeDatasource = config?.datasources?.[0]
140
+
164
141
  return {
165
- provider: trimQuotes(datasource.assignments.filter(({ key }) => key === 'provider')[0].value),
166
- url
142
+ provider: activeDatasource.provider,
143
+ url: extractConnectionString(activeDatasource)
167
144
  }
168
145
  }
169
146
 
@@ -7,34 +7,6 @@
7
7
 
8
8
  const url = require('url')
9
9
 
10
- module.exports.selfRegister = function selfRegister(shimmer) {
11
- shimmer.registerInstrumentation({
12
- moduleName: 'amqplib',
13
- type: 'message',
14
- onRequire: instrumentChannelAPI
15
- })
16
- shimmer.registerInstrumentation({
17
- moduleName: 'amqplib/channel_api',
18
- type: 'message',
19
- onRequire: instrumentChannelAPI
20
- })
21
- shimmer.registerInstrumentation({
22
- moduleName: 'amqplib/channel_api.js',
23
- type: 'message',
24
- onRequire: instrumentChannelAPI
25
- })
26
- shimmer.registerInstrumentation({
27
- moduleName: 'amqplib/callback_api',
28
- type: 'message',
29
- onRequire: instrumentCallbackAPI
30
- })
31
- shimmer.registerInstrumentation({
32
- moduleName: 'amqplib/callback_api.js',
33
- type: 'message',
34
- onRequire: instrumentCallbackAPI
35
- })
36
- }
37
-
38
10
  module.exports.instrumentPromiseAPI = instrumentChannelAPI
39
11
  module.exports.instrumentCallbackAPI = instrumentCallbackAPI
40
12
 
@@ -0,0 +1,20 @@
1
+ /*
2
+ * Copyright 2023 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+ const amqplib = require('./amqplib')
8
+
9
+ module.exports = [
10
+ {
11
+ moduleName: 'amqplib/callback_api',
12
+ type: 'message',
13
+ onRequire: amqplib.instrumentCallbackAPI
14
+ },
15
+ {
16
+ moduleName: 'amqplib/channel_api',
17
+ type: 'message',
18
+ onRequire: amqplib.instrumentPromiseAPI
19
+ }
20
+ ]
@@ -11,7 +11,7 @@ const asyncHooks = require('async_hooks')
11
11
  module.exports = initialize
12
12
 
13
13
  function initialize(agent, shim) {
14
- if (agent.config.feature_flag.async_local_context) {
14
+ if (!agent.config.feature_flag.legacy_context_manager) {
15
15
  logger.debug(
16
16
  'New AsyncLocalStorage context enabled. Not enabling manual async_hooks or promise instrumentation'
17
17
  )
@@ -11,9 +11,9 @@ const Timers = require('timers')
11
11
  module.exports = initialize
12
12
 
13
13
  function initialize(agent, timers, _moduleName, shim) {
14
- const isAsyncLocalContext = agent.config.feature_flag.async_local_context
14
+ const isLegacyContext = agent.config.feature_flag.legacy_context_manager
15
15
 
16
- if (!isAsyncLocalContext) {
16
+ if (isLegacyContext) {
17
17
  instrumentProcessMethods(shim, process)
18
18
  instrumentSetImmediate(shim, [timers, global])
19
19
  }
@@ -11,27 +11,23 @@ const { DESTINATIONS } = require('../../config/attribute-filter')
11
11
  const DESTINATION = DESTINATIONS.TRANS_EVENT | DESTINATIONS.ERROR_EVENT
12
12
  const semver = require('semver')
13
13
 
14
- module.exports = function instrument(shim) {
15
- const grpcVersion = shim.require('./package.json').version
16
- const genericShim = shim.makeSpecializedShim(shim.GENERIC, 'grpc-client-interceptor')
17
-
18
- if (semver.gte(grpcVersion, '1.8.0')) {
19
- const resolvingCall = genericShim.require('./build/src/resolving-call')
20
- genericShim.wrap(resolvingCall.ResolvingCall.prototype, 'start', wrapStart)
21
- } else {
22
- const callStream = genericShim.require('./build/src/call-stream')
23
- genericShim.wrap(callStream.Http2CallStream.prototype, 'start', wrapStart)
24
- }
14
+ module.exports.wrapStartResolve = function wrappedClient(shim, resolvingCall) {
15
+ shim.wrap(resolvingCall.ResolvingCall.prototype, 'start', wrapStart)
16
+ }
25
17
 
26
- const webFrameworkShim = shim.makeSpecializedShim(shim.WEB_FRAMEWORK, 'server')
18
+ module.exports.wrapStartCall = function wrappedClient(shim, callStream) {
19
+ shim.wrap(callStream.Http2CallStream.prototype, 'start', wrapStart)
20
+ }
21
+
22
+ module.exports.wrapServer = function wrapServer(shim, server) {
23
+ const grpcVersion = shim.require('./package.json').version
27
24
  if (semver.lt(grpcVersion, '1.4.0')) {
28
25
  shim.logger.debug('gRPC server-side instrumentation only supported on grpc-js >=1.4.0')
29
26
  return
30
27
  }
31
28
 
32
- const server = webFrameworkShim.require('./build/src/server')
33
- webFrameworkShim.setFramework('gRPC')
34
- webFrameworkShim.wrap(server.Server.prototype, 'register', wrapRegister)
29
+ shim.setFramework('gRPC')
30
+ shim.wrap(server.Server.prototype, 'register', wrapRegister)
35
31
  }
36
32
 
37
33
  /**
@@ -7,13 +7,25 @@
7
7
  const grpc = require('./grpc')
8
8
 
9
9
  /**
10
- * Need to use nr-hooks style for grpc because we're using the onResolved hook
11
- * to register instrumentation.
10
+ * Need to use nr-hooks style for grpc because we're instrumentation a submodule.
12
11
  */
13
12
  module.exports = [
14
13
  {
15
- type: 'conglomerate', // generic shim for client, web framework shim for server
16
- moduleName: '@grpc/grpc-js',
17
- onResolved: grpc
14
+ type: 'generic',
15
+ moduleName: '@grpc/grpc-js/build/src/resolving-call',
16
+ isEsm: true,
17
+ onRequire: grpc.wrapStartResolve
18
+ },
19
+ {
20
+ type: 'generic',
21
+ moduleName: '@grpc/grpc-js/build/src/call-stream',
22
+ isEsm: true,
23
+ onRequire: grpc.wrapStartCall
24
+ },
25
+ {
26
+ type: 'web-framework',
27
+ moduleName: '@grpc/grpc-js/build/src/server',
28
+ isEsm: true,
29
+ onRequire: grpc.wrapServer
18
30
  }
19
31
  ]
@@ -7,13 +7,12 @@
7
7
  const pino = require('./pino')
8
8
 
9
9
  /**
10
- * Need to use nr-hooks style for pino because we're using the onResolved hook
11
- * to register instrumentation.
10
+ * Need to use nr-hooks style because we are instrumenting a submodule.
12
11
  */
13
12
  module.exports = [
14
13
  {
15
14
  type: 'generic',
16
- moduleName: 'pino',
17
- onResolved: pino
15
+ moduleName: 'pino/lib/tools',
16
+ onRequire: pino
18
17
  }
19
18
  ]