前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为什么 Node 里要用 Winston 打印日志?

为什么 Node 里要用 Winston 打印日志?

作者头像
神说要有光zxg
发布2023-10-29 19:15:11
2720
发布2023-10-29 19:15:11
举报

Node 里怎么打印日志呢?

有同学说,不也是用 console.log 么。

不,服务端打印日志一般不会用 console.log。

因为 console.log 打印完就没了,而服务端的日志经常要用来排查问题,需要搜索、分析日志内容,所以需要写入文件或者数据库里。

而且打印的日志需要分级别,比如有的是错误的日志,有的只是普通日志,需要能够过滤不同级别的日志。

此外,打印的日志需要带上时间戳,所在的代码位置等信息。

这些都是 console.log 没有的功能。

所以我们一般都会用专门的日志框架来做,比如 winston。

它是 Node 最流行的日志框架,npm 官网上可以看到每周千万级的下载量:

那 winston 都有什么功能?怎么用呢?

我们试试看:

代码语言:javascript
复制
mkdir winston-test
cd winston-test
npm init -y

先创建个项目。

安装 winston:

代码语言:javascript
复制
npm install --save winston

然后写下 index.js

代码语言:javascript
复制
import winston from 'winston';

const logger = winston.createLogger({
    level: 'debug',
    format: winston.format.simple(),
    transports: [
        new winston.transports.Console(),
        new winston.transports.File({ 
            dirname: 'log', filename: 'test.log' 
        }),
    ]
});

logger.info('光光光光光光光光光');
logger.error('东东东东东东东东');
logger.debug(66666666);

用 createLogger 创建了 logger 实例,指定 level、format、tranports。

level:打印的日志级别

format:日志格式

transports:日志的传输方式

我们指定了 Console 和 File 两种传输方式。

在 package.json 里指定 type 为 module,也就是所有代码都是 es module 的:

这样代码里就可以直接用 import、export 这些语法了。

用 node 跑一下:

代码语言:javascript
复制
node index.js

可以看到控制台和文件里都有了打印的日志。

再跑一遍:

代码语言:javascript
复制
node index.js

会在后面追加:

那么问题来了,如果所有日志都写在一个文件里,那这个文件最终会不会特别大?

不用担心,winston 支持按照大小自动分割文件:

我们指定 maxsize 为 1024 字节,也就是 1kb。

然后再跑几次:

大概跑了 10 次左右,出现了第二个文件:

而这时第一个日志文件刚好是 1kb:

这就是根据大小自动分割日志文件的功能。

有同学说,一般日志都是按照日期自动分割的,比如 2023-10-28 的日志文件,2023-10-29 的日志文件,这样之后也好管理。

这个支持么?

当然支持,但是要换别的 Transport 了。

在 winston 文档里可以看到有很多 Transport:

Console、File、Http、Stream 这几个 Transport 是内置的。

下面还有很多社区的 Transport,比如 MongoDB 的 Transport,很明显就是把日志写入 mongodb 的。

这里的 DailyRotateFile 就是按照日期滚动存储到日志文件的 Transport。

我们试试看:

代码语言:javascript
复制
npm install --save winston-daily-rotate-file

安装这个 Transport。

然后改下代码:

代码语言:javascript
复制
import winston from 'winston';
import 'winston-daily-rotate-file';

const logger = winston.createLogger({
    level: 'debug',
    format: winston.format.simple(),
    transports: [
        new winston.transports.Console(),
        new winston.transports.DailyRotateFile({
            level: 'info',
            dirname: 'log2',
            filename: 'test-%DATE%.log',
            datePattern: 'YYYY-MM-DD-HH-mm',
            maxSize: '1k'
        })
    ]
});

logger.info('光光光光光光光光光');
logger.error('东东东东东东东东');
logger.debug(66666666);

这里使用了 DailyRotateFile 的 transport,然后指定了文件名和日期格式。

指定文件名里的日志格式包含分钟,所以不同的分钟打印的日志会写入不同文件里:

这就达到了滚动日志的效果。

基本上,内置的和社区的 transport 就足够用了,不管是想把日志发送到别的服务,还是把日志存到数据库等,都可以用不同 Transport 实现。

再就是日志级别,winston 有 6 种级别的日志:

从上往下,重要程度依次降低。

比如当你指定 level 是 info 时,那 info、warn、error 的日志会输出,而 http、debug 这些不会。

日志级别的功能虽然简单,但却是很实用的功能。

日志可以通过 format 指定格式:

simple:

json:

prettyPrint(比 json 的格式多了一些空格):

用 combine 组合 timestamp 和 json:

或者再组合个 label:

加上个标签,再搜索相关日志就方便多了。

彩色:

通过这些,就可以指定各种日志格式。

但现在有个问题,如果我不同的 transport 要指定不同的格式呢?

可以这样:

代码语言:javascript
复制
import winston from 'winston';

const logger = winston.createLogger({
    level: 'debug',
    transports: [
        new winston.transports.Console({
            format: winston.format.combine(
                winston.format.colorize(),
                winston.format.simple()
            ),
        }),
        new winston.transports.File({ 
            dirname: 'log3',
            filename: 'test.log',
            format: winston.format.json()
        }),
    ]
});

logger.info('光光光光光光光光光');
logger.error('东东东东东东东东');
logger.debug(66666666);

每个 transport 单独指定 format 就好了。

那如果我有的日志只想 console,而有的日志希望写入文件,而且配置都不同呢?

我们可以创建多个 logger 实例,每个 logger 实例有不同的 format、transport、level 等配置:

代码语言:javascript
复制
import winston from 'winston';

winston.loggers.add('console', {
    format: winston.format.combine(
        winston.format.colorize(),
        winston.format.simple()
    ),
    transports: [
        new winston.transports.Console()
    ]
});

winston.loggers.add('file', {
    format:winston.format.combine(
        winston.format.timestamp(),
        winston.format.json()
    ),
    transports: [
        new winston.transports.File({
            dirname: 'log4',
            filename: 'test.log',
            format: winston.format.json()
        })
    ]
});


const logger1 = winston.loggers.get('console');

logger1.info('aaaaa');
logger1.error('bbbbb');

const logger2 = winston.loggers.get('file');

logger2.info('xxxx');
logger2.info('yyyy');

我们创建了 2 个 logger 实例,其中一个只写入 console,另一个只写入 file,并且 format 都不同。

然后分别用不同的 logger 来打印日志。

这样,项目中有不同的日志需求的时候,就可以创建多个 logger 实例。

总结

Node 服务端我们不会用 console.log 打印日志,而是会用日志框架,比如 winston。

winston 支持 tranport 配置,可以把日志传输到 console、file、通过 http 发送到别的服务,写入 mongodb 数据库等。

社区有很多 transport 可用,我们尝试了滚动日志的 transport,可以根据日期来自动分割日志文件。

winston 还支持 level 配置,可以根据级别来过滤日志。

而且还支持 format 的设置,比如 json、simple、label、timstamp 等,一般我们输出到文件里的都是 json 格式,并且给他加上时间戳和 label,这样方便之后分析。

每个 transport 都可以单独指定 format,而且还可以创建多个 logger,每个 logger 用不同的配置。

总之,相比直接 console.log,用 winston 这样的灵活强大的日志框架可太香了。

本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-10-28,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 神光的编程秘籍 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 总结
相关产品与服务
云数据库 MongoDB
腾讯云数据库 MongoDB(TencentDB for MongoDB)是腾讯云基于全球广受欢迎的 MongoDB 打造的高性能 NoSQL 数据库,100%完全兼容 MongoDB 协议,支持跨文档事务,提供稳定丰富的监控管理,弹性可扩展、自动容灾,适用于文档型数据库场景,您无需自建灾备体系及控制管理系统。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com