plaxtony
Version:
Static code analysis of SC2 Galaxy Script
149 lines (130 loc) • 4.87 kB
text/typescript
import { createLogger, format, transports } from 'winston';
import * as util from 'util';
export const logger = createLogger({
level: process.env['PLAXTONY_LOG_LEVEL'] || 'warn',
format: format.combine(
format.timestamp({
alias: 'time',
format: 'hh:mm:ss.SSS',
}),
format.ms(),
format.prettyPrint({ colorize: false, depth: 2 }),
format.printf(info => {
const out = [
`${info.time} ${info.level.substr(0, 3).toUpperCase()} ${info.message}`
];
if (info.durationMs) {
out[out.length - 1] += ` ${info.ms}`;
}
const splat: any[] = info[<any>Symbol.for('splat')];
if (Array.isArray(splat)) {
const dump = splat.length === 1 ? splat.pop() : splat;
out.push(util.inspect(dump, {
colors: false,
depth: 3,
compact: true,
maxArrayLength: 500,
breakLength: 140,
}));
}
return out.join('\n');
}),
),
transports: [
new transports.Console(),
],
});
function isPromise(val: any): val is Promise<any> {
return !!val && typeof val === 'object' && typeof val.then === 'function' && typeof val.catch === 'function';
}
function formatMemoryUsage(mem: NodeJS.MemoryUsage) {
function toMegabytes(n: number) {
return (Math.round(n / 1024 / 1024 * 100) / 100).toFixed(1).padEnd(5);
}
return `${toMegabytes(mem.rss)}M ${toMegabytes(mem.heapTotal)}M ${toMegabytes(mem.heapUsed)}M`;
}
export interface LogItOptions {
level?: 'error' | 'warn' | 'info' | 'verbose' | 'debug';
message?: string;
profiling?: boolean;
profTime?: boolean;
profMemory?: boolean;
argsDump?: ((...args: any[]) => any) | boolean;
resDump?: ((res: any) => any) | boolean;
}
export function logIt(lgOpts: LogItOptions = {}) {
lgOpts = Object.assign<LogItOptions, LogItOptions>({
level: 'info',
profiling: true,
profTime: false,
profMemory: false,
}, lgOpts);
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
if (!(<any>logger).isLevelEnabled(lgOpts.level)) {
return;
}
const fn = <Function>descriptor.value;
let msgPrefix: string;
function markDone(fnResult: any, pTimeSnapshot: [number, number]) {
const diff = process.hrtime(pTimeSnapshot);
const diffMs = (diff[0] * 1000) + (diff[1] / 1000000);
const out = [`-${msgPrefix.padEnd(35)} = ${diffMs.toFixed(0).padStart(4)}ms`];
if (lgOpts.profiling || lgOpts.profMemory) {
out.push(` | ${formatMemoryUsage(process.memoryUsage())}`);
}
let metaArgs: any[] = [];
if (lgOpts.resDump === true) {
metaArgs = [fnResult];
}
else if (typeof lgOpts.resDump === 'function') {
metaArgs = [lgOpts.resDump(fnResult)];
}
else {
if (!lgOpts.profiling) {
return;
}
}
logger.log(lgOpts.level, out.join(''), ...metaArgs);
}
const proxyFn = function(this: any, ...args: any[]) {
if (!msgPrefix) {
msgPrefix = `${this.constructor.name}:${propertyKey}`;
}
const pTimeSnapshot = process.hrtime();
const out: string[] = [` ${msgPrefix.padEnd(35 + 9)}`];
if (lgOpts.message) {
out.push(lgOpts.message);
}
else if (lgOpts.profiling || lgOpts.profMemory) {
out.push(` | ${formatMemoryUsage(process.memoryUsage())}`);
}
let metaArgs: any[] = [];
if (lgOpts.argsDump === true) {
metaArgs = args;
}
else if (typeof lgOpts.argsDump === 'function') {
metaArgs = [lgOpts.argsDump(...args)];
}
logger.log(lgOpts.level, out.join(''), ...metaArgs);
let fnResult = fn.apply(this, args);
if (isPromise(fnResult)) {
fnResult = fnResult
.then(res => {
markDone(res, pTimeSnapshot);
return res;
})
.catch((err: Error) => {
markDone(err, pTimeSnapshot);
throw err;
})
;
return fnResult;
}
else {
markDone(fnResult, pTimeSnapshot);
return fnResult;
}
};
descriptor.value = proxyFn;
};
}