improved logger and added shutdown handler
This commit is contained in:
parent
7c2e055dd4
commit
83e8c44d98
4 changed files with 123 additions and 2 deletions
116
libs/logger/src/gracefulShutdown.ts
Normal file
116
libs/logger/src/gracefulShutdown.ts
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
import pino from 'pino';
|
||||
|
||||
interface ShutdownHandler {
|
||||
name: string;
|
||||
handler: () => Promise<void> | void;
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
export class GracefulShutdownManager {
|
||||
private logger: pino.Logger;
|
||||
private handlers: ShutdownHandler[] = [];
|
||||
private isShuttingDown = false;
|
||||
private startTime = Date.now();
|
||||
|
||||
constructor(logger: pino.Logger) {
|
||||
this.logger = logger;
|
||||
this.setupSignalHandlers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a shutdown handler
|
||||
*/
|
||||
addHandler(handler: ShutdownHandler): void {
|
||||
this.handlers.push(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup signal handlers for graceful shutdown
|
||||
*/
|
||||
private setupSignalHandlers(): void {
|
||||
// Graceful shutdown signals
|
||||
process.on('SIGTERM', () => this.shutdown('SIGTERM', 0));
|
||||
process.on('SIGINT', () => this.shutdown('SIGINT', 0));
|
||||
process.on('SIGUSR2', () => this.shutdown('SIGUSR2', 0)); // nodemon
|
||||
|
||||
// Fatal error handlers
|
||||
process.on('uncaughtException', (error) => {
|
||||
this.logger.error('Uncaught exception', error, { fatal: true });
|
||||
this.shutdown('uncaughtException', 1);
|
||||
});
|
||||
|
||||
process.on('unhandledRejection', (reason, promise) => {
|
||||
this.logger.error('Unhandled promise rejection', {
|
||||
reason: reason instanceof Error ? reason.message : reason,
|
||||
stack: reason instanceof Error ? reason.stack : undefined,
|
||||
fatal: true
|
||||
});
|
||||
this.shutdown('unhandledRejection', 1);
|
||||
});
|
||||
|
||||
// Process warnings
|
||||
process.on('warning', (warning) => {
|
||||
this.logger.warn('Process warning', {
|
||||
name: warning.name,
|
||||
message: warning.message,
|
||||
stack: warning.stack
|
||||
});
|
||||
});
|
||||
|
||||
// Final exit
|
||||
process.on('exit', (code) => {
|
||||
const uptime = Date.now() - this.startTime;
|
||||
console.log(`Process exiting with code ${code} after ${uptime}ms`);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute graceful shutdown
|
||||
*/
|
||||
private async shutdown(signal: string, exitCode: number): Promise<void> {
|
||||
if (this.isShuttingDown) {
|
||||
this.logger.warn('Force shutdown - multiple signals received');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
this.isShuttingDown = true;
|
||||
const shutdownStart = Date.now();
|
||||
|
||||
this.logger.info('Graceful shutdown initiated', {
|
||||
signal,
|
||||
exitCode,
|
||||
uptime: Date.now() - this.startTime,
|
||||
memoryUsage: process.memoryUsage(),
|
||||
handlersCount: this.handlers.length
|
||||
});
|
||||
|
||||
// Execute shutdown handlers
|
||||
for (const handler of this.handlers) {
|
||||
try {
|
||||
this.logger.info(`Executing shutdown handler: ${handler.name}`);
|
||||
const timeout = handler.timeout || 5000;
|
||||
|
||||
await Promise.race([
|
||||
Promise.resolve(handler.handler()),
|
||||
new Promise((_, reject) =>
|
||||
setTimeout(() => reject(new Error(`Timeout after ${timeout}ms`)), timeout)
|
||||
)
|
||||
]);
|
||||
|
||||
this.logger.info(`Shutdown handler completed: ${handler.name}`);
|
||||
} catch (error) {
|
||||
this.logger.error(`Shutdown handler failed: ${handler.name}`, error);
|
||||
}
|
||||
}
|
||||
|
||||
const shutdownDuration = Date.now() - shutdownStart;
|
||||
this.logger.info('Graceful shutdown completed', {
|
||||
signal,
|
||||
shutdownDuration,
|
||||
totalUptime: Date.now() - this.startTime
|
||||
});
|
||||
|
||||
// Give logs time to flush
|
||||
setTimeout(() => process.exit(exitCode), 100);
|
||||
}
|
||||
}
|
||||
|
|
@ -45,3 +45,5 @@ export type {
|
|||
} from './types';
|
||||
|
||||
export type { LoggingMiddlewareOptions } from './middleware';
|
||||
|
||||
export { GracefulShutdownManager } from './gracefulShutdown';
|
||||
|
|
|
|||
|
|
@ -7,5 +7,6 @@
|
|||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
], "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|
||||
],
|
||||
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"],
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue