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.
| Language | Install | Framework support |
|---|---|---|
| Node | npm install @octri/ | Express, Fastify |
| Python | pip install octri | Flask, FastAPI, Starlette, Django |
| Go | go get github.com/ | net/ middleware |
| Ruby | gem install octri | Rack, Rails |
| Java | dev.octri:octri-monitoring | Manual |
| Kotlin | dev.octri:octri-monitoring-kotlin | Manual |
| PHP | composer require octri/ | Manual |
| Rust | cargo add octri-monitoring | Manual |
| Swift | OctriMonitoring | Manual |
| Dart | octri_monitoring | Manual |
Setting up
- 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.
- Copy the configuration
The Monitoring connection settings show your Ingest URL, token and environment. Standalone SDK configuration copies them all.
- Call init once at startup
Keep the token in an environment variable, and set
releaseto your git SHA. See below.
Turning monitoring on again issues a new token, and old ones stay revoked. Update anything using the old one.
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.
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.
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:
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:
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:
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.
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.