https://github.com/monoscope-tech/monoscope-web
Browser client sdk for otel instrumentation and session replays
https://github.com/monoscope-tech/monoscope-web
Last synced: about 2 months ago
JSON representation
Browser client sdk for otel instrumentation and session replays
- Host: GitHub
- URL: https://github.com/monoscope-tech/monoscope-web
- Owner: monoscope-tech
- License: mit
- Created: 2025-07-25T17:59:01.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2026-04-14T18:02:02.000Z (2 months ago)
- Last Synced: 2026-04-14T19:29:46.611Z (2 months ago)
- Language: TypeScript
- Size: 129 KB
- Stars: 2
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Monoscope Browser SDK
The **Monoscope Browser SDK** is a lightweight JavaScript library for adding **session replay**, **performance tracing**, **error tracking**, and **web vitals** to your web applications.
When used together with the [Monoscope Server SDKs](https://monoscope.tech/docs/sdks/), you gain **end-to-end observability** — seamlessly connecting user interactions in the browser to backend services, APIs, and databases.
This means you can:
- **Replay user sessions** to see exactly what happened.
- **Trace requests** from the frontend, through your backend, and into your database.
- **Capture errors and console logs** with full context and breadcrumbs for faster debugging.
- **Collect Web Vitals** (CLS, INP, LCP, FCP, TTFB) automatically.
- **Track SPA navigations** across pushState, replaceState, and popstate.
---
## Installation
Install via **npm/bun**:
```bash
npm install @monoscopetech/browser
```
Or include it directly in your HTML using a `` tag:
```html
<script src="https://unpkg.com/@monoscopetech/browser@latest/dist/monoscope.min.js">
```
---
## Quick Start
Initialize Monoscope with your **API key** (found in your project settings):
```javascript
import Monoscope from "@monoscopetech/browser";
const monoscope = new Monoscope({
apiKey: "YOUR_API_KEY",
});
// Identify the current user
monoscope.setUser({
id: "user-123",
email: "user@example.com",
});
```
On `localhost`, debug mode is auto-enabled — you'll see a status overlay and console diagnostics. Call `monoscope.test()` to verify your setup:
```javascript
const result = await monoscope.test();
console.log(result); // { success: true, message: "Test span sent successfully." }
```
---
## Configuration
The `Monoscope` constructor accepts the following options:
| Name | Type | Description |
| --- | --- | --- |
| `apiKey` | `string` | **Required** – Your Monoscope API key (found in project settings). |
| `serviceName` | `string` | Service name. Defaults to `location.hostname`. |
| `projectId` | `string` | Deprecated alias for `apiKey`. |
| `exporterEndpoint` | `string` | Endpoint for exporting traces. Defaults to Monoscope's ingest endpoint (`/v1/traces`). |
| `metricsExporterEndpoint` | `string` | Endpoint for exporting metrics (web vitals). Defaults to the trace endpoint with `/v1/traces` → `/v1/metrics`. |
| `propagateTraceHeaderCorsUrls` | `RegExp[]` | URL patterns where trace context headers should be propagated. Defaults to same-origin only. |
| `resourceAttributes` | `Record` | Additional OpenTelemetry resource attributes. |
| `instrumentations` | `unknown[]` | Additional OpenTelemetry instrumentations to register. |
| `replayEventsBaseUrl` | `string` | Base URL for session replay events. Defaults to Monoscope's ingest endpoint. |
| `enableNetworkEvents` | `boolean` | Include network timing events in document load spans. Default `false`. |
| `user` | `MonoscopeUser` | Default user information for the session. |
| `debug` | `boolean` | Enable debug logging to the console. Auto-enabled on `localhost`. |
| `sampleRate` | `number` | Trace sampling rate from `0` to `1`. Default `1` (100%). |
| `replaySampleRate` | `number` | Replay sampling rate from `0` to `1`. Default `1` (100%). |
| `enabled` | `boolean` | Whether to start collecting data immediately. Default `true`. |
| `resourceTimingThresholdMs` | `number` | Minimum resource duration (ms) to report. Default `200`. |
| `captureResourceTiming` | `boolean` | Emit a span per resource over the threshold. Default `false` (high volume — opt-in). |
| `captureLongTasks` | `boolean` | Emit a span per long task (>50ms blocked main thread). Default `true`. |
| `captureWebVitals` | `boolean` | Capture Core Web Vitals (LCP/INP/CLS/FCP/TTFB) as OTel metrics. Default `true`. |
| `enableUserInteraction` | `boolean` | Trace user clicks/submits, linking them to downstream network calls. Default `true`. |
---
### User Object
The `MonoscopeUser` object can contain:
| Name | Type | Description |
| --- | --- | --- |
| `email` | `string` | User's email address. |
| `full_name` | `string` | User's full name. |
| `name` | `string` | User's preferred name. |
| `id` | `string` | User's unique identifier. |
| `roles` | `string[]` | User's roles. |
Additional string-keyed attributes are also accepted and forwarded as custom user attributes.
---
## API
### `setUser(user: MonoscopeUser)`
Associates the given user with the current session. Can be called at any time.
```javascript
monoscope.setUser({
id: "user-123",
email: "user@example.com",
});
```
### `startSpan(name: string, fn: (span: Span) => T): T`
Creates a custom OpenTelemetry span. The span is automatically ended when the function returns. Supports async functions.
```javascript
monoscope.startSpan("checkout", (span) => {
span.setAttribute("cart.items", 3);
// ... your logic
});
```
### `recordEvent(name: string, attributes?: Record)`
Records a custom event as a span with the given attributes.
```javascript
monoscope.recordEvent("button_click", {
"button.name": "subscribe",
"button.variant": "primary",
});
```
### `getSessionId(): string`
Returns the current session ID.
### `getTabId(): string`
Returns the current tab ID (unique per browser tab).
### `test(): Promise<{success: boolean, message: string}>`
Sends a test span and flushes it to verify the connection is working.
```javascript
const result = await monoscope.test();
console.log(result.success); // true if the span was accepted
```
### `enable()` / `disable()`
Dynamically enable or disable all data collection.
```javascript
monoscope.disable(); // pause collection
monoscope.enable(); // resume collection
```
### `isEnabled(): boolean`
Returns whether the SDK is currently enabled.
### `destroy(): Promise`
Stops all collection, flushes pending data, and shuts down the OpenTelemetry provider. Call this when your application is being torn down.
```javascript
await monoscope.destroy();
```
---
## React / Next.js
For React apps, use the `@monoscopetech/browser/react` subpath export for idiomatic integration with hooks and context.
```tsx
import { MonoscopeProvider, useMonoscope, useMonoscopeUser, MonoscopeErrorBoundary } from "@monoscopetech/browser/react";
// Wrap your app with MonoscopeProvider
function App() {
return (
Something went wrong}>
);
}
// Access the instance via hook
function MyApp() {
const monoscope = useMonoscope();
// Reactively set user when auth state changes
useMonoscopeUser(currentUser ? { id: currentUser.id, email: currentUser.email } : null);
return
...;
}
```
**Next.js App Router**: The provider includes `"use client"` — import it in a client component or your root layout.
### React API
| Export | Description |
| --- | --- |
| `MonoscopeProvider` | Context provider. Creates and destroys the SDK instance. Strict Mode safe. |
| `useMonoscope()` | Returns the `Monoscope` instance (or `null` during SSR). |
| `useMonoscopeUser(user)` | Calls `setUser` reactively when the user object changes. |
| `MonoscopeErrorBoundary` | Error boundary that reports caught errors to Monoscope. Accepts `fallback` prop. |
---
## Custom Instrumentation
### Custom Spans
Use `startSpan()` to instrument specific operations with timing and attributes. It supports both sync and async functions — the span is automatically ended when the function returns or the promise resolves.
```javascript
// Sync
monoscope.startSpan("parse-config", (span) => {
span.setAttribute("config.size", rawConfig.length);
return parseConfig(rawConfig);
});
// Async
const data = await monoscope.startSpan("fetch-dashboard", async (span) => {
span.setAttribute("dashboard.id", dashboardId);
const res = await fetch(`/api/dashboards/${dashboardId}`);
span.setAttribute("http.status", res.status);
return res.json();
});
```
### Custom Events
Use `recordEvent()` to track discrete events without wrapping a code block:
```javascript
monoscope.recordEvent("feature_flag_evaluated", {
"flag.name": "new-checkout",
"flag.value": true,
});
```
### React Components
Use the `useMonoscope()` hook to instrument React components:
```tsx
import { useMonoscope } from "@monoscopetech/browser/react";
function CheckoutButton() {
const monoscope = useMonoscope();
const handleClick = () => {
monoscope?.startSpan("checkout.submit", async (span) => {
span.setAttribute("cart.items", cartItems.length);
await submitOrder();
});
};
return Checkout;
}
```
### Additional OpenTelemetry Instrumentations
Pass extra OTel instrumentations via the `instrumentations` config to extend tracing beyond the built-in set:
```javascript
import { LongTaskInstrumentation } from "@opentelemetry/instrumentation-long-task";
const monoscope = new Monoscope({
apiKey: "YOUR_API_KEY",
instrumentations: [new LongTaskInstrumentation()],
});
```
---
## Features
### Session Replay
Captures DOM changes via [rrweb](https://github.com/rrweb-io/rrweb) to enable full session replay. Sensitive inputs are masked by default.
### Error Tracking
Automatically captures `window.onerror`, unhandled promise rejections, and `console.error` calls with stack traces and breadcrumbs.
### SPA Navigation Tracking
Detects client-side navigations (`pushState`, `replaceState`, `popstate`) and emits navigation spans.
### Web Vitals
Collects Core Web Vitals (CLS, INP, LCP) and additional metrics (FCP, TTFB) via the [web-vitals](https://github.com/GoogleChrome/web-vitals) library.
### Performance Observers
Reports long tasks and slow resource loads as spans for performance debugging.
### Session Management
Sessions persist across page reloads via `sessionStorage` and automatically rotate after 30 minutes of inactivity.
---
## License
This SDK is licensed under the [MIT License](LICENSE).