@nacew/server-errors
v0.2.0
Published
uTestMe server errors for Node.js, and (`/edge`) for Supabase Edge Functions, Cloudflare Workers and Vercel Edge: unhandled exceptions with their request, breadcrumbs, and requests and 5xx per minute.
Readme
@nacew/server-errors
Server errors for Node.js apps, sent to uTestMe: every exception the app does not handle, with its type, stack and the request it happened in, the console lines just before it, and requests and 5xx responses per minute.
It never sends request bodies, headers, cookies or query strings, and uTestMe removes secrets from what it does send. It never changes how the app behaves: a crash still crashes (the error is sent on the way down).
Install
npm install @nacew/server-errorsGet a key in uTestMe: Logs → Add server or app → An app. Put it in the app's environment:
UTESTME_KEY=utm_sk_…
UTESTME_URL=https://utest.meExpress (or any Connect-style server)
const utestme = require("@nacew/server-errors");
utestme.init({ app: "shop-api", release: process.env.GIT_SHA });
app.use(utestme.requestHandler()); // first: counts requests, remembers the request
// … your routes …
app.use(utestme.errorHandler()); // last: sends errors that become a 5xxNext.js 15+
// instrumentation.ts
import { init, captureRequestError } from "@nacew/server-errors";
export function register() {
if (process.env.NEXT_RUNTIME === "nodejs") init({ app: "shop" });
}
export const onRequestError = captureRequestError;Anywhere else
const { captureException, flush, setUser, addBreadcrumb } = require("@nacew/server-errors");
try {
await chargeOrder(order);
} catch (err) {
captureException(err, { tags: { job: "charge" } });
throw err;
}
// A script or a serverless function that is about to end:
await flush();Edge functions (Supabase, Cloudflare Workers, Vercel Edge)
@nacew/server-errors/edge uses only fetch and Web APIs, nothing from Node. It counts each response by status, sends an error the handler throws (then throws it on), and sends before the function is frozen, through the platform's waitUntil when there is one.
// supabase/functions/checkout/index.ts (supabase secrets set UTESTME_KEY=… UTESTME_URL=…)
import { init, withUTestMe } from "npm:@nacew/server-errors/edge";
init({ app: "checkout" });
Deno.serve(
withUTestMe(async (req) => {
// …
return new Response("ok");
}),
);On Cloudflare Workers, call init({ key: env.UTESTME_KEY, url: env.UTESTME_URL }) inside the handler, since env only exists there. captureException(err) and await flush() work anywhere.
Options
| Option | Default | What it does |
| -------------------- | --------------------------------- | ------------------------------------------------------- |
| key | UTESTME_KEY | The app's key. Without one, nothing is sent. |
| url | UTESTME_URL, https://utest.me | Where uTestMe is. |
| app | UTESTME_APP, the package name | The service's name on each error. |
| release | UTESTME_RELEASE | The version running, to tie errors to a deploy. |
| environment | UTESTME_ENVIRONMENT, NODE_ENV | |
| flushIntervalMs | 5000 | How often errors and counts are sent. |
| captureUncaught | true | Send uncaught exceptions and unhandled rejections. |
| consoleBreadcrumbs | true | Keep the last 10 console lines as each error's context. |
| beforeSend | | Change an error, or return null to drop it. |
Node 18 or later.
