logger.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. const chalk = require('chalk')
  2. const escapeStringRegexp = require('escape-string-regexp')
  3. const util = require('node:util')
  4. const valuesToMask = []
  5. /**
  6. * Adds a list of strings that should be masked by the logger.
  7. * This function can only be called once through out the life of the server.
  8. *
  9. * @param {Array} maskables a list of strings to be masked
  10. */
  11. exports.setMaskables = (maskables) => {
  12. maskables.forEach((i) => {
  13. valuesToMask.push(escapeStringRegexp(i))
  14. })
  15. Object.freeze(valuesToMask)
  16. }
  17. /**
  18. * Mask the secret content of a message
  19. *
  20. * @param {string} msg the message whose content should be masked
  21. * @returns {string}
  22. */
  23. function maskMessage(msg) {
  24. let out = msg
  25. for (const toBeMasked of valuesToMask) {
  26. const toBeReplaced = new RegExp(toBeMasked, 'gi')
  27. out = out.replace(toBeReplaced, '******')
  28. }
  29. return out
  30. }
  31. let processName = 'companion'
  32. exports.setProcessName = (newProcessName) => {
  33. processName = newProcessName
  34. }
  35. /**
  36. * message log
  37. *
  38. * @param {object} params
  39. * @param {string | Error} params.arg the message or error to log
  40. * @param {string} params.tag a unique tag to easily search for this message
  41. * @param {string} params.level error | info | debug
  42. * @param {string} [params.traceId] a unique id to easily trace logs tied to a request
  43. * @param {Function} [params.color] function to display the log in appropriate color
  44. */
  45. const log = ({ arg, tag = '', level, traceId = '', color = (message) => message }) => {
  46. const time = new Date().toISOString()
  47. const whitespace = tag && traceId ? ' ' : ''
  48. function msgToString() {
  49. // We don't need to log stack trace on special errors that we ourselves have produced
  50. // (to reduce log noise)
  51. // @ts-ignore
  52. if ((arg instanceof Error && arg.name === 'ProviderApiError') && typeof arg.message === 'string') {
  53. return arg.message
  54. }
  55. if (typeof arg === 'string') return arg
  56. return util.inspect(arg)
  57. }
  58. const msgString = msgToString()
  59. const masked = maskMessage(msgString)
  60. // eslint-disable-next-line no-console
  61. console.log(color(`${processName}: ${time} [${level}] ${traceId}${whitespace}${tag}`), color(masked))
  62. }
  63. /**
  64. * INFO level log
  65. *
  66. * @param {string} msg the message to log
  67. * @param {string} [tag] a unique tag to easily search for this message
  68. * @param {string} [traceId] a unique id to easily trace logs tied to a request
  69. */
  70. exports.info = (msg, tag, traceId) => {
  71. log({ arg: msg, tag, level: 'info', traceId })
  72. }
  73. /**
  74. * WARN level log
  75. *
  76. * @param {string} msg the message to log
  77. * @param {string} [tag] a unique tag to easily search for this message
  78. * @param {string} [traceId] a unique id to easily trace logs tied to a request
  79. */
  80. exports.warn = (msg, tag, traceId) => {
  81. log({ arg: msg, tag, level: 'warn', traceId, color: chalk.bold.yellow })
  82. }
  83. /**
  84. * ERROR level log
  85. *
  86. * @param {string | Error} msg the message to log
  87. * @param {string} [tag] a unique tag to easily search for this message
  88. * @param {string} [traceId] a unique id to easily trace logs tied to a request
  89. */
  90. exports.error = (msg, tag, traceId) => {
  91. log({ arg: msg, tag, level: 'error', traceId, color: chalk.bold.red })
  92. }
  93. /**
  94. * DEBUG level log
  95. *
  96. * @param {string} msg the message to log
  97. * @param {string} [tag] a unique tag to easily search for this message
  98. * @param {string} [traceId] a unique id to easily trace logs tied to a request
  99. */
  100. exports.debug = (msg, tag, traceId) => {
  101. if (process.env.NODE_ENV !== 'production') {
  102. log({ arg: msg, tag, level: 'debug', traceId, color: chalk.bold.blue })
  103. }
  104. }