None of these packages are on a public registry yet (npm, PyPI, RubyGems, Packagist, and a Go module proxy are the plan). Until then, every install command below installs the real, current mirror straight from GitHub, not a placeholder. Go is the one exception: a Go module needs nothing but a public git repo and a tag, so go get already works exactly the way it will once the others catch up.
Every SDK shares the same contract: it never throws or panics out of a public function, it scrubs card numbers, JWTs, API keys, and known secret headers before anything leaves the process, and user.email / user.username are dropped unless you opt them back in by exact field name. See the API reference for the full ingest contract these SDKs post to.
Next.js
The JS SDK's App Router adapter, wired through the instrumentation.ts convention Next.js itself defines. Works with Next 15 and newer.
npm install github:RealUptimeHQ/realuptime-errors-js// instrumentation.ts, at your project root
export async function register() {
// register() also runs under the edge runtime and during `next build`'s
// trace/compile step -- gate to nodejs so neither of those opens a
// transport.
if (process.env.NEXT_RUNTIME !== "nodejs") return;
const { registerErrorTracking } = await import("@realuptime/errors/adapters/nextjs.ts");
registerErrorTracking({ dsn: process.env.REALUPTIME_ERRORS_DSN! });
}
// Next (App Router, 15+) calls this for every server-side rendering,
// Server Action, and Route Handler error. Re-export it verbatim.
export { onRequestError } from "@realuptime/errors/adapters/nextjs.ts";This alone captures every server-side rendering, Server Action, and Route Handler error Next hands to onRequestError, with the request's method and path (never headers, cookies, or bodies by default). To cover a specific Route Handler even before that hook fires, or to get its method and path when the global hook's aren't specific enough, wrap it directly:
// app/api/orders/route.ts
import { withRouteErrors } from "@realuptime/errors/adapters/nextjs.ts";
export const GET = withRouteErrors(async (req: Request) => {
// ...
});For errors that happen in the browser (client components, event handlers), follow the React section below: it is the same core SDK, initialized once on the client.
React
There is no React-specific package: React apps use the same browser build every other JavaScript app uses. Call init() once, before your app renders.
npm install github:RealUptimeHQ/realuptime-errors-js// main.tsx (or index.tsx), before rendering the app
import { init } from "@realuptime/errors";
init({
dsn: import.meta.env.VITE_REALUPTIME_ERRORS_DSN, // or process.env, per your bundler
release: import.meta.env.VITE_GIT_SHA,
environment: import.meta.env.MODE,
});That alone captures unhandled exceptions and promise rejections anywhere on the page. React error boundaries are a separate mechanism (React does not let window.onerror see an error a boundary already caught), so if you use one, report from it explicitly with captureException in componentDidCatch. The SDK ships no boundary component of its own; this is a plain one:
// error-boundary.tsx
import { Component, type ErrorInfo, type ReactNode } from "react";
import { captureException } from "@realuptime/errors";
export class ErrorBoundary extends Component<{ children: ReactNode }, { hasError: boolean }> {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error: unknown, info: ErrorInfo) {
captureException(error, { context: { componentStack: info.componentStack ?? "" } });
}
render() {
return this.state.hasError ? <p>Something went wrong.</p> : this.props.children;
}
}Node
Plain Node (a script, a worker, a queue consumer, anything that is not a web framework with its own adapter) uses the same core SDK as the browser build, imported for its Node entry point instead.
npm install github:RealUptimeHQ/realuptime-errors-jsimport { init, captureException } from "@realuptime/errors";
init({
dsn: process.env.REALUPTIME_ERRORS_DSN!,
release: process.env.GIT_SHA,
environment: process.env.NODE_ENV,
});
// init() installs process-level handlers for uncaughtException and
// unhandledRejection by default (captureUnhandled: false turns that off).
// Capture anything else you catch yourself:
try {
await chargeCustomer(order);
} catch (err) {
captureException(err, { tags: { queue: "billing" } });
throw err;
}Running Express (or any Connect-style framework using the same (err, req, res, next) convention: Connect, Restify)? Mount the error-handling middleware last, after every route:
import * as realuptimeErrors from "@realuptime/errors";
import { errorHandler } from "@realuptime/errors/adapters/express.ts";
realuptimeErrors.init({ dsn: process.env.REALUPTIME_ERRORS_DSN! });
const app = express();
// ... your routes ...
// Mount LAST, after every route and other middleware. Express only treats a
// 4-argument function as error-handling middleware, and only errors that
// reach the end of the chain get here.
app.use(errorHandler());The middleware always calls next(err); it never sends a response itself, so your app's own error handling is unaffected. It captures method, path, and status by default, nothing else.
Python
Standard library only, zero runtime dependencies.
pip install "git+https://github.com/RealUptimeHQ/realuptime-errors-py"import realuptime_errors
realuptime_errors.init(
dsn="https://ingest.realuptime.io/api/errors/v1/ingest/rue_...", # from your project's dashboard
release=os.environ.get("GIT_SHA"),
environment="production",
)
try:
charge(order)
except Exception as exc:
realuptime_errors.capture_exception(exc, tags={"tenant": "acme"})
raiseFramework adapters share the one capture/scrub/transport path above; each is feature-detected (importing the adapter module never requires the framework to be installed).
Flask
from flask import Flask
from realuptime_errors_flask import FlaskErrors
app = Flask(__name__)
FlaskErrors(app, dsn=os.environ["REALUPTIME_ERRORS_DSN"])
# or the two-step application-factory pattern:
# errors = FlaskErrors()
# errors.init_app(app)Django
# settings.py
MIDDLEWARE = [
# ...
"realuptime_errors_django.RealuptimeErrorsMiddleware",
]
import realuptime_errors
realuptime_errors.init(dsn=os.environ["REALUPTIME_ERRORS_DSN"])FastAPI
from fastapi import FastAPI
from realuptime_errors_fastapi import FastApiMiddleware
import realuptime_errors
realuptime_errors.init(dsn=os.environ["REALUPTIME_ERRORS_DSN"])
app = FastAPI()
app.add_middleware(FastApiMiddleware)Locals in a captured frame's variables are never sent unless you turn it on explicitly with include_local_variables=True, off by default: the variable holding the password is, definitionally, in scope at the frame that failed to use it.
Ruby
Standard library only: `json`, `net/http`, `uri`, `time`, `rbconfig`.
gem "realuptime-errors", git: "https://github.com/RealUptimeHQ/realuptime-errors-ruby"require "realuptime/errors"
Realuptime::Errors.init(
dsn: "https://ingest.realuptime.io/api/errors/v1/ingest/rue_...", # from your project's dashboard
release: ENV["GIT_SHA"],
environment: "production"
)
begin
charge(order)
rescue => e
Realuptime::Errors.capture_exception(e, tags: { "tenant" => "acme" })
raise
endRails
# Gemfile
gem "realuptime-errors", git: "https://github.com/RealUptimeHQ/realuptime-errors-ruby",
require: "realuptime/errors/rails"
# config/initializers/realuptime_errors.rb
Rails.application.config.realuptime_errors.dsn = ENV.fetch("REALUPTIME_ERRORS_DSN")
Rails.application.config.realuptime_errors.release = ENV["GIT_SHA"]Delivery runs on a background thread per process (re-spawned after a fork, so Puma, Unicorn, and Sidekiq workers keep flushing), with exponential backoff on failure and a synchronous Realuptime::Errors.flush that runs at exit.
PHP
Zero runtime dependencies beyond ext-json and ext-curl.
composer require realuptime/errors:dev-mainrequire 'vendor/autoload.php';
\RealUptime\Errors\Client::init(
dsn: 'https://ingest.realuptime.io/api/errors/v1/ingest/rue_...',
release: 'v2.4.1',
environment: 'production',
);
\RealUptime\Errors\install_exception_handler(); // captures uncaught exceptions, then re-raises
try {
riskyThing();
} catch (\Throwable $e) {
\RealUptime\Errors\Client::instance()?->captureException($e);
}Laravel
The service provider auto-registers via Composer's package discovery. Set the DSN in .env:
REALUPTIME_ERRORS_DSN=https://ingest.realuptime.io/api/errors/v1/ingest/rue_...
REALUPTIME_ERRORS_RELEASE=v2.4.1That is it for exceptions: the provider decorates Laravel's own exception handler, so every exception report() already sees is also captured here, unchanged behavior otherwise. Failed queue jobs are captured the same way, because a queue worker process never runs through the HTTP exception handler at all.
Go
Standard library only. A Go module needs nothing but a public git repo and a tag, so this installs from the real mirror today.
go get github.com/RealUptimeHQ/realuptime-errors-goimport realuptimeerrors "github.com/RealUptimeHQ/realuptime-errors-go"
client := realuptimeerrors.NewClient(realuptimeerrors.Config{
DSN: "https://ingest.realuptime.io/api/errors/v1/ingest/rue_...", // from your project's dashboard
Release: "v2.4.1",
Environment: "production",
})
defer client.Close()
if err := doSomething(); err != nil {
client.CaptureException(err)
}net/http
mux := http.NewServeMux()
mux.HandleFunc("/orders", ordersHandler)
handler := realuptimeerrors.Middleware(client)(mux)
http.ListenAndServe(":8080", handler)Middleware recovers a panic escaping the handler below it, reports it with minimal request context (method and path, never headers, cookies, or bodies), answers with a 500, and does not re-panic, so one broken handler cannot take the process down.
Next steps
- See the API reference for the ingest endpoint's full wire contract, rate limits, and the events REST API.
- Use the CLI's
realuptime errors releases announceto attach a release to a deploy from CI, andrealuptime errors issues listto read issues from the terminal.