diff --git a/docs/02-app/01-building-your-application/06-optimizing/09-instrumentation.mdx b/docs/02-app/01-building-your-application/06-optimizing/09-instrumentation.mdx index 9fbf79e1f2030..693b6b7e09bdc 100644 --- a/docs/02-app/01-building-your-application/06-optimizing/09-instrumentation.mdx +++ b/docs/02-app/01-building-your-application/06-optimizing/09-instrumentation.mdx @@ -1,77 +1,78 @@ --- title: Instrumentation description: Learn how to use instrumentation to run code at server startup in your Next.js app +related: + title: Learn more about Instrumentation + links: + - app/api-reference/file-conventions/instrumentation + - app/api-reference/next-config-js/instrumentationHook --- {/* The content of this doc is shared between the app and pages router. You can use the `Content` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */} Instrumentation is the process of using code to integrate monitoring and logging tools into your application. This allows you to track the performance and behavior of your application, and to debug issues in production. -Next.js provides a `register` function that can be exported from a `instrumentation.ts|js` file in the **root directory** of your project (or inside the `src` folder if using one). Next.js will then call `register` whenever a new Next.js server instance is bootstrapped. +## Convention - +To set up instrumentation, create `instrumentation.ts|js` file in the **root directory** of your project (or inside the [`src`](/docs/app/building-your-application/configuring/src-directory) folder if using one). -> **Good to know** -> -> - This feature is **experimental**. To use it, you must explicitly opt in by defining `experimental.instrumentationHook = true;` in your `next.config.js`. -> - The `instrumentation` file should be in the root of your project and not inside the `app` or `pages` directory. If you're using the `src` folder, then place the file inside `src` alongside `pages` and `app`. -> - If you use the [`pageExtensions` config option](/docs/app/api-reference/next-config-js/pageExtensions) to add a suffix, you will also need to update the `instrumentation` filename to match. -> - We have created a basic [with-opentelemetry](https://github.com/vercel/next.js/tree/canary/examples/with-opentelemetry) example that you can use. - - - - - -> **Good to know** -> -> - This feature is **experimental**. To use it, you must explicitly opt in by defining `experimental.instrumentationHook = true;` in your `next.config.js`. -> - The `instrumentation` file should be in the root of your project and not inside the `app` or `pages` directory. If you're using the `src` folder, then place the file inside `src` alongside `pages` and `app`. -> - If you use the [`pageExtensions` config option](/docs/pages/api-reference/next-config-js/pageExtensions) to add a suffix, you will also need to update the `instrumentation` filename to match. -> - We have created a basic [with-opentelemetry](https://github.com/vercel/next.js/tree/canary/examples/with-opentelemetry) example that you can use. - - - -When your `register` function is deployed, it will be called on each cold boot (but exactly once in each environment). - -Sometimes, it may be useful to import a file in your code because of the side effects it will cause. For example, you might import a file that defines a set of global variables, but never explicitly use the imported file in your code. You would still have access to the global variables the package has declared. +Then, export a `register` function in the file. This function will be called **once** when a new Next.js server instance is initiated. -You can import files with side effects in `instrumentation.ts`, which you might want to use in your `register` function as demonstrated in the following example: +For example, to use Next.js with [OpenTelemetry](https://opentelemetry.io/) and [@vercel/otel](https://github.com/vercel/otel): -```ts filename="your-project/instrumentation.ts" switcher -import { init } from 'package-init' +```ts filename="instrumentation.ts" switcher +import { registerOTel } from '@vercel/otel' export function register() { - init() + registerOTel('next-app') } ``` -```js filename="your-project/instrumentation.js" switcher -import { init } from 'package-init' +```js filename="instrumentation.js" switcher +import { registerOTel } from '@vercel/otel' export function register() { - init() + registerOTel('next-app') } ``` -However, we recommend importing files with side effects using `import` from within your `register` function instead. The following example demonstrates a basic usage of `import` in a `register` function: +See the [Next.js with OpenTelemetry example](https://github.com/vercel/next.js/tree/canary/examples/with-opentelemetry) for a complete implementation. + +> **Good to know** +> +> - This feature is **experimental**. To use it, you must explicitly opt in by defining [`experimental.instrumentationHook = true;`](/docs/app/api-reference/next-config-js/instrumentationHook) in your `next.config.js`. +> - The `instrumentation` file should be in the root of your project and not inside the `app` or `pages` directory. If you're using the `src` folder, then place the file inside `src` alongside `pages` and `app`. +> - If you use the [`pageExtensions` config option](/docs/app/api-reference/next-config-js/pageExtensions) to add a suffix, you will also need to update the `instrumentation` filename to match. + +## Examples -```ts filename="your-project/instrumentation.ts" switcher +### Importing files with side effects + +Sometimes, it may be useful to import a file in your code because of the side effects it will cause. For example, you might import a file that defines a set of global variables, but never explicitly use the imported file in your code. You would still have access to the global variables the package has declared. + +We recommend importing files using JavaScript `import` syntax within your `register` function. The following example demonstrates a basic usage of `import` in a `register` function: + +```ts filename="instrumentation.ts" switcher export async function register() { await import('package-with-side-effect') } ``` -```js filename="your-project/instrumentation.js" switcher +```js filename="instrumentation.js" switcher export async function register() { await import('package-with-side-effect') } ``` -By doing this, you can colocate all of your side effects in one place in your code, and avoid any unintended consequences from importing files. +> **Good to know:** +> +> We recommend importing the file from within the `register` function, rather than at the top of the file. By doing this, you can colocate all of your side effects in one place in your code, and avoid any unintended consequences from importing globally at the top of the file. + +### Importing runtime-specific code -We call `register` in all environments, so it's necessary to conditionally import any code that doesn't support both `edge` and `nodejs`. You can use the environment variable `NEXT_RUNTIME` to get the current environment. Importing an environment-specific code would look like this: +Next.js calls `register` in all environments, so it's important to conditionally import any code that doesn't support specific runtimes (e.g. [Edge](/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes#edge-runtime) or [Node.js](/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes#nodejs-runtime)). You can use the `NEXT_RUNTIME` environment variable to get the current environment: -```ts filename="your-project/instrumentation.ts" switcher +```ts filename="instrumentation.ts" switcher export async function register() { if (process.env.NEXT_RUNTIME === 'nodejs') { await import('./instrumentation-node') @@ -83,7 +84,7 @@ export async function register() { } ``` -```js filename="your-project/instrumentation.js" switcher +```js filename="instrumentation.js" switcher export async function register() { if (process.env.NEXT_RUNTIME === 'nodejs') { await import('./instrumentation-node') diff --git a/docs/02-app/02-api-reference/02-file-conventions/instrumentation.mdx b/docs/02-app/02-api-reference/02-file-conventions/instrumentation.mdx new file mode 100644 index 0000000000000..6f4eb854e4b03 --- /dev/null +++ b/docs/02-app/02-api-reference/02-file-conventions/instrumentation.mdx @@ -0,0 +1,53 @@ +--- +title: instrumentation.js +description: API reference for the instrumentation.js file. +related: + title: Learn more about Instrumentation + links: + - app/building-your-application/optimizing/instrumentation +--- + +The `instrumentation.js|ts` file is used to integrate monitoring and logging tools into your application. This allows you to track the performance and behavior of your application, and to debug issues in production. + +To use it, place the file in the **root** of your application or inside a [`src` folder](/docs/app/building-your-application/configuring/src-directory) if using one. + +## Config Option + +Instrumentation is currently an experimental feature, to use the `instrumentation` file, you must explicitly opt-in by defining [`experimental.instrumentationHook = true;`](/docs/app/api-reference/next-config-js/instrumentationHook) in your `next.config.js`: + +```js filename="next.config.js" +module.exports = { + experimental: { + instrumentationHook: true, + }, +} +``` + +## Exports + +### `register` (required) + +The file exports a `register` function that is called **once** when a new Next.js server instance is initiated. `register` can be an async function. + +```ts filename="instrumentation.ts" switcher +import { registerOTel } from '@vercel/otel' + +export function register() { + registerOTel('next-app') +} +``` + +```js filename="instrumentation.js" switcher +import { registerOTel } from '@vercel/otel' + +export function register() { + registerOTel('next-app') +} +``` + +## Version History + +| Version | Changes | +| --------- | ------------------------------------------------------- | +| `v14.0.4` | Turbopack support for `instrumentation` | +| `v13.2.0` | `instrumentation` introduced as an experimental feature | diff --git a/docs/02-app/02-api-reference/05-next-config-js/instrumentationHook.mdx b/docs/02-app/02-api-reference/05-next-config-js/instrumentationHook.mdx new file mode 100644 index 0000000000000..ff183d402b739 --- /dev/null +++ b/docs/02-app/02-api-reference/05-next-config-js/instrumentationHook.mdx @@ -0,0 +1,21 @@ +--- +title: instrumentationHook +description: Use the instrumentationHook option to set up instrumentation in your Next.js App. +related: + title: Learn more about Instrumentation + links: + - app/api-reference/file-conventions/instrumentation + - app/building-your-application/optimizing/instrumentation +--- + +{/* The content of this doc is shared between the app and pages router. You can use the `Content` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */} + +The experimental `instrumentationHook` option allows you to set up instrumentation via the [`instrumentation` file](/docs/app/api-reference/file-conventions/instrumentation) in your Next.js App. + +```js filename="next.config.js" +module.exports = { + experimental: { + instrumentationHook: true, + }, +} +``` diff --git a/docs/03-pages/02-api-reference/03-next-config-js/instrumentationHook.mdx b/docs/03-pages/02-api-reference/03-next-config-js/instrumentationHook.mdx new file mode 100644 index 0000000000000..784b768d37634 --- /dev/null +++ b/docs/03-pages/02-api-reference/03-next-config-js/instrumentationHook.mdx @@ -0,0 +1,7 @@ +--- +title: instrumentationHook +description: Use the instrumentationHook option to set up instrumentation in your Next.js App. +source: app/api-reference/next-config-js/instrumentationHook +--- + +{/* The content of this doc is shared between the app and pages router. You can use the `Content` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */}