◉
24observe
DOCUMENTATION • ERROR TRACKING • 5 MIN READ

Error tracking + Real User Monitoring.

Two drop-in integrations that reuse the SDKs you already run. Keep your existing @sentry/* client and just repoint its DSN at us for Sentry-style error grouping. Keep Google's web-vitals library and beacon its readings to us for Core Web Vitals. No re-instrumentation, no second agent, no per-seat bill — errors and vitals land in the same Logs and metrics pipeline you already use.

Start free → Quickstart

TL;DR

Two drop-in integrations that reuse the SDKs you already run. Keep your existing @sentry/* client and just repoint its DSN at us for Sentry-style error grouping. Keep Google's web-vitals library ...

Docs · error tracking + RUM

Error tracking + Real User Monitoring.

Two drop-in integrations that reuse the SDKs you already run. Keep your existing @sentry/* client and just repoint its DSN at us for Sentry-style error grouping. Keep Google's web-vitals library and beacon its readings to us for Core Web Vitals. No re-instrumentation, no second agent, no per-seat bill — errors and vitals land in the same Logs and metrics pipeline you already use.

Sentry-SDK error ingest

Keep the free, open-source @sentry/* SDK exactly as it is. Change one value — the DSN — to point at us. The unmodified SDK then ships its error events to us instead of Sentry, and they flow straight into the Error-tracking view you already have.

DSN format

https://<obs_PAT>@api.24observe.com/<project>
  • <obs_PAT> is a 24Observe Personal Access Token with the logs:write scope. Like a normal Sentry DSN key, it's a public, write-only credential — safe to ship in your application bundle. It can write errors; it can't read your data.
  • <project> can be any identifier you like — it labels the source of the events.

Under the hood, the unmodified SDK POSTs its envelope to /api/<project>/envelope/?sentry_key=<obs_PAT> — the standard Sentry envelope endpoint. You don't call this directly; the SDK does, the moment you set the DSN.

JavaScript

import * as Sentry from '@sentry/node'; // or @sentry/browser, etc.

Sentry.init({
  dsn: 'https://obs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@api.24observe.com/my-app',
});

// Then capture as usual — no other changes.
Sentry.captureException(new Error('something broke'));

This works with any Sentry SDK — Node, browser, Python, and the rest — because they all speak the same envelope protocol. Initialize with the 24Observe DSN and your existing capture calls just work.

What we do with it

We translate each Sentry error event into one of our error-level log events. The message becomes "ExceptionType: value" — the same string Sentry groups on — so it fingerprints and groups exactly the way you're used to. From there, everything downstream works unchanged:

  • Error fingerprint grouping — repeated occurrences collapse into a single row with first-seen, last-seen, and a running count in the Error-tracking view.
  • Search — errors are queryable alongside the rest of your logs (KQL-lite, facets, the lot).
  • Redaction + quota — the same privacy and volume controls that govern your logs apply automatically; no separate config.

The result: Sentry-style error grouping inside the same Logs pipeline you already pay for, with no separate per-seat bill. Grouped errors surface in the dashboard under Logs → Error tracking.

Real User Monitoring (Core Web Vitals)

Keep Google's free, open-source web-vitals library on your site. Report its readings to us and they become first-class metrics — queryable and alertable like anything else. No new SDK, no bundle bloat.

Endpoint

POST https://api.24observe.com/api/v1/rum/vitals?key=<obs_PAT>

<obs_PAT> is a Personal Access Token with the metrics:write scope — again a public, write-only key, safe to ship in the page. The standard pattern is navigator.sendBeacon(url, JSON.stringify(payload)), which fires reliably even as the page is unloading.

Payload shapes

The endpoint accepts three shapes, so you can wire it up however the library hands you data:

  • Batched object: { service, url, metrics: [ { name, value, rating?, id?, navigationType? } ] }
  • Bare array of metric objects.
  • Single metric object — the exact shape the web-vitals onLCP / onCLS / … callbacks hand you, so you can forward each reading as it arrives.

Metric names

  • LCP, FCP, INP, FID, TTFB — recorded in milliseconds.
  • CLS — the unitless cumulative layout-shift score.

Each reading becomes a metric named web_vitals.lcp, web_vitals.cls, and so on — queryable and alertable like any other metric in 24Observe. service defaults to the URL host when omitted, so a single line of config tags every reading by site.

Response + CORS

  • Returns 202.
  • sendBeacon is a simple request and needs no CORS preflight — it just works from any page.
  • A fetch(url, { keepalive: true }) reporter from any origin works too, if you prefer fetch over beacon.

JavaScript

import { onLCP, onCLS, onINP, onFCP, onTTFB } from 'web-vitals';

const URL = 'https://api.24observe.com/api/v1/rum/vitals?key=obs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

function report(metric) {
  // metric = { name, value, rating, id, navigationType } from web-vitals
  navigator.sendBeacon(URL, JSON.stringify(metric));
}

// Wire each Core Web Vital to the reporter.
onLCP(report);
onCLS(report);
onINP(report);
onFCP(report);
onTTFB(report);

Prefer to batch? Collect the callbacks into an array and send a single { service, url, metrics: [...] } beacon on visibilitychange — the endpoint accepts that shape directly.

Ready to build with 24Observe?

Explore live telemetry, zero-friction integration, and automated SOC investigation.

+ Get Free Trial / Demo