nodejs 日志模块 winston 的使用

韩瑛
• 阅读 6366

winston 日志模块

在使用 nodejs winston 模块中,加上相关的两个模块,事倍功半。

  • express-winston
  • winston-daily-rotate-file

express-winston

是 express-winston 的 winston 的增加版, 是作为 express 的中间件来打印日志,不仅有请求头信息,并且有响应时间。
作为中间件, 为什么会有响应时间呢? 因为 express-winston 改写了 express 的 res.end 办法, 是请求结束后再打的日志。

代码片段

var end = res.end;
res.end = function(chunk, encoding) {
    res.responseTime = (new Date) - req._startTime;
    res.end = end;
    res.end(chunk, encoding);
    ...
    }

express-winston 没有修改或者扩展 winston 的transport, 而 winston-daily-rotate-file 正是增强了 winston 的transport 办法

winston-daily-rotate-file

winston-daily-rotate-file 是 winston 扩展, 增加了 transport 的办法,使 winston 有滚动日志的能力。

结合使用

我们来一个需求: 如何让 express-winston 打印日志的时候,也打印出接口 /api 的请求参数和响应数据?

  • 该日志中间件应该在调用链 api 后面, api/* 业务处理之前。 like: app.use('/api', apiRequestLogger, apiHandler)
  • 要获取到响应数据, 就要在业务处理完后 send 出来后才能捕获到,express 所有的请求响应最后都是走 res.send 我们可以从这里入手捕获响应数据

代码如下

import winston from 'winston'
import expressWinston from 'express-winston'
import 'winston-daily-rotate-file'
import path from 'path'

export let DailyRotateFileTransport = (fileName) => {
  return new (winston.transports.DailyRotateFile)({
    filename: path.join(process.env.LOGPATH, `${fileName}-%DATE%.log`),
    datePattern: 'YYYY-MM-DD-HH',
    // maxSize: '20m',
    maxFiles: '7d',
    timestamp: () => new Date().format('yyyy-MM-dd hh:mm:ss.S')
  })
}

export let pageRequestLogger = expressWinston.logger({
  transports: [
    DailyRotateFileTransport('page-request')
  ],
  meta: true, // optional: control whether you want to log the meta data about the request (default to true)
  msg: 'HTTP {{req.method}} {{req.url}}', // optional: customize the default logging message. E.g. "{{res.statusCode}} {{req.method}} {{res.responseTime}}ms {{req.url}}"
  expressFormat: true, // Use the default Express/morgan request formatting. Enabling this will override any msg if true. Will only output colors with colorize set to true
  colorize: false, // Color the text and status code, using the Express/morgan color palette (text: gray, status: default green, 3XX cyan, 4XX yellow, 5XX red).
  ignoreRoute: function (req, res) {
    // 只打印页面请求信息
    let notPageRequest = false
    let ignoreArr = ['/api', '.js', '.css', '.png', '.jpg', '.gif']
    ignoreArr.forEach(item => {
      if (req.url.indexOf(item) > -1) notPageRequest = true
    })
    return notPageRequest
  } // optional: allows to skip some log messages based on request and/or response
})

export let apiRequestLogger = (req, res, next) => {
  let send = res.send
  let content = ''
  let query = req.query || {}
  let body = req.body || {}
  res.send = function () {
    content = arguments[0]
    send.apply(res, arguments)
  }
  expressWinston.logger({
    transports: [
      DailyRotateFileTransport('api-request')
    ],
    meta: true, // optional: control whether you want to log the meta data about the request (default to true)
    msg () {
      return `HTTP ${req.method} ${req.url} query ${JSON.stringify(query)} body ${JSON.stringify(body)} resData ${content} `
    },
    colorize: true, // Color the text and status code, using the Express/morgan color palette (text: gray, status: default green, 3XX cyan, 4XX yellow, 5XX red).
    ignoreRoute: function (req, res) {
      if (req.headers.self) return true
      return false
    } // optional: allows to skip some log messages based on request and/or response
  })(req, res, next)
}
点赞
收藏
评论区
推荐文章
xiguaapp xiguaapp
4年前
如何设计一个数据库?
设计两个大模块,存储(文件系统)与程序的实例模块。程序的实例模块划分为:存储管理,缓存机制,SQL解析,日志管理,权限划分,容灾机制,索引管理,锁管理。为什么使用索引?假设使用原始的全表查询,那么对于小量数据可能速度并没有影响,但是在大量数据的情况下会使得速度很慢。而索引,则类似于字典中的偏旁部首,加快了查询的效率。二叉
Stella981 Stella981
4年前
Python 日志(Log)
日志?日志,就是用来记录程序运行的时候都发生了什么事。事件按严重程度划分level事件内容:时间位置事件的严重程度level内容用logging模块实现logging模块
Wesley13 Wesley13
4年前
DRF
DRFTracking模块源码分析一、drftracking是什么?drftracking是为DRF的view访问提供一个日志记录模块。使用mixin的方式无缝的和DRF相结合。从源码结构上来看也是Django的一个APP项目,提供Model将日志记录到数据库、自定Manger操作等.其核心为该
Easter79 Easter79
4年前
Spring之AOP
一、AOP的引入这里可以把单个模块当做是一圆柱,假如没有aop,在做日志处理的时候,我们会在每个模块中添加日志或者权限处理,日志或权限类似圆柱体的部分圆柱。!(https://images2018.cnblogs.com/blog/733213/201809/73321320180909230546751573513561.png)一般
Stella981 Stella981
4年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Stella981 Stella981
4年前
Python中collections模块的使用
本文将详细讲解collections模块中的所有类,和每个类中的方法,从源码和性能的角度剖析。一个模块主要用来干嘛,有哪些类可以使用,看__init__.py就知道'''Thismoduleimplementsspecializedcontainerdatatypesprovidingalternativest
Stella981 Stella981
4年前
Logstash
 Logstash数据处理工具具有实时渠道能力的数据收集引擎,包含输入、过滤、输出模块,一般在过滤模块中做日志格式化的解析工作日志信息logstshjson形式mysql\\hbase\\ESlogstsh(select\fromuser)ESlogstsh架
Wesley13 Wesley13
4年前
ES6模块化与常用功能
目前开发环境已经普及使用,如vue,react等,但浏览器环境却支持不好,所以需要开发环境编译,下面介绍下开发环境的使用和常用语法:一,ES6模块化1,模块化的基本语法ES6的模块自动采用严格模式,不管你有没有在模块头部加上"usestrict";。模块功能主要由两个命令构成:export和import(注意有无defaul
Stella981 Stella981
4年前
Noark入门之异步事件
引入异步事件主要是为了各模块的解耦,每当完成一个动作时,向系统发布一个事件,由关心的模块自己监听处理,可选择同步处理,异步处理,延迟处理。何时发布事件,当其他模块关心此动作时<br比如获得道具时,任务系统模块要判定完成进度,BI模块需要上报等等都可以监听此事件,已达模块解耦0x00事件源一个实现xyz.noark.core.event
Stella981 Stella981
4年前
Python3常用模块
logging模块一、日志级别CRITICAL50FATALCRITICALERROR40WARNING30WARNWARNINGINFO20DEBUG10NOTSET0不设置二、默认级
Nginx的HTTP模块与Stream模块:区别与应用场景
Nginx是一个多功能的开源Web服务器,它支持多个模块,其中两个重要的模块是HTTP模块和Stream模块。这两个模块在不同的网络场景中有各自的用途,本文将深入研究它们之间的区别以及何时应该使用哪一个。