'use strict'; const debug = require('debug')('log4js:file'); const path = require('path'); const streams = require('streamroller'); const os = require('os'); const eol = os.EOL || '\n'; function openTheStream(file, fileSize, numFiles, options) { const stream = new streams.RollingFileStream( file, fileSize, numFiles, options ); stream.on('error', (err) => { console.error('log4js.fileAppender - Writing to file %s, error happened ', file, err); //eslint-disable-line }); return stream; } /** * File Appender writing the logs to a text file. Supports rolling of logs by size. * * @param file file log messages will be written to * @param layout a function that takes a logEvent and returns a string * (defaults to basicLayout). * @param logSize - the maximum size (in bytes) for a log file, * if not provided then logs won't be rotated. * @param numBackups - the number of log files to keep after logSize * has been reached (default 5) * @param options - options to be passed to the underlying stream * @param timezoneOffset - optional timezone offset in minutes (default system local) */ function fileAppender(file, layout, logSize, numBackups, options, timezoneOffset) { file = path.normalize(file); numBackups = numBackups === undefined ? 5 : numBackups; // there has to be at least one backup if logSize has been specified numBackups = numBackups === 0 ? 1 : numBackups; debug( 'Creating file appender (', file, ', ', logSize, ', ', numBackups, ', ', options, ', ', timezoneOffset, ')' ); const writer = openTheStream(file, logSize, numBackups, options); const app = function (loggingEvent) { writer.write(layout(loggingEvent, timezoneOffset) + eol, 'utf8'); }; app.reopen = function () { writer.closeTheStream(writer.openTheStream.bind(writer)); }; app.sighupHandler = function () { debug('SIGHUP handler called.'); app.reopen(); }; app.shutdown = function (complete) { process.removeListener('SIGHUP', app.sighupHandler); writer.write('', 'utf-8', () => { writer.end(complete); }); }; // On SIGHUP, close and reopen all files. This allows this appender to work with // logrotate. Note that if you are using logrotate, you should not set // `logSize`. process.on('SIGHUP', app.sighupHandler); return app; } function configure(config, layouts) { let layout = layouts.basicLayout; if (config.layout) { layout = layouts.layout(config.layout.type, config.layout); } return fileAppender( config.filename, layout, config.maxLogSize, config.backups, config, config.timezoneOffset ); } module.exports.configure = configure;