LoggingEvent.js 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. const flatted = require('flatted');
  2. const levels = require('./levels');
  3. /**
  4. * @name LoggingEvent
  5. * @namespace Log4js
  6. */
  7. class LoggingEvent {
  8. /**
  9. * Models a logging event.
  10. * @constructor
  11. * @param {string} categoryName name of category
  12. * @param {Log4js.Level} level level of message
  13. * @param {Array} data objects to log
  14. * @author Seth Chisamore
  15. */
  16. constructor(categoryName, level, data, context, location) {
  17. this.startTime = new Date();
  18. this.categoryName = categoryName;
  19. this.data = data;
  20. this.level = level;
  21. this.context = Object.assign({}, context); // eslint-disable-line prefer-object-spread
  22. this.pid = process.pid;
  23. if (location) {
  24. this.functionName = location.functionName;
  25. this.fileName = location.fileName;
  26. this.lineNumber = location.lineNumber;
  27. this.columnNumber = location.columnNumber;
  28. this.callStack = location.callStack;
  29. }
  30. }
  31. serialise() {
  32. return flatted.stringify(this, (key, value) => {
  33. // JSON.stringify(new Error('test')) returns {}, which is not really useful for us.
  34. // The following allows us to serialize errors correctly.
  35. // duck-typing for Error object
  36. if (value && value.message && value.stack) {
  37. // eslint-disable-next-line prefer-object-spread
  38. value = Object.assign({message: value.message, stack: value.stack}, value);
  39. }
  40. // JSON.stringify({a: parseInt('abc'), b: 1/0, c: -1/0}) returns {a: null, b: null, c: null}.
  41. // The following allows us to serialize to NaN, Infinity and -Infinity correctly.
  42. else if (typeof value === 'number' && (Number.isNaN(value) || !Number.isFinite(value))) {
  43. value = value.toString();
  44. }
  45. // JSON.stringify([undefined]) returns [null].
  46. // The following allows us to serialize to undefined correctly.
  47. else if (typeof value === 'undefined') {
  48. value = typeof value;
  49. }
  50. return value;
  51. });
  52. }
  53. static deserialise(serialised) {
  54. let event;
  55. try {
  56. const rehydratedEvent = flatted.parse(serialised, (key, value) => {
  57. if (value && value.message && value.stack) {
  58. const fakeError = new Error(value);
  59. Object.keys(value).forEach((k) => { fakeError[k] = value[k]; });
  60. value = fakeError;
  61. }
  62. return value;
  63. });
  64. rehydratedEvent.location = {
  65. functionName: rehydratedEvent.functionName,
  66. fileName: rehydratedEvent.fileName,
  67. lineNumber: rehydratedEvent.lineNumber,
  68. columnNumber: rehydratedEvent.columnNumber,
  69. callStack: rehydratedEvent.callStack
  70. };
  71. event = new LoggingEvent(
  72. rehydratedEvent.categoryName,
  73. levels.getLevel(rehydratedEvent.level.levelStr),
  74. rehydratedEvent.data,
  75. rehydratedEvent.context,
  76. rehydratedEvent.location
  77. );
  78. event.startTime = new Date(rehydratedEvent.startTime);
  79. event.pid = rehydratedEvent.pid;
  80. event.cluster = rehydratedEvent.cluster;
  81. } catch (e) {
  82. event = new LoggingEvent(
  83. 'log4js',
  84. levels.ERROR,
  85. ['Unable to parse log:', serialised, 'because: ', e]
  86. );
  87. }
  88. return event;
  89. }
  90. }
  91. module.exports = LoggingEvent;