http.js 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. const Metrics = require('./index')
  2. function monitor(logger, level = 'debug') {
  3. return function (req, res, next) {
  4. const startTime = Date.now()
  5. req.logger = new RequestLogger(logger, level)
  6. const { end } = res
  7. res.end = function (...args) {
  8. end.apply(this, args)
  9. const responseTimeMs = Date.now() - startTime
  10. const requestSize = parseInt(req.headers['content-length'], 10)
  11. const routePath = getRoutePath(req)
  12. if (routePath != null) {
  13. Metrics.timing('http_request', responseTimeMs, null, {
  14. method: req.method,
  15. status_code: res.statusCode,
  16. path: routePath,
  17. })
  18. if (requestSize) {
  19. Metrics.summary('http_request_size_bytes', requestSize, {
  20. method: req.method,
  21. status_code: res.statusCode,
  22. path: routePath,
  23. })
  24. }
  25. }
  26. req.logger.addFields({ responseTimeMs })
  27. req.logger.emit(req, res)
  28. }
  29. next()
  30. }
  31. }
  32. function getRoutePath(req) {
  33. if (req.route && req.route.path != null) {
  34. return req.route.path
  35. .toString()
  36. .replace(/\//g, '_')
  37. .replace(/:/g, '')
  38. .slice(1)
  39. }
  40. if (req.swagger && req.swagger.apiPath != null) {
  41. return req.swagger.apiPath
  42. }
  43. return null
  44. }
  45. class RequestLogger {
  46. constructor(logger, level) {
  47. this._logger = logger
  48. this._level = level
  49. this._info = {}
  50. }
  51. addFields(fields) {
  52. Object.assign(this._info, fields)
  53. }
  54. setLevel(level) {
  55. this._level = level
  56. }
  57. disable() {
  58. this._disabled = true
  59. }
  60. emit(req, res) {
  61. if (this._disabled) {
  62. return
  63. }
  64. this.addFields({ req, res })
  65. const url = req.originalUrl || req.url
  66. this._logger[this._level](this._info, '%s %s', req.method, url)
  67. }
  68. }
  69. module.exports = { monitor, RequestLogger }