import { IS_SERVER } from '../check-environment'; import { isDebugMode } from '../debug/is-debug-mode'; import { LOG_LEVEL } from './levels'; import { currentLevel, loggers, setCurrentLevel } from './vars'; export interface IDebugger { readonly enabled: boolean; fn: (...args: any[]) => void; level: number|string; (formatter: any|string, ...args: any[]): void; } const output = (IS_SERVER? console.error : console.info).bind(console); export function setDebugLevel(level: LOG_LEVEL) { if (level === currentLevel) { return; } if (!LOG_LEVEL.hasOwnProperty(level)) { throw new Error(`unknown log level: ${level}`); } output('change log level to %s(%s)', level, LOG_LEVEL[level]); setCurrentLevel(level); loggers.forEach((logger) => { logger.level = LOG_LEVEL[level]; }); } init_env(); function init_env() { if (process.env.LOG_LEVEL) { const lv = LOG_LEVEL[process.env.LOG_LEVEL]; if (lv === undefined) { console.error('environment variable LOG_LEVEL is not available.'); console.error('All levels are: %s', Object.keys(LOG_LEVEL).join(', ')); throw new TypeError(); } setDebugLevel(lv); } else if (isDebugMode()) { setDebugLevel(LOG_LEVEL.SILLY); } else { setDebugLevel(LOG_LEVEL.INFO); } } declare const global: any; let creator; if (IS_SERVER) { creator = module.require('@gongt/ts-stl-server/debug/winston-logger').createLoggerServer; } else { creator = require('./_debug_client').createLoggerClient; } export function createLogger(level: LOG_LEVEL = LOG_LEVEL.INFO, title: string): IDebugger { return creator(level, title); } export interface IDebuggerBundle { data: IDebugger; debug: IDebugger; error: IDebugger; info: IDebugger; silly: IDebugger; warn: IDebugger; } export function createLoggerBundle(title: string): IDebuggerBundle { return { error: createLogger(LOG_LEVEL.ERROR, title), warn: createLogger(LOG_LEVEL.WARN, title), info: createLogger(LOG_LEVEL.INFO, title), debug: createLogger(LOG_LEVEL.DEBUG, title), data: createLogger(LOG_LEVEL.DATA, title), silly: createLogger(LOG_LEVEL.SILLY, title), }; } export function debugType(object) { switch (typeof object) { case 'object': const debug = {}; Object.keys(object).forEach((i) => { debug[i] = debugTypeInObj(object[i]); }); return debug; default: return debugTypeInObj(object); } } export function debugTypeInObj(object) { switch (typeof object) { case 'boolean': return `[Boolean ${object? 'true' : 'false'}]`; case 'string': return `[String ${object.substr(0, 6)}..(${object.length})]`; case 'number': return `[Number ${object}]`; case 'undefined': return '[undefined]'; case 'function': return `[Function ${object.name || 'anonymous'}]`; case 'symbol': return `[${object.toString()}]`; case 'object': if (object === null) { return '[Object null]'; } if (Array.isArray(object)) { return `[Array [${object.slice(0, 2).toString()}]...(${object.length})]`; } return `[Object ${object.toString()}]`; } }