UNPKG

@wnqueiroz/ecs-winston

Version:

A formatter for the winston logger compatible with Elastic Common Schema (ECS) 🚀

169 lines (168 loc) • 6.34 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ecsWinstonFormat = exports.getECSLogParsed = exports.getErrorData = exports.getMetadata = exports.getHttpRequestData = exports.stringify = void 0; const fast_json_stringify_1 = __importDefault(require("fast-json-stringify")); const lodash_merge_1 = __importDefault(require("lodash.merge")); const lodash_unset_1 = __importDefault(require("lodash.unset")); const qs_1 = __importDefault(require("qs")); const winston = __importStar(require("winston")); const ecs_schema_1 = require("./ecs-schema"); const { combine, timestamp, printf } = winston.format; exports.stringify = (0, fast_json_stringify_1.default)(ecs_schema_1.ecsSchema); function getHttpRequestData({ req, res, requestId, }) { var _a; if (!req || !res) return null; const { httpVersion, method, body } = req; const request = { id: requestId, method, body: { bytes: Number(req.get('content-length')), content: body, }, mime_type: req.get('content-type'), }; const response = { status_code: res.statusCode, mime_type: res.get('content-type'), body: { bytes: Number(res.get('content-length')), content: res.locals.body, }, }; const user_agent = { original: req.get('user-agent'), }; const http = { version: httpVersion, request, response, }; const { hostname, url, query, protocol } = req; const ecsUrl = {}; if (hostname) { const [host, port] = hostname.split(':'); ecsUrl.domain = host; ecsUrl.port = Number(port); } const hasQuery = url.indexOf('?'); if (hasQuery) ecsUrl.query = qs_1.default.stringify(query); return { http, user_agent, url: { domain: ecsUrl.domain || undefined, path: ((_a = req === null || req === void 0 ? void 0 : req.route) === null || _a === void 0 ? void 0 : _a.path) || undefined, port: ecsUrl.port || undefined, query: ecsUrl.query || undefined, scheme: ['http', 'https'].includes(protocol) ? protocol : undefined, }, }; } exports.getHttpRequestData = getHttpRequestData; function getMetadata({ rest, config, message }) { const exclude = { config: (config === null || config === void 0 ? void 0 : config.exclude) || [], message: message.exclude || rest.exclude || [], }; return { req: message.req || rest.req, res: message.res || rest.res, ecs: message.ecs || rest.ecs, error: message.error || rest.error || null, exclude: [...exclude.config, ...exclude.message], }; } exports.getMetadata = getMetadata; function getErrorData(error) { if (!error || !(error instanceof Error)) return undefined; return { type: Object.prototype.toString.call(error.constructor) === '[object Function]' ? error.constructor.name : error.name, message: error.message, stack_trace: error.stack, }; } exports.getErrorData = getErrorData; function getECSLogParsed({ config, level, message, timestamp, rest, }) { var _a; const { req, res, ecs, exclude, error } = getMetadata({ rest: rest, config, message: message, }); const messageIsString = typeof message === 'string'; const traceId = ((_a = config === null || config === void 0 ? void 0 : config.setTraceId) === null || _a === void 0 ? void 0 : _a.call(config)) || null; const httpRequestData = getHttpRequestData({ req, res, requestId: traceId, }); let ecsLogData = Object.assign(Object.assign({ '@timestamp': timestamp, log: { level: String(level) }, message: messageIsString ? message : null, ecs: { version: '1.12.0', } }, (httpRequestData ? httpRequestData : {})), (traceId ? { trace: { id: traceId, }, } : {})); ecsLogData.error = getErrorData(error); if (ecs) ecsLogData = (0, lodash_merge_1.default)(ecsLogData, ecs); // Excluding properties by paths in "exclude" option exclude.forEach((path = '') => { const splittedPath = path.split('.'); (0, lodash_unset_1.default)(ecsLogData, splittedPath); }); return (0, exports.stringify)(ecsLogData); } exports.getECSLogParsed = getECSLogParsed; const ecsWinstonFormat = (config) => combine(timestamp(), printf((_a) => { var { level, message, timestamp } = _a, rest = __rest(_a, ["level", "message", "timestamp"]); return getECSLogParsed({ config, level, message, timestamp, rest, }); })); exports.ecsWinstonFormat = ecsWinstonFormat;