-
Notifications
You must be signed in to change notification settings - Fork 230
could we log.warn if require.cache
already has modules we typically instrument at agent.start()
time?
#2578
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This could be interesting in combination with #1967 |
If/when this is done, having a reference to this in https://www.elastic.co/guide/en/apm/agent/nodejs/current/starting-the-agent.html might be worthwhile as well. |
OTel does this in _warnOnPreloadedModules() {
this._modules.forEach((module) => {
const { name } = module;
try {
const resolvedModule = require.resolve(name);
if (require.cache[resolvedModule]) {
// Module is already cached, which means the instrumentation hook might not work
this._diag.warn(`Module ${name} has been loaded before ${this.instrumentationName} so it might not work, please initialize it before requiring ${name}`);
}
}
catch (_a) {
// Module isn't available, we can simply skip
}
});
} |
modules we instrument that we also load in the agentHere is a quick patch to index.js to list the modules that we instrument that we also load as part of the APM agent. diff --git a/index.js b/index.js
index 04711888..8899840d 100644
--- a/index.js
+++ b/index.js
@@ -6,6 +6,44 @@
'use strict'
+function intersection (setA, setB) {
+ const _intersection = new Set()
+ for (const elem of setB) {
+ if (setA.has(elem)) {
+ _intersection.add(elem)
+ }
+ }
+ return _intersection
+}
+
+var modPathsBefore = new Set(Object.keys(require.cache))
+
var Agent = require('./lib/agent')
module.exports = new Agent()
+
+var modPathsAfter = new Set(Object.keys(require.cache))
+function difference (setA, setB) {
+ const _difference = new Set(setA)
+ for (const elem of setB) {
+ _difference.delete(elem)
+ }
+ return _difference
+}
+var diff = difference(modPathsAfter, modPathsBefore)
+// console.log('XXX modPaths loaded:', diff)
+
+const moduleDetailsFromPath = require('module-details-from-path')
+var modNames = new Set()
+diff.forEach(p => {
+ var details = moduleDetailsFromPath(p)
+ if (details) {
+ modNames.add(details.name)
+ }
+})
+// console.log('XXX modNames: ', modNames)
+
+var modsWeInstrument = new Set(require('./lib/instrumentation').modules.flat())
+
+const inter = intersection(modNames, modsWeInstrument)
+console.log('XXX modsWeInstrument that we have loaded: ', inter) Currently that includes:
This is relevant for first stabdiff --git a/lib/instrumentation/index.js b/lib/instrumentation/index.js
index b721b064..b7c06ff7 100644
--- a/lib/instrumentation/index.js
+++ b/lib/instrumentation/index.js
@@ -228,6 +228,28 @@ Instrumentation.prototype.start = function (runContextClass) {
}
}
+ const modNamesWeRequireOurself = new Set(['@opentelemetry/api', '@opentelemetry/sdk-metrics'])
+ const modNamesAlreadyRequired = new Set()
+ this._patches.keys.forEach(modName => {
+ if (modNamesWeRequireOurself.has(modName)) {
+ return
+ }
+ try {
+ const resolvePath = require.resolve(modName)
+ if (require.cache[resolvePath]) {
+ modNamesAlreadyRequired.add(modName)
+ }
+ } catch (_resolveErr) {
+ // skip
+ }
+ })
+ if (modNamesAlreadyRequired.size > 0) {
+ this._log.warn('modules have been `require`d before the APM agent started, ' +
+ 'instrumentation might not work for them: %s ' +
+ '(see https://www.elastic.co/guide/en/apm/agent/nodejs/current/starting-the-agent.html)',
+ Array.from(modNamesAlreadyRequired).join(', '))
+ }
+
this._runCtxMgr.enable()
this._startHook()
This results in a warning like the following in a script that requires "express" before starting the APM agent:
checklist of suggested improvements on this first take
nice to haveIt would be nice to be able to warn appropriately for
Of those, option (2) might be easiest. I'm not sure the other two are worth the complexity. |
A reasonably common mistake when using the APM agent is to
.start()
it after havingrequire()
d some modules that the agent would have instrumented. We could probably look throughrequire.cache
atAgent#start()
-time to see if it already had imported modules that the agent would have instrumented (moduloactive
anddisableInstrumentations
), and if so, then emit alog.warn('yo, you need to apm.start() earlier')
. Then that log message could be in the troubleshooting docs to explain the issue.The text was updated successfully, but these errors were encountered: