UNPKG

@tshifhiwa/ohrm-ui-automation-framework

Version:

Playwright and TypeScript–based test automation framework for validating core UI features and workflows of the OrangeHRM demo application.

185 lines (163 loc) 5.84 kB
import winston, { format } from "winston"; import moment from "moment-timezone"; import path from "path"; import * as fs from "fs"; import { winstonLoggerConfig } from "./logger.config.js"; import type { LogLevel } from "./logger.config.js"; import type { EnvironmentStage } from "../../environment/constants/environment.constants.js"; export default class LoggerFactory { private static directoryEnsured = false; public static createLogger(): winston.Logger { this.ensureLogDirectoryExists(); const fileTransports = this.createFileTransports(); return winston.createLogger({ level: winstonLoggerConfig.logLevels.debug, transports: [ fileTransports.info, fileTransports.warn, fileTransports.error, fileTransports.debug, this.createConsoleTransport(), ], exceptionHandlers: [this.createCustomHandler("exceptions.log")], rejectionHandlers: [this.createCustomHandler("rejections.log")], }); } /** * Public method to ensure log directory exists * Only creates directory once per application lifecycle */ public static ensureLogDirectoryExists(): void { if (this.directoryEnsured) { return; } const directory = winstonLoggerConfig.logDirectory; if (!fs.existsSync(directory)) { fs.mkdirSync(directory, { recursive: true }); } this.directoryEnsured = true; } private static createFileTransports() { const createTransport = this.createTransportFactory(this.createBaseTransportConfig()); return this.createLogLevelTransports(createTransport); } private static createBaseTransportConfig() { return { maxsize: winstonLoggerConfig.logFileLimit, timestampFormat: this.customTimestampFormat(), customFormat: this.logCustomFormat(), }; } private static createTransportFactory( baseConfig: ReturnType<typeof this.createBaseTransportConfig>, ) { return (level: LogLevel, filename: string) => new winston.transports.File({ maxsize: baseConfig.maxsize, filename: this.resolvePath(filename), level, format: this.createCombinedFormat(level, baseConfig), }); } private static createCombinedFormat( level: LogLevel, baseConfig: ReturnType<typeof this.createBaseTransportConfig>, ): winston.Logform.Format { return winston.format.combine( this.levelFilter(level), winston.format.uncolorize(), baseConfig.timestampFormat, baseConfig.customFormat, ); } private static createLogLevelTransports( createTransport: ( level: LogLevel, filename: string, ) => winston.transports.FileTransportInstance, ) { return { info: createTransport( winstonLoggerConfig.logLevels.info, winstonLoggerConfig.logFilePaths.info, ), warn: createTransport( winstonLoggerConfig.logLevels.warn, winstonLoggerConfig.logFilePaths.warn, ), error: createTransport( winstonLoggerConfig.logLevels.error, winstonLoggerConfig.logFilePaths.error, ), debug: createTransport( winstonLoggerConfig.logLevels.debug, winstonLoggerConfig.logFilePaths.debug, ), }; } private static createConsoleTransport(): winston.transports.ConsoleTransportInstance { return new winston.transports.Console({ level: this.getConsoleLogLevel((process.env.ENV as EnvironmentStage) || "dev"), format: this.createConsoleFormat(), }); } private static createConsoleFormat(): winston.Logform.Format { return winston.format.combine( this.customTimestampFormat(), winston.format.colorize({ colors: { error: "red", warn: "yellow", info: "green", debug: "magenta", }, }), this.logCustomFormatColored(), ); } private static createCustomHandler(filename: string) { return new winston.transports.File({ filename: this.resolvePath(filename), format: this.createUncolorizedFormat(), }); } private static createUncolorizedFormat(): winston.Logform.Format { return winston.format.combine( winston.format.uncolorize(), this.customTimestampFormat(), this.logCustomFormat(), ); } private static getConsoleLogLevel(environment: EnvironmentStage): LogLevel { const levelMap: Record<EnvironmentStage, LogLevel> = { dev: winstonLoggerConfig.logLevels.debug, qa: winstonLoggerConfig.logLevels.debug, uat: winstonLoggerConfig.logLevels.info, preprod: winstonLoggerConfig.logLevels.warn, prod: winstonLoggerConfig.logLevels.error, }; return levelMap[environment] || winstonLoggerConfig.logLevels.debug; } private static levelFilter(level: LogLevel): winston.Logform.Format { return format((info) => (info.level === level ? info : false))(); } private static logCustomFormat(): winston.Logform.Format { return winston.format.printf(({ level, message, timestamp }) => { return `${timestamp} [${level}]: ${message}`; }); } private static logCustomFormatColored(): winston.Logform.Format { return winston.format.printf((info) => { return `${info.timestamp} [${info.level}]: ${info.message}`; }); } private static customTimestampFormat(): winston.Logform.Format { return winston.format.timestamp({ format: () => moment().tz(winstonLoggerConfig.timeZone).format(winstonLoggerConfig.dateFormat), }); } private static resolvePath(fileName: string): string { return path.join(winstonLoggerConfig.logDirectory, fileName); } }