Getting an error report three weeks after your app broke is not a plan. The only way to catch production failures in real time is to add error tracking to your application — and the good news is it's straightforward once you understand the pattern. Every SDK, across every language and framework, follows the same fundamental steps: install the SDK package, initialize it once at startup with a DSN (a unique endpoint), and errors flow in automatically from that moment on. No manual wrapping, no boilerplate, just one setup that works.
This guide walks you through that universal pattern and shows you exactly how to implement it in whatever tech stack you're running. By the end, errors from your production code will be grouped, contextual, and waiting on your dashboard instead of hiding in user complaints.
How SDK-based error tracking works
Modern error trackers work by instrumenting your application at startup. You install a lightweight SDK, give it a destination to report to (via a DSN), and it hooks into your runtime's global error handlers. From that point forward, every uncaught exception, failed promise, or runtime crash is captured automatically and sent to your error tracker before your app even crashes the user's browser or request.
The beauty of this approach is that you don't need to wrap functions in try-catch blocks or scatter error reporting code everywhere. The SDK does it for you. This is why error tracking is so much more effective than hoping developers manually log errors — it catches things that never hit your logs in the first place.
Install the SDK for your runtime
Every major language has a Sentry SDK, and since LightTrace is Sentry-SDK-compatible, you can use the unmodified official package. Here are the most common ones:
Node.js / Express:
npm install @sentry/node
React / Browser:
npm install @sentry/react
Python:
pip install sentry-sdk
Java / Spring Boot:
<dependency>
<groupId>io.sentry</groupId>
<artifactId>sentry-spring-boot-starter</artifactId>
<version>7.0.0</version>
</dependency>
Go:
go get github.com/getsentry/sentry-go
Ruby on Rails:
gem "sentry-ruby"
gem "sentry-rails"
That's step one. The SDK package is tiny and ships with zero dependencies in most languages, so it's safe to add to any production application.
Initialize the SDK at startup
The initialization pattern is identical across all languages. You create a Sentry init call once, at the very start of your application, before any business logic runs. This is where you pass the DSN (which points to your LightTrace instance) and set optional configuration like environment, release, and sampling.
Node.js:
import * as Sentry from "@sentry/node";
Sentry.init({
dsn: "https://<key>@your-lighttrace-host/1",
environment: process.env.NODE_ENV,
release: "api@1.2.3",
tracesSampleRate: 1.0,
});
// Your app code runs here. All uncaught errors are now captured.
React:
import * as Sentry from "@sentry/react";
import { createRoot } from "react-dom/client";
import App from "./App";
Sentry.init({
dsn: "https://<key>@your-lighttrace-host/1",
environment: import.meta.env.MODE,
release: `web@${import.meta.env.VITE_APP_VERSION}`,
tracesSampleRate: 1.0,
});
createRoot(document.getElementById("root")!).render(<App />);
Python (Flask, Django, FastAPI):
import sentry_sdk
sentry_sdk.init(
dsn="https://<key>@your-lighttrace-host/1",
environment="production",
release="api@1.2.3",
traces_sample_rate=1.0,
)
# Flask, Django, or FastAPI app creation happens below this
Java / Spring Boot:
import io.sentry.spring.boot.SentryLogbackInitializer;
// In application.properties or application.yml:
sentry.dsn=https://<key>@your-lighttrace-host/1
sentry.environment=production
sentry.release=api@1.2.3
sentry.traces-sample-rate=1.0
The key here is placement. The init call must come before you spin up your web server, create your React root, or start handling requests. If it runs after, the SDK won't be ready to catch the first error. That's why it goes at the very top of your main entry file.
The DSN is safe to commit to your repository — it identifies only the project and environment, not any secret credentials. Your actual API key lives server-side in LightTrace.
Upload source maps so stack traces are readable
Production code is minified. A raw JavaScript stack trace looks like app-4f9a.js:1:52210 — completely useless. Source maps are the file that translates minified coordinates back to your original .js, .ts, or .tsx source files.
When you deploy, build your application with source maps enabled, then upload them to LightTrace. Every error that arrives after that will show the real filename and line number, not the minified mess.
Vite example:
// vite.config.ts
export default defineConfig({
build: {
sourcemap: true,
},
});
Then in your CI pipeline:
npm run build
npx sentry-cli releases files upload-sourcemaps dist/
The exact mechanics vary by build tool — Webpack, Next.js, esbuild — but the principle is the same: generate the .map files, upload them alongside your release, and LightTrace uses them to decode every stack frame. Without source maps, debugging is guesswork. With them, you get line-by-line accuracy.
Never upload source maps to a CDN or commit them to your public artifact. Upload them only to your error tracker, where they're used server-side to decode stack traces.
Add context so errors are fast to fix
A stack trace is a good start, but context is what transforms a confusing crash into a clear one-line fix. Set the user so you know who hit the error, add breadcrumbs to record what they did, and tag the event with relevant metadata.
Setting the user:
Sentry.setUser({
id: user.id,
email: user.email,
username: user.username,
});
Now every error that happens for that user includes their identity, and the dashboard groups errors by affected user.
Adding breadcrumbs:
Sentry.addBreadcrumb({
category: "payment",
message: "Stripe charge initiated",
level: "info",
data: {
amount: 2999,
currency: "USD",
},
});
Breadcrumbs are the events leading up to a crash — clicks, network requests, state changes, logs. When an error happens, you see the entire trail, so you can reproduce it without asking the user "what were you doing when it broke?"
Adding tags and context:
Sentry.setTag("checkout_flow", "guest");
Sentry.setContext("order", {
order_id: "12345",
total: 2999,
items_count: 3,
});
Tags are single values (good for filtering), context is richer metadata (good for debugging). They all attach to every error from that point until you clear them.
Gracefully handle framework-specific errors
Some frameworks need a bit more configuration to catch all errors:
React error boundaries catch render-phase crashes that global handlers miss:
import * as Sentry from "@sentry/react";
export function App() {
return (
<Sentry.ErrorBoundary fallback={<ErrorFallback />}>
<Routes />
</Sentry.ErrorBoundary>
);
}
Express middleware ensures every uncaught error in route handlers gets captured:
import * as Sentry from "@sentry/node";
app.use(Sentry.Handlers.requestHandler());
app.use(Sentry.Handlers.errorHandler());
Django middleware works similarly — just ensure it's in your MIDDLEWARE list in settings.py and the SDK will wire it in automatically.
For framework-specific guidance, see the full guides: React and Node.js (and similar guides for every major stack).
Test your setup
Deploy your instrumented app and wait a few seconds. If errors are flowing, you'll see them in your LightTrace dashboard almost immediately. To verify without waiting for a real error, most SDKs ship a test function:
// Node.js / Express
Sentry.captureException(new Error("Test error"));
// React
Sentry.captureException(new Error("Test error"));
// Python
sentry_sdk.capture_exception(Exception("Test error"))
Call this once during deployment or in a test endpoint, then check your dashboard. You should see the event arrive within seconds, grouped under a single issue.
What happens after your first event
Once errors are flowing in, LightTrace automatically groups them into issues based on the stack trace and error type. One bug becomes one issue, even if it threw a thousand times. You'll see:
- Grouped issues with a count of events and affected users — instantly know which error is hitting the most people.
- Stack traces that map back to your original source code, thanks to the source maps you uploaded.
- Breadcrumbs showing exactly what happened before the crash — the user's clicks, API calls, state changes, and logs that led to it.
- Release context so you know which deploy introduced the regression, letting you roll back or push a fix with confidence.
- Alert rules you can configure to notify the team when something new or spiking appears, without drowning you in noise.
- User info showing how many unique people were affected and which ones — so you can reach out to high-value users or early adopters before they churn.
The real power of error tracking isn't the data — it's the velocity. Instead of debugging for two hours and guessing what went wrong, you have the exact line and the user count in seconds. This is how reducing MTTR works: faster detection, faster diagnosis, faster fix. What once took a day now takes ten minutes.
If you're migrating from another error tracker, most have plugins to help you switch. LightTrace is Sentry-SDK-compatible, so if you're on a Sentry alternative already, the migration is just a DSN change — see how to migrate off Sentry for a step-by-step runbook.
The pattern applies everywhere
Whether you're shipping a browser app, a microservice, a mobile backend, or a Lambda function, the pattern doesn't change: install, init, and context. The SDKs are maintained by the Sentry team and kept up to date with each framework and runtime. This is why error tracking with a hosted provider beats self-managed solutions — you get automatic, centralized updates without touching your infrastructure.
Start tracking errors in minutes
Point a Sentry SDK at LightTrace and capture your first production errors in minutes — your first 5,000 events every month are free.
Once you have error tracking in place, you'll wonder how you ever shipped without it. Production failures stop being surprises and become one-line fixes on your dashboard.