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

相关文章

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

MySQL中EXISTS与IN用法使用与对比分析

《MySQL中EXISTS与IN用法使用与对比分析》在MySQL中,EXISTS和IN都用于子查询中根据另一个查询的结果来过滤主查询的记录,本文将基于工作原理、效率和应用场景进行全面对比... 目录一、基本用法详解1. IN 运算符2. EXISTS 运算符二、EXISTS 与 IN 的选择策略三、性能对比

Apache Ignite 与 Spring Boot 集成详细指南

《ApacheIgnite与SpringBoot集成详细指南》ApacheIgnite官方指南详解如何通过SpringBootStarter扩展实现自动配置,支持厚/轻客户端模式,简化Ign... 目录 一、背景:为什么需要这个集成? 二、两种集成方式(对应两种客户端模型) 三、方式一:自动配置 Thick

使用Python构建智能BAT文件生成器的完美解决方案

《使用Python构建智能BAT文件生成器的完美解决方案》这篇文章主要为大家详细介绍了如何使用wxPython构建一个智能的BAT文件生成器,它不仅能够为Python脚本生成启动脚本,还提供了完整的文... 目录引言运行效果图项目背景与需求分析核心需求技术选型核心功能实现1. 数据库设计2. 界面布局设计3

使用IDEA部署Docker应用指南分享

《使用IDEA部署Docker应用指南分享》本文介绍了使用IDEA部署Docker应用的四步流程:创建Dockerfile、配置IDEADocker连接、设置运行调试环境、构建运行镜像,并强调需准备本... 目录一、创建 dockerfile 配置文件二、配置 IDEA 的 Docker 连接三、配置 Do

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符