rum-sdk
v1.0.0
Published
Lightweight Real User Monitoring SDK for More Retail frontend apps
Downloads
7
Maintainers
Readme
@more-retail/rum-sdk
Lightweight Real User Monitoring SDK for More Retail frontend apps. Drop this into any React app to get full observability: interactions, API calls, errors, and performance — with zero config.
Installation
# From the monorepo (local package)
npm install ../sdk
# Or via npm link during development
cd sdk && npm link
cd ../picker-app && npm link @more-retail/rum-sdkQuick Start
1. Initialize in src/index.jsx or src/App.jsx
import RumSDK from "@more-retail/rum-sdk";
RumSDK.init({
appId: "picker-app", // identifies which app in the dashboard
endpoint: process.env.REACT_APP_RUM_ENDPOINT, // your ingest API URL
debug: process.env.NODE_ENV === "development", // logs events to console
});2. Or use the React hook for tighter integration
import { useRum, RumErrorBoundary } from "@more-retail/rum-sdk";
function App() {
const { id: userId, role } = useAuthUser(); // your auth hook
const { captureError, track } = useRum({
appId: "picker-app",
endpoint: process.env.REACT_APP_RUM_ENDPOINT,
user: { id: userId, role }, // auto-identified when available
debug: process.env.NODE_ENV !== "production",
enabled: process.env.NODE_ENV !== "test", // disable in Jest
});
return (
<RumErrorBoundary fallback={<AppCrashScreen />}>
<RouterProvider router={router} />
</RumErrorBoundary>
);
}What Gets Tracked Automatically
| Category | Events Captured |
|---|---|
| Interactions | All clicks — element tag, selector, label, position |
| Navigation | Page views, time-on-page, SPA route changes |
| API Calls | URL, method, status, duration, slow flag |
| JS Errors | window.onerror, unhandled rejections, console.error |
| Performance | TTFB, FCP, LCP, FID, CLS, Long Tasks, page load |
Configuration Options
RumSDK.init({
appId: string, // REQUIRED — "picker-app" | "manager-dashboard"
endpoint: string, // REQUIRED — "https://rum-api.more.com/ingest"
userId?: string, // Set if user is known at init time
userMeta?: object, // { name, role, email, ... }
debug?: boolean, // Default: false — logs events to console
capturePayloads?: boolean, // Default: false — include request/response bodies
ignoredUrls?: string[], // Skip tracking for URL substrings e.g. ["/auth/token"]
slowThreshold?: number, // Default: 1000ms — flag API calls slower than this
trackers?: { // Opt-out specific trackers
clicks?: boolean, // Default: true
navigation?: boolean, // Default: true
network?: boolean, // Default: true
errors?: boolean, // Default: true
performance?: boolean, // Default: true
},
});Manual APIs
Identify the user (after login)
RumSDK.identify(user.id, {
name: user.displayName,
role: user.role, // "picker" | "manager"
storeId: user.storeId,
});Capture an error manually
try {
await assignOrder(orderId);
} catch (err) {
RumSDK.captureError(err, { orderId, pickerId });
}Track a custom business event
// Track domain-specific actions for your dashboard
RumSDK.track("order_picked", { orderId, itemCount, timeTaken });
RumSDK.track("barcode_scan_failed", { barcode, reason });
RumSDK.track("order_reassigned", { orderId, fromPicker, toPicker });Reset on logout
RumSDK.reset(); // clears user identityTagging Elements in JSX
Add data-rum-id to important elements so they're easily identifiable in the dashboard:
<button data-rum-id="confirm-order" data-rum-label="Confirm Order">
Confirm Order
</button>
<input
data-rum-id="barcode-scan-input"
placeholder="Scan barcode..."
/>Event Schema
Every event sent to the ingest API has this shape:
{
"type": "interaction | page_view | api_call | js_error | performance | custom",
"appId": "picker-app",
"timestamp": "2024-01-15T10:30:00.000Z",
"sessionId": "ses_k7x2m9p1",
"deviceId": "dev_q3r8n2x5",
"sessionAge": 45230,
"userId": "usr_123",
"data": { ... }
}Privacy Considerations
- No PII by default — user-typed text is never captured from inputs.
- Payload capture is opt-in —
capturePayloads: falseby default. - URL normalization —
/api/orders/12345→/api/orders/:idto prevent cardinality explosion. - Ignore sensitive endpoints — use
ignoredUrls: ["/auth/token", "/users/password"]. - The ingest endpoint itself is automatically excluded from network tracking.
Architecture
Your React App
│
├── RumSDK.init()
│ │
│ ├── ClickTracker → window.addEventListener("click")
│ ├── NavigationTracker → history.pushState patch + popstate
│ ├── NetworkTracker → window.fetch + XMLHttpRequest patch
│ ├── ErrorTracker → window.onerror + unhandledrejection
│ └── PerformanceTracker → PerformanceObserver (FCP/LCP/CLS/FID)
│
└── Transport (event queue)
│
├── Batches events (max 20 / 5s interval)
├── Flushes on visibilitychange/pagehide via sendBeacon
└── Retry with exponential backoff (3 attempts)