UNPKG

@hoangnam.io/qa-tools

Version:

Logging, Error handling, Notifying for Express codebase

90 lines (81 loc) 3.12 kB
function getErrorHandlerMiddleware(notifier, extractCallerFunc = (req) => req.caller, appName) { process.on("unhandledRejection", async (error) => { try { console.error(error); if (!isIgnoredError({}, error)) { await notifier.send(`appName: ${appName}, unhandledRejection: ${error}`); } } finally { process.exit(-1); } }); process.on("uncaughtException", async (error) => { try { console.error(error); if (!isIgnoredError({}, error)) { await notifier.send(`appName: ${appName}, uncaughtException: ${error}`); } } finally { process.exit(-1); } }); function isIgnoredError(req, err) { try { if (!req || !err) return false; if (err.toString()?.includes("BSONError")) return true; if (err.toString()?.includes("LoggingServiceV2")) return true; if (err.name === "MongoServerError" && err.message.includes("E11000")) return true; if (err.name === "ZodError") return true; if (err.name === "SyntaxError") return true; if (req.extendedLog?.clientDisconnected) return true; return false; } catch (error) { return false; } } // error: name, message, [details] // send notify error: context, error return function errorHandlerMiddleware(err, req, res, next) { // context const context = { appName, method: req.method, url: req.originalUrl, caller: extractCallerFunc(req), extendedLog: req.extendedLog, }; // axios error if (err.response) { const { status, statusText } = err.response; const { baseURL, method, url, data } = err.response.config; let response = err.response.data; if (response instanceof Buffer) response = response.toString(); const error = { name: "axios error", message: `failed to call api: ${method} ${baseURL}${url}`, details: { status, response }, }; if (!isIgnoredError(req, err)) notifier.send(JSON.stringify({ context, error }, null, 2)); return res.status(status).json(error); } // mongodb error if (err.name === "MongoServerError") { const error = { name: err.name, message: err.message }; if (!isIgnoredError(req, err)) notifier.send(JSON.stringify({ context, error }, null, 2)); return res.status(err.statusCode || 500).json(error); } // zod if (err.name === "ZodError") { const issues = err.issues.map((item) => ({ field: item.path.join("."), message: item.message })); const message = JSON.stringify(issues); const error = { name: "Invalid input data", message }; if (!isIgnoredError(req, err)) notifier.send(JSON.stringify({ context, error }, null, 2)); return res.status(err.statusCode || 500).json(error); } // BaseError or other Error const error = { ...err, name: err.name, message: err.message }; if (!isIgnoredError(req, err)) notifier.send(JSON.stringify({ context, error }, null, 2)); return res.status(err.statusCode || 500).json(error); }; } module.exports = { getErrorHandlerMiddleware };