Skip to content

SmooAI/observability

Repository files navigation

@smooai/observability — Error capture and grouping, your backend only.

npm Smoo AI license

TypeScript CI downloads

Features  ·  Install  ·  Usage  ·  Architecture  ·  Platform


The error-tracking platform we wished was already in our stack. You ship a deploy; somewhere out there a webpack chunk is 404'ing for one user and your sign-in page is silently broken. Your error boundary console.errors into the void, and your only signal is the support ticket that arrives forty minutes later. @smooai/observability fills that gap: automatic capture and grouping across every runtime, your events going to your Smoo backend only.

✨ Features

Browser

  • 🛑 Uncaught exceptionswindow.onerror, unhandledrejection, console.error taps
  • 🍞 Breadcrumbsfetch / XHR calls, click events, navigation events, custom traces
  • 🧭 Release tagging — every event ships with the git sha so symbolication is one click away
  • 🗺️ Source maps — uploaded to S3 at build time, applied lazily on view
  • 🚪 Beacon flush — events queued at pagehide ship via navigator.sendBeacon
  • 💾 Offline queue — events captured while offline persist in IndexedDB and retry on focus
  • 🔐 PII scrubpassword, token, Bearer ..., and friends are redacted before transport

Node

  • 🛑 uncaughtException + unhandledRejection with full stack
  • 🪢 Hono middleware — captures errors propagating to the global onError handler
  • 🧠 AsyncLocalStorage scope — per-request user, tags, breadcrumbs without leaking across requests
  • 📦 Batched transportundici with retry / backoff
  • 🔐 Same PII scrub policy as the browser

React / Next.js

  • 🧱 <ErrorBoundary> — drop-in component, captures and renders your fallback
  • useErrorHandler() — for async event-handler errors React boundaries can't see
  • 🏗️ withSmooObservability(nextConfig) — enables production browser source maps and uploads them in CI
  • 🛡️ <RootErrorBoundary> — drop into app/global-error.tsx / app/error.tsx

What does NOT get captured

  • console.log / console.info / console.warn — only console.error is tapped, and that's opt-out
  • HTTP request bodies — only method, path, status, and duration appear in breadcrumbs
  • Anything matching the PII scrub regex unless you explicitly allowlist it

📦 Install

pnpm add @smooai/observability                      # core (browser + Node)
pnpm add @smooai/observability-react                # React bindings
pnpm add @smooai/observability-next                 # Next.js wrapper

or with npm / yarn / bun — same names.

Package npm Purpose
@smooai/observability npm Core client — browser + Node universal
@smooai/observability-react npm React <ErrorBoundary> + useErrorHandler
@smooai/observability-next npm Next.js wrapper + sourcemap upload

🚀 Usage

Next.js

// next.config.ts
import { withSmooObservability } from '@smooai/observability-next/build';

export default withSmooObservability(
    {
        /* your config */
    },
    {
        org: 'your-org',
        release: process.env.GITHUB_SHA ?? 'dev',
        uploadSourcemaps: process.env.CI === 'true',
    },
);
// instrumentation.ts
export async function register() {
    const { Client } = await import('@smooai/observability');
    Client.init({
        dsn: process.env.OBSERVABILITY_INGEST_URL!,
        environment: process.env.STAGE,
        release: process.env.GITHUB_SHA ?? 'dev',
    });
}
// app/global-error.tsx
'use client';
import { RootErrorBoundary } from '@smooai/observability-next';

export default function GlobalError({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {
    return (
        <html>
            <body>
                <RootErrorBoundary error={error} resetError={reset} fallback={<YourBrandedError onRetry={reset} />} />
            </body>
        </html>
    );
}

Browser SPA

import { Client } from '@smooai/observability';

Client.init({
    dsn: process.env.SMOO_OBSERVABILITY_DSN!,
    environment: 'production',
    release: import.meta.env.VITE_GIT_SHA,
});

Client.setUser({ id: 'user_abc', orgId: 'org_xyz' });

Node / Hono

import { Client, observabilityMiddleware } from '@smooai/observability/node';

Client.init({
    dsn: process.env.OBSERVABILITY_INGEST_URL!,
    environment: process.env.STAGE!,
    release: process.env.LAMBDA_FUNCTION_VERSION ?? 'dev',
});

app.use('*', observabilityMiddleware());

Multi-language support

The same ingest contract (POST /webhooks/observability/{org_id}/{token} with type: 'error') accepts events from any language. Follow-up SDKs:

  • 🐍 Pythonsmooai-observability on PyPI (tracked in SMOODEV-1067 follow-ups)
  • 🦀 Rustsmooai-observability crate (tracked in SMOODEV-1067 follow-ups)
  • 🐹 Gogithub.com/smooai/observability-go (tracked in SMOODEV-1067 follow-ups)
  • 💠 .NETSmooAI.Observability on NuGet (tracked in SMOODEV-1067 follow-ups)

📖 Architecture

The SDK is intentionally thin. It captures, batches, redacts PII, and POSTs to a Smoo ingest endpoint. All of the heavy lifting — fingerprint grouping, source-map symbolication, dashboards, alerts, retention — lives in the Smoo platform.

%%{init: {'theme':'base','themeVariables':{
  'background':'#020618','primaryColor':'#0b1426','primaryTextColor':'#e6edf6','primaryBorderColor':'#2b3a52',
  'lineColor':'#7c8aa0','secondaryColor':'#0b1426','tertiaryColor':'#0b1426','fontFamily':'ui-sans-serif, system-ui, sans-serif',
  'clusterBkg':'#0b1426','clusterBorder':'#22304a'}}}%%
flowchart LR
  REACT["observability-react<br/>ErrorBoundary · useErrorHandler"] -->|wraps| CORE
  NEXT["observability-next<br/>withSmooObservability · sourcemaps"] -->|wraps| CORE
  CORE["@smooai/observability<br/>capture · scope · scrub · batch"]
  CORE -->|"POST /webhooks/observability/{org}/{token}<br/>Bearer B2M JWT · gzipped JSON"| INGEST[("Smoo platform<br/>group · symbolicate · alert")]

  classDef warm fill:#f49f0a,stroke:#ff6b6c,color:#1a0f00;
  classDef teal fill:#00a6a6,stroke:#00c2c2,color:#011;
  class CORE warm
  class INGEST teal
Loading

Full backend architecture: SmooAI/smooai → docs/Architecture/Observability-Architecture.md.

📖 Built with

  • TypeScript — strict mode, ESM-only, dual browser/Node entries via package exports map
  • tsup — bundling, dual ESM/types output, sourcemaps
  • turborepo — fast pipeline across the three packages
  • vitest — unit tests
  • changesets — versioning + npm publish via GitHub Actions

📖 Privacy & telemetry

This SDK is opinionated about privacy:

  • We never capture form bodies, request bodies, or response bodies by default
  • We never capture cookies
  • We never send anything to a third-party service — your events go to your Smoo backend only
  • PII scrubbing is enabled by default and can be tuned per-tenant

📖 Status

0.1.0 — types and client skeleton are stable. The capture handlers, stack parsers, transport, and source-map upload land incrementally in upcoming 0.x releases. The backend ingest, fingerprint grouping, dashboard, and customer-org rollout live in the SmooAI/smooai monorepo and are tracked under SMOODEV-1067.

🧩 Part of Smoo AI {#part-of-smoo-ai}

@smooai/observability is built and open-sourced by Smoo AI — the AI-powered business platform with AI built into every product: CRM, customer support, campaigns, field service, observability, and developer tools.

🤝 Contributing

Issues and PRs welcome. Maintained by Brent Rager — email · LinkedIn · BlueSky · TikTok · Instagram.

📄 License

MIT © Smoo AI, Inc. See LICENSE.

(back to top)


Built by Smoo AI — AI built into every product.

About

Sentry-like error tracking SDK for the Smoo AI platform — browser, Node, React, and Next.js. The open-core companion to the hosted error + metrics dashboards.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors