Next.js

TracesMetricsApp LogsCustom LogsProfiling

1. Prerequisites#

  • Next.js 13.4+ (instrumentation file support). Check:
    1npx next --version
  • Enable the instrumentation hook. In Next.js, the instrumentation.ts file is wired via the experimental instrumentationHook flag (still documented as experimental).
  • OpenTelemetry API peer range (required by the agent):
    1npm i @opentelemetry/api@">=1.3.0 <1.5.0"
  • (Optional but recommended) Middleware Host Agent on the same host/cluster. In containers, set MW_AGENT_SERVICE so your app can reach the agent:
    • Docker: MW_AGENT_SERVICE=172.17.0.1
    • Kubernetes: MW_AGENT_SERVICE=mw-service.mw-agent-ns.svc.cluster.local

2. Install the Next.js APM package#

1npm install @middleware.io/agent-apm-nextjs

3. Modify next.config.js#

Add the instrumentation flag. For newer projects, it’s also recommended to allow the package in server components’ externals:

1// next.config.js
2const nextConfig = {
3  experimental: {
4    instrumentationHook: true,
5    // recommended on modern projects
6    serverComponentsExternalPackages: ['@middleware.io/agent-apm-nextjs'],
7  },
8};
9module.exports = nextConfig;

This mirrors the package guidance and Next.js’ own docs on enabling the instrumentation hook.

4. Create the instrumentation file#

Place instrumentation.ts (or .js) at the project root (or inside src/ if you use a src directory). The file must export a register() function as Next.js calls it once when a server instance boots.

With Host Agent (default path):

1// instrumentation.ts
2// @ts-expect-error: type declarations are not yet complete
3import tracker from '@middleware.io/agent-apm-nextjs';
4
5export function register() {
6  tracker.track({
7    serviceName: '{APM-SERVICE-NAME}',
8    accessToken: '<MW_API_KEY>',
9  });
10}

Serverless / no Host Agent (send direct to Middleware):

1// instrumentation.ts
2import tracker from '@middleware.io/agent-apm-nextjs';
3
4export function register() {
5  tracker.track({
6    serviceName: '{APM-SERVICE-NAME}',
7    accessToken: '<MW_API_KEY>',
8    target: 'https://<MW_UID>.middleware.io:443',
9  });
10}

If you customise pagesExtension, ensure the filename matches (e.g., instrumentation.ts).

5. Container variables (only if using the Host Agent)#

Docker

1MW_AGENT_SERVICE=172.17.0.1
  • (172.17.0.1 is Docker’s default bridge gateway.)

Kubernetes

1MW_AGENT_SERVICE=mw-service.mw-agent-ns.svc.cluster.local

You can locate the service with:

1kubectl get service --all-namespaces | grep mw-service

6. Enable custom logs (optional)#

Use the logger helpers anywhere in your API routes, Route Handlers, or server actions:

1// @ts-expect-error
2import tracker from '@middleware.io/agent-apm-nextjs';
3
4export default async function handler(req, res) {
5  tracker.info('Info Sample');
6  tracker.warn('Warn Sample', { tester: 'Alex' });
7  tracker.debug('Debug Sample');
8  tracker.error('Error Sample');
9  // ...
10}

7. View your Data#

After deploy/startup, wait 3–5 minutes and then open APM → Traces, Logs, and APM → Continuous Profiling in your Middleware account. (For Next.js, metrics and app-logs are not collected by this agent; use Custom Logs as shown above.)

8. Environment variables#

These mirror the options you’d otherwise pass in tracker.track(...).

VariablePurposeExample
MW_API_KEYAuthentication token for exports.xxxxxxxx…
MW_TARGETOTLP endpoint (serverless/remote). Defaults to Host Agent when omitted.https://<MW_UID>.middleware.io:443
MW_SERVICE_NAMEAPM service identifier.nextjs-web
MW_PROJECT_NAMELogical project/app name (optional).ShopApp
MW_CONSOLE_EXPORTEREcho spans/logs to the console for local verification.true
MW_AGENT_SERVICEHost/Service for the Agent when in containers.172.17.0.1 or mw-service.mw-agent-ns.svc.cluster.local

9. Troubleshooting quick checks#

  • register() didn’t run / no traces: ensure experimental.instrumentationHook: true is set and the file is named and placed correctly (root or src/).
  • On Vercel builds: also include serverComponentsExternalPackages: ['@middleware.io/agent-apm-nextjs'] as recommended by the package and Vercel integration notes.
  • Container reachability: set MW_AGENT_SERVICE as shown above.

Need assistance or want to learn more about Middleware? Get in touch with us via our Contact Us or join our Slack channel.

What did you think of this content?