logger.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. const escapeStringRegexp = require('escape-string-regexp')
  2. const util = require('node:util')
  3. const supportsColors = require('supports-color')
  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. const styleText =
  36. typeof util.styleText === "function" && supportsColors.stderr ?
  37. util.styleText
  38. : (style, text) => text;
  39. /**
  40. * message log
  41. *
  42. * @param {object} params
  43. * @param {string | Error} params.arg the message or error to log
  44. * @param {string} params.tag a unique tag to easily search for this message
  45. * @param {string} params.level error | info | debug
  46. * @param {string} [params.traceId] a unique id to easily trace logs tied to a request
  47. * @param {string[]} [params.color] Format(s) that can be passed to `util.styleText`.
  48. */
  49. const log = ({ arg, tag = '', level, traceId = '', color = [] }) => {
  50. const time = new Date().toISOString()
  51. const whitespace = tag && traceId ? ' ' : ''
  52. function msgToString() {
  53. // We don't need to log stack trace on special errors that we ourselves have produced
  54. // (to reduce log noise)
  55. // @ts-ignore
  56. if ((arg instanceof Error && arg.name === 'ProviderApiError') && typeof arg.message === 'string') {
  57. return arg.message
  58. }
  59. if (typeof arg === 'string') return arg
  60. return util.inspect(arg)
  61. }
  62. const msgString = msgToString()
  63. const masked = maskMessage(msgString)
  64. // eslint-disable-next-line no-console
  65. console.log(styleText(color, `${processName}: ${time} [${level}] ${traceId}${whitespace}${tag}`), styleText(color, masked))
  66. }
  67. /**
  68. * INFO level log
  69. *
  70. * @param {string} msg the message to log
  71. * @param {string} [tag] a unique tag to easily search for this message
  72. * @param {string} [traceId] a unique id to easily trace logs tied to a request
  73. */
  74. exports.info = (msg, tag, traceId) => {
  75. log({ arg: msg, tag, level: 'info', traceId })
  76. }
  77. /**
  78. * WARN level log
  79. *
  80. * @param {string} msg the message to log
  81. * @param {string} [tag] a unique tag to easily search for this message
  82. * @param {string} [traceId] a unique id to easily trace logs tied to a request
  83. */
  84. exports.warn = (msg, tag, traceId) => {
  85. log({ arg: msg, tag, level: 'warn', traceId, color: ['bold', 'yellow'] })
  86. }
  87. /**
  88. * ERROR level log
  89. *
  90. * @param {string | Error} msg the message to log
  91. * @param {string} [tag] a unique tag to easily search for this message
  92. * @param {string} [traceId] a unique id to easily trace logs tied to a request
  93. */
  94. exports.error = (msg, tag, traceId) => {
  95. log({ arg: msg, tag, level: 'error', traceId, color: ['bold', 'red'] })
  96. }
  97. /**
  98. * DEBUG level log
  99. *
  100. * @param {string} msg the message to log
  101. * @param {string} [tag] a unique tag to easily search for this message
  102. * @param {string} [traceId] a unique id to easily trace logs tied to a request
  103. */
  104. exports.debug = (msg, tag, traceId) => {
  105. if (process.env.NODE_ENV !== 'production') {
  106. log({ arg: msg, tag, level: 'debug', traceId, color: ['bold', 'blue'] })
  107. }
  108. }