transaction-logger
Version:
This is a custom logging library based on winston.
161 lines (139 loc) • 6.06 kB
text/typescript
import httpContext from 'express-http-context';
import config from 'config';
import path from 'path';
import { createLogger, format, transports } from 'winston';
import os from 'os';
import 'winston-syslog';
import fileUtils from './utils/file-utils';
const logFolder = process.env.LOG_LOCAL_FOLDER || `./logs/`;
const exeptionsFileName = process.env.LOG_LOCAL_EXCEPTION_FILE_NAME || 'exceptions.log';
const logFileName = process.env.LOG_LOCAL_FILE_NAME || 'logs.log';
const logEnvironment = process.env.LOG_ENVIRONMENT || 'console';
const logLevel = process.env.LOG_LEVEL || 'info';
const applicationName = process.env.SERVICE_NAME || '';
const execptionsFilePath = path.join(logFolder, exeptionsFileName);
const regularLogFilePath = path.join(logFolder, logFileName);
export class Logger {
private selectedTransports: any[];
private exceptionTransports: any[];
private logger: any;
public info: (message: string, initTime: number, endTime: number, guid: string) => void;
public debug: (message: string, initTime: number, endTime: number, guid: string) => void;
public warn: (message: string, initTime: number, endTime: number, guid: string) => void;
public error: (message: string, initTime: number, endTime: number, guid: string) => void;
public fatal: (message: string, initTime: number, endTime: number, guid: string) => void;
constructor(globalFilename: string) {
const colorizer = format.colorize();
this.selectedTransports = [];
this.exceptionTransports = [];
const customLevels = {
levels: {
crit: 0,
error: 1,
warn: 2,
info: 3,
debug: 4,
},
};
const defaultLoggingFormat = format.combine(
format.simple(),
format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss',
}),
format.printf((info) =>
colorizer.colorize(
info.level,
`[${info.timestamp}][${info.level}][${info.applicationName}][${info.filenamePath}]#${info.message}`,
),
),
);
const filenamePath = fileUtils.getFolderAndFilename(globalFilename);
const consoleLogging = new transports.Console({
format: defaultLoggingFormat,
level: logLevel,
});
// Default transport always to console
this.selectedTransports.push(consoleLogging);
this.exceptionTransports.push(consoleLogging);
// Defining extra transports based on Environment variable LOG_ENVIRONMENT
if (logEnvironment.toLowerCase() === 'local') {
const fileLogging = new transports.File({
filename: regularLogFilePath,
format: defaultLoggingFormat,
});
const exceptionsfileLogging = new transports.File({
filename: execptionsFilePath,
format: defaultLoggingFormat,
});
this.selectedTransports.push(fileLogging);
this.exceptionTransports.push(exceptionsfileLogging);
}
this.logger = createLogger({
level: logLevel,
levels: customLevels.levels,
format: defaultLoggingFormat,
defaultMeta: {
applicationName: applicationName,
filenamePath: filenamePath,
},
transports: this.selectedTransports,
exceptionHandlers: this.exceptionTransports,
});
const prepareMessage = (message: string, initTime: number , endTime: number, guid: string) => {
let separator = ' >>> ';
const transactionId = httpContext.get('Transaction-ID');
separator = transactionId ? `[Transaction-ID:${transactionId}]${separator}` : separator;
let messageToLog = '';
if (isNaN(initTime)) {
messageToLog = buildMessageWithoutTime(initTime, messageToLog, separator, message);
} else {
if (isNaN(endTime)) {
messageToLog = buildMessageWithInitTime(initTime, endTime, messageToLog, separator, message);
} else {
messageToLog = buildMessageWithBothTime(endTime, initTime, guid, messageToLog, separator, message);
}
}
return messageToLog;
};
this.info = (message, initTime, endTime, guid) =>
this.logger.info(prepareMessage(message, initTime, endTime, guid));
this.debug = (message, initTime, endTime, guid) =>
this.logger.debug(prepareMessage(message, initTime, endTime, guid));
this.warn = (message, initTime, endTime, guid) =>
this.logger.warn(prepareMessage(message, initTime, endTime, guid));
this.error = (message, initTime, endTime, guid) =>
this.logger.error(prepareMessage(message, initTime, endTime, guid));
this.fatal = (message, initTime, endTime, guid) =>
this.logger.crit(prepareMessage(message, initTime, endTime, guid));
}
}
function buildMessageWithBothTime(endTime: number, initTime: number, guid:string, messageToLog:string, separator:string, message:string) {
const difference = endTime - initTime;
if (typeof guid !== 'undefined' && guid !== null) {
const _guid = guid;
messageToLog = `[${difference}ms][Guid:${_guid}]${separator}${message}`;
} else {
messageToLog = `[${difference}ms]${separator}${message}`;
}
return messageToLog;
}
function buildMessageWithInitTime(initTime: number, endTime: number, messageToLog:string, separator:string, message :string) {
const _endTime = new Date().getTime();
const difference = _endTime - initTime;
if (typeof endTime !== 'undefined' && endTime !== null) {
const _guid = endTime;
messageToLog = `[${difference}ms][Guid:${_guid}]${separator}${message}`;
} else {
messageToLog = `[${difference}ms]${separator}${message}`;
}
return messageToLog;
}
function buildMessageWithoutTime(initTime: number, messageToLog: string, separator: string, message: string) {
if (typeof initTime !== 'undefined' && initTime !== null) {
const _guid = initTime;
messageToLog = `[Guid:${_guid}]${separator}${message}`;
} else {
messageToLog = separator + message;
}
return messageToLog;
}