Skip to content
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

Support for nextjs #1611

Closed
jooj123 opened this issue Feb 3, 2020 · 9 comments · Fixed by #2959
Closed

Support for nextjs #1611

jooj123 opened this issue Feb 3, 2020 · 9 comments · Fixed by #2959
Assignees
Labels
8.5-candidate agent-nodejs Make available for APM Agents project planning. enhancement
Milestone

Comments

@jooj123
Copy link

jooj123 commented Feb 3, 2020

I am having trouble figuring out how to get elastic apm working with a hybrid express + nextjs app in an effective way.

It seems to pick up requests fine (to specific URLs) and it also picks up error codes and they show up in the elastic UI "transactions" tab.
But I cant seem to get errors to show up in the "errors" tab.

If i throw an error in a next page - eg: ~/page/test.js
Say I have:

function Test() {
  throw new Error('Blah');
  return (
    <p>
      Hello World
    </p>
  )
}

export default Test

It does not show up in the elastic UI.

Describe the solution you'd like
I need exceptions that occur in nextjs to show up in the "error" tab in the elastic apm UI.

A hybrid express + nextjs app would look like this as an example:
https://github.com/jooj123/test-nextjs

Describe alternatives you've considered

I have tired to send errors manually in the next page, via captureError:
https://www.elastic.co/guide/en/apm/agent/nodejs/3.x/agent-api.html#apm-capture-error

But then i get a compile error like:

./node_modules/elastic-apm-node/lib/instrumentation/async-hooks.js
Module not found: Can't resolve 'async_hooks' in '/Users/martin.jujou/Documents/projects/fe-server-auction-results/node_modules/elastic-apm-node/lib/instrumentation'

> Build error occurred
Error: > Build failed because of webpack errors

This I believe is because nextjs pages are built for client and server and because elastic apm is a node client it blows up with the async_hooks error, much like:
vercel/next.js#4348

Not sure if you have any suggestions ...

For any exceptions at the express side of things i'm ok, but if an exception occurs in nextjs context im blind at the moment which is far from ideal

@jooj123
Copy link
Author

jooj123 commented Feb 3, 2020

I ended up working around this by doing these steps:

In next.config.js:

webpack: (config, { isServer, webpack }) => {
      if (!isServer) {
        config.node = {
          dgram: 'empty',
          fs: 'empty',
          net: 'empty',
          tls: 'empty',
          child_process: 'empty',
        };

        // ignore apm (might use in nextjs code but dont want it in client bundles)
        config.plugins.push(
          new webpack.IgnorePlugin(/^(elastic-apm-node)$/),
        );
      }

      return config;
} 

Then in _error.js render func you can call captureError manually:


function Error({ statusCode, message, err }) {

const serverSide = typeof window === 'undefined';

  // only run this on server side as APM only works on server
  if (serverSide) {
    // my apm instance (imports elastic-apm-node and returns  captureError)
    const { captureError } = require('../src/apm'); 

    if (err) {
      captureError(err);
    } else {
      captureError(`Message: ${message}, Status Code: ${statusCode}`);
    }
  }

}

Not very elegant - if there is any other suggestions that would be helpful - thanks.

@trentm
Copy link
Member

trentm commented Jul 21, 2022

I've spent a little time learning Next.js finally. We'd have to add the basic instrumentation of the next module and docs around this as a first step to trace the next server-side actions. I think that should be relatively straightforward.

As stretch work, or for later/separate work, it might be interesting to see if we can use our newish Lambda support to support tracing of Next.js apps deployed to Vercel.

@trentm trentm added this to the 8.5 milestone Jul 28, 2022
@trentm trentm self-assigned this Sep 12, 2022
@trentm trentm moved this from Planned to In Progress in APM-Agents (OLD) Sep 12, 2022
@trentm
Copy link
Member

trentm commented Oct 19, 2022

I know this has been a while in coming. I'm getting close on my PR for this and came back here to sanity check that this case is covered. My PR has an example Next.js app setup with APM (https://github.com/elastic/apm-agent-nodejs/tree/trentm/feat-nextjs/examples/nextjs/).

  1. I added "pages/test.js" as above:
% cat pages/test.js
function Test() {
  throw new Error('Blah');
  return (
    <p>
      Hello World
    </p>
  )
}

export default Test
  1. I configured APM with my APM server URL (in "elastic-apm-node.js"). I ran the dev server, npm run dev, and then visited http://localhost:3000/test:

Screen Shot 2022-10-19 at 4 38 45 PM

The error is captured, and here is what I see in the Kibana APM app:

Screenshot 2022-10-19 at 16-40-26 GET _test - Transactions - my-app - Services - APM - Observability - Elastic

And here is the error group page:

Screen Shot 2022-10-19 at 4 41 39 PM

APM-Agents (OLD) automation moved this from In Progress to Done Oct 28, 2022
@trentm
Copy link
Member

trentm commented Nov 1, 2022

Hi all,
I know it has been a long time since this issue was opened. If you are a Next.js user who uses the Elastic APM agent (or is interested in doing so), I would love to hear feedback on the new Next.js server instrumentation in elastic-apm-node@3.40.0. Thanks.

@mindyourlifeguide
Copy link

@trentm Can you, please, tell me, how to connect it to nextjs in standalone mode? Without standalone mode, it worked well. With him - does not find the package, since standalone does not drag it into the bundle

@trentm
Copy link
Member

trentm commented May 9, 2023

Can you, please, tell me, how to connect it to nextjs in standalone mode?

@mindyourlifeguide Hi! I assume you mean https://nextjs.org/docs/pages/api-reference/next-config-js/output

I was able to get it to work by making the following changes to the small example Next.js app here: https://github.com/elastic/apm-agent-nodejs/tree/main/examples/nextjs

diff --git a/examples/nextjs/next.config.js b/examples/nextjs/next.config.js
index ae887958..7eb7101a 100644
--- a/examples/nextjs/next.config.js
+++ b/examples/nextjs/next.config.js
@@ -2,6 +2,7 @@
 const nextConfig = {
   reactStrictMode: true,
   swcMinify: true,
+  output: 'standalone',
 }

 module.exports = nextConfig
diff --git a/examples/nextjs/package.json b/examples/nextjs/package.json
index 45168c85..6d94b1a4 100644
--- a/examples/nextjs/package.json
+++ b/examples/nextjs/package.json
@@ -9,8 +9,8 @@
     "lint": "next lint"
   },
   "dependencies": {
-    "elastic-apm-node": "elastic/apm-agent-nodejs#main",
-    "next": "12.3.1",
+    "elastic-apm-node": "^3.45.0",
+    "next": "^12.3.1",
     "react": "18.2.0",
     "react-dom": "18.2.0"
   },
diff --git a/examples/nextjs/pages/api/hello.js b/examples/nextjs/pages/api/hello.js
index df63de88..10526995 100644
--- a/examples/nextjs/pages/api/hello.js
+++ b/examples/nextjs/pages/api/hello.js
@@ -1,5 +1,7 @@
 // Next.js API route support: https://nextjs.org/docs/api-routes/introduction

+import 'elastic-apm-node'
+
 export default function handler(req, res) {
   res.status(200).json({ name: 'John Doe' })
 }

The run:

npm install
npm run build
cd .next/standalone
node -r elastic-apm-node/start-next.js server.js

The trick was in adding import 'elastic-apm-node' in one of my page handlers. This resulted in Next.js's dependency scanning including elastic-apm-node and all of its modules.


However, a warning: when I tried this with next@13.2.3 the built .next/standalone was totally bogus. Is standalone mode possibly broken in next@13? I didn't try next@13.3 or next@13.4 because elastic-apm-node doesn't currently support those versions (see #3263).

@mindyourlifeguide
Copy link

@trentm I have version 13.2.1. Without standalone mode, everything worked as it should. It won't start with it.

@mindyourlifeguide
Copy link

mindyourlifeguide commented May 11, 2023

I managed to get it to work via API route but I am getting an unknown route.
usePathAsTransactionName: true does not add readability

/pages/api/hello.js

import apm from 'elastic-apm-node';

apm.start({
   ... my config from elastic-apm-node.js
});

I use:
"elastic-apm-node": "3.45.0",
"next": "13.2.1",

@trentm
Copy link
Member

trentm commented May 11, 2023

See #3073 for supporting usePathAsTransactionName: true.

I'd need more detail to try to understand why you are getting an unknown route.

/pages/api/hello.js

import apm from 'elastic-apm-node';

apm.start({
   ... my config from elastic-apm-node.js
});

You don't want to be starting the apm agent (apm.start(...)) twice. The agent is started in the -r elastic-apm-node/start-next.js module.

(At this point, please open a separate issue, otherwise this discussion is likely to get lost on a closed issue.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
8.5-candidate agent-nodejs Make available for APM Agents project planning. enhancement
Projects
Development

Successfully merging a pull request may close this issue.

3 participants