file.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. const debug = require('debug')('log4js:file');
  2. const path = require('path');
  3. const streams = require('streamroller');
  4. const os = require('os');
  5. const eol = os.EOL;
  6. function openTheStream(file, fileSize, numFiles, options) {
  7. const stream = new streams.RollingFileStream(
  8. file,
  9. fileSize,
  10. numFiles,
  11. options
  12. );
  13. stream.on('error', (err) => {
  14. console.error('log4js.fileAppender - Writing to file %s, error happened ', file, err); //eslint-disable-line
  15. });
  16. stream.on('drain', () => {
  17. process.emit("log4js:pause", false);
  18. });
  19. return stream;
  20. }
  21. /**
  22. * File Appender writing the logs to a text file. Supports rolling of logs by size.
  23. *
  24. * @param file file log messages will be written to
  25. * @param layout a function that takes a logEvent and returns a string
  26. * (defaults to basicLayout).
  27. * @param logSize - the maximum size (in bytes) for a log file,
  28. * if not provided then logs won't be rotated.
  29. * @param numBackups - the number of log files to keep after logSize
  30. * has been reached (default 5)
  31. * @param options - options to be passed to the underlying stream
  32. * @param timezoneOffset - optional timezone offset in minutes (default system local)
  33. */
  34. function fileAppender(file, layout, logSize, numBackups, options, timezoneOffset) {
  35. file = path.normalize(file);
  36. numBackups = numBackups === undefined ? 5 : numBackups;
  37. // there has to be at least one backup if logSize has been specified
  38. numBackups = numBackups === 0 ? 1 : numBackups;
  39. debug(
  40. 'Creating file appender (',
  41. file, ', ',
  42. logSize, ', ',
  43. numBackups, ', ',
  44. options, ', ',
  45. timezoneOffset, ')'
  46. );
  47. let writer = openTheStream(file, logSize, numBackups, options);
  48. const app = function (loggingEvent) {
  49. if (options.removeColor === true) {
  50. // eslint-disable-next-line no-control-regex
  51. const regex = /\x1b[[0-9;]*m/g;
  52. loggingEvent.data = loggingEvent.data.map(d => {
  53. if (typeof d === 'string') return d.replace(regex, '')
  54. return d
  55. })
  56. }
  57. if (!writer.write(layout(loggingEvent, timezoneOffset) + eol, "utf8")) {
  58. process.emit('log4js:pause', true);
  59. }
  60. };
  61. app.reopen = function () {
  62. writer.end(() => { writer = openTheStream(file, logSize, numBackups, options); });
  63. };
  64. app.sighupHandler = function () {
  65. debug('SIGHUP handler called.');
  66. app.reopen();
  67. };
  68. app.shutdown = function (complete) {
  69. process.removeListener('SIGHUP', app.sighupHandler);
  70. writer.end('', 'utf-8', complete);
  71. };
  72. // On SIGHUP, close and reopen all files. This allows this appender to work with
  73. // logrotate. Note that if you are using logrotate, you should not set
  74. // `logSize`.
  75. process.on('SIGHUP', app.sighupHandler);
  76. return app;
  77. }
  78. function configure(config, layouts) {
  79. let layout = layouts.basicLayout;
  80. if (config.layout) {
  81. layout = layouts.layout(config.layout.type, config.layout);
  82. }
  83. return fileAppender(
  84. config.filename,
  85. layout,
  86. config.maxLogSize,
  87. config.backups,
  88. config,
  89. config.timezoneOffset
  90. );
  91. }
  92. module.exports.configure = configure;