Enabling the Node.js Application Insights SDK in Next.js
Enabling the Node.js App Insights SDK in Next.js to monitor server-side rendered pages is not straightforward. This guide will show you how to enable it using a workaround.
Application Insights can be used to monitor and debug backend and frontend code in various programming languages such as C#, Java, Python, JavaScript etc. In the JavaScript realm specifically, App Insights provides two SDKs, one for server-side pages rendered through Node.js, and a separate one for client-side pages that render in the browser. This guide addresses the former, but I plan to write a future post about the latter as well.
Next.js is a popular React web framework that allows individual web pages to be server-side rendered, statically generated at build time, and client-side rendered.
Some page types in Next.js render on the server side initially and then the same code also executes client-side in the user’s browser. This feature can introduce problems because when JavaScript bundles are created at build time the resulting code is stripped out of any server-specific functions.
If you try to follow the normal guide to enable the App Insights SDK for Node.js, you will start seeing puzzling errors such as:
error - ./node_modules/applicationinsights/out/Library/Context.js:3:0
Module not found: Can't resolve 'fs'
...
TypeError: Cannot read property 'setup' of undefined
The most likely reason is, like I alluded above, how Next.js creates JavaScript bundles and strips out server-specific code so it can also run in the browser.
I discussed this problem with the App Insights SDK team and they pointed me to this Github issue. Based on the discussion in this item I created a simple workaround which loads the Node.js SDK before Node.js starts, by using the Node.js preload feature.
In package.json under the scripts section I modified the dev and start entries, which are the ones that run for yarn dev and yarn start, respectively, to load a script before running Next.js:
"scripts": {
...
"dev": "node --require ./load-appinsights.js node_modules/next/dist/bin/next dev -p $PORT",
"start": "node --require ./load-appinsights.js node_modules/next/dist/bin/next start -p $PORT",
...
}
Then inside load-appinsights.js I loaded the SDK:
let appInsights = require('applicationinsights');
appInsights
.setup(process.env.APPLICATIONINSIGHTS_CONNECTION_STRING)
.setAutoCollectConsole(true)
.setAutoCollectDependencies(true)
.setAutoCollectExceptions(true)
.setAutoCollectHeartbeat(true)
.setAutoCollectPerformance(true, true)
.setAutoCollectRequests(true)
.setAutoDependencyCorrelation(true)
.setDistributedTracingMode(appInsights.DistributedTracingModes.AI_AND_W3C)
.setSendLiveMetrics(true)
.setUseDiskRetryCaching(true);
appInsights.defaultClient.setAutoPopulateAzureProperties(true);
appInsights.start();
This solves the problem and the App Insights Node.js SDK loads correctly.