UNPKG

@contentstack/cli-utilities

Version:

Utilities for contentstack projects

190 lines (189 loc) 7.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const traverse_1 = tslib_1.__importDefault(require("traverse")); const full_1 = require("klona/full"); const path_1 = require("path"); const winston = tslib_1.__importStar(require("winston")); const logging_1 = require("../constants/logging"); class Logger { constructor(config) { this.sensitiveKeys = [ /authtoken/i, /^email$/i, /^password$/i, /secret/i, /token/i, /api[-._]?key/i, /management[-._]?token/i, /sessionid/i, /orgid/i, ]; this.config = config; this.loggers = { error: this.getLoggerInstance('error'), warn: this.getLoggerInstance('warn'), info: this.getLoggerInstance('info'), debug: this.getLoggerInstance('debug'), success: this.getLoggerInstance('info'), // Map success to info }; } getLoggerInstance(level = 'info') { const filePath = (0, path_1.normalize)(process.env.CS_CLI_LOG_PATH || this.config.basePath).replace(/^(\.\.(\/|\\|$))+/, ''); if (level === 'hidden') { return this.createLogger('error', filePath); } return this.createLogger(level, filePath); } get loggerOptions() { return { filename: '', maxFiles: 20, tailable: true, maxsize: 1000000, }; } createLogger(level, filePath) { return winston.createLogger({ levels: logging_1.logLevels, level: level, transports: [ new winston.transports.File(Object.assign(Object.assign({}, this.loggerOptions), { filename: `${filePath}/${level}.log`, format: winston.format.combine(winston.format.timestamp(), winston.format.json()) })), new winston.transports.Console({ format: winston.format.combine(winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format.printf((info) => { const colorizer = winston.format.colorize(); const levelText = info.level.toUpperCase(); const timestamp = info.timestamp; const message = info.message; const meta = info.meta; let fullLine = `[${timestamp}] ${levelText}: ${message}`; if (meta && (info.level !== 'info' && info.level !== 'success')) { const redactedMeta = this.isLogEntry(meta) ? JSON.stringify(this.redact(meta)) : JSON.stringify(this.redact(meta)); fullLine += ` - ${redactedMeta}`; } return colorizer.colorize(info.level, fullLine); })), }), ], }); } isSensitiveKey(keyStr) { return keyStr && typeof keyStr === 'string' ? this.sensitiveKeys.some((regex) => regex.test(keyStr)) : false; } redactObject(obj) { const self = this; (0, traverse_1.default)(obj).forEach(function redactor() { if (this.key && self.isSensitiveKey(this.key)) { this.update('[REDACTED]'); } }); } redact(info) { try { const copy = (0, full_1.klona)(info); this.redactObject(copy); const splat = copy[Symbol.for('splat')]; if (splat) this.redactObject(splat); return copy; } catch (error) { return info; } } isLogEntry(obj) { return typeof obj === 'object' && 'level' in obj && 'message' in obj; } shouldLog(level, target) { const configLevel = target === 'console' ? this.config.consoleLogLevel : this.config.logLevel; const minLevel = configLevel ? logging_1.logLevels[configLevel] : 2; // default: info const entryLevel = logging_1.logLevels[level]; return entryLevel <= minLevel; } /* === Public Log Methods === */ error(message, meta) { if (this.shouldLog('error', 'console') || this.shouldLog('error', 'file')) { this.loggers.error.error(message, meta); } } warn(message, meta) { if (this.shouldLog('warn', 'console') || this.shouldLog('warn', 'file')) { this.loggers.warn.warn(message, meta); } } info(message, meta) { if (this.shouldLog('info', 'console') || this.shouldLog('info', 'file')) { this.loggers.info.info(message, meta); } } success(message, meta) { if (this.shouldLog('info', 'console') || this.shouldLog('info', 'file')) { this.loggers.success.info(message, Object.assign(Object.assign({}, meta), { type: 'success' })); } } debug(message, meta) { if (this.shouldLog('debug', 'console') || this.shouldLog('debug', 'file')) { this.loggers.debug.debug(message, meta); } } /* === Structured Logging === */ logError(params) { const logPayload = { level: logging_1.logLevels.error, message: params.message, timestamp: new Date(), meta: Object.assign({ type: params.type, error: params.error, context: params.context }, params.meta), }; const targetLevel = params.hidden ? 'debug' : 'error'; if (this.shouldLog(targetLevel, 'console') || this.shouldLog(targetLevel, 'file')) { this.loggers[targetLevel].error(logPayload); } } logWarn(params) { const logPayload = { level: logging_1.logLevels.warn, message: params.message, timestamp: new Date(), meta: Object.assign({ type: params.type, context: params.context }, params.meta), }; if (this.shouldLog('warn', 'console') || this.shouldLog('warn', 'file')) { this.loggers.warn.warn(logPayload); } } logInfo(params) { const logPayload = { level: logging_1.logLevels.info, message: params.message, timestamp: new Date(), meta: Object.assign({ type: params.type, info: params.info, context: params.context }, params.meta), }; if (this.shouldLog('info', 'console') || this.shouldLog('info', 'file')) { this.loggers.info.info(logPayload); } } logSuccess(params) { const logPayload = { level: logging_1.logLevels.success, message: params.message, timestamp: new Date(), meta: Object.assign({ type: params.type, data: params.data, context: params.context }, params.meta), }; if (this.shouldLog('info', 'console') || this.shouldLog('info', 'file')) { this.loggers.success.info(logPayload); } } logDebug(params) { const logPayload = { level: logging_1.logLevels.debug, message: params.message, timestamp: new Date(), meta: Object.assign({ type: params.type, debug: params.debug, context: params.context }, params.meta), }; if (this.shouldLog('debug', 'console') || this.shouldLog('debug', 'file')) { this.loggers.debug.debug(logPayload); } } } exports.default = Logger;