刘万林的博客

Node.js + Express 日志管理,winston + morgan 的使用

模块选择

访问日志记录模块:winston
输出日志记录模块:morgan
辅助模块(按日期分割日志文件):winston-daily-rotate-file

实现功能

  • 访问记录日志保存在 access.log.txt 文件中。
  • 错误级别日志保存在 error.log.txt 文件中。
  • 警告级别日志保存在 warn.log.txt 文件中。
  • 其他级别日志保存在 normal.log.txt 文件中。
  • 以上日志均按每天生成一个新的文件,前缀为日期,e.g. 2017-12-25.normal.log.txt
  • 访问记录日志一个文件最大为 10M,否则生成新的文件。
  • 输出的日志记录时,记录输出位置,什么文件哪行输出的。

使用方式

初始化

  1. let express = require('express');
  2. let app = express();
  3. let Logger = require('./common/logger');
  4. Logger.initRequestLogger(app);

调用

  1. let Logger = require('./common/logger');
  2. Logger.debug('test', 'test test');
  3. Logger.info('test');
  4. Logger.warn('test');
  5. Logger.error('test', 'test test');

代码

./common/logger.js

  1. let morgan = require('morgan');
  2. let winston = require('winston');
  3. let path = require('path');
  4. let moment = require('moment');
  5. let stackTrace = require('stack-trace');
  6. require('winston-daily-rotate-file');
  7. // 日志打印位置
  8. const LOGS_DIR = path.join(__dirname, '../logs');
  9. // 公共配置选项,每天生成一个日志文件,一个文件最大 10M
  10. const LOGGER_COMMON_CONFIG = {
  11. timestamp: moment().format('YYYY-MM-DD HH:mm:ss:SSS'),
  12. prepend: true,
  13. datePattern:'yyyy-MM-dd.',
  14. maxsize: 1024 * 1024 * 10,
  15. colorize: false,
  16. json: false,
  17. handleExceptions: true,
  18. };
  19. /**
  20. * info 普通日志记录
  21. * error 错误严重时记录
  22. * warn 普通错误记录
  23. * debug 输出到控制台,不记录到文件中
  24. */
  25. let logger = new winston.Logger({
  26. transports: [
  27. new (winston.transports.DailyRotateFile) ({
  28. name: 'error',
  29. level: 'error',
  30. filename: LOGS_DIR + '/error.log.txt',
  31. ...LOGGER_COMMON_CONFIG,
  32. }),
  33. new (winston.transports.DailyRotateFile) ({
  34. name: 'warn',
  35. level: 'warn',
  36. filename: LOGS_DIR + '/warn.log.txt',
  37. ...LOGGER_COMMON_CONFIG,
  38. }),
  39. new (winston.transports.DailyRotateFile) ({
  40. name: 'normal',
  41. level: 'info',
  42. filename: LOGS_DIR + '/normal.log.txt',
  43. ...LOGGER_COMMON_CONFIG,
  44. }),
  45. new winston.transports.Console({
  46. name: 'debug',
  47. level: 'debug',
  48. colorize: true,
  49. json: false,
  50. handleExceptions: true,
  51. }),
  52. ],
  53. exitOnError: false,
  54. });
  55. /**
  56. * 打印 Access Log 使用
  57. * 不输出到控制台中
  58. */
  59. let accessLogger = new winston.Logger({
  60. transports: [
  61. new (winston.transports.DailyRotateFile) ({
  62. name: 'access',
  63. level: 'info',
  64. filename: LOGS_DIR + '/access.log.txt',
  65. ...LOGGER_COMMON_CONFIG,
  66. }),
  67. ],
  68. exitOnError: false,
  69. });
  70. // 提供 morgan 使用
  71. logger.stream = {
  72. write: function(message) {
  73. accessLogger.info(message.trim()); // trim 去除多余换行
  74. }
  75. };
  76. /**
  77. * 日志处理对象
  78. */
  79. let Logger = {
  80. // 初始化 morgan 记录请求记录
  81. initRequestLogger: function(app) {
  82. app.use(
  83. morgan('combined', {
  84. 'stream': logger.stream,
  85. // OPTIONS 类型请求不记录在日志中
  86. 'skip': (req, res) => req.method === 'OPTIONS'
  87. })
  88. );
  89. },
  90. // 开发模式才开启
  91. debug: function() {
  92. if(process.env['NODE_ENV'] === 'development') {
  93. let cellSite = stackTrace.get()[1];
  94. logger.debug.apply(
  95. logger,
  96. [
  97. ...arguments,
  98. {
  99. FilePath: cellSite.getFileName(),
  100. LineNumber: cellSite.getLineNumber(),
  101. }
  102. ]
  103. );
  104. }
  105. },
  106. info: function() {
  107. let cellSite = stackTrace.get()[1];
  108. logger.info.apply(
  109. logger,
  110. [
  111. ...arguments,
  112. {
  113. FilePath: cellSite.getFileName(),
  114. LineNumber: cellSite.getLineNumber(),
  115. }
  116. ]
  117. );
  118. },
  119. warn: function() {
  120. let cellSite = stackTrace.get()[1];
  121. logger.warn.apply(
  122. logger,
  123. [
  124. ...arguments,
  125. {
  126. FilePath: cellSite.getFileName(),
  127. LineNumber: cellSite.getLineNumber(),
  128. }
  129. ]
  130. );
  131. },
  132. // 错误日志并记录行号
  133. error: function() {
  134. let cellSite = stackTrace.get()[1];
  135. logger.error.apply(
  136. logger,
  137. [
  138. ...arguments,
  139. {
  140. filePath: cellSite.getFileName(),
  141. lineNumber: cellSite.getLineNumber(),
  142. }
  143. ]
  144. );
  145. },
  146. };
  147. module.exports = Logger;

我要留言

留言列表0 条 )

    更早留言 >>