Error monitoring and reporting are crucial components in maintaining a healthy and reliable Express.js application.
Error monitoring in Express.js involves tracking and recording application errors and exceptions that occur during runtime. With error monitoring in place, developers can detect and resolve issues faster, improving the overall reliability and user experience.
Express.js provides built-in error-handling capabilities, allowing developers to catch and manage errors efficiently.
Express comes with a default error handler that sends a generic error response to the client. However, for production applications, it’s essential to customize this handler to ensure that sensitive information is not exposed.
In Express.js, error-handling middleware functions are identified by having four parameters: err
, req
, res
, and next
. Here’s a basic example:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
throw new Error('Something went wrong!');
});
// Error-handling middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('An unexpected error occurred!');
});
app.listen(3000, () => console.log('Server running on port 3000'));
err.stack
logs the error details, while res.status(500).send()
returns a 500 status code.Custom error handling helps define different behaviors for various error types, such as 404 (Not Found) errors or 500 (Internal Server) errors.
Define a custom error class for handling specific errors with additional context.
class AppError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
this.isOperational = true;
Error.captureStackTrace(this, this.constructor);
}
}
Using this class in middleware provides more structured error responses.
app.get('/error', (req, res, next) => {
const error = new AppError('This is a custom error message', 400);
next(error);
});
app.use((err, req, res, next) => {
const statusCode = err.statusCode || 500;
const message = err.isOperational ? err.message : 'Internal Server Error';
res.status(statusCode).json({
status: 'error',
message: message,
});
});
AppError
lets us customize error details.isOperational
is true, else it sends “Internal Server Error”.Error logs are essential for debugging and can be stored locally or externally.
Logging errors to the console is a quick way to monitor them during development
app.use((err, req, res, next) => {
console.error(`Error logged: ${err.message}`);
next(err);
});
For production applications, structured logging tools like Winston or Morgan offer more control
const winston = require('winston');
const logger = winston.createLogger({
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' })
]
});
app.use((err, req, res, next) => {
logger.error(err.message);
res.status(500).send('An error occurred!');
});
error.log
file.error.log
Error monitoring tools provide real-time tracking and alerts. Popular tools include Sentry, LogRocket, and Datadog.
npm install @sentry/node
2. Initialize Sentry in the main application file:
const Sentry = require('@sentry/node');
Sentry.init({ dsn: 'your_sentry_dsn' });
app.use(Sentry.Handlers.requestHandler());
app.get('/sentry-error', (req, res) => {
throw new Error('Sentry test error');
});
app.use(Sentry.Handlers.errorHandler());
3. Configure Error Handler to integrate with Sentry:
app.use((err, req, res, next) => {
Sentry.captureException(err);
res.status(500).send('An error occurred!');
});
Most monitoring tools support alert configurations, such as email or SMS, for critical errors.
.catch()
in promises and try-catch
in async functions.Error monitoring and reporting are essential for maintaining stable Express.js applications. By implementing effective error-handling middleware, structured logging, and real-time monitoring with tools like Sentry, you can detect, log, and resolve issues quickly, ensuring a reliable experience for end users. Happy Coding!❤️