NodeJS 中的日志记录

Isaac Tony 2023年1月30日 2022年5月13日
  1. 在 NodeJS 中使用 Logging 创建和存储日志
  2. 在 NodeJS 中使用 console.log() 跟踪程序执行
  3. 结论
NodeJS 中的日志记录

Logging 是记录应用程序流程和行为的过程。Logging 应该在生产模式下执行到更持久的输出流。

除了帮助应用程序开发之外,记录是调试复杂应用程序的一个重要方面。

此外,日志提供了重要信息,可用作审计跟踪以监控系统行为并更快地诊断问题。

在 NodeJS 中使用 Logging 创建和存储日志

在生产环境中,正确存储的日志文件也可以用作分析的数据源,并简化新功能的开发过程。

并非应监控应用程序的所有方面。决定记录哪些信息是记录过程的重要部分。

某些无法记录的数据类型包括个人数据,例如用户名信用卡号密码

在 Node js 和大多数编程语言中,各种日志级别可以告知要记录什么样的数据。它们包括:

  • 警告
  • 错误
  • 信息
  • 调试
  • 详细

在 NodeJS 中使用 console.log() 跟踪程序执行

我们可以使用各种方法在 Node js 中创建和管理日志文件。

console.log() 函数是最基本的方法之一,也许是开发阶段使用最多的方法。其他类似的方法包括 console.err()console.warn()

console.log()console.err() 方法允许我们将消息记录到标准输出 stdout 和标准错误 stderr

在下面的示例中,我们使用 console.log() 来跟踪程序执行。

ages = [34, 33, 37, 29, 12, 10, 42, 44];

function check_ages(item) {
  if (item < 40) {
    console.info(`Age "${item}" is within the required range!`);
  } else {
    console.error(`Age "${item}" is out of the required range!`);
  }
}
for (const age of ages) {
  check_ages(age);
}

输出:

Age "34" is within the required range!
Age "33" is within the required range!
Age "37" is within the required range!
Age "29" is within the required range!
Age "12" is within the required range!
Age "10" is within the required range!
Age "42" is out of the required range!
Age "44" is out of the required range!

现在,虽然使用 console.log() 编写日志消息非常简单,但无法将这种方法用于部署到生产环境的应用程序,因为在这个阶段,你无法访问控制台。

此外,这些方法并不表示任何错误的严重性或紧迫性,因此在构建更强大的应用程序时并不可靠。

假设我们想将这些日志存储在某个文件中以供进一步参考。为此,我们需要将 stdoutstderr 重定向到一个具有 .log 扩展名的文件,该文件将存储这些日志,如下所示。

node index.js > log_info.log

输出:

Age "34" is within the required range!
Age "33" is within the required range!
Age "37" is within the required range!
Age "29" is within the required range!
Age "12" is within the required range!
Age "10" is within the required range!
Age "42" is out of the required range!
Age "44" is out of the required range!
Age "42" is out of the required range!
Age "44" is out of the required range!

使用此处显示的命令将 stderrstdout 日志存储在不同的文件中。

node index.js > stdout_main.log 2> stderr_main.log

这将自动创建包含各自日志的 stdout_main.logstderr_main.log 文件,如下所示。

Age "34" is within the required range!
Age "33" is within the required range!
Age "37" is within the required range!
Age "29" is within the required range!
Age "12" is within the required range!
Age "10" is within the required range!
node : Age "42" is out of the required range!
At line:1 char:1
+ node index.js > stdout_main.log 2> stderr_main.log
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Age "42" is out of the required range!:Strin
   g) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

Age "44" is out of the required range!

虽然这种方法适合生产环境中的开发阶段需求,但我们需要一个更灵活的库来支持所有日志记录级别并允许我们格式化和集中日志。

Winston 平均每周有 9,686,809 次下载,是 Node js 开发人员最喜欢的简单通用日志库。

它易于配置,同时支持不同的日志格式,提供不同的日志通道,也称为传输,还允许我们为日志级别分配不同的优先级。

当我们想要保存或共享我们的日志文件时,我们可以使用 Winston 支持的传输包括:保存到文件、电子邮件、数据库和控制台。

要开始使用 Winston,我们首先需要创建并初始化一个 Node js 应用程序。我们可以使用 npm 包管理器使用以下命令安装 Winston 包。

npm install Winston.

然后我们可以在我们的程序中要求这个包来访问它的功能,如下所示。

const winston = require('winston');

最推荐的使用 Winston 的方法是使用 Winston.createLogger() 方法创建我们的记录器。

由于我们还需要指定传输、级别和格式等配置,我们可以在记录器中创建一个单独的配置对象。

const winston = require('winston');

const logger = winston.createLogger({

  transports: [
    new winston.transports.Console()

  ],

});

一旦配置到位,我们现在可以注销消息。在这种情况下,我们的传输是控制台;因此,我们的消息将显示在控制台中。

const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.Console()

  ],

});

logger.log({

      message: 'This is a message with Info log level !',

      level: 'info'
});

输出:

{"level":"info","message":"This is a message with Info log level !"}

或者,我们可以创建一个单独的配置对象并将对象的名称传递给记录器,如下所示。

const winston = require('winston');

const logConfigs = {
  level: 'info',
  format: winston.format.json(),
  transports: [

    new winston.transports.Console()

  ],

}

const logger = winston.createLogger(logConfigs);

logger.log({

      message: 'This is a message with Info log level !',

      level: 'info'
});

我们还可以将日志文件存储到不同的传输中。在这种情况下,我们希望将日志存储在外部文件夹中的文件中。

为此,我们需要更改配置对象下的传输,而不是新的 Winston.transports.Console() 具有新的 Winston.transports.File 并指定指示如何存储日志文件的位置。

这是一个图示。

const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  'transports': [
    new winston.transports.File({
        filename: 'logs/files.log'
    })
],

});

logger.log({

      message: 'This is a message with Info log level !',

      level: 'info'
});

由于配置对象下 Winstone 包的灵活性,我们可以同时指定多种传输形式。

例如,我们可以指定所有日志都显示在控制台中。同时,其他日志级别(例如错误级别)的日志专门针对外部文件或数据库。

const winston = require('winston');
const logConfigs = {
  transports: [
      new winston.transports.Console({
          level: 'warn'
      }),
      new winston.transports.File({
          level: 'error',
          // Create the log directory if it does not exist
          filename: 'logs/files.log'
      })
  ]
};
const logger = winston.createLogger(logConfigs);

logger.log({

      message: 'This is a message with warn log level !',

      level: 'warn'
  });
  logger.log({

    message: 'This is a message with error log level !',

    level: 'error'
});

输出:

{"level":"warn","message":"This is a message with warn log level !"}
{"level":"error","message":"This is a message with error log level !"}

结论

Winston 包不限于我们上面讨论过的传输介质。我们还可以将日志存储在服务器的数据库中或通过电子邮件共享。

还值得注意的是,Node js 中还有其他存储和管理日志的方式,例如使用中间件软件,如 BunyanLog4jsMorgan

然而,Winston 包脱颖而出,因为它易于配置和灵活。

Author: Isaac Tony
Isaac Tony avatar Isaac Tony avatar

Isaac Tony is a professional software developer and technical writer fascinated by Tech and productivity. He helps large technical organizations communicate their message clearly through writing.

LinkedIn