Node.js and Next.js
Send requests, queries, outgoing requests, exceptions and logs from Next.js, Express, Hono and other Node.js servers with raccoon-nodejs.
The raccoon-nodejs package sets up OpenTelemetry and exports to Raccoon. It needs Node.js 22.15 or later.
Set up with one command#
Run this in the root of your app, with a token from Settings → Environments:
npx raccoon-nodejs@latest init --url https://raccoon.watch --token <environment token>
It installs the package with your package manager (npm, pnpm, yarn or bun) and writes RACCOON_URL and RACCOON_TOKEN to .env.local (Next.js) or .env.
- In a Next.js app, it creates
instrumentation.tsand turns on server source maps innext.config. Add--browser-key <browser key>to also createinstrumentation-client.tsfor browser monitoring. - In another Node.js server, it adds
--import raccoon-nodejs/registerto thenode ...start script.
It lists anything it couldn't do. Set the same two variables where the app is deployed.
Set up by hand#
npm install raccoon-nodejs
RACCOON_URL=https://raccoon.watch
RACCOON_TOKEN=<environment token>
Without both variables, the package logs one warning and sends nothing. When they aren't in the environment, it reads them from .env.local or .env in the working directory.
Next.js#
Create instrumentation.ts in the project root, or in src/:
export { register, onRequestError } from 'raccoon-nodejs/next';
Next.js creates the request and fetch() spans itself. The package adds Postgres and MySQL queries and outgoing http requests, and reports errors through onRequestError.
Production builds are minified. For stack traces that point at your source files, turn on server source maps:
// next.config.js
export default {
experimental: { serverSourceMaps: true },
};
On Vercel, the package exports each request's events when the request ends and keeps the function alive until the export finishes, so a frozen function doesn't drop them. Only the Node.js runtime is traced. Edge middleware and edge routes aren't.
Express, Hono, Vite SSR and other servers#
Load the package before the app:
node --import raccoon-nodejs/register server.js
Or call register() at the top of the entry file, before importing express, pg or mysql2. That works for CommonJS apps. ES module apps need --import, so the package can patch modules as they're imported.
import { register } from 'raccoon-nodejs';
register({ captureConsole: true });
Options#
| Option | Default | What it does |
|---|---|---|
url |
RACCOON_URL |
Raccoon's URL. |
token |
RACCOON_TOKEN |
The environment token. |
server |
The host name | Server name shown on events. |
deploy |
RACCOON_DEPLOY, VERCEL_GIT_COMMIT_SHA or RAILWAY_GIT_COMMIT_SHA |
Release name for deploy markers on charts. |
captureConsole |
false (RACCOON_CAPTURE_CONSOLE=true with --import) |
Sends console.* output as logs. |
instrumentations |
[] |
More OpenTelemetry instrumentations, such as new PrismaInstrumentation() from @prisma/instrumentation. |
API#
import { setRoute, setUser, captureException, log } from 'raccoon-nodejs';
// Name the current request's route, for frameworks that don't (AdonisJS, Koa).
setRoute('/posts/:id');
// Attach the signed-in user to the current request. Shows on the Users page.
setUser({ id: user.id, name: user.name, email: user.email });
// Report a caught exception. Pass { handled: false } for errors the user saw.
captureException(error);
// Write a log entry linked to the current request.
log('warning', 'Payment provider is slow', { provider: 'stripe' });
What shows up where#
| Dashboard page | Comes from |
|---|---|
| Requests | The outermost server span of each trace. The route comes from http.route, which Next.js and Express set. Requests without a route are grouped as "(unmatched)". |
| Queries | Spans with db.system and a statement (pg, mysql2, Prisma). |
| Outgoing Requests | Client HTTP spans (fetch, http, undici). |
| Exceptions and Issues | Exceptions recorded on spans. |
| Logs | OpenTelemetry log records, linked to their request. |
| Users | setUser() |
Jobs, commands, scheduled tasks, mail, notifications and cache are Laravel concepts, so those pages stay empty for Node.js apps.
Troubleshooting#
- Nothing arrives. Check that
RACCOON_URLandRACCOON_TOKENare set where the app runs. Without them, the package logs one warning at startup. - Requests arrive, queries don't (ES modules). The package loaded after
pgormysql2. Usenode --import raccoon-nodejs/registerinstead of callingregister(). - Stack traces point at
.next/server/chunks/.... Turn onexperimental.serverSourceMapsand redeploy.