/
file.js
132 lines (114 loc) · 3.63 KB
/
file.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
const debug = require('debug')('log4js:file');
const path = require('path');
const streams = require('streamroller');
const os = require('os');
const eol = os.EOL;
let mainSighupListenerStarted = false;
const sighupListeners = new Set();
function mainSighupHandler() {
sighupListeners.forEach((app) => {
app.sighupHandler();
});
}
function openTheStream(file, fileSize, numFiles, options) {
const stream = new streams.RollingFileStream(
file,
fileSize,
numFiles,
options
);
stream.on('drain', () => {
process.emit("log4js:pause", false);
});
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, ')'
);
let alive = true;
let writer = openTheStream(file, logSize, numBackups, options);
writer.on('error', (err) => {
alive = false;
console.error('log4js.fileAppender - Writing to file %s, error happened ', file, err); //eslint-disable-line
});
const app = function (loggingEvent) {
if (!alive) {
return;
}
if (options.removeColor === true) {
// eslint-disable-next-line no-control-regex
const regex = /\x1b[[0-9;]*m/g;
loggingEvent.data = loggingEvent.data.map(d => {
if (typeof d === 'string') return d.replace(regex, '')
return d
})
}
if (!writer.write(layout(loggingEvent, timezoneOffset) + eol, "utf8")) {
process.emit('log4js:pause', true);
}
};
app.reopen = function () {
writer.end(() => { writer = openTheStream(file, logSize, numBackups, options); });
};
app.sighupHandler = function () {
debug('SIGHUP handler called.');
app.reopen();
};
app.shutdown = function (complete) {
sighupListeners.delete(app);
if (sighupListeners.size === 0 && mainSighupListenerStarted) {
process.removeListener('SIGHUP', mainSighupHandler);
mainSighupListenerStarted = false;
}
writer.end('', 'utf-8', 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`.
sighupListeners.add(app);
if (!mainSighupListenerStarted) {
process.on('SIGHUP', mainSighupHandler);
mainSighupListenerStarted = true;
}
return app;
}
function configure(config, layouts) {
let layout = layouts.basicLayout;
if (config.layout) {
layout = layouts.layout(config.layout.type, config.layout);
}
// security default (instead of relying on streamroller default)
config.mode = config.mode || 0o600;
return fileAppender(
config.filename,
layout,
config.maxLogSize,
config.backups,
config,
config.timezoneOffset
);
}
module.exports.configure = configure;