multiFile.js 2.6 KB

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