Quickstart
Adding Observra to an existing application takes three lines. This page walks through exactly which three, and where they go.
1. Install
npm i observra-sdk-node @opentelemetry/api
The SDK is ESM-only, so your package.json needs "type": "module" (or use an
.mjs file).
2. Get a gateway key
In the Observra Dashboard, under Gateway Keys,
create a key for the Application and Environment these calls should be attributed
to. It starts with obs_.
OBSERVRA_GATEWAY_KEY=obs_your_key_here
That's the only Observra credential you need. Your provider key stays exactly where it is — you keep sending it yourself, and Observra forwards it without storing it.
3. Add three lines to your app
Here is an ordinary application that calls Groq. Nothing Observra-specific:
import Groq from "groq-sdk";
const groq = new Groq({ apiKey: process.env.GROQ_API_KEY });
export async function ask(question: string) {
const res = await groq.chat.completions.create({
model: "llama-3.3-70b-versatile",
messages: [{ role: "user", content: question }],
});
return res.choices[0].message.content;
}
And the same application with Observra. The highlighted lines are the entire change:
import * as observra from "observra-sdk-node";
import Groq from "groq-sdk";
observra.configure({ serviceName: "my-app" });
await observra.instrument();
const groq = new Groq({ apiKey: process.env.GROQ_API_KEY });
export async function ask(question: string) {
const res = await groq.chat.completions.create({
model: "llama-3.3-70b-versatile",
messages: [{ role: "user", content: question }],
});
return res.choices[0].message.content;
}
Your Groq client didn't change. Your call site didn't change. No baseURL, no
wrapper class, no custom headers. Every call this application makes from now on is
routed through the Observra Gateway and traced.
What those lines do
observra.configure() reads OBSERVRA_GATEWAY_KEY from the environment and points
at Observra's hosted gateway. serviceName is optional — it labels this application
in your trace data, which matters once you run more than one.
observra.instrument() patches the global fetch, which is how a stock provider SDK
ends up talking to your gateway without knowing anything about Observra. It's async,
so await it.
Where to put them
Before you construct any provider client, once per process. In a real application that usually means the top of your entry point:
import * as observra from "observra-sdk-node";
observra.configure({ serviceName: "my-app" });
await observra.instrument();
// Everything imported after this point is instrumented.
const { startServer } = await import("./server.js");
startServer();
If your entry point can't use top-level await, wrap it:
async function main() {
const observra = await import("observra-sdk-node");
observra.configure({ serviceName: "my-app" });
await observra.instrument();
const { startServer } = await import("./server.js");
startServer();
}
main();
4. See it
Open the dashboard, go to Observations, and set the range to the last hour. Your calls are there with model, token counts, cost, and latency. Click one and choose Request flow to see it as a tree.
That's the whole integration
Everything else in these docs is optional:
- Guardrails — catch PII in prompts before they leave
- Tracing — group multi-step operations into one trace
- Agents and tools — trace an agent run as one flow
- Providers — the other 14 supported provider SDKs
Nothing showing up?
Check the request actually reached the gateway. Log the URL your provider SDK
requested — after instrument() it should point at your gateway, not the provider:
const realFetch = globalThis.fetch;
globalThis.fetch = async (input, init) => {
console.log("→", typeof input === "string" ? input : input.url);
return realFetch(input, init);
};
await observra.instrument(); // install the logger BEFORE this line
The order matters. A logger installed after instrument() records the original
URL, before the SDK rewrote it — which looks like a routing failure on a perfectly
working setup.
Check your provider is one the SDK reroutes. See the supported list. Anything not on it passes straight through to its own API, untraced.
Check instrument() ran first. A call made before it completes goes direct to
the provider. If you forgot the await, that's the likely cause.
Check the key. An invalid or revoked gateway key gets a 401, which surfaces as
whatever error your provider SDK raises for that status.