Node.js Error Tracking: Exceptions with Stack Traces
Node.js Error Tracking: Debug Uncaught Exceptions with Contextual Stack Traces
Introduction
Uncaught exceptions are the silent killers of Node.js services. One missing try/catch can terminate a process, erase valuable debugging information, and increase mean time to recovery (MTTR). This guide walks you through a complete project—from idea to production—showing how to instrument your code, capture contextual stack traces, and leverage Lescopr’s observability platform to keep your service reliable and compliant.
Planning the Project
Defining Requirements
Before writing any code, list the concrete goals you want to achieve:
- Capture every uncaught exception with full request context.
- Correlate errors with SLA metrics such as response time and error rate.
- Enable real‑time alerts for error spikes that breach your service‑level agreement.
- Store traces in a GDPR‑compliant way, respecting user consent.
These requirements shape the architecture and the choice of tooling.
Choosing the Stack
For this tutorial we use a classic Express server running on Node.js 18. The stack includes:
- Express – lightweight HTTP framework.
- Lescopr APM SDK – provides automatic instrumentation and contextual stack traces.
- Winston – structured logging that forwards to Lescopr.
- Docker – containerised deployment for reproducibility.
Why Express? It is the most common entry point for Node.js APIs, making the example instantly relatable for most backend engineers.
Implementing Error Tracking
Installing Lescopr SDK
npm install @lescopr/apm
The SDK auto‑patches core modules (http, fs, net) and adds a global handler for uncaught exceptions.
Configuring Contextual Stack Traces
Lescopr enriches each stack frame with metadata such as request ID, user ID, and custom tags. Follow these steps:
- Initialize the SDK early in your entry file (
app.js). - Register a request‑level context using middleware.
- Add custom tags that capture business‑critical data (e.g., tenant ID, feature flag state).
const lescopr = require('@lescopr/apm');
lescopr.init({
serviceName: 'order‑service',
environment: process.env.NODE_ENV,
captureUncaught: true,
});
app.use((req, res, next) => {
lescopr.setContext({
requestId: req.headers['x‑request‑id'] || lescopr.generateId(),
userId: req.user?.id,
route: req.path,
});
next();
});
Result: When an exception occurs, the trace sent to Lescopr includes every key‑value pair from the context, turning a raw stack trace into a searchable incident record.
Handling Uncaught Exceptions
Even with automatic capture, you should still guard critical async flows:
- Wrap
async/awaitcalls intry/catchblocks. - Use
process.on('unhandledRejection')to log promise rejections. - For legacy callbacks, employ
domainorasync‑hooksto propagate context.
process.on('unhandledRejection', (reason) => {
lescopr.captureException(reason);
console.error('Unhandled Rejection:', reason);
});
Testing and Observability
Simulating Errors
Create a test endpoint that deliberately throws an error:
app.get('/debug/crash', (req, res) => {
JSON.parse('invalid‑json'); // triggers SyntaxError
});
Send a request with a custom header (X‑User‑Id) and watch Lescopr display the enriched stack trace.
Analyzing Traces
In the Lescopr UI, filter by serviceName:order‑service and error.type:SyntaxError. The panel shows:
- Timestamp
- Request ID
- User ID (from the context)
- Full stack with line numbers.
These details let you reproduce the bug locally in minutes instead of hours.
Setting Up Alerts
Configure an alert rule that triggers when the error rate exceeds 0.5 % over a five‑minute window:
- Metric:
error.count - Threshold:
> 0.5% - Notification: Slack channel
#sre‑alerts
This proactive stance reduces MTTR by notifying the on‑call engineer before the issue escalates.
Launching and Monitoring in Production
Deploying with CI/CD
Integrate the Lescopr SDK into your CI pipeline:
- Run
npm testwith the SDK in dry‑run mode to ensure no runtime errors. - Use Docker multi‑stage builds to keep the final image lean.
- Deploy to Kubernetes with a side‑car that forwards logs to Lescopr.
SLA Dashboards
Create a dashboard that visualises:
- 99.9 % uptime (availability)
- Average response time (latency)
- Error rate (percentage of uncaught exceptions)
Link the dashboard to your SLA contract so stakeholders can verify compliance in real time.
Continuous Improvement
After each incident, perform a post‑mortem that records:
- Root cause (e.g., missing validation).
- Time to detect and resolve.
- Action items (e.g., add stricter schema validation).
Feed these insights back into the codebase, and watch the error rate gradually decline.
Conclusion
By instrumenting your Node.js service with Lescopr, you turn opaque uncaught exceptions into rich, searchable events that include request context and precise stack information. This approach shortens MTTR, improves SLA adherence, and provides a solid foundation for continuous reliability engineering.
To go further, Lescopr's documentation covers step-by-step setup.
Internal Links