/
logger.js
155 lines (133 loc) · 4.27 KB
/
logger.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/* eslint no-underscore-dangle: ["error", { "allow": ["_log"] }] */
const debug = require("debug")("log4js:logger");
const LoggingEvent = require("./LoggingEvent");
const levels = require("./levels");
const clustering = require("./clustering");
const categories = require("./categories");
const configuration = require("./configuration");
const stackReg = /at (?:(.+)\s+\()?(?:(.+?):(\d+)(?::(\d+))?|([^)]+))\)?/;
function defaultParseCallStack(data, skipIdx = 4) {
try {
const stacklines = data.stack.split("\n").slice(skipIdx);
const lineMatch = stackReg.exec(stacklines[0]);
/* istanbul ignore else: failsafe */
if (lineMatch && lineMatch.length === 6) {
return {
functionName: lineMatch[1],
fileName: lineMatch[2],
lineNumber: parseInt(lineMatch[3], 10),
columnNumber: parseInt(lineMatch[4], 10),
callStack: stacklines.join("\n")
};
} else { // eslint-disable-line no-else-return
// will never get here unless nodejs has changes to Error
console.error('log4js.logger - defaultParseCallStack error'); // eslint-disable-line no-console
}
}
catch (err) {
// will never get error unless nodejs has breaking changes to Error
console.error('log4js.logger - defaultParseCallStack error', err); // eslint-disable-line no-console
}
return null;
}
/**
* Logger to log messages.
* use {@see log4js#getLogger(String)} to get an instance.
*
* @name Logger
* @namespace Log4js
* @param name name of category to log to
* @param level - the loglevel for the category
* @param dispatch - the function which will receive the logevents
*
* @author Stephan Strittmatter
*/
class Logger {
constructor(name) {
if (!name) {
throw new Error("No category provided.");
}
this.category = name;
this.context = {};
this.parseCallStack = defaultParseCallStack;
debug(`Logger created (${this.category}, ${this.level})`);
}
get level() {
return levels.getLevel(
categories.getLevelForCategory(this.category),
levels.OFF
);
}
set level(level) {
categories.setLevelForCategory(
this.category,
levels.getLevel(level, this.level)
);
}
get useCallStack() {
return categories.getEnableCallStackForCategory(this.category);
}
set useCallStack(bool) {
categories.setEnableCallStackForCategory(this.category, bool === true);
}
log(level, ...args) {
const logLevel = levels.getLevel(level);
if (!logLevel) {
if (configuration.validIdentifier(level) && args.length > 0) {
// logLevel not found but of valid signature, WARN before fallback to INFO
this.log(levels.WARN, 'log4js:logger.log: valid log-level not found as first parameter given:', level);
this.log(levels.INFO, `[${level}]`, ...args);
} else {
// apart from fallback, allow .log(...args) to be synonym with .log("INFO", ...args)
this.log(levels.INFO, level, ...args);
}
} else if (this.isLevelEnabled(logLevel)) {
this._log(logLevel, args);
}
}
isLevelEnabled(otherLevel) {
return this.level.isLessThanOrEqualTo(otherLevel);
}
_log(level, data) {
debug(`sending log data (${level}) to appenders`);
const loggingEvent = new LoggingEvent(
this.category,
level,
data,
this.context,
this.useCallStack && this.parseCallStack(new Error())
);
clustering.send(loggingEvent);
}
addContext(key, value) {
this.context[key] = value;
}
removeContext(key) {
delete this.context[key];
}
clearContext() {
this.context = {};
}
setParseCallStackFunction(parseFunction) {
this.parseCallStack = parseFunction;
}
}
function addLevelMethods(target) {
const level = levels.getLevel(target);
const levelStrLower = level.toString().toLowerCase();
const levelMethod = levelStrLower.replace(/_([a-z])/g, g =>
g[1].toUpperCase()
);
const isLevelMethod = levelMethod[0].toUpperCase() + levelMethod.slice(1);
Logger.prototype[`is${isLevelMethod}Enabled`] = function () {
return this.isLevelEnabled(level);
};
Logger.prototype[levelMethod] = function (...args) {
this.log(level, ...args);
};
}
levels.levels.forEach(addLevelMethods);
configuration.addListener(() => {
levels.levels.forEach(addLevelMethods);
});
module.exports = Logger;