Node: 通过Console打印日志 (Log Message via Console)
In normal development, we are likely to use 'console.log' for message logging, yet it’s simple, we are unfortunately not able to persist the messages in production mode. And you may look for some third party libraries to meet this demand, actually we can easily achieve it via 'Console' object, so why don’t implement one by ourselves?
Today I will show you a simple logger program with 'Console' object, and imitate a real logger library.
As we mentioned above, we often use 'console.log' for printing message on terminal, in fact, the 'console' is a module in Node.js, we can import explicitly with require('module'), but unnecessary, because it's also a build-in global variable, that's why we can use it directly.
Since the global console instance configured to write to 'process.stdout' and 'process.stderr', the two forms below will behave the same:
// to stdout
console.log('hello');
// to stderr
console.warn('warn');
console.error('error');
// they are equivalent to:
// create our own console
let myConsole = new console.Console(process.stdout, process.stderr);
// to stdout
myConsole.log('hello');
// to stderr
myConsole.warn('warn');
myConsole.error('error');
What if we change process.stdout and process.stderr to other streams? The file streams, for an instance:
// index.js
let fs = require('fs');
let options = {
flags: 'a', // append mode
encoding: 'utf8', // utf8 encoding
};
let stdout = fs.createWriteStream('./stdout.log', options);
let stderr = fs.createWriteStream('./stderr.log', options);
let logger = new console.Console(stdout, stderr);
// to stdout.log file
logger.log('hello');
// to stderr.log file
logger.warn('warn');
logger.error('error');
Run the code it will create two files: 'stdout.log' and 'stderr.log', and write messages into them:


And then, we can improve it slightly by adding datetime prefix to the message, which make it more like a real log library:
// index.js
let fs = require('fs');
// add a format prototype function
Date.prototype.format = function (format) {
if (!format) {
format = 'yyyy-MM-dd HH:mm:ss';
}
// pad with 0
let padNum = function (value, digits) {
return Array(digits - value.toString().length + 1).join('0') + value;
};
let cfg = {
yyyy: this.getFullYear(), // year
MM: padNum(this.getMonth() + 1, 2), // month
dd: padNum(this.getDate(), 2), // day
HH: padNum(this.getHours(), 2), // hour
mm: padNum(this.getMinutes(), 2), // minute
ss: padNum(this.getSeconds(), 2), // second
fff: padNum(this.getMilliseconds(), 3), // millisecond
};
return format.replace(/([a-z])(\1)*/ig, function (m) {
return cfg[m];
});
}
let options = {
flags: 'a', // append mode
encoding: 'utf8', // utf8 encoding
};
let stdout = fs.createWriteStream('./stdout.log', options);
let stderr = fs.createWriteStream('./stderr.log', options);
let logger = new console.Console(stdout, stderr);
for (let i = 0; i < 100; i++) {
let time = new Date().format('yyyy-MM-dd HH:mm:ss.fff');
logger.log(`[${time}] - log message ${i}`);
logger.error(`[${time}] - err message ${i}`);
}
Run the code again, and take a look at the file contents:


Looks pretty, isn't it? Now we should think about a question, how to log message into new files according to some rules? By doing so, we can easily locate the exact logs. Yeah, that's the so-called 'rolling' policy.
We will be rolling the logs by time here.
'node-schedule' is great module for this feature, it's a flexible and easy-to-use job scheduler for Node.js, and we can create our policy based on it.
The following program is bound to print the message at the beginning of every minute:
let schedule = require('node-schedule');
// invoke the function at each time which second is 0
schedule.scheduleJob({second: 0}, function() {
console.log('rolling');
});
And accordingly, 'minute: 0' config will run the function code at the beginning of each hour, 'hour: 0' config will run it at the beginning of each day.
Going back to our logger program, now all we need to do is create a new 'logger' instance for new stream files and replace the old one, let's change the code for adding a schedule:
let fs = require('fs');
let schedule = require('node-schedule');
// add a format prototype function
Date.prototype.format = function (format) {
if (!format) {
format = 'yyyy-MM-dd HH:mm:ss';
}
// pad with 0
let padNum = function (value, digits) {
return Array(digits - value.toString().length + 1).join('0') + value;
};
let cfg = {
yyyy: this.getFullYear(), // year
MM: padNum(this.getMonth() + 1, 2), // month
dd: padNum(this.getDate(), 2), // day
HH: padNum(this.getHours(), 2), // hour
mm: padNum(this.getMinutes(), 2), // minute
ss: padNum(this.getSeconds(), 2), // second
fff: padNum(this.getMilliseconds(), 3), // millisecond
};
return format.replace(/([a-z])(\1)*/ig, function (m) {
return cfg[m];
});
};
function getLogger() {
let options = {
flags: 'a', // append mode
encoding: 'utf8', // utf8 encoding
};
// name the file according to the date
let time = new Date().format('yyyy-MM-dd');
let stdout = fs.createWriteStream(`./stdout-${time}.log`, options);
let stderr = fs.createWriteStream(`./stderr-${time}.log`, options);
return new console.Console(stdout, stderr);
}
let logger = getLogger();
// alter the logger instance at the beginning of each day
schedule.scheduleJob({hour: 0}, function() {
logger = getLogger();
});
// logging test
setInterval(function () {
for (let i = 0; i < 100; i++) {
let time = new Date().format('yyyy-MM-dd HH:mm:ss.fff');
logger.log(`[${time}] - log message ${i}`);
logger.error(`[${time}] - err message ${i}`);
}
}, 1000);
It's done, we will get two new log files at 00:00 of each day, and all messages will be writen into them.
Now, a simple logger program is completed, and it can be published as a library after proper encapsulation.
Node: 通过Console打印日志 (Log Message via Console)的更多相关文章
- python打印日志log
整理一个python打印日志的配置文件,是我喜欢的格式. # coding:utf-8 # 2019/11/7 09:19 # huihui # ref: import logging LOG_FOR ...
- 打印日志 Log
Log.v(tag,msg);所有内容 Log.d(tag,msg);debug Log.i(tag,msg);一般信息 Log.w(tag,msg);警告信息 Log.e(tag,msg);错误信息
- Android学习----打印日志Log
Log.v(tag,msg);所有内容 Log.d(tag,msg);debug Log.i(tag,msg);一般信息 Log.w(tag,msg);警告信息 Log.e(tag,msg);错误信息 ...
- 大数据项目中js中代码和java中代码(解决Tomcat打印日志中文乱码)
Idea2018中集成Tomcat9导致OutPut乱码找到tomcat的安装目录,打开logging.properties文件,增加一行代码,覆盖默认设置,将日志编码格式修改为GBK.java.ut ...
- Node.js系列文章:利用console输出日志文件
通常我们在写Node.js程序时,都习惯使用console.log打印日志信息,但这也仅限于控制台输出,有时候我们需要将信息输出到日志文件中,实际上利用console也可以达到这个目的的,今天就来简单 ...
- Log打印日志遇到的问题
Log日志打印出现空指针问题 AndroidRuntime(372): Caused by: java.lang.NullPointerException: println needs a messa ...
- 使用log4j2打印Log,log4j不能打印日志信息,log4j2不能打印日志信息,log4j和logj2,idea控制台信息乱码(文末)
说来惭愧,今天就写了个"hello world",了解了一下log4j的日志. 本来是想在控制台打印个log信息,也是遇到坎坷重重,开始也没去了解log4j就来使用,log4j配置 ...
- Ubuntu系统配置日志/var/log/message
ubuntu系统默认不生成/var/log/messages文件,有时候想查看相关日志就很不方便,于是我们可以设置使系统生成此文件. 1.先安装 apt-get install rsyslog2.用v ...
- rsyslog 不打印日志到/var/log/messages
*.info;mail.none;authpriv.none;cron.none;local3.none /var/log/messages 表示 所有来源的info级别都记录到/var/log/me ...
随机推荐
- JDBC连接抽象方法的使用例子
package com.zdlt.auth.api.base.datasource; import java.sql.*; import java.util.ArrayList; import jav ...
- Android studio:URI is not registered 的解决办法
今天新导入一个android studio的工程,发现在布局文件中报URI is not registerd的错误,布局文件的命名空间变成红色的了. 解决方案: 进入 File->Setting ...
- Linux(CentOS)安装JDK1.8
1.JDK的RPM包安装方式: https://www.cnblogs.com/hunttown/p/5450463.html 2.JDK的tar包安装方式: 首先,从SUN公司网站下载最新的JDK ...
- matlab学习笔记11_3高维数组操作 filp, shiftdim, size, permute, ipermute
一起来学matlab-matlab学习笔记11 11_3 高维数组处理和运算 filp, shiftdim, size, permute, ipermute 觉得有用的话,欢迎一起讨论相互学习~Fol ...
- mockito的用法
well,说来惭愧,之前一直知道有这么个东西,但总是看不进去.刚好趁着这次迭代间隙有些闲暇,认真看了下,大概明白是怎么回事了. 首先,mock是个概念,这个词的本意就是“虚假的”.“模仿的”.在测试的 ...
- robotframework启动ride失败,提示wxpython ImportError: DLL load failed: 找不到指定的模块
背景:按照rf的操作,安装是没有问题,就是在启动ride.py 这个文件,就有问题了,提示 wxpython ImportError: DLL load failed: 找不到指定的模块 在pytho ...
- Apache显示目录列表及icons目录的问题
今天想部署下开源项目pig,发现它的mysql需要5.7.8 +,为了能支持多个版本并且可以方便切换,所以选择了phpstudy_pro 刚开始Apache不支持目录访问 修改配置 <Virtu ...
- 将你的数据导入到json格式
不知道为什么大家那么偏爱json格式,清晰?跨平台?或许这都是它的优点吧,之前我都是将我的数据放到txt中,今后就用json吧.初步写了一个写入json的模板,就这么用吧. def get_qq_05 ...
- Oracle Spatial分区应用研究之七:同等分区粒度下全局索引优于分区索引的原因分析
1.实验结论 同等分区粒度下,使用分区空间索引进行空间查询,比使用全局空间索引进行查询,对数据字典表的访问次数更多.假设分区数为X,则大概多3X次访问.具体说明见6实验结论. 2.实验目的 在之前的测 ...
- Linux学习、Mongodb部署 踩到的坑学习
一.安装Centos 7虚拟机系统 1.系统安装 下载阿里云的镜像,下载后安装,默认全程图形界面:虚拟机使用Win10自带的Hyper:碰到的坑记录下 1.在Hyper加载镜像启动的时候,提示“虚拟机 ...