Sitemap
Ashish Kumar

Ashish Kumar

Client-side Observability

9 min readJan 15, 2026

--

Press enter or click to view image in full size

Till now, we’ve only focused on the server side observability in this journey. But what about the user’s actual experience? When a user clicks a button and nothing happens, or a page loads slowly, the server logs might show “200 OK” while the user experiences frustration.

Client-side monitoring bridges this gap, giving us visibility into real user interactions, frontend errors, and performance bottlenecks happening right in the browser.

Sentry, a tool we are going to use throughout this blog. It primarily captures error (events) occurred at client side using sdk & report to centralized server. In addition to events, it also captures logs, metrics and traces.

Press enter or click to view image in full size

As a UI developer, focused on building smooth, responsive, and delightful user interfaces. Modern day client side observability tools offer dozens of features, but here covering few of them that will make the biggest difference in day-to-day work.

Events:

To make the concepts in this blog easier to grasp, I’ve created a small React application for demonstration. This web app asks users to enter a number, which it uses to create an array and calculate its estimated memory usage. Here are some of the real events that were captured while testing it, let’s walk through each one —

Press enter or click to view image in full size

1. Capturing Client-Side Errors

Let’s say building app in React, and need to validate user input. If a user enters 0 as the array length, it will raise an exception. This error occurs entirely in the browser, this allows to see exactly what went wrong on the client side — like validation failures errors — even when server logs are clean.

// ./src/App.jsx
try {
length = BigInt(input);
if (length === 0n) {
throw new Error('Array length cannot be zero');
}
} catch (err) {
// Optionally report to Sentry
Sentry.captureException(err);
setError(err.message);
return;
}

Here’s an snippet ./src/App.jsx of how an error gracefully can be handled while also reporting it to Sentry. By capturing errors this way, ensure that no frontend issue goes unnoticed, helping deliver a more reliable user experience.

2. Capturing “Unhandled” Client-Side Errors

Beyond explicit error handling, there are numerous runtime errors that can slip through try-catch blocks — like RangeError, TypeError from undefined properties, or ReferenceError from missing variables. These unpredicted errors often occur in production when users interact with app in unexpected ways. Sentry can captures these unhandled exceptions, promise rejections, and JS runtime errors, giving visibility into issues developer didn't anticipate.

Press enter or click to view image in full size

Imagine users input “4294967296” and it pass validation but JS arrays have a maximum allowed length because the length property is stored as an unsigned 32-bit integer. That means valid array lengths are in the range 0 to ²³²-1 (i.e., 0 to 4294967295)

By monitoring unhandled errors, can identify and fix edge cases with try-catch, improving application stability and user trust — even for issues beyond developer’s initial assumptions.

3. Capturing Non-Error Events for Evaluation

Sometimes need visibility into important application flows that aren’t errors but are crucial for understanding user behavior or system performance. Sentry can capture custom events (Sentry.captureMessage) that help evaluate how logic executes in production. This is valuable for tracking successful operations, monitoring business-critical flows, or identifying areas that may need optimization later.

// ./src/App.jsx
Sentry.captureMessage("Array memory calculation completed", {
level: 'info',
extra: {
arrayLength: lenNum,
memoryReadable: `${hr.value} ${hr.unit}`,
}
});

These captured events appear in Sentry alongside errors, giving a complete picture of what’s happening in application — not just what’s breaking. Later analyze these events to identify patterns, optimize performance, or refine user flows that may appear messy or inefficient in real-world usage.

4. Rage Click

When users repeatedly click the same button or element in frustration, it often indicates a poor user experience — perhaps the interface is unresponsive, feedback is unclear, or an action isn’t working as expected.

Press enter or click to view image in full size

Sentry can automatically detect these “rage click” patterns, where a user clicks an element multiple times within a short time frame. Actual reason has been captured using sdk and reported, can be seen highlighted in red.

5. Downtime

Sometimes the problem is broader, entire application or key endpoints may be down. Sentry can monitor uptime / detect downtime events for specific domain / url, alerting when users can’t access service at all.

Traces:

While errors tell what broke, distributed traces show where bottlenecks occur — across entire application flow. Sentry’s tracing capabilities let user to monitor journeys from the initial click through backend processing and back to the UI response, creating a complete timeline of events.

Each trace receives a unique ID that appears alongside results, allowing to correlate user actions with backend performance data. When errors occur, Sentry automatically attaches these trace IDs, so developer can jump from an error directly to the full transaction that caused it.

Sentry supports both automatic and manual instrumentation for tracing, enabling you to capture performance data across your stack with flexibility and precision.

Auto tracing —

Press enter or click to view image in full size

Use automatic tracing when you need broad, out-of-the-box performance visibility without writing extra code.

Manual tracing —

Use manual tracing when you need to instrument specific, custom, or critical sections of your application for detailed insight —

Press enter or click to view image in full size
//1. Input Validation - checking user input
const validationSpan = addManualSpan('manual.input_validation', { input }, 'validation');

//2. Array Creation - initializing the data structure
const arraySpan = addManualSpan('manual.array_creation', { length: lenNum }, 'process');

//3. Memory Calculation - performing the computation
const calcSpan = addManualSpan('manual.memory_calculation', { length: lenNum }, 'compute');

//4. Result Processing - formatting and displaying output
const resultSpan = addManualSpan('manual.result_processing', { bytes: bytes.toString(), readable: `${hr.value} ${hr.unit}`}, 'process');

Source Maps: Translating Minified Code Back to Readable Code

Press enter or click to view image in full size

When React application is built for production, clean, readable source code gets bundled, minified, and optimized — turning meaningful variable names and line numbers into cryptic, compressed JavaScript. While this improves performance, it makes debugging nearly impossible when errors occur in production.

// After source map translation
Error at ./src/App.jsx:70 in processCalculate: "Array length cannot be zero"

Source maps are companion files that act as a “translation dictionary” between minified production code and original development source code. Sentry uses these maps to show errors in their original context:

How It Works?

Vite configuration automatically generates source maps during the build process —

// vite.config.js
build: {
sourcemap: true, // ✅ Required for source maps
}

The Sentry Vite plugin then uploads these source maps to Sentry’s servers during deployment:

sentryVitePlugin({
org: process.env.VITE_SENTRY_ORG,
project: process.env.VITE_SENTRY_PROJECT,
release: {
name: process.env.VITE_RELEASE_NAME,
dist: process.env.VITE_SENTRY_DIST,
},
})

When an error occurs in production, Sentry:

  1. Receives the stack trace from minified code
  2. Uses the uploaded source maps to “reverse-engineer” the original file names, line numbers, and even variable names
  3. Displays the error in the context of actual source code

This means debugging production issues as if running the code locally — seeing the exact line that failed (./src/App.jsx:70), the function where it occurred (processCalculate), and the actual error message that makes sense as a developer. Without source maps, developer'd be left with meaningless minified references; with them, get actionable insights that match development experience.

Session Replays:

While error reports and traces tell what went wrong and where, Session Replays show how it happened — literally. This powerful feature records and replays real user sessions, giving a video-like playback of everything users see and do in application: mouse movements, clicks, form inputs, and UI interactions.

Press enter or click to view image in full size

What Session Replays Capture:

  • UI Interactions: Every click, scroll, and navigation
  • Network Activity: API calls and their timing
  • Console Output: Logs and warnings from the browser console
  • Performance Metrics: Render times and layout shifts
  • Error Context: What users were doing right before an error occurred

Uptime:

Press enter or click to view image in full size

Unlike application errors that affect individual users, downtime impacts everyone trying to access your service. When UI goes down or any DNS issue or Response time, users experience complete service interruption — which often translates to immediate business impact, lost revenue, and damaged reputation.

Get Ashish Kumar’s stories in your inbox

Join Medium for free to get updates from this writer.

Sentry’s uptime monitoring continuously checks your endpoints from multiple global locations, tracking:

  • HTTP response codes (200 OK, 500 errors, timeouts)
  • Response times (latency across different regions)
  • DNS resolution (can users find your service?)
  • SSL/TLS validity (are certificates working?)

Challenges in client side observability:

1. Limited Internet Bandwidth at the End-User

When end users have poor network connections (slow mobile data, rural areas, congested Wi-Fi), every kilobyte matters. Traditional monitoring solutions that send verbose error reports, large session replays, or frequent heartbeat signals can:

  • Consume valuable data plans, especially for mobile users
  • Increase page load times on already-slow connections
  • Cause timeouts or failures in the monitoring itself
  • Degrade user experience further when they’re already struggling

Error Deduplication (Intelligent Throttling and Sampling): Sentry addresses this through smart data management. Instead of sending the same error hundreds of times, Sentry uses fingerprinting to identify duplicates and reports only unique errors or at controlled intervals. Custom implementation in Sentry.js shows this beautifully:

// Custom deduplication strategy reports only 1st, 11th, 21st... occurrences
const shouldReportError = (fingerprint) => {
const count = incrementErrorCount(fingerprint);
return count === 1 || (count - 1) % 10 === 0; // Smart throttling
};

Output in browser console —

Press enter or click to view image in full size

Recorded in Sentry server, let’s verify—

Press enter or click to view image in full size

Compressed Payloads: Sentry compresses error reports and session data before transmission, significantly reducing bandwidth usage without losing diagnostic value.

Configurable Sampling: You control how much data gets sent —

tracesSampleRate: 1.0, // Sample 100% for critical paths
replaysSessionSampleRate: 0.1, // Sample only 10% of sessions
replaysOnErrorSampleRate: 1.0, // But capture 100% of sessions with errors

2. Personally Identifiable Information (PII) Protection

Events metadata & Session replays and error reports can inadvertently capture sensitive user data:

  • Form inputs (passwords, credit cards, personal messages)
  • URL parameters (session tokens, user IDs)
  • Page content (names, addresses, private messages)
  • Cookies and localStorage data

Capturing PII violates privacy regulations (GDPR, CCPA, HIPAA) and erodes user trust. It is recommended to store only generic info like browser details, OS details, device details, user IP geo location etc.

Press enter or click to view image in full size

Automatic Data Masking: Sentry provides multiple layers of protection. Configure what gets masked in session replays.

const replay = Sentry.replayIntegration({
maskAllText: false, // Show UI text for debugging
maskAllInputs: true, // Hide all form inputs (passwords, etc.)
blockAllMedia: true, // Block images/videos that may contain PII
});

Compliance-First Architecture:

  • Data Minimization: Only collect what’s needed for debugging
  • Purpose Limitation: Use data only for error diagnostics
  • Storage Limitation: Automatic data retention policies
  • User Control: Provide opt-out mechanisms for users

SLA —

Press enter or click to view image in full size

Sentry drives SLA compliance by instantly measuring client-side failures to resolve issues faster and hit MTTR goals, supported by Uptime metrics for UI availability / DNS / Response time / SSL certs expiry time to ensure consistent end-to-end availability.

--

--