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实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

redis中使用lua脚本的原理与基本使用详解

《redis中使用lua脚本的原理与基本使用详解》在Redis中使用Lua脚本可以实现原子性操作、减少网络开销以及提高执行效率,下面小编就来和大家详细介绍一下在redis中使用lua脚本的原理... 目录Redis 执行 Lua 脚本的原理基本使用方法使用EVAL命令执行 Lua 脚本使用EVALSHA命令

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

使用Python和Pyecharts创建交互式地图

《使用Python和Pyecharts创建交互式地图》在数据可视化领域,创建交互式地图是一种强大的方式,可以使受众能够以引人入胜且信息丰富的方式探索地理数据,下面我们看看如何使用Python和Pyec... 目录简介Pyecharts 简介创建上海地图代码说明运行结果总结简介在数据可视化领域,创建交互式地

Java Stream流使用案例深入详解

《JavaStream流使用案例深入详解》:本文主要介绍JavaStream流使用案例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录前言1. Lambda1.1 语法1.2 没参数只有一条语句或者多条语句1.3 一个参数只有一条语句或者多

Java Spring 中 @PostConstruct 注解使用原理及常见场景

《JavaSpring中@PostConstruct注解使用原理及常见场景》在JavaSpring中,@PostConstruct注解是一个非常实用的功能,它允许开发者在Spring容器完全初... 目录一、@PostConstruct 注解概述二、@PostConstruct 注解的基本使用2.1 基本代

C#使用StackExchange.Redis实现分布式锁的两种方式介绍

《C#使用StackExchange.Redis实现分布式锁的两种方式介绍》分布式锁在集群的架构中发挥着重要的作用,:本文主要介绍C#使用StackExchange.Redis实现分布式锁的... 目录自定义分布式锁获取锁释放锁自动续期StackExchange.Redis分布式锁获取锁释放锁自动续期分布式

springboot使用Scheduling实现动态增删启停定时任务教程

《springboot使用Scheduling实现动态增删启停定时任务教程》:本文主要介绍springboot使用Scheduling实现动态增删启停定时任务教程,具有很好的参考价值,希望对大家有... 目录1、配置定时任务需要的线程池2、创建ScheduledFuture的包装类3、注册定时任务,增加、删

使用Python实现矢量路径的压缩、解压与可视化

《使用Python实现矢量路径的压缩、解压与可视化》在图形设计和Web开发中,矢量路径数据的高效存储与传输至关重要,本文将通过一个Python示例,展示如何将复杂的矢量路径命令序列压缩为JSON格式,... 目录引言核心功能概述1. 路径命令解析2. 路径数据压缩3. 路径数据解压4. 可视化代码实现详解1