diff --git a/src/middlewares/logs.ts b/src/middlewares/logs.ts new file mode 100644 index 0000000..8c992dd --- /dev/null +++ b/src/middlewares/logs.ts @@ -0,0 +1,73 @@ +import { NextFunction, Request, Response } from "express"; +import { Client } from "@elastic/elasticsearch"; + +if (!process.env.ELASTICSEARCH_INDEX) { + throw new Error("Require ELASTICSEARCH_INDEX to store log."); +} + +const ELASTICSEARCH_INDEX = process.env.ELASTICSEARCH_INDEX; + +const LOG_LEVEL_MAP: Record = { + debug: 4, + info: 3, + warning: 2, + error: 1, + none: 0, +}; + +const elasticsearch = new Client({ + node: `${process.env.ELASTICSEARCH_PROTOCOL}://${process.env.ELASTICSEARCH_HOST}:${process.env.ELASTICSEARCH_PORT}`, +}); + +async function logMiddleware(req: Request, res: Response, next: NextFunction) { + if (!req.url.startsWith("/api/")) return next(); + + let data: any; + + const originalJson = res.json; + + res.json = function (v: any) { + data = v; + return originalJson.call(this, v); + }; + + const timestamp = new Date().toString(); + const start = performance.now(); + + req.app.locals.logData = {}; + + res.on("finish", () => { + if (!req.url.startsWith("/api/")) return; + + const level = LOG_LEVEL_MAP[process.env.LOG_LEVEL ?? "info"] || 1; + + if (level === 1 && res.statusCode < 500) return; + if (level === 2 && res.statusCode < 400) return; + if (level === 3 && res.statusCode < 200) return; + + const obj = { + logType: res.statusCode >= 500 ? "error" : res.statusCode >= 400 ? "warning" : "info", + systemName: "BMA_EHR_DEVELOPMENT", + startTimeStamp: timestamp, + endTimeStamp: new Date().toString(), + processTime: performance.now() - start, + host: req.hostname, + method: req.method, + endpoint: req.url, + responseCode: res.statusCode === 304 ? 200 : res.statusCode, + responseDescription: data?.code, + input: (level === 4 && JSON.stringify(req.body, null, 2)) || undefined, + output: (level === 4 && JSON.stringify(data, null, 2)) || undefined, + ...req.app.locals.logData, + }; + + elasticsearch.index({ + index: ELASTICSEARCH_INDEX, + document: obj, + }); + }); + + return next(); +} + +export default logMiddleware;