Weird mysql error
I've just started to implement appinsights in a monorepo, for a Next.js app router project. the appinsights client has to be in a package. All good, so I've created a file called app-insights-server.ts and put this in it:
import * as appInsights from 'applicationinsights';
const connectionString = process.env.APPLICATIONINSIGHTS_CONNECTION_STRING;
// Check if the SDK is already started
// This prevents re-initialization during hot-reloads in development
if (!appInsights.defaultClient && connectionString) {
appInsights
.setup(connectionString)
.setAutoCollectRequests(true)
.setAutoCollectPerformance(false, false)
.setAutoCollectExceptions(true)
.setAutoCollectDependencies(true)
.setAutoCollectConsole(false, false)
.setAutoCollectPreAggregatedMetrics(true)
.setSendLiveMetrics(false)
.setInternalLogging(false, true)
.enableWebInstrumentation(false)
.start();
}
else if (appInsights.defaultClient) {
// In development, the client may exist but not be started
// This ensures it starts on the next server-side request
appInsights.start();
}
// Export the client for manual tracking
export const telemetryClient = appInsights.defaultClient;
Disclaimer: an AI helped me to set it up like this. It looks fine to me.
Then, starting the application, and importing the telemetryClient anywhere at all, without even using it, an error is spewed into the server console:
./node_modules/diagnostic-channel-publishers/dist/src/mysql.pub.js:71:21
Module not found: Can't resolve <dynamic>
69 | "_enqueueCallback"
70 | ];
> 71 | var poolClass = require(path.dirname(originalMysqlPath) + "/lib/Pool");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
72 | poolCallbackFunctions.forEach(function (value) { return patchClassMemberFunction(poolClass, "Pool")(value); });
73 | return originalMysql;
74 | };
Import trace:
Server Component:
./node_modules/diagnostic-channel-publishers/dist/src/mysql.pub.js
./node_modules/diagnostic-channel-publishers/dist/src/index.js
./node_modules/applicationinsights/out/src/logs/diagnostic-channel/initialization.js
./node_modules/applicationinsights/out/src/logs/autoCollectLogs.js
./node_modules/applicationinsights/out/src/main.js
./node_modules/applicationinsights/out/src/index.js
./packages/api/src/app-insights-server.ts
./packages/api/src/fetch.ts
./packages/api/src/gen/sitecore.ts
./packages/api/src/server.ts
./apps/myapplication/src/components/Footer/Footer.server.tsx
./apps/myapplication/src/components/layout/AppLayout.tsx
./apps/myapplication/src/app/[lang]/layout.tsx
https://nextjs.org/docs/messages/module-not-found
Okay? I don't use mysql. Anywhere. Never used it, never installed it. Why is it trying to do anything with it? Is it sort of blindly assuming I use mysql? Because I don't.
The same AI told me the "solution", which is even more gobsmacking to me. In the application, put this in the next.config.ts:
const nextConfig: NextConfig = {
serverExternalPackages: ['applicationinsights'],
// ...
};
What? Why? Why does this help? Because it does. What kind of solution even is this? I've not seen this in the documentation, making it feel like a filthy workaround... For a problem that needn't exist in the first place.
Just don't touch packages that aren't there? Seems pretty basic to me.
More to the point - I would like to know why appinsights wants the mysql package. Seriously, why? 🤨 I want to send errors to appinsights (duh), not to mysql.
Update: the documentation suggests:
Individual instrumentations can be disabled by setting the APPLICATION_INSIGHTS_NO_PATCH_MODULES environment variable to a comma separated list of packages to disable
So adding APPLICATION_INSIGHTS_NO_PATCH_MODULES=mysql prevents it from patching mysql? No it doesn't. This doesn't do anything.
Also, adding .setAutoCollectDependencies(false) in the setup doesn't solve the problem. Reason being, it doesn't even get that far - it can't find a module, so it's not about to execute any code just yet. IOW, no amount of runtime configuration will solve a build-time error.
@thany Ok, the first thing I notice is that the setup script is extremely strange. That else if isn't doing anything good for you. The SDK should never find itself in a state where that would be necessary so removing it is the first good idea.
Regarding the stack trace you shared. The error is coming from diagnostic-channel-publishers, which is a package we rely on in the SDK. We could diagnose what's going on with that mySql issue in a follow up, but if this issue persists you can disable diagnostic channel by disabling auto collection of console logs (bunyan and winston are handled by OpenTelemetry instrumentations). Something in the config like:
appInsights
.setup(connectionString)
.setAutoCollectConsole(false, false)
.start();
Should work to disable this functionality and resolve the error. And finally, as for the solution you specified I'm not a Next.js expert and not exactly sure what/why it "resolved" the error. In my experience AI agents have a tendency to overcomplicate what are really very simple setup scenarios. If you'd like I can share a sample of a basic Next.js app instrumented with this library in case you continue to experience trouble. Thanks for filing an issue!
Also for a little context, the diagnostic-channel-publishers package isn't attempting to send telemetry to mySQL, it's attempting to instrument it in order to collect telemetry about it. Still not correct behavior and happy to help debug if the issue persists after implementing the above.
It's a build error that happens before it even gets to the configuration. I can just put a simple console.log before appInsights....start(); and it will not execute, simply because it doesn't build.
The problem appears to be that there's a require() and the compiler will happily replace that with the actual module... If it existed. I suspect if I install mysql (and all other supported modules) it will work, but I don't want to balloon our dependency tree for no good reason.
@thany Given I can't repro this in a sample Next.js app and based on the fix you have with serverExternalPackages, this is likely a bundling issue. While I'm not a Next.js expert, I wouldn't expect you to need to bundle telemetry collection setup for the client.
Just some excerpts from a copilot description of this feature:
This is a Next.js App Router feature introduced for server components and server-only code.
By default, Next.js bundles all dependencies into the server build. However, some packages (like applicationinsights) are large or rely on Node.js internals.
Adding them to serverExternalPackages tells Next.js:
Do not bundle this package into the server build.
Instead, require it at runtime from node_modules.
This reduces bundle size and avoids issues with packages that cannot be easily bundled (e.g., telemetry libraries, database drivers).
And in specific relation as to why this might be used with the applicationinsights package:
Why use it for applicationinsights?
applicationinsights is a Node.js telemetry SDK for Azure.
It’s not needed in client-side code and can cause bundling errors if included.
Declaring it as external ensures it runs only on the server and is loaded dynamically.
Seems like a reasonable resolution to the bundling issue. There's no documentation included in the project regarding bundling issues specific to certain JS frameworks.