blanc-logger
Version:
Advanced Winston logger for NestJS & TypeORM with structured logging.
106 lines (105 loc) • 5.05 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.blancLogger = void 0;
const chalk = require("chalk");
const nest_winston_1 = require("nest-winston");
const util = require("util");
const winston = require("winston");
const DailyRotateFile = require("winston-daily-rotate-file");
const uuid_1 = require("../helper/uuid");
const logger_config_1 = require("./logger.config");
const { LOG_DIR, CONSOLE_LOG_LEVEL, FILE_LOG_LEVEL, ROTATION_DAYS, MAX_FILE_SIZE } = logger_config_1.LOGGING_CONFIG;
const MAX_OBJECT_DEPTH = 5;
const MAX_OBJECT_WIDTH = 120;
/** util.inspect의 사전 정의된 옵션을 사용하여 객체를 문자열로 포맷팅 */
const deepInspector = (obj) => util.inspect(obj, {
colors: true,
depth: MAX_OBJECT_DEPTH,
breakLength: MAX_OBJECT_WIDTH,
compact: false,
sorted: true,
});
/** 로그 레벨에 해당하는 이모지를 매핑 */
const emojiMap = {
error: '🚨',
warn: '⚠️',
info: '🍀',
verbose: '📢',
debug: '🐛',
};
/** 로그 레벨에 해당하는 chalk 색상 함수를 매핑 */
const levelColorMap = {
error: chalk.hex('#FF6B6B'),
warn: chalk.hex('#FFD93D'),
info: chalk.hex('#845EC2'),
debug: chalk.hex('#4D96FF'),
verbose: chalk.hex('#6BCB77'),
};
/** 모듈 경로를 색상이 적용된 계층적 문자열로 변환 */
const moduleHierarchyTransform = (info) => {
var _a, _b, _c, _d;
info.moduleName =
(_d = (_c = (_b = (_a = info.moduleName) === null || _a === void 0 ? void 0 : _a.split('/')) === null || _b === void 0 ? void 0 : _b.map((part) => chalk.cyan(part))) === null || _c === void 0 ? void 0 : _c.join(chalk.dim(' → '))) !== null && _d !== void 0 ? _d : info.moduleName;
return info;
};
/** 파일 로그에 대한 타임스탬프와 JSON 포맷을 결합 */
const fileLogFormat = winston.format.combine(winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format.json());
/** 로그 파일 순환을 위한 DailyRotateFile 전송 객체를 생성 */
const createDailyRotateFileTransport = (filename, level) => new DailyRotateFile({
dirname: LOG_DIR,
filename: `${filename}-%DATE%.log`,
datePattern: 'YYYY-MM-DD',
level,
zippedArchive: true,
maxSize: MAX_FILE_SIZE,
maxFiles: ROTATION_DAYS,
format: fileLogFormat,
});
/** 로그 메타데이터에 고유한 logId가 없으면 추가 */
const addMetaDataTransform = (info) => {
var _a;
(_a = info.logId) !== null && _a !== void 0 ? _a : (info.logId = (0, uuid_1.generateUUID)());
return info;
};
/** 제공된 moduleName 또는 context 속성을 사용하여 모듈 이름을 포맷팅 */
const formatModuleName = (info) => {
var _a, _b;
const moduleName = (_a = info.moduleName) !== null && _a !== void 0 ? _a : (typeof info.context === 'object' ? (_b = info.context) === null || _b === void 0 ? void 0 : _b.moduleName : info.context);
return moduleName ? `[${moduleName}]` : '';
};
/** 로그 메시지를 포맷팅하며, 객체인 경우 deepInspector를 사용하여 포맷팅 */
const formatMessage = (info) => {
const message = info.stack || info.message;
return typeof message === 'object' ? deepInspector(message) : String(message);
};
/** 이모지를 추가하고 대문자로 변환하여 로그 레벨을 변환 */
const transformLogLevel = (info) => {
info.rawLevel = info.level;
info.level = `${emojiMap[info.level] || ''} ${info.level.toUpperCase()}`.padEnd(5);
return info;
};
/** 다양한 포맷팅 함수를 결합하여 최종 콘솔 로그 포맷을 생성 */
const customConsoleFormat = winston.format.combine(winston.format(addMetaDataTransform)(), winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format(moduleHierarchyTransform)(), winston.format(transformLogLevel)(), winston.format.printf((info) => {
var _a;
const colorFunc = levelColorMap[(_a = info.rawLevel) !== null && _a !== void 0 ? _a : ''] || ((text) => chalk.bold.white(text));
const coloredLevel = colorFunc(info.level);
const simpleLogId = info.logId ? chalk.hex('#00008B')(`[${info.logId.substring(0, 8)}]`) : '';
const moduleStr = formatModuleName(info);
const messageStr = formatMessage(info);
return `${simpleLogId} ${chalk.dim(info.timestamp)} ${coloredLevel} ${moduleStr} - ${chalk.blueBright(messageStr)}`;
}));
/** 구성된 전송 및 포맷을 사용하여 WinstonModule로 blancLogger를 생성 */
exports.blancLogger = nest_winston_1.WinstonModule.createLogger({
transports: [
new winston.transports.Console({
level: CONSOLE_LOG_LEVEL,
format: customConsoleFormat,
handleExceptions: true,
handleRejections: true,
}),
createDailyRotateFileTransport('error', 'error'),
createDailyRotateFileTransport('combined', FILE_LOG_LEVEL),
],
exceptionHandlers: [createDailyRotateFileTransport('exceptions', 'error')],
rejectionHandlers: [createDailyRotateFileTransport('rejections', 'error')],
});