Next.js Advanced Config
How Highlight captures Next.js errors
Page Router | App Router | |
---|---|---|
API Errors | PageRouterHighlight | AppRouterHighlight |
SSR Errors | pages/_error.tsx | app/error.tsx |
Client | <HighlightInit /> | <HighlightInit /> |
Edge runtime | EdgeHighlight | EdgeHighlight |
Our Next.js SDK gives you access to frontend session replays and server-side monitoring, all-in-one.
- On the frontend, the
<HighlightInit/>
component sets up client-side session replays. - On the backend, the
PageRouterHighlight
wrapper exported from@highlight-run/next/server
captures server-side errors and logs from Page Router API endpoints. - On the backend, the
AppRouterHighlight
wrapper exported from@highlight-run/next/app-router
captures errors and logs from App Router API endpoints. - The
EdgeHighlight
wrapper exported from@highlight-run/next/server
captures server-side errors and logs from both Page and App Router endpoints using Vercel's Edge runtime. - Use
pages/_error.tsx
andapp/error.tsx
to forward Page Router and App Router SSR errors from the client to Highlight. - The
withHighlightConfig
configuration wrapper automatically proxies Highlight data to bypass ad-blockers and uploads source maps so your frontend errors include stack traces to your source code.
How Highlight captures Next.js logs
<HighlightInit />
captures front-end logs.
PageRouterHighlight
and AppRouterHighlight
capture server-side logs in traditional server runtimes. These wrappers typically fail in serverless runtimes (including Vercel), because we cannot guarantee that the serverless process will stay alive long enough to send all log data to Highlight.
Configure logging for your serverless cloud provider using one of our cloud provider logging guides, including Vercel Log Drain for Highlight.
Tracing Auto-instrumentation
Open Telemetry auto-instrumentation supports a wide array of packages.
Follow the Open Telemetry Instrumentation Initialization guide to initialize any of these supported library and framework..
Custom Tracing Spans
The Next.js Open Telemetry docs have some tips and patterns for using custom spans.
We went ahead and exposed H.startActiveSpan
from @highlight-run/next/server
to automatically integrate into our Next.js SDK. Wrap your API endpoints as always, then kick off spans as needed. Each span will be wrapped under a custom Highlight span that tracks session and request data, automatically tying your custom spans into the broader request context that Highlight is already tracking.
Here's a quick example:
// pages/api/page-router-trace.ts import { NextApiRequest, NextApiResponse } from 'next' import { withPageRouterHighlight } from '@/app/_utils/page-router-highlight.config' import { H } from '@highlight-run/next/server' export default withPageRouterHighlight(async function handler( req: NextApiRequest, res: NextApiResponse, ) { return new Promise<void>(async (resolve) => { const span = await H.startActiveSpan('page-router-span', {}) console.info('Here: /pages/api/page-router-trace.ts ⌚⌚⌚') res.send(`Trace sent! Check out this random number: ${Math.random()}`) span.end() resolve() }) })
// app/api/app-router-trace/route.ts import { NextRequest, NextResponse } from 'next/server' import { withAppRouterHighlight } from '@/app/_utils/app-router-highlight.config' import { H } from '@highlight-run/next/server' export const GET = withAppRouterHighlight(async function GET( request: NextRequest, ) { return new Promise(async (resolve) => { const span = await H.startActiveSpan('app-router-span', {}) console.info('Here: /pages/api/app-router-trace/route.ts ⏰⏰⏰') span.end() resolve(new Response('Success: /api/app-router-trace')) }) })
Environment variables
This section is extra opinionated about Next.js constants. It's not for everyone. We like how
zod
and TypeScript work together to validateprocess.env
inputs... but this is a suggestion. Do your own thing and replace our imports (import { CONSTANTS } from 'src/constants'
) with your own!
- Install Zod:
npm install zod
- Edit
.env
to add your projectID toNEXT_PUBLIC_HIGHLIGHT_PROJECT_ID
# .env NEXT_PUBLIC_HIGHLIGHT_PROJECT_ID='<API KEY>'
- Feed your environment variables into the application with a constants file. We're using
zod
for this example, because it creates a validated, typedCONSTANTS
object that plays nicely with TypeScript.
// constants.ts import { z } from 'zod'; // Must assign NEXT_PUBLIC_* env vars to a variable to force Next to inline them const publicEnv = { NEXT_PUBLIC_HIGHLIGHT_PROJECT_ID: process.env.NEXT_PUBLIC_HIGHLIGHT_PROJECT_ID, }; export const CONSTANTS = z .object({ NEXT_PUBLIC_HIGHLIGHT_PROJECT_ID: z.string(), }) .parse(publicEnv);
Vercel Log Drain
Install our Vercel + Highlight Integration to enable Vercel Log Drain on your project.
Our API wrappers automatically send logs to Highlight in all runtime environments, but Vercel shuts down its Node.js and Edge processes so quickly that log messages are often lost.
Vercel Log Drain is a reliable way to capture those logs.
Next.js plugin
Proxy your front-end Highlight calls by adding withHighlightConfig
to your next.config
. Frontend session recording and error capture data will be piped through your domain on /highlight-events
to sneak Highlight network traffic past ad-blockers.
The following example demonstrates both private source maps and the request proxy. withHighlightConfig
does not require a second argument if you are only using the request proxy.
Request proxy only
// next.config.js const { withHighlightConfig } = require('@highlight-run/next/config') /** @type {import('next').NextConfig} */ const nextConfig = { experimental: { serverComponentsExternalPackages: ['@highlight-run/node'], }, productionBrowserSourceMaps: true, // optionally ship source maps to production } module.exports = withHighlightConfig(nextConfig)
Private source maps + request proxy
-
Get your Highlight API key from your project settings. You can also enable the Highlight + Vercel integration to inject
HIGHLIGHT_SOURCEMAP_UPLOAD_API_KEY
directly into your Vercel environment. -
Verify that
HIGHLIGHT_SOURCEMAP_UPLOAD_API_KEY=<apiKey>
is set in your environment variables--try.env.local
for testing purposes--or passapiKey
in as an optional argument towithHighlightConfig
. -
Ensure that
productionBrowserSourceMaps
is eitherfalse
or omitted. -
Wrap your
nextConfig
withwithHighlightConfig
.apiKey
is unnecessary if you haveHIGHLIGHT_SOURCEMAP_UPLOAD_API_KEY
in your environment variables. -
Run
npm run build && npm run start
to test. Your logs should show files uploading like so:
Uploaded /root/dev/highlight/next-test/.next/server/pages/index.js
// next.config.js const { withHighlightConfig } = require('@highlight-run/next/config') /** @type {import('next').NextConfig} */ const nextConfig = { experimental: { serverComponentsExternalPackages: ['@highlight-run/node'], }, productionBrowserSourceMaps: false, } module.exports = withHighlightConfig(nextConfig, { apiKey: '<API KEY>', uploadSourceMaps: true, })
Configure inlineImages
We use a package called rrweb to record web sessions. rrweb supports inlining images into sessions to improve replay accuracy, so that images that are only available from your local network can be saved; however, the inlined images can cause CORS issues in some situations.
We currently default inlineImages
to true
on localhost
. Explicitly set inlineImages={false}
if you run into trouble loading images on your page while Highlight is running. This will degrade tracking on localhost
and other domains that are inaccessible to app.highlight.io
.
Configure tracingOrigins
and networkRecording
See Fullstack Mapping for details on how to associate your back-end errors to client sessions.