• 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.

  • 相关阅读:
    不同分辨率在线查看
    HtmlAgilityPack
    CSS知识点记录
    移动端和PC端区分
    Oracle命令
    Navicat操作Oracle
    用 Maven 做项目构建
    Java 异常处理的误区和经验总结
    ExtJs4学习(三)组件查找 ComponentQuery类
    Extjs4 操作TreeStore 处理proxyAjax 获取的数据
  • 原文地址:https://www.cnblogs.com/liuhe688/p/9618549.html
Copyright © 2020-2023  润新知