nest日志包pino、winston配置-懒人的折腾

nest日志

三种node服务端日志选型

2023年5月23日

看star数:winston > pino > log4js

使用体验:

  1. pino 格式简洁,速度快,支持输入日志到任意数据库,日志暂无自动清理(可能是我方式不对?知道的朋友评论下告诉我,十分感谢~)
  2. winston 通用,稳定,日志可自动清理。
  3. log4js 不知为啥,不想使用,除非你劝我。

pino

目前使用 pino

npm install pino nestjs-pino pino-http
npm install nanoid
npm install pino-pretty -D
npm install pino-roll -D

pino-pretty: 格式化用
pino-roll: 日志,设置文件大小,分割周期,日志名。

特点:

  • Pino的内部架构基于Worker Threads
  • 配置简单
  • 支持日志类型指定输出到不同文件(会导致速度慢)
  • 支持输出日志到任意数据库中

问题:日志需要自己做定时任务清理,避免占用内存。

main.ts

import { Logger } from 'nestjs-pino';
const app = await NestFactory.create<NestExpressApplication>(AppModule, {
    bufferLogs: true, // 使用外部的日志包pino
  });
  app.useLogger(app.get(Logger));
  app.flushLogs();

logger.config.ts

import { nanoid } from 'nanoid';
import type { Request } from 'express';
import { IncomingMessage } from 'http';
import type { Params } from 'nestjs-pino';
import { multistream } from 'pino';
import type { ReqId } from 'pino-http';
import { join } from 'path';
import { format } from 'date-fns';
const passUrl = new Set(['./health']);
export const loggerOptions: Params = {
  pinoHttp: [
    {
      // https://getpino.io/#/docs/api?id=timestamp-boolean-function
      quietReqLogger: true,
      genReqId: (req: IncomingMessage): ReqId =>
        (<Request>req).header('X-Request-id') || nanoid(),
      ...(process.env.NODE_ENV === 'production'
        ? {
            // https://www.npmjs.com/package/pino-roll
            level: 'error',
            transport: {
              target: 'pino-roll',
              options: {
                file: join('logs', 'log'),
                size: '10m',
                // 周期
                frequency: 'daily',
                mkdir: true,
                extension: `.${format(new Date(), 'yyyy-MM-dd')}.json`,
              },
            },
          }
        : {
            level: 'debug',
            transport: {
              // https://github.com/pinojs/pino-pretty
              target: 'pino-pretty',
              options: { sync: true, colorize: true },
              // options: { sync: true, singleLine: true, colorize: true }, // 生产环境再设置压缩为一行
            },
          }),
      autoLogging: {
        ignore: (req: IncomingMessage) =>
          passUrl.has((<Request>req).originalUrl),
      },
    },
    multistream(
      [
        { level: 'debug', stream: process.stdout },
        { level: 'error', stream: process.stdout },
        { level: 'fatal', stream: process.stdout },
      ],
      { dedupe: true }, // 删除重复输出
    ),
  ],
};

其他设置模式,不如上面的设置,少了日志分割和文件大小配置,但pino还有流操作,里面可以写逻辑,自己写怎么分割日志或者限制文件大小等,等于自配。

// 1. pino/file
const file =
  process.cwd() + `/logs/log-${format(new Date(), 'yyyy-MM-dd')}.json`;
{
  level: 'info',
  transport: {
    target: 'pino/file',
    options: {
      destination: file, // 1 是直接输出, 2是错误时输出,其他为自己设置的目录文件
      mkdir: true,
    },
  },
}
// 使用内置的pino/file传输和使用pino.destination的区别在于,pino.destination在主线程中运行,而pino/file在工作线程中设置pino.destimation

// 2. pino/file
target: 'pino-pretty',

使用 winston

  • [nest-winston][nest-winston] 日志记录
  • [winston-daily-rotate-file][winston-daily-rotate-file] 配置生产环境日志

npm install --save nest-winston winston
npm install winston-daily-rotate-file

采用[bootstrap配置方式][replacing-the-nest-logger-also-for-bootstrapping]

main.ts

const app = await NestFactory.create<NestExpressApplication>(AppModule, {
  logger: WinstonModule.createLogger({
    instance: createLogger({ ...loggerOptions }),
  }),
});

logger.config.ts

import * as winston from 'winston';
import { utilities as nestWinstonModuleUtilities } from 'nest-winston';
import DailyRotateFile from 'winston-daily-rotate-file';
const format = (label?: string) => {
  switch (label) {
    case 'isDev':
      return {
        format: winston.format.combine(
          winston.format.timestamp(),
          winston.format.ms(),
          nestWinstonModuleUtilities.format.nestLike('nestBk', {
            colors: true,
            prettyPrint: true,
          }),
        ),
      };
    default:
      return {
        format: winston.format.combine(
          winston.format.timestamp(),
          winston.format.ms(),
        ),
      };
  }
};
const prodLoggerConfig = [
  new DailyRotateFile({
    level: 'warn',
    filename: 'nestBk-%DATE%.log',
    dirname: 'logs',
    datePattern: 'YYYY-MM-DD-HH',
    maxSize: '20m',
    maxFiles: '14d',
    zippedArchive: true,
    ...format(),
  }),
  new DailyRotateFile({
    level: 'info',
    filename: 'info-%DATE%.log',
    dirname: 'logs',
    datePattern: 'YYYY-MM-DD-HH',
    maxSize: '20m',
    maxFiles: '14d',
    zippedArchive: true,
    ...format(),
  }),
];

export const loggerOptions = {
  transports: [
    new winston.transports.Console({
      level: 'info',
      ...format('isDev'),
    }),
    ...(IsProMode ? prodLoggerConfig : []),
  ],
};

使用时
xxx.module.ts

  providers: [CatsService, Logger],

xxx.controller.ts

  import { Logger } from '@nestjs/common';
  private readonly logger: Logger,

  this.logger.log('请求成功');
  this.logger.warn('请求警告');
  this.logger.error('请求错误');

在这里插入图片描述
样式没啥变化(反而喜欢pino的简洁样式)

主要是多了个自动到期删除的配置,不用自己手动删除日志
在这里插入图片描述

QA:

  1. nanoid esm 问题,直接降级处理
    官方issues

“nanoid”: “^.4.x.x” => “nanoid”: “^3.3.6”,

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值