Next.js Plugin
Use development tunnels and configure server-side Next.js telemetry independently.
@outray/next provides a development tunnel wrapper, server-side observability initialization, and App Router request instrumentation. These are separate integrations: a tunnel is not required to export telemetry.
Install
npm install @outray/nextThe package declares compatibility with Next.js 13–16. Its observability dependency requires Node.js 20 or later; use the runtime supported by your Next.js version.
Development tunnel
In next.config.ts:
import withOutray from "@outray/next";
export default withOutray(
{},
{
apiKey: process.env.OUTRAY_API_KEY,
subdomain: "my-app",
},
);Use a token with tunnel:connect. Run your normal next dev command and copy the URL printed by OutRay.
The wrapper starts only when NODE_ENV === "development". It starts from config loading, not a webpack hook, and reads PORT to determine the target port (default 3000). For a different port, set PORT as well as the port used by Next.js.
| Tunnel option | Default | Behavior |
|---|---|---|
apiKey | OUTRAY_API_KEY | Tunnel credential; no CLI-login fallback |
subdomain | OUTRAY_SUBDOMAIN | Requested subdomain |
customDomain | Unset | Verified custom tunnel hostname |
serverUrl | OUTRAY_SERVER_URL or wss://connect.outray.co/ | Tunnel server |
enabled | OUTRAY_ENABLED !== "false" | Enable development tunnel |
silent | false | Suppress tunnel status output |
local | false | Also provide mDNS LAN access |
Callbacks include onTunnelReady(url), onError(error), onClose(), onReconnecting(), and onLocalReady(info).
Initialize observability
Use Next.js's server instrumentation hook. In instrumentation.ts (or src/instrumentation.ts when your application uses src):
export async function register() {
if (process.env.NEXT_RUNTIME !== "nodejs") return;
const { registerOutrayObservability } =
await import("@outray/next/observability");
const telemetry = registerOutrayObservability({
apiKey: process.env.OBSERVABILITY_TOKEN,
serviceName: "storefront",
environment: process.env.NODE_ENV,
captureConsole: true,
});
telemetry.info("observability started");
}Use a token with observability:write (Send telemetry), supplied from server-only configuration. Do not use NEXT_PUBLIC_* variables for the credential.
The runtime check and dynamic import keep the Node.js SDK out of edge runtimes. The configuration wrapper alone does not initialize this telemetry integration.
Instrument App Router handlers
// app/api/orders/route.ts
import { withOutrayRequest } from "@outray/next";
export const POST = withOutrayRequest(
async (request: Request) => {
const order = await request.json();
return Response.json({ accepted: true, itemCount: order.items.length });
},
{
routeResolver: () => "/api/orders",
capturePayloads: {
maxBodyBytes: 16 * 1024,
redactedFields: ["accountPin"],
},
},
);The wrapper records route-aware spans, response status, failures, and HTTP request count, duration, and active-request metrics. It reuses a recording server span when one exists, or creates one through the configured provider.
routeResolver supplies a stable route template; otherwise common identifier segments are normalized to :id. ignore can skip additional requests. Common Next.js asset paths are ignored by default.
Payload capture is disabled by default. When enabled, eligible JSON and URL-encoded payloads are bounded and common sensitive fields and headers are redacted. Capture inspects clones rather than consuming or replacing the handler's original Request/Response.
withOutrayPayloadCapture(handler, options) is a shortcut for request instrumentation with capture enabled. These wrappers are for App Router handlers returning a Response, not Pages Router API handlers.
Application logs and spans
import { outray, withOutraySpan } from "@outray/next/observability";
outray.info("order accepted", { orderId: "order_123" });
await withOutraySpan("process order", async () => {
// Perform the operation here.
});Structured logging preserves local output and can correlate logs with the active trace. Console capture is separately opt-in via captureConsole.
See the Node.js SDK for shared configuration, export timing, payload privacy, and shutdown behavior.