@genie-solutions/genie-logger
Version:
Reusable Node.js logger for platform Lambda services.
114 lines (102 loc) • 2.41 kB
text/typescript
import winston, { createLogger, transports, format } from "winston";
import { TransformableInfo, FormatWrap } from "logform";
import Transport from "winston-transport";
import { v4 } from "uuid";
type LogFunction<T> = (event: T) => void;
export interface Logger<T> {
debug: LogFunction<T>;
info: LogFunction<T>;
warn: LogFunction<T>;
error: LogFunction<T>;
profile: LogFunction<string>;
extend: (extraMeta: object) => Logger<T>;
}
export interface HasLogger<T> {
logger: Logger<T>;
}
export interface LoggerMetaData {
application: string;
environment: string;
correlationRequestId?: string;
}
export const createNoopLogger = <T>(): Logger<T> => {
const logger: Logger<T> = {
debug() {},
info() {},
warn() {},
error() {},
profile() {},
extend() {
return logger;
}
};
return logger;
};
const withMetaData: FormatWrap = format(
(info: TransformableInfo, meta: LoggerMetaData) => {
return {
...meta,
...info
};
}
);
const loggerFromWinstonLogger = <T extends object>(
logger: winston.Logger
): Logger<T> => {
return {
debug(event: T) {
logger.debug(event);
},
info(event: T) {
logger.info(event);
},
warn(event: T) {
logger.warn(event);
},
error(event: T) {
logger.error(event);
},
profile(id: string) {
logger.profile(id);
},
extend(extraMeta: object) {
return loggerFromWinstonLogger(logger.child(extraMeta));
}
};
};
const createWinstonLogger = <T extends object>(
meta: LoggerMetaData,
level: string = "info",
transport: Transport = new transports.Console()
): Logger<T> => {
const logger = createLogger({
level,
transports: [transport],
format: format.combine(
withMetaData(meta),
format.timestamp(),
format.ms(),
format.errors({ stack: true }),
format.json()
)
});
return loggerFromWinstonLogger(logger);
};
export const createDefaultLogger = createWinstonLogger;
export const createLoggerFromContext = <T extends object>(
application: string,
environment: string,
level: string,
creator: (
meta: LoggerMetaData,
level: string
) => Logger<T> = createDefaultLogger
) => (correlationRequestId?: string) =>
creator(
{
application,
environment,
correlationRequestId: correlationRequestId || `UNKNOWN/${v4()}`
},
level
);