2020-07-21 13:20:51 +00:00
|
|
|
/**
|
|
|
|
* Configures grist logging. This is merely a customization of the 'winston' logging module,
|
|
|
|
* and all winston methods are available. Additionally provides log.timestamp() function.
|
|
|
|
* Usage:
|
|
|
|
* var log = require('./lib/log');
|
|
|
|
* log.info(...);
|
|
|
|
*/
|
|
|
|
|
|
|
|
import {timeFormat} from 'app/common/timeFormat';
|
|
|
|
import * as winston from 'winston';
|
|
|
|
|
|
|
|
interface LogWithTimestamp extends winston.LoggerInstance {
|
|
|
|
timestamp(): string;
|
|
|
|
// We'd like to log raw json, for convenience of parsing downstream.
|
|
|
|
// We have a customization that interferes with meta arguments, and
|
|
|
|
// existing log messages that depend on that customization. For
|
|
|
|
// clarity then, we just add "raw" flavors of the primary level
|
|
|
|
// methods that pass their object argument through to winston.
|
|
|
|
rawError(msg: string, meta: ILogMeta): void;
|
|
|
|
rawInfo(msg: string, meta: ILogMeta): void;
|
|
|
|
rawWarn(msg: string, meta: ILogMeta): void;
|
|
|
|
rawDebug(msg: string, meta: ILogMeta): void;
|
|
|
|
origLog(level: string, msg: string, ...args: any[]): void;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hack winston to provide a saner behavior with regard to its optional arguments. Winston allows
|
|
|
|
* two optional arguments at the end: "meta" (if object) and "callback" (if function). We don't
|
|
|
|
* use them, but we do use variable number of arguments as in log.info("foo %s", foo). If foo is
|
|
|
|
* an object, winston dumps it in an ugly way, not at all as intended. We fix by always appending
|
|
|
|
* {} to the end of the arguments, so that winston sees an empty meta object.
|
|
|
|
* We can add support for callback if ever needed.
|
|
|
|
*/
|
|
|
|
const origLog = winston.Logger.prototype.log;
|
|
|
|
winston.Logger.prototype.log = function(level: string, msg: string, ...args: any[]) {
|
|
|
|
return origLog.call(this, level, msg, ...args, {});
|
|
|
|
};
|
|
|
|
|
|
|
|
const rawLog = new (winston.Logger)();
|
|
|
|
const log: LogWithTimestamp = Object.assign(rawLog, {
|
|
|
|
timestamp,
|
|
|
|
/**
|
|
|
|
* Versions of log.info etc that take a meta parameter. For
|
|
|
|
* winston, logs are streams of info objects. Info objects
|
|
|
|
* have two mandatory fields, level and message. They can
|
|
|
|
* have other fields, called "meta" fields. When logging
|
|
|
|
* in json, those fields are added directly to the json,
|
|
|
|
* rather than stringified into the message field, which
|
|
|
|
* is what we want and why we are adding these variants.
|
|
|
|
*/
|
|
|
|
rawError: (msg: string, meta: ILogMeta) => origLog.call(log, 'error', msg, meta),
|
|
|
|
rawInfo: (msg: string, meta: ILogMeta) => origLog.call(log, 'info', msg, meta),
|
|
|
|
rawWarn: (msg: string, meta: ILogMeta) => origLog.call(log, 'warn', msg, meta),
|
|
|
|
rawDebug: (msg: string, meta: ILogMeta) => origLog.call(log, 'debug', msg, meta),
|
|
|
|
origLog,
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the current timestamp as a string in the same format as used in logging.
|
|
|
|
*/
|
|
|
|
function timestamp() {
|
|
|
|
return timeFormat("A", new Date());
|
|
|
|
}
|
|
|
|
|
|
|
|
const fileTransportOptions = {
|
|
|
|
stream: process.stderr,
|
2020-10-28 17:37:36 +00:00
|
|
|
level: process.env.GRIST_LOG_LEVEL || 'debug',
|
2020-07-21 13:20:51 +00:00
|
|
|
timestamp: log.timestamp,
|
|
|
|
colorize: true,
|
|
|
|
json: process.env.GRIST_HOSTED_VERSION ? true : false
|
|
|
|
};
|
|
|
|
|
|
|
|
// Configure logging to use console and simple timestamps.
|
|
|
|
log.add(winston.transports.File, fileTransportOptions);
|
|
|
|
|
|
|
|
// Also update the default logger to use the same format.
|
|
|
|
winston.remove(winston.transports.Console);
|
|
|
|
winston.add(winston.transports.File, fileTransportOptions);
|
|
|
|
|
|
|
|
// It's a little tricky to export a type when the top-level export is an object.
|
|
|
|
// tslint:disable-next-line:no-namespace
|
|
|
|
declare namespace log { // eslint-disable-line @typescript-eslint/no-namespace
|
|
|
|
interface ILogMeta {
|
|
|
|
[key: string]: any;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
type ILogMeta = log.ILogMeta;
|
|
|
|
|
|
|
|
export = log;
|