最终目标
基于色彩权重的显示
如果红色代表错误提示,绿色代表信息展示,灰色代表普通日志,实时监测状态下可保持清晰的整体结构。
详细时间点与日志类型
尤其是在日常维护过程中,日志几乎是最先被提取的模块,哪个时间点触发的事件对于性能分析,数据追踪等很重要。
笔者曾参与二开某 PHP项目,由于日志筛选等级较低,大量PHP语法警告充斥在日志文件,对硬盘造成了很大伤害,也严重影响到正常的网页文件读取(类似于CGI形式的混编即使用缓存也不方便)。
原料准备
输出到命令行时文本着色,个人采用第三方模块 colors
进行处理。此时相当于为 String 类型动态赋予了具有着色功能的内部方法,因此无需赋值给任何变量;
字符串格式化,需要用到 util.format
方法,可直接嵌套在代码中,本例独立出来;该方法具备自动追加条目间空格的功能,因此各个条目之间会自带一个空格。
require('colors');
const util = require('util');
模块开发
时间戳转换
首先是一个数字格式化方法,通过前导0的方式进行位数补全;然后读取当前时间的各个节点,通过占位符进行格式化输出。
function p(n,s) {return ('0000' + s).substr(-n)}
function getDate() {
let a = new Date;
return util.format('%s-%s-%s %s:%s:%s:%s ',
a.getFullYear(),
p(2, a.getMonth()+1),
p(2, a.getDate()),
p(2, a.getHours()),
p(2, a.getMinutes()),
p(2, a.getSeconds()),
p(3, a.getMilliseconds())
);
}
解析不定项参数
通常,我们会直接输出基本数据类型,形如console.log(123, 'abc')
,当遇到 Object 类型或者 Array,直接输出往往不能达到想要的效果,因此需要借助JSON.stringify(object)
进行转化。
/**
* 使用进程的标准输出模块,展开数组所有条目的内容
* @param tips 日志类型,String
* @param a 输出内容,Array
* @param c 文本颜色,String
**/
function w(tips, a, c) {
let u = [];
for (let i of a) u.push(typeof i != 'object' ? i : util.inspect(i));
process.stdout.write((tips + getDate() + util.format(...u) + '\n')[c]);
}
覆盖原有方法
将参数本身再次作为参数传递到解析模块,由解析模块负责输出。console.debug
方法中,变量debug
为全局变量,即全局测试模式下代理执行console.log
,而在正式环境中则没有任何输出。
console.log = function(){w('LOG ', arguments, 'gray')};
console.trace = function(){w('TRACE ', arguments, 'blue')};
console.info = function(){w('INFO ', arguments, 'green')};
console.warn = function(){w('WARN ', arguments, 'yellow')};
console.error = function(){w('ERROR ', arguments, 'red')};
console.debug = function(){if(debug) console.log(...arguments)};
总结
整体优化只有26行代码,已经足够我们在生产环境中使用。为什么我用很简短的变量名来代替正常的语义性的单词呢?因为执行效率更高。
与PM2的融合过程中,发现由于PM2也包含文本着色处理,上述代码中的颜色标记将会被忽略,文本格式依旧保持,目前尚未寻找解决办法。
网友评论