file.js 2.7 KB

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