wip: add some error logging to the server
This commit is contained in:
parent
8158668190
commit
25724eac23
@ -135,6 +135,102 @@ export async function startApi(): Promise<{ app: FastifyInstance; io: Server }>
|
||||
httpRequestDurationHistogram.observe({ method, route, status }, duration);
|
||||
});
|
||||
|
||||
// Global error handler
|
||||
app.setErrorHandler(async (error, request, reply) => {
|
||||
const method = request.method;
|
||||
const url = request.url;
|
||||
const userAgent = request.headers['user-agent'] || 'unknown';
|
||||
const ip = request.ip || 'unknown';
|
||||
|
||||
// Log the error with comprehensive context
|
||||
log({
|
||||
module: 'fastify-error',
|
||||
level: 'error',
|
||||
method,
|
||||
url,
|
||||
userAgent,
|
||||
ip,
|
||||
statusCode: error.statusCode || 500,
|
||||
errorCode: error.code,
|
||||
stack: error.stack
|
||||
}, `Unhandled error: ${error.message}`);
|
||||
|
||||
// Return appropriate error response
|
||||
const statusCode = error.statusCode || 500;
|
||||
|
||||
if (statusCode >= 500) {
|
||||
// Internal server errors - don't expose details
|
||||
return reply.code(statusCode).send({
|
||||
error: 'Internal Server Error',
|
||||
message: 'An unexpected error occurred',
|
||||
statusCode
|
||||
});
|
||||
} else {
|
||||
// Client errors - can expose more details
|
||||
return reply.code(statusCode).send({
|
||||
error: error.name || 'Error',
|
||||
message: error.message || 'An error occurred',
|
||||
statusCode
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Error hook for additional logging
|
||||
app.addHook('onError', async (request, reply, error) => {
|
||||
const method = request.method;
|
||||
const url = request.url;
|
||||
const duration = (Date.now() - (request.startTime || Date.now())) / 1000;
|
||||
|
||||
log({
|
||||
module: 'fastify-hook-error',
|
||||
level: 'error',
|
||||
method,
|
||||
url,
|
||||
duration,
|
||||
statusCode: reply.statusCode || error.statusCode || 500,
|
||||
errorName: error.name,
|
||||
errorCode: error.code
|
||||
}, `Request error: ${error.message}`);
|
||||
});
|
||||
|
||||
// Handle uncaught exceptions in routes
|
||||
app.addHook('preHandler', async (request, reply) => {
|
||||
// Store original reply.send to catch errors in response serialization
|
||||
const originalSend = reply.send.bind(reply);
|
||||
reply.send = function(payload: any) {
|
||||
try {
|
||||
return originalSend(payload);
|
||||
} catch (error: any) {
|
||||
log({
|
||||
module: 'fastify-serialization-error',
|
||||
level: 'error',
|
||||
method: request.method,
|
||||
url: request.url,
|
||||
stack: error.stack
|
||||
}, `Response serialization error: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// Not found handler
|
||||
app.setNotFoundHandler(async (request, reply) => {
|
||||
log({
|
||||
module: 'fastify-not-found',
|
||||
level: 'warn',
|
||||
method: request.method,
|
||||
url: request.url,
|
||||
userAgent: request.headers['user-agent'] || 'unknown',
|
||||
ip: request.ip || 'unknown'
|
||||
}, `404 Not Found: ${request.method} ${request.url}`);
|
||||
|
||||
return reply.code(404).send({
|
||||
error: 'Not Found',
|
||||
message: `Route ${request.method} ${request.url} not found`,
|
||||
statusCode: 404
|
||||
});
|
||||
});
|
||||
|
||||
// Authentication decorator
|
||||
app.decorate('authenticate', async function (request: any, reply: any) {
|
||||
try {
|
||||
|
@ -46,6 +46,60 @@ async function main() {
|
||||
log('Shutting down...');
|
||||
}
|
||||
|
||||
// Process-level error handling
|
||||
process.on('uncaughtException', (error) => {
|
||||
log({
|
||||
module: 'process-error',
|
||||
level: 'error',
|
||||
stack: error.stack,
|
||||
name: error.name
|
||||
}, `Uncaught Exception: ${error.message}`);
|
||||
|
||||
console.error('Uncaught Exception:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
process.on('unhandledRejection', (reason, promise) => {
|
||||
const errorMsg = reason instanceof Error ? reason.message : String(reason);
|
||||
const errorStack = reason instanceof Error ? reason.stack : undefined;
|
||||
|
||||
log({
|
||||
module: 'process-error',
|
||||
level: 'error',
|
||||
stack: errorStack,
|
||||
reason: String(reason)
|
||||
}, `Unhandled Rejection: ${errorMsg}`);
|
||||
|
||||
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
process.on('warning', (warning) => {
|
||||
log({
|
||||
module: 'process-warning',
|
||||
level: 'warn',
|
||||
name: warning.name,
|
||||
stack: warning.stack
|
||||
}, `Process Warning: ${warning.message}`);
|
||||
});
|
||||
|
||||
// Log when the process is about to exit
|
||||
process.on('exit', (code) => {
|
||||
if (code !== 0) {
|
||||
log({
|
||||
module: 'process-exit',
|
||||
level: 'error',
|
||||
exitCode: code
|
||||
}, `Process exiting with code: ${code}`);
|
||||
} else {
|
||||
log({
|
||||
module: 'process-exit',
|
||||
level: 'info',
|
||||
exitCode: code
|
||||
}, 'Process exiting normally');
|
||||
}
|
||||
});
|
||||
|
||||
main().catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
|
Loading…
Reference in New Issue
Block a user