multiFile.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. const debug = require('debug')('log4js:multiFile');
  2. const path = require('path');
  3. const fileAppender = require('./file');
  4. const findFileKey = (property, event) =>
  5. event[property] || event.context[property];
  6. module.exports.configure = (config, layouts) => {
  7. debug('Creating a multi-file appender');
  8. const files = new Map();
  9. const timers = new Map();
  10. function checkForTimeout(fileKey) {
  11. const timer = timers.get(fileKey);
  12. const app = files.get(fileKey);
  13. /* istanbul ignore else: failsafe */
  14. if (timer && app) {
  15. if (Date.now() - timer.lastUsed > timer.timeout) {
  16. debug('%s not used for > %d ms => close', fileKey, timer.timeout);
  17. clearInterval(timer.interval);
  18. timers.delete(fileKey);
  19. files.delete(fileKey);
  20. app.shutdown((err) => {
  21. if (err) {
  22. debug('ignore error on file shutdown: %s', err.message);
  23. }
  24. });
  25. }
  26. } else {
  27. // will never get here as files and timers are coupled to be added and deleted at same place
  28. debug('timer or app does not exist');
  29. }
  30. }
  31. const appender = (logEvent) => {
  32. const fileKey = findFileKey(config.property, logEvent);
  33. debug('fileKey for property ', config.property, ' is ', fileKey);
  34. if (fileKey) {
  35. let file = files.get(fileKey);
  36. debug('existing file appender is ', file);
  37. if (!file) {
  38. debug('creating new file appender');
  39. config.filename = path.join(config.base, fileKey + config.extension);
  40. file = fileAppender.configure(config, layouts);
  41. files.set(fileKey, file);
  42. if (config.timeout) {
  43. debug('creating new timer');
  44. timers.set(fileKey, {
  45. timeout: config.timeout,
  46. lastUsed: Date.now(),
  47. interval: setInterval(
  48. checkForTimeout.bind(null, fileKey),
  49. config.timeout
  50. ),
  51. });
  52. }
  53. } else if (config.timeout) {
  54. debug('%s extending activity', fileKey);
  55. timers.get(fileKey).lastUsed = Date.now();
  56. }
  57. file(logEvent);
  58. } else {
  59. debug('No fileKey for logEvent, quietly ignoring this log event');
  60. }
  61. };
  62. appender.shutdown = (cb) => {
  63. let shutdownFunctions = files.size;
  64. if (shutdownFunctions <= 0) {
  65. cb();
  66. }
  67. let error;
  68. timers.forEach((timer, fileKey) => {
  69. debug('clearing timer for ', fileKey);
  70. clearInterval(timer.interval);
  71. });
  72. files.forEach((app, fileKey) => {
  73. debug('calling shutdown for ', fileKey);
  74. app.shutdown((err) => {
  75. error = error || err;
  76. shutdownFunctions -= 1;
  77. if (shutdownFunctions <= 0) {
  78. cb(error);
  79. }
  80. });
  81. });
  82. };
  83. return appender;
  84. };