๐ก๐๐ฎ๐ป๐ฑ๐น๐ถ๐ป๐ด ๐๐น๐ผ๐ฏ๐ฎ๐น ๐๐ ๐ฐ๐ฒ๐ฝ๐๐ถ๐ผ๐ป๐ & ๐๐ฟ๐ฎ๐ฐ๐ฒ๐ณ๐๐น ๐ฆ๐ต๐๐๐ฑ๐ผ๐๐ป๐ ๐ถ๐ป ๐ง๐๐ฝ๐ฒ๐ฆ๐ฐ๐ฟ๐ถ๐ฝ๐ ๐๐ถ๐๐ต ๐ก๐ฒ๐๐๐๐ฆ ๐
As developers, weโve all faced the frustrating issue of an app unexpectedly crashing and leaving us to dig through logs to figure out what went wrong. Recently, I encountered this exact problem โ my app would suddenly stop, causing downtime and impacting users. After implementing global exception handling in my TypeScript-based NestJS application, I was able to handle crashes gracefully and automatically restart the app after logging the error. ๐
Let me walk you through how I tackled this issue by using process.on to catch exceptions and signals, and restart the app if necessary.
๐ ๏ธ The Code
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
import { Logger } from "@nestjs/common";
async function bootstrap() {
const logger = new Logger("Global Exception Handling Service");
// Handle uncaught exceptions (sync errors not handled in your app)
process.on("uncaughtException", (error: any, origin: any) => {
logger.error({
module: "main process",
method: "uncaughtException",
correlationId: "To be implemented",
timestamp: new Date().toISOString(),
error: error?.message,
stack: error?.stack,
origin: origin,
});
// You may restart the app here
});
// Handle unhandled promise rejections (async errors not caught)
process.on("unhandledRejection", (err: any) => {
logger.error({
module: "main process",
method: "unhandledRejection",
correlationId: "To be implemented",
timestamp: new Date().toISOString(),
error: err?.message,
});
});
// Catch exit events (when the app is about to shut down)
process.on("exit", (code) => {
logger.error({
module: "main process",
method: "exit",
correlationId: "To be implemented",
timestamp: new Date().toISOString(),
error: code,
});
});
// Handle graceful shutdown on SIGTERM (used by cloud providers)
process.on("SIGTERM", async () => {
logger.log("Received SIGTERM. Shutting down gracefully...");
await app.close();
process.exit(0);
});
// Handle graceful shutdown on SIGINT (when user interrupts the process)
process.on("SIGINT", async () => {
logger.log("Received SIGINT. Shutting down gracefully...");
await app.close();
process.exit(0);
});
const app = await NestFactory.create(AppModule);
const appPort = parseInt(process?.env?.APP_PORT) || 3000;
await app.listen(appPort);
}
bootstrap();
๐ Breaking It Down
1. process.on(โuncaughtExceptionโ):
Catches synchronous errors that werenโt caught elsewhere. These are typically errors that escape the try-catch blocks or unhandled errors in your app. Logging such exceptions allows you to identify the root cause and ensure the app can recover.
2. process.on(โunhandledRejectionโ):
Deals with asynchronous errors โ promise rejections that werenโt handled. Itโs crucial to log these to prevent hidden issues from slipping through the cracks.
3. process.on(โexitโ):
This event gets triggered when the Node.js process is about to exit. Useful for logging any final state or doing cleanup tasks before the app closes completely.
4. process.on(โSIGTERMโ):
Used by many cloud providers (like AWS, Heroku) to gracefully terminate an app. When receiving this signal, we can close the app gracefully, ensuring all operations complete properly.
5. process.on(โSIGINTโ):
This is fired when a user presses Ctrl+C in the terminal to stop the application. Similar to SIGTERM, we handle this gracefully, ensuring the app shuts down without data loss.
๐ก Why This Matters?
Before implementing this, my app would just stop without notice. Now, every exception or signal is logged, and I can automatically restart the app after a crash, reducing downtime and improving user experience.
The next time you encounter a random app shutdown, youโll have all the details logged โ no more digging through endless logs trying to figure out what went wrong!
๐ช Takeaway:
Handling exceptions gracefully and ensuring a smooth shutdown process is critical for any production app. By implementing process.on, you:
โข Catch and log all errors (both sync and async).
โข Handle shutdown signals gracefully.
โข Restart the app or perform necessary cleanups when unexpected issues occur.
๐ Using ๐๐ป๐น๐ถ๐ป๐ฒ ๐๐ฟ๐ฟ๐ฎ๐๐ and ๐๐ผ๐น๐น๐ฒ๐ฐ๐๐ถ๐ผ๐ป ๐๐ ๐ฝ๐ฟ๐ฒ๐๐๐ถ๐ผ๐ป๐ in C# 12 simplifies your code and boosts performance. Start leveraging these features in your projects to write cleaner, faster, and more readable code!
Follow Apurv Upadhyay โ๏ธ for more insightful content..
#TypeScript #NestJS #NodeJS #ErrorHandling #GracefulShutdown #Programming