@neodx/log
Version:
A lightweight universal logging framework
142 lines (138 loc) • 4.52 kB
JavaScript
;
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