Nestjs框架: 可集成在Nestjs上的日志模块pino和winston的使用

2024-02-26 02:04

本文主要是介绍Nestjs框架: 可集成在Nestjs上的日志模块pino和winston的使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

日志模块 pino

  • npmjs.com/package/pino

  • getpino.io

  • 安装:$ npm i nestjs-pino

  • 注册:

    import { LoggerModule, Logger } from 'nestjs-pino'@Module({controllers: [AppController],imports: [LoggerModule.forRoot()] // 注意这里
    })
    
  • 在控制器中测试使用

    import { Logger } from 'nestjs-pino'@Controller('user')
    export class UserController {private logger = Loggerconstructor() {this.logger.log('init') // 类似这样,在需要的地方调用}
    }
    
    • 这样写,在访问这个控制器的时候,会打印两次,因为不需要手动调用,所以
    • 需要删除这个 this.logger.log('init') 调用,因为这个是没有必要的
    • 所以 pino 是一个比较适合懒人的库
    • 它会默认打印日志,但是目前看来,日志输出不友好(不好阅读)

友好化 pino 方案

  • $ npm i pino-pretty pino-roll

  • 在 user.module.ts 中

    import { LoggerModule } from 'nestjs-pino'
    const isDev = process.env.NODE_ENV === 'development'
    @Module({imports: [LoggerModule.forRoot({pinoHttp: {transport: isDev ? {target: 'pino-pretty',level: 'info',options: {colorize: true}} : {target: 'pino-roll',level: 'info',options: {file: path.join('log', 'log.txt'), // 文件名称可以用时间frequency: 'daily', // hourlysize: '10m' // 只要超过这个,就会多生成一个文件mkdir: true}}}})]
    })
    
  • 这里开发环境和生产环境用的不同的pino插件

  • pino是一个开箱即用,稍稍配置就可以使用的日志插件

高度集成的日志模块 winston

  • 如果把pino比作成vite, winston就像是webpack

  • npmjs.com/package/winston

  • winston官方没有提供与nestjs集成的demo

  • nest-winston 可以和nestjs高度集成,安装:

    • $ npm i -S nest-winston winston
  • 示例都在 npm 上

  • 找到 文档 Replacing the Nest logger (also for bootstrapping)

    • 这里的配置可以用到nestjs工程里
    • 这里就是在启动的时候,把 nest 的 logger 替换为 winston 的 logger
  • 集成

    // main.ts
    import { transports, format, createLogger } from 'winston';
    import { WinstonModule, utilities } from 'nest-winston';async function bootstrap() {// 第一步 创建 insconst instance = createLogger({transports: [new transports.Console({format: format.combine(format.timestamp(),utilities.format.nestLike(),)})]})const app = await NestFactory.create(AppModule, {// 第二步 配置 loggerlogger: WinstonModule.createLogger({instance, // 使用 ins})})
    }
    
  • 通过以上就创建好了,但是 还要在 app.module.ts 中全局提供logger

    import { Logger, Module } from '@nestjs/common'@Module({providers: [Logger] // 后面进行 DI 依赖注入
    })export class AppModule {}
    
  • 这里为什么要导入 @nestjs/common 中的 logger

    • 我们可以使用 implements LoggerService 来重构官方的logger方法
    • 如果使用官方的 demo 在user.controller.ts中来使用 @Inject来注册则会报错
  • 解决问题

    • 我们替换了nestjs默认的logger, 并且在app.module.ts中providers提供了logger
    • 但是其他模块并不知道,这样,有3种解决方式
      • 第一种是每个controller中引用的时候,在对应的module,比如user.module.ts的 providers中提供,不推荐
        • 参考:https://github.com/gremo/nest-winston/tree/main/sample/replace-nest-logger-bootstrap/src
        • 这里写法和上面我们的一致,它在自己的控制器中引入,并使用
        • 我们知道Nest整个系统的运行是先告诉自己的DI, 哪些实例去进行注册,模块与模块之间如果要相互引用
        • 就要把它 export 出来 或者把这个模块注册成为一个全局模块,其他模块才能去使用
        • 所以这个问题就是,DI系统不知道 Logger 从哪里来,虽然替换了 Nestjs中的 Logger, 并且在 app.module中提供了Logger
        • 但是其他模块并不知道,常见的处理方法是,比如 user.module中需要,就在 user.module.ts 中的providers中再次配置一次 Logger
        • 但是这就比较麻烦了
      • 第二种是在app.module.ts中providers下面加一个exports的配置,在其他模块进行import即可
        • 在 app.module 中添加 exports
          // app.module
          providers: [Logger]
          exports: [Logger]
          
          • 在其他模块,比如在user.module中进行import
      • 第三种是全局使用:
        • 如果想让logger变成全局模块,logger中的方法在全局可直接使用,则需要这样
          import {} from '@nest/common'
          // app.module
          @Global() // 加上global
          @Module({}) // 内部不变,仍要加 exports
          
        • 也就是说使用Global注解,将app.module模块全局模块
        • 使用的时候,在 user.module 中,其实这个logger 不需要这样写,在 constructor 参数中
          import { Logger } from '@nestjs/common'
          constructor(private userService: UserService,private configService: ConfigService,@Inject(Logger) private readonly logger: LoggerService
          )
          
        • 换成下面的写法
          import { Logger } from '@nestjs/common'
          constructor(private userService: UserService,private configService: ConfigService,private readonly logger: Logger, // 注意这里
          )
          
        • 之后,就可以在某个方法(API)中进行测试了
          this.logger.log('test log', UserController.name)
          this.logger.warn('test warn', UserController.name)
          this.logger.error('test error', UserController.name)
          this.logger.debug('test debug', UserController.name)
          this.logger.verbose('test verbose', UserController.name)
          
        • 像是上面几种,都是有颜色区分的

winston的滚动日志

  • 安装 winston-daily-rotate-file 这个库 $ npm i -S winston-daily-rotate-file
  • 安装后,在main.ts中
    import 'winston-daily-rotate-file'// 之后在 bootstrap 的 createLogger中的 transports中 新 new 一个
    // 而且提供一些 events: archive, 
    new winston.transports.DailyRotateFile({// ...填入官方配置level: 'warn',dirname: 'logs', // 在生产环境中指定一个绝对路径比较好,方便做一个文件映射filename: 'application-%DATE%log'datePattern: 'YYYY-MM-DD-HH',zippedArchive: true, // 对文件压缩maxSize: '20m',maxFiles: '14d', // 超过14天会自动删除format: winston.format.combine(winston.format.timestamp(),utilities.format.nestLike(),// winston.format.simple(), // 打印简洁版本)
    })
    
  • 它提供的 events 比如每次打包的时候,archive; 执行的时候 rotate
  • 注意,上述 new winston.transports.DailyRotateFile 方法可以复制多份
  • 比如基于 level 配置项的不同,而进行不同的打印或输出
  • 当然可以封装一个方法来复用,参数化进行区分
  • 更多信息,浏览文档

总结

  • 两个第三方的包:winston, pino
    • winston好处:DailyRotateFile 方便
    • winston缺点:是需要在自己手动加入日志,, 麻烦
    • pino的好处:开箱即用
    • pino的缺点:配置没有winston丰富
  • Nest官方内置的日志,够用,但是不详细
  • 关于选择
    • 懒人用pino, 而且性能较高
    • 用 winston,一般日志手动加,方便调试

这篇关于Nestjs框架: 可集成在Nestjs上的日志模块pino和winston的使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/747387

相关文章

Python使用PIL库将PNG图片转换为ICO图标的示例代码

《Python使用PIL库将PNG图片转换为ICO图标的示例代码》在软件开发和网站设计中,ICO图标是一种常用的图像格式,特别适用于应用程序图标、网页收藏夹图标等场景,本文将介绍如何使用Python的... 目录引言准备工作代码解析实践操作结果展示结语引言在软件开发和网站设计中,ICO图标是一种常用的图像

使用Java发送邮件到QQ邮箱的完整指南

《使用Java发送邮件到QQ邮箱的完整指南》在现代软件开发中,邮件发送功能是一个常见的需求,无论是用户注册验证、密码重置,还是系统通知,邮件都是一种重要的通信方式,本文将详细介绍如何使用Java编写程... 目录引言1. 准备工作1.1 获取QQ邮箱的SMTP授权码1.2 添加JavaMail依赖2. 实现

MyBatis与其使用方法示例详解

《MyBatis与其使用方法示例详解》MyBatis是一个支持自定义SQL的持久层框架,通过XML文件实现SQL配置和数据映射,简化了JDBC代码的编写,本文给大家介绍MyBatis与其使用方法讲解,... 目录ORM缺优分析MyBATisMyBatis的工作流程MyBatis的基本使用环境准备MyBati

使用Python开发一个图像标注与OCR识别工具

《使用Python开发一个图像标注与OCR识别工具》:本文主要介绍一个使用Python开发的工具,允许用户在图像上进行矩形标注,使用OCR对标注区域进行文本识别,并将结果保存为Excel文件,感兴... 目录项目简介1. 图像加载与显示2. 矩形标注3. OCR识别4. 标注的保存与加载5. 裁剪与重置图像

使用Python实现表格字段智能去重

《使用Python实现表格字段智能去重》在数据分析和处理过程中,数据清洗是一个至关重要的步骤,其中字段去重是一个常见且关键的任务,下面我们看看如何使用Python进行表格字段智能去重吧... 目录一、引言二、数据重复问题的常见场景与影响三、python在数据清洗中的优势四、基于Python的表格字段智能去重

Spring AI集成DeepSeek三步搞定Java智能应用的详细过程

《SpringAI集成DeepSeek三步搞定Java智能应用的详细过程》本文介绍了如何使用SpringAI集成DeepSeek,一个国内顶尖的多模态大模型,SpringAI提供了一套统一的接口,简... 目录DeepSeek 介绍Spring AI 是什么?Spring AI 的主要功能包括1、环境准备2

Spring AI集成DeepSeek实现流式输出的操作方法

《SpringAI集成DeepSeek实现流式输出的操作方法》本文介绍了如何在SpringBoot中使用Sse(Server-SentEvents)技术实现流式输出,后端使用SpringMVC中的S... 目录一、后端代码二、前端代码三、运行项目小天有话说题外话参考资料前面一篇文章我们实现了《Spring

使用Apache POI在Java中实现Excel单元格的合并

《使用ApachePOI在Java中实现Excel单元格的合并》在日常工作中,Excel是一个不可或缺的工具,尤其是在处理大量数据时,本文将介绍如何使用ApachePOI库在Java中实现Excel... 目录工具类介绍工具类代码调用示例依赖配置总结在日常工作中,Excel 是一个不可或缺的工http://

Java之并行流(Parallel Stream)使用详解

《Java之并行流(ParallelStream)使用详解》Java并行流(ParallelStream)通过多线程并行处理集合数据,利用Fork/Join框架加速计算,适用于大规模数据集和计算密集... 目录Java并行流(Parallel Stream)1. 核心概念与原理2. 创建并行流的方式3. 适

SpringBoot集成图片验证码框架easy-captcha的详细过程

《SpringBoot集成图片验证码框架easy-captcha的详细过程》本文介绍了如何将Easy-Captcha框架集成到SpringBoot项目中,实现图片验证码功能,Easy-Captcha是... 目录SpringBoot集成图片验证码框架easy-captcha一、引言二、依赖三、代码1. Ea