'What is the best way to add APM to NuxtJS project

What is the right way to configure/enable an Elastic APM agent in a Nuxtjs project?

I referred this documentation for a custom NodeJS app. The key takeaway was:

It’s important that the agent is started before you require any other modules in your Node.js application - i.e. before http and before your router etc.

I added the following snippet in nuxt.config.js, but the APM agent is not started or working. I do not see any errors in the app logs.

var apm = require('elastic-apm-node').start({
  serviceName: 'nuxt-app',
  serverUrl: 'http://ELK_APM_SERVER:8200'
})

Is there any other way to do this?



Solution 1:[1]

We managed to get this working using a custom Nuxt module which explicitly requires the Node modules to instrument after it has initiated the APM module.

modules/elastic-apm.js:

    const apm = require('elastic-apm-node');
    const defu = require('defu');
    
    module.exports = function() {
      this.nuxt.hook('ready', async(nuxt) => {
        const runtimeConfig = defu(nuxt.options.privateRuntimeConfig, nuxt.options.publicRuntimeConfig);
        const config = (runtimeConfig.elastic && runtimeConfig.elastic.apm) || {};
    
        if (!config.serverUrl) {
          return;
        }
    
        if (!apm.isStarted())  {
          await apm.start(config);
    
          // Now explicitly require the modules we want APM to hook into, as otherwise
          // they would not be instrumented.
          //
          // Docs: https://www.elastic.co/guide/en/apm/agent/nodejs/master/custom-stack.html
          // Modules: https://github.com/elastic/apm-agent-nodejs/tree/master/lib/instrumentation/modules
          require('http');
          require('http2');
          require('https');
        }
      });
    }

nuxt.config.js:

    module.exports = {
      // Must be in modules, not buildModules
      modules: ['~/modules/elastic-apm'],
      
      publicRuntimeConfig: {
        elastic: {
          apm: {
            serverUrl: process.env.ELASTIC_APM_SERVER_URL,
            serviceName: 'my-nuxt-app',
            usePathAsTransactionName: true // prevent "GET unknown route" transactions
          }
        }
      }
    };

Solution 2:[2]

All the answers are outdated and from beginning incorrect (17.02.2022)

To make it work follow these steps:

1.) Create a nodeApm.js in your root dir with the following content:

const nodeApm = require('elastic-apm-node')

if (!nodeApm.isStarted()) { 
    nodeApm.start()
}

2.) Use environment variables to store your config. For example:

ELASTIC_APM_SERVICE_NAME=NUXT_PRODUCTION
ELASTIC_APM_SECRET_TOKEN=yoursecrettokenhere

3.) Edit your package.json

"scripts": {
    // if you want apm also on dev to test, add it also here
    "dev": "node -r ./nodeApm.js node_modules/nuxt/bin/nuxt",
    ...
    "start": "node -r ./nodeApm.js node_modules/nuxt/bin/nuxt start",
...

! Be awere that in ~2022 the node_modules bin folder has lost the "." in the directory name

! In all othere anwsers people forget the start parameter at the end

"start": "node -r ./nodeApm.js node_modules/nuxt/bin/nuxt start",

Solution 3:[3]

Based on Alan Storm answer (from Nuxt team) I made it work but with a little modification:

  • I created a file named nodeApm.js where I added the following code:
    const nodeApm = require('elastic-apm-node')
    
    if (!nodeApm.isStarted()) { ... // configuration magic }
    
  • In script sections I added:
    "start": "node -r ./nodeApm.js node_modules/nuxt/.bin/nuxt"
    

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 RWD
Solution 2 Philipp S.
Solution 3 Dharman