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,一般日志手动加,方便调试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/702449.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[今天跟AI聊聊职场] ~你能接受你的直接领导能力不如你,年纪还比你小很多吗?

知乎问题: 弟弟今年35岁,刚换了一份工作,直接领导小A比他小5岁,各方面经验没有他成熟。难的工作都是弟弟在做,功劳都被直接领导小A抢走了,有时候还要被直接领导小A打压。弟弟感觉升职加薪无望。现在找工作不…

Movelt使用笔记-Movelt Setup Assistant

目录 Setup Assistant配置1 Start 加载urdf模型3 Virtual joints 虚拟关节5 Robot Poses 机器人位姿7 Passive Joints 被动关节8 Controllers 控制器9 Simulation 仿真10 3D Perception 3D感知11 Author Information 作者信息12 Configuration Files 配置文件启动MoveIt!Setup…

Vulnhub-OSCP

信息收集 # nmap -sn 192.168.1.0/24 -oN live.nmap Starting Nmap 7.94 ( https://nmap.org ) at 2024-02-07 17:49 CST Nmap scan report for 192.168.1.1 Host is up (0.00052s latency). MAC Address: 00:50:56:C0:00:08 (VMware) Nmap scan report for 192.168.1.…

深度解析:Integer.parseInt() 源码解读

深度解析:Integer.parseInt() 源码解读 关键要点 解析字符:用于将字符转换为对应的数字值 Character.digit(s.charAt(i),radix) 确定limit:根据正负号分别设定 int limit -Integer.MAX_VALUE;【正】 limit Integer.MIN_VALUE;【负】 负数…

Java基础知识点:入门篇(一)

目录 Java起源第一个Java程序注意点 Java基本语法Java标识符命名规范(驼峰命名法)注意点 Java修饰符访问控制修饰符privateprotectedpublicdefault 非访问控制修饰符final修饰符abstract修饰符synchronized 修饰符transient 修饰符volatile 修饰符 Java变…

挑战!贪吃蛇小游戏的实现(2)

在贪吃蛇小游戏的实现&#xff08;1&#xff09;中&#xff0c;我们学习了win32 相关的一些知识&#xff0c;本篇文章&#xff0c;博主将带领大家从0开始实现贪吃蛇小游戏&#xff01; 贪吃蛇游戏设计与分析 本地化 <locale.h>实现本地化&#xff0c;该头文件提供的函数…

备战蓝桥杯————二叉树解题思维1

解决二叉树问题时&#xff0c;常采用两种思维模式&#xff1a; 遍历思维模式&#xff1a; 这种思维模式强调是否可以通过一次遍历二叉树来得到答案。通常使用一个遍历函数&#xff08;比如前序、中序、后序遍历&#xff09;结合外部变量来实现。这种方法适用于需要在每个节点上…

QT c++ 海康红外热像仪

//本文描述2通道海康通道红外热像仪预览和抓图 #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); userID-1; …

如何进行JMeter分布式压测?一个案例教你详细解读!

引言 当前快速发展的互联网应用领域&#xff0c;高效的性能测试已经成为了确保在线应用质量和用户满意度的重要手段之一。 而JMeter分布式压测则是实现这一目标的最佳选择。然而&#xff0c;很多人并不知道如何使用JMeter进行分布式压测&#xff0c;更不知道如何获取准确的测…

前端工程化面试题 | 15.精选前端工程化高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Ubuntu18.04虚拟机磁盘扩容-lvm

Ubuntu18.04虚拟机磁盘扩容-lvm 前提虚拟机虚拟磁盘扩容使用新增的磁盘空间扩展vg和lv 前提 没有虚拟机快照虚拟磁盘不是一次性分配空间其它会影响扩容的前置条件 虚拟机虚拟磁盘扩容 此部分不做详细说明。 使用新增的磁盘空间 此节有两种办法&#xff0c;第一种是将新增的…

java之Tomcat

Tomcat概念 Tomcat是一个开源免费的web服务器&#xff0c;支持Servlet/JSP 等少量javaEE规范Tomcat也被称为Web容器&#xff0c;Servlet容器。Servlet程序需要依赖Tomcat才能运行javaEE : java Enterprise Edition, java企业版&#xff0c;指的是java企业开发的技术规范总和。…

Mybatis学习笔记:延迟加载

本文是自己的学习笔记&#xff0c;主要参考以下资料 - 马士兵教育 1、延迟加载2、开启延迟加载2.1、配置信息2.2、查询语法2.2.1、前置条件2.2.2、xml语法2.2.3、总结 1、延迟加载 延迟加载是用于优化一对多或者多对多的查询。 比如员工表和部门表&#xff0c;员工表left jo…

物奇ENC算法开关接口修改方法

物奇ENC算法开关接口修改 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)&#xff1f;可加我微信hezkz17, 本群提供音频技术答疑服务&#xff0c;群赠送语音信号处理降噪算法&#xff0c;蓝牙耳机音频&#xff0c;DSP音频项目核心开发资料, 1 配置工具事件接口 2 代…

LeetCode 热题 100 | 二叉树(四)

目录 1 114. 二叉树展开为链表 2 105. 从前序与中序遍历序列构造二叉树 3 437. 路径总和 III 菜鸟做题&#xff08;即将返校版&#xff09;&#xff0c;语言是 C 1 114. 二叉树展开为链表 题眼&#xff1a;展开后的单链表应该与二叉树 先序遍历 顺序相同。 而先序遍历就…

【编译原理】用Python实现LR(0)语法分析

实验内容 对于给定的如下文法&#xff0c;编写调试一个上下文无关文法的LR(0)分析程序。 文法G’为&#xff1a; S → E S\to E S→E E → a A E\to aA E→aA E → b B E \to bB E→bB A → c A A\to cA A→cA A → d A\to d A→d B → c B B\to cB B→cB B → d B\to …

8.6 OpenGL纹理和采样器:备用纹理图像规范命令

备用纹理图像规范命令 Alternate Texture Image Specification Commands 二维和一维纹理图像也可以使用直接从帧缓冲区获取的图像数据进行指定&#xff0c;并且可以重新指定现有纹理图像的矩形子区域。 定义一个二维纹理图像 void glCopyTexImage2D( enum target, int level…

03|count(*)查询优化

count(*) count(1) count(字段) count(主键 id) 字段有索引&#xff1a;count(*)≈count(1)>count(字段)>count(主键 id) 字段有索引&#xff0c;count(字段)统计走二级索引&#xff0c;二级索引存储数据比主键索引少&#xff0c;所以count(字段)>count(主键 id) 字段…

网购商城系统源码 积分兑换商城系统源码 独立后台附教程

应用介绍 本文来自&#xff1a;网购商城系统源码 积分兑换商城系统源码 独立后台附教程 - 源码1688 简介&#xff1a; 网购商城系统源码 积分兑换商城系统源码 独立后台附教程 测试环境&#xff1a;NginxPHP7.0MySQL5.6thinkphp伪静态 图片&#xff1a;

软件实际应用实例,茶楼收银软件管理系统操作流程,茶室计时计费会员管理系统软件试用版教程

软件实际应用实例&#xff0c;茶楼收银软件管理系统操作流程&#xff0c;茶室计时计费会员管理系统软件试用版教程 一、前言 以下软件以 佳易王茶社计时计费管理系统软件V17.9为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、计时计费&…