1 | /**
|
---|
2 | * @fileoverview log4js is a library to log in JavaScript in similar manner
|
---|
3 | * than in log4j for Java (but not really).
|
---|
4 | *
|
---|
5 | * <h3>Example:</h3>
|
---|
6 | * <pre>
|
---|
7 | * const logging = require('log4js');
|
---|
8 | * const log = logging.getLogger('some-category');
|
---|
9 | *
|
---|
10 | * //call the log
|
---|
11 | * log.trace('trace me' );
|
---|
12 | * </pre>
|
---|
13 | *
|
---|
14 | * NOTE: the authors below are the original browser-based log4js authors
|
---|
15 | * don't try to contact them about bugs in this version :)
|
---|
16 | * @author Stephan Strittmatter - http://jroller.com/page/stritti
|
---|
17 | * @author Seth Chisamore - http://www.chisamore.com
|
---|
18 | * @since 2005-05-20
|
---|
19 | * Website: http://log4js.berlios.de
|
---|
20 | */
|
---|
21 | const debug = require("debug")("log4js:main");
|
---|
22 | const fs = require("fs");
|
---|
23 | const deepClone = require("rfdc")({ proto: true });
|
---|
24 | const configuration = require("./configuration");
|
---|
25 | const layouts = require("./layouts");
|
---|
26 | const levels = require("./levels");
|
---|
27 | const appenders = require("./appenders");
|
---|
28 | const categories = require("./categories");
|
---|
29 | const Logger = require("./logger");
|
---|
30 | const clustering = require("./clustering");
|
---|
31 | const connectLogger = require("./connect-logger");
|
---|
32 |
|
---|
33 | let enabled = false;
|
---|
34 |
|
---|
35 | function sendLogEventToAppender(logEvent) {
|
---|
36 | if (!enabled) return;
|
---|
37 | debug("Received log event ", logEvent);
|
---|
38 | const categoryAppenders = categories.appendersForCategory(
|
---|
39 | logEvent.categoryName
|
---|
40 | );
|
---|
41 | categoryAppenders.forEach(appender => {
|
---|
42 | appender(logEvent);
|
---|
43 | });
|
---|
44 | }
|
---|
45 |
|
---|
46 | function loadConfigurationFile(filename) {
|
---|
47 | debug(`Loading configuration from ${filename}`);
|
---|
48 | try {
|
---|
49 | return JSON.parse(fs.readFileSync(filename, "utf8"));
|
---|
50 | } catch (e) {
|
---|
51 | throw new Error(
|
---|
52 | `Problem reading config from file "${filename}". Error was ${e.message}`,
|
---|
53 | e
|
---|
54 | );
|
---|
55 | }
|
---|
56 | }
|
---|
57 |
|
---|
58 | function configure(configurationFileOrObject) {
|
---|
59 | let configObject = configurationFileOrObject;
|
---|
60 |
|
---|
61 | if (typeof configObject === "string") {
|
---|
62 | configObject = loadConfigurationFile(configurationFileOrObject);
|
---|
63 | }
|
---|
64 | debug(`Configuration is ${configObject}`);
|
---|
65 |
|
---|
66 | configuration.configure(deepClone(configObject));
|
---|
67 |
|
---|
68 | clustering.onMessage(sendLogEventToAppender);
|
---|
69 |
|
---|
70 | enabled = true;
|
---|
71 |
|
---|
72 | // eslint-disable-next-line no-use-before-define
|
---|
73 | return log4js;
|
---|
74 | }
|
---|
75 |
|
---|
76 | /**
|
---|
77 | * Shutdown all log appenders. This will first disable all writing to appenders
|
---|
78 | * and then call the shutdown function each appender.
|
---|
79 | *
|
---|
80 | * @params {Function} cb - The callback to be invoked once all appenders have
|
---|
81 | * shutdown. If an error occurs, the callback will be given the error object
|
---|
82 | * as the first argument.
|
---|
83 | */
|
---|
84 | function shutdown(cb) {
|
---|
85 | debug("Shutdown called. Disabling all log writing.");
|
---|
86 | // First, disable all writing to appenders. This prevents appenders from
|
---|
87 | // not being able to be drained because of run-away log writes.
|
---|
88 | enabled = false;
|
---|
89 |
|
---|
90 | // Call each of the shutdown functions in parallel
|
---|
91 | const appendersToCheck = Array.from(appenders.values());
|
---|
92 | const shutdownFunctions = appendersToCheck.reduceRight(
|
---|
93 | (accum, next) => (next.shutdown ? accum + 1 : accum),
|
---|
94 | 0
|
---|
95 | );
|
---|
96 | let completed = 0;
|
---|
97 | let error;
|
---|
98 |
|
---|
99 | debug(`Found ${shutdownFunctions} appenders with shutdown functions.`);
|
---|
100 | function complete(err) {
|
---|
101 | error = error || err;
|
---|
102 | completed += 1;
|
---|
103 | debug(`Appender shutdowns complete: ${completed} / ${shutdownFunctions}`);
|
---|
104 | if (completed >= shutdownFunctions) {
|
---|
105 | debug("All shutdown functions completed.");
|
---|
106 | if (cb) {
|
---|
107 | cb(error);
|
---|
108 | }
|
---|
109 | }
|
---|
110 | }
|
---|
111 |
|
---|
112 | if (shutdownFunctions === 0) {
|
---|
113 | debug("No appenders with shutdown functions found.");
|
---|
114 | return cb !== undefined && cb();
|
---|
115 | }
|
---|
116 |
|
---|
117 | appendersToCheck.filter(a => a.shutdown).forEach(a => a.shutdown(complete));
|
---|
118 |
|
---|
119 | return null;
|
---|
120 | }
|
---|
121 |
|
---|
122 | /**
|
---|
123 | * Get a logger instance.
|
---|
124 | * @static
|
---|
125 | * @param loggerCategoryName
|
---|
126 | * @return {Logger} instance of logger for the category
|
---|
127 | */
|
---|
128 | function getLogger(category) {
|
---|
129 | if (!enabled) {
|
---|
130 | configure(
|
---|
131 | process.env.LOG4JS_CONFIG || {
|
---|
132 | appenders: { out: { type: "stdout" } },
|
---|
133 | categories: { default: { appenders: ["out"], level: "OFF" } }
|
---|
134 | }
|
---|
135 | );
|
---|
136 | }
|
---|
137 | return new Logger(category || "default");
|
---|
138 | }
|
---|
139 |
|
---|
140 | /**
|
---|
141 | * @name log4js
|
---|
142 | * @namespace Log4js
|
---|
143 | * @property getLogger
|
---|
144 | * @property configure
|
---|
145 | * @property shutdown
|
---|
146 | */
|
---|
147 | const log4js = {
|
---|
148 | getLogger,
|
---|
149 | configure,
|
---|
150 | shutdown,
|
---|
151 | connectLogger,
|
---|
152 | levels,
|
---|
153 | addLayout: layouts.addLayout
|
---|
154 | };
|
---|
155 |
|
---|
156 | module.exports = log4js;
|
---|