Skip to content

What do you need to do?

Docs

Errors quickstarts

The real install command and the real init() call for every framework RealUptime Errors ships a first-party SDK for today: Next.js, React, Node, Python, Ruby, PHP, and Go. Every DSN looks like https://ingest.realuptime.io/api/errors/v1/ingest/<project_key>, copied once from your project's page under Errors, and it is safe to ship inside a client bundle: it can only submit events to that one project.

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.

bash
npm install github:RealUptimeHQ/realuptime-errors-js
ts
// 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:

ts
// 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.

bash
npm install github:RealUptimeHQ/realuptime-errors-js
ts
// 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:

tsx
// 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.

bash
npm install github:RealUptimeHQ/realuptime-errors-js
ts
import { 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:

ts
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.

bash
pip install "git+https://github.com/RealUptimeHQ/realuptime-errors-py"
python
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"})
    raise

Framework 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

python
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

python
# settings.py
MIDDLEWARE = [
    # ...
    "realuptime_errors_django.RealuptimeErrorsMiddleware",
]

import realuptime_errors
realuptime_errors.init(dsn=os.environ["REALUPTIME_ERRORS_DSN"])

FastAPI

python
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`.

bash
gem "realuptime-errors", git: "https://github.com/RealUptimeHQ/realuptime-errors-ruby"
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
end

Rails

ruby
# 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.

bash
composer require realuptime/errors:dev-main
php
require '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:

bash
REALUPTIME_ERRORS_DSN=https://ingest.realuptime.io/api/errors/v1/ingest/rue_...
REALUPTIME_ERRORS_RELEASE=v2.4.1

That 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.

bash
go get github.com/RealUptimeHQ/realuptime-errors-go
go
import 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

go
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 announce to attach a release to a deploy from CI, and realuptime errors issues list to read issues from the terminal.