-
Notifications
You must be signed in to change notification settings - Fork 404
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: Migrated Next.js instrumentation into agent (#2409)
- Loading branch information
Showing
51 changed files
with
2,157 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# FAQs | ||
|
||
Are you having an issue with New Relic Next.js Instrumentation? Take a look at the following FAQS: | ||
|
||
* [Deploying Next.js to Cloud Provider](./cloud-providers.md) | ||
* [Injecting New Relic Browser Agent](./browser-agent.md) | ||
* [Instrumenting 3rd Party Libraries](./instrument-third-party-libraries.md) | ||
* [Error Handling](./error-handling.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Injecting Browser Agent | ||
|
||
Q: How can I inject the [New Relic Browser Agent](https://docs.newrelic.com/docs/browser/browser-monitoring/installation/install-browser-monitoring-agent/) into a Next.js project? | ||
|
||
A: It depends on if you are using the Pages or App Router for Next.js. | ||
|
||
|
||
## Inject Browser Agent | ||
The following links demonstrates how to inject the browser agent. | ||
|
||
* [Pages Router](https://github.com/newrelic/newrelic-node-examples/blob/e118117470ae9f9038c60d8a171a6f0d440f6291/nextjs-legacy/pages/_document.jsx) | ||
* [App Router](https://github.com/newrelic/newrelic-node-examples/blob/58f760e828c45d90391bda3f66764d4420ba4990/nextjs-app-router/app/layout.js) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Deploy Next.js to Cloud Provider | ||
|
||
Q: Can Next.js instrumentation work when deploying to [Vercel](https://vercel.com/frameworks/nextjs), [AWS Amplify](https://aws.amazon.com/amplify/), [Netlify](https://www.netlify.com/with/nextjs/), [Azure Static Sites](https://azure.microsoft.com/en-us/products/app-service/static), etc? | ||
|
||
A: The short answer is no. Most of these cloud providers lack the ability to control run options to load the New Relic Node.js agent. Also, most of these cloud providers execute code in a Function as a Service(FaaS) environment. Our agent requires a different setup and then additional processes to load the telemetry. Our recommendation is to rely on OpenTelemetry and load the telemetry via our OTLP endpoint. | ||
|
||
## OpenTelemetry setup with New Relic | ||
|
||
To setup Next.js to load OpenTelemetry data to New Relic you must do the following: | ||
|
||
1. Enable [experimental instrumentation hook](https://nextjs.org/docs/app/building-your-application/optimizing/open-telemetry). In your `next.config.js` add: | ||
|
||
```js | ||
{ | ||
experimental: { | ||
instrumentationHook: true | ||
} | ||
} | ||
``` | ||
|
||
2. Install OpenTelemetry packages. | ||
|
||
```sh | ||
npm install @opentelemetry/sdk-node @opentelemetry/resources @opentelemetry/semantic-conventions @opentelemetry/sdk-trace-node @opentelemetry/exporter-trace-otlp-http | ||
``` | ||
|
||
3. Setup OpenTelemetry configuration in `new-relic-instrumentation.js` | ||
|
||
```js | ||
const { NodeSDK } = require('@opentelemetry/sdk-node') | ||
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node') | ||
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http') | ||
const { Resource } = require('@opentelemetry/resources') | ||
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions') | ||
const { SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-node') | ||
|
||
const sdk = new NodeSDK({ | ||
resource: new Resource({ | ||
[SemanticResourceAttributes.SERVICE_NAME]: 'next-app', | ||
}), | ||
spanProcessor: new SimpleSpanProcessor(new OTLPTraceExporter({ | ||
url: 'https://otlp.nr-data.net', | ||
headers: { | ||
'api-key': process.env.NEW_RELIC_API_KEY | ||
} | ||
})), | ||
instrumentations: [getNodeAutoInstrumentations()] | ||
}) | ||
sdk.start() | ||
``` | ||
|
||
4. Add the following to `instrumentation.ts` in the root of your Next.js project: | ||
|
||
```js | ||
export async function register() { | ||
if (process.env.NEXT_RUNTIME === 'nodejs') { | ||
require('./new-relic-instrumentation.js') | ||
} | ||
} | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Injecting Browser Agent | ||
|
||
Q: How can I get the Next.js instrumentation to log errors to [New Relic Errors Inbox](https://docs.newrelic.com/docs/errors-inbox/errors-inbox/)? | ||
|
||
A: The Node.js agent has an API to log errors `newrelic.noticeError`. Next.js has an error page that can be used to add the API call. | ||
|
||
|
||
## Log errors to Errors Inbox | ||
|
||
The error page varies between [Pages Router](https://nextjs.org/docs/pages/building-your-application/routing/custom-error) and [App Router](https://nextjs.org/docs/app/building-your-application/routing/error-handling) Next.js projects. | ||
|
||
|
||
* [Pages Router](https://github.com/newrelic/newrelic-node-examples/blob/e118117470ae9f9038c60d8a171a6f0d440f6291/nextjs-legacy/pages/_error.jsx) error handling example. | ||
|
||
|
23 changes: 23 additions & 0 deletions
23
documentation/nextjs/faqs/instrument-third-party-libraries.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Instrument 3rd Party Libraries within Next.js | ||
|
||
Q: How can I get instrumentation to load for 3rd party libraries within my Next.js application like mysql, mongodb, pino, winston, etc? | ||
|
||
A: Typically the New Relic Node.js agent auto-instruments all supported [3rd party libraries](https://docs.newrelic.com/docs/apm/agents/nodejs-agent/getting-started/compatibility-requirements-nodejs-agent/#instrument). Next.js, however, bundles your project and code spilts between server and client side via webpack. To get auto-instrumentation to work, you must externalize all libraries within webpack. | ||
|
||
## Externalize 3rd party libraries in webpack | ||
|
||
To externalize all supported 3rd party libraries, add the following to `next.config.js`: | ||
|
||
```js | ||
const nrExternals = require('newrelic/load-externals') | ||
|
||
module.exports = { | ||
// In order for newrelic to effectively instrument a Next.js application, | ||
// the modules that newrelic supports should not be mangled by webpack. Thus, | ||
// we need to "externalize" all of the modules that newrelic supports. | ||
webpack: (config) => { | ||
nrExternals(config) | ||
return config | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Segments and spans | ||
|
||
Segments and spans (when distributed tracing is enabled) are captured for Next.js middleware and `getServerSideProps`(Server-Side Rendering). | ||
|
||
## Next.js middleware segments/spans | ||
|
||
[Next.js middleware](https://nextjs.org/docs/middleware) was made stable in 12.2.0. As of v0.2.0 of `@newrelic/next`, it will only instrument Next.js middleware in versions greater than or equal to 12.2.0. | ||
|
||
`/Nodejs/Middleware/Nextjs//middleware` | ||
|
||
Since middleware executes for every request you will see the same span for every request if middleware is present even if you aren't executing any business logic for a given route. If you have middleware in a deeply nested application, segments and spans will be created for every unique middleware. | ||
|
||
## Server-side rendering segments/spans | ||
|
||
`/Nodejs/Nextjs/getServerSideProps/<Next.js page name>` | ||
|
||
Next.js pages that contain server-side rendering must export a function called `getServerSideProps`. The function execution will be captured and an additional attribute will be added for the name of the page. | ||
|
||
**Attributes** | ||
| Name | Description | | ||
| --------- | ---------------------------------------------------------- | | ||
| next.page | Name of the page, including dynamic route where applicable | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Transactions | ||
|
||
Transactions are captured as web transactions and named based on the Next.js page or API route. If you are using Next.js as a [custom server](https://nextjs.org/docs/advanced-features/custom-server), our Next.js instrumentation overrides the transaction naming of existing instrumentation for the custom server framework (for example, express, fastify, hapi, koa). Also, the transaction will be renamed based on the Next.js page or API route. | ||
|
||
Let's say we have a Next.js app with the following application structure: | ||
|
||
``` | ||
pages | ||
index.js | ||
dynamic | ||
static.js | ||
[id].js | ||
api | ||
hiya.js | ||
dynamic | ||
[id].js | ||
``` | ||
|
||
The transactions will be named as follows: | ||
|
||
| Request | Transaction Name | | ||
| --------------------- | -------------------------------- | | ||
| /pages/ | Nextjs/GET// | | ||
| /pages/dynamic/static | Nextjs/GET//pages/dynamic/static | | ||
| /pages/dynamic/example | Nextjs/GET//pages/dynamic/[id] | | ||
| /api/hiya | Nextjs/GET//api/hiya | | ||
| /api/dynamic/example | Nextjs/GET//api/dynamic/[id] | | ||
|
||
|
||
## Errors | ||
There are two exceptions to the transaction naming above. | ||
|
||
### 404s | ||
If a request to a non-existent page or API route is made, the transaction name will flow through the Next.js 404 page and will be named as `Nextjs/GET//404`. | ||
|
||
### Non 404 errors | ||
If a request is made that results in a 4xx or 5xx error, the transaction will flow through the Next.js error component and will be named as `Nextjs/GET//_error`. | ||
|
||
|
Oops, something went wrong.