UNPKG

@neodx/log

Version:

A lightweight universal logging framework

142 lines (138 loc) 4.52 kB
'use strict'; var colors = require('@neodx/colors'); var readArguments = require('../_internal/read-arguments-BBlq0hOP.cjs'); var node_index = require('../_internal/index-nVOtHMCA.cjs'); function createHttpLogger({ simple = process.env.NODE_ENV === 'development', colors: colors$1 = colors.colors, logger: rootLogger = node_index.createLogger(), getRequestId = node_index.createRequestIdGenerator(), getMeta, getErrorMeta, getErrorMessage = simple ? simpleErrorMessage : defaultErrorMessage, getRequestMeta, getRequestMessage = defaultRequestMessage, getResponseMeta, getResponseMessage = defaultResponseMessage, shouldLog = true, shouldLogError = true, shouldLogRequest = false, shouldLogResponse = true } = {}) { function handleEnd(ctx) { const { error, logger, res, responseTime } = ctx; const err = error || res.err || (res.statusCode >= 500 && new Error('failed with status code ' + res.statusCode)); if (err) { if (!condition(shouldLogError, ctx)) return; const errorMeta = getErrorMeta?.(ctx) ?? { err, res, responseTime }; if (simple) { logger.error( { err }, getErrorMessage(ctx) ); logger.debug(errorMeta, 'Error details:'); return; } logger.error(errorMeta, getErrorMessage(ctx)); return; } if (!condition(shouldLogResponse, ctx)) return; const responseMeta = getResponseMeta?.(ctx) ?? { res, responseTime }; if (simple) { logger.done(getResponseMessage(ctx)); logger.debug(responseMeta, 'Response details:'); return; } logger.done(responseMeta, getResponseMessage(ctx)); } return function httpLogger(req, res, next) { if (!condition(shouldLog, req, res)) return next?.(); // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition req.id ??= getRequestId(req, res); const startTime = Date.now(); const logger = rootLogger.fork({ meta: { ...rootLogger.meta, ...getMeta?.(req, res), ...(!simple && { requestId: req.id, req }) } }); const baseContext = { req, res, logger, colors: colors$1, responseTime: 0 }; // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition req.log ??= logger; res[node_index.HTTP_LOG_START_TIME_SYMBOL] = startTime; const handleResponse = error => { res.removeListener('finish', handleResponse); res.removeListener('close', handleResponse); res.removeListener('error', handleResponse); return handleEnd({ ...baseContext, error, responseTime: Date.now() - startTime }); }; res.on('error', handleResponse); res.on('close', handleResponse); res.on('finish', handleResponse); if (condition(shouldLogRequest, baseContext)) { if (!simple) { logger.info(getRequestMeta?.(baseContext) ?? {}, getRequestMessage(baseContext)); } else { logger.info(getRequestMessage(baseContext)); if (getRequestMeta) { logger.debug(getRequestMeta(baseContext), 'Request details:'); } } } next?.(); }; } const createMessageFormatter = (fn, { ignoreWritableEnded = false, delimiter = _ => ' ' } = {}) => ctx => { const requestMessage = node_index.formatIncomingMessage(ctx.req, ctx.colors, delimiter(ctx)); return ignoreWritableEnded || ctx.res.writableEnded ? fn(requestMessage, ctx) : `(aborted) ${requestMessage}`; }; const defaultRequestMessage = createMessageFormatter(readArguments.identity, { ignoreWritableEnded: true }); const defaultResponseMessage = createMessageFormatter( (msg, ctx) => `${ctx.colors.greenBright(node_index.formatResponseTime(ctx.responseTime))} ${msg}` ); const defaultErrorMessage = createMessageFormatter( (msg, ctx) => `${ctx.colors.redBright(node_index.formatResponseTime(ctx.responseTime))} ${msg}` ); const simpleErrorMessage = createMessageFormatter( (msg, ctx) => `${ctx.colors.redBright(node_index.formatResponseTime(ctx.responseTime))} ${msg}`, { delimiter: ({ colors, res }) => colors.italic(` (${node_index.formatOutgoingMessageStatus(res)}) `) } ); const condition = (condition, ...args) => typeof condition === 'function' ? condition(...args) : condition; exports.createHttpLogger = createHttpLogger; //# sourceMappingURL=index.cjs.map