Octri

Backend SDKs

Generated SDKs report from your customers' applications. The Octri monitoring runtimes report from your own server, or from any other application, with no generated SDK needed. Together they show both sides of a failed request as one trace.

There are ten, one per language.

LanguageInstallFramework support
Nodenpm install @octri/nodeExpress, Fastify
Pythonpip install octriFlask, FastAPI, Starlette, Django
Gogo get github.com/octridev/octri-gonet/http middleware
Rubygem install octriRack, Rails
Javadev.octri:octri-monitoringManual
Kotlindev.octri:octri-monitoring-kotlinManual
PHPcomposer require octri/monitoringManual
Rustcargo add octri-monitoringManual
SwiftOctriMonitoringManual
Dartoctri_monitoringManual

Setting up

  1. Turn on monitoring

    In your project's Monitoring tab, choose Enable monitoring. Events are refused while it's off, and a runtime can't turn it on for you.

  2. Copy the configuration

    The Monitoring connection settings show your Ingest URL, token and environment. Standalone SDK configuration copies them all.

  3. Call init once at startup

    Keep the token in an environment variable, and set release to your git SHA. See below.

Enabling creates or rotates the token

Turning monitoring on again issues a new token, and old ones stay revoked. Update anything using the old one.

typescript
import { init } from "@octri/node";

init({
  url: process.env.MONITORING_URL,
  token: process.env.OCTRI_TOKEN,
  environment: "YOUR_PROJECT_ID",
  release: process.env.GIT_SHA,
});

Reporting errors automatically

Add the middleware for your framework, and unhandled errors are reported, then raised again as normal.

Express
import { octriErrorHandler } from "@octri/node/express";

// after your routes, before your own error handler
app.use(octriErrorHandler());

Go's middleware also recovers panics, reports them and panics again.

Reporting your own events

Send any event, not just errors.

typescript
import { captureEvent } from "@octri/node";

captureEvent("checkout.completed", {
  level: "info",
  user: { id: customer.id },
  tags: { region: "eu-west", plan: "growth" },
  context: { orderId: order.id },
});

The options are level, timestamp, operation and request metadata, user, tags, context, breadcrumbs, fingerprint, trace IDs and an event ID. Supplying an eventId makes a retried delivery safe.

To report an error by hand, with the trace from the incoming request:

typescript
import { captureError, traceFromHeader } from "@octri/node";

captureError(err, {
  trace: traceFromHeader(req.headers.traceparent),
  method: req.method,
  path: req.url,
  statusCode: 500,
});

Seeing where the time goes

The middleware times each request as a span. To see inside it, let Octri trace common I/O for you:

typescript
import { autoInstrument, instrument } from "@octri/node";

autoInstrument();                    // outbound fetch, plus pg, mysql2 and ioredis if installed
instrument(cache, ["get", "set"], { op: "cache" });

Or open spans yourself:

typescript
import { withSpan, startSpan } from "@octri/node";

const rows = await withSpan("orders.list", () => db.query(sql), { op: "db" });

const span = startSpan("render", { op: "view" });
// ...work...
span.finish();

op, such as db, cache or http, color-codes the bar in the trace waterfall.

Linking client and server

Your generated SDK sends a W3C traceparent header with each request. A runtime on your server reads it, and reports its error with the same trace ID. The dashboard then shows the client call that failed and the server code that threw as one trace.

Without a runtime on your server, you see only the client's side of a failure.

Controlling what's sent

Credentials and personal data are redacted before anything leaves your process.

typescript
import { addScrubFields, setBeforeSend } from "@octri/node";

addScrubFields("accountNumber", "otp");

// Return null to drop an event
setBeforeSend((payload) => (payload.path === "/health" ? null : payload));

Redaction isn't consent management: the runtime doesn't record consent, so only call capture methods once your application has decided it may send data. See redaction.

If reporting fails

Reporting is best-effort. Delivery failures are suppressed, and they never change how your application behaves.