]> git.r.bdr.sh - rbdr/cologne/blob - lib/cologne.js
646fe79fc368f1515ee1a05256ad9246b5730dfb
[rbdr/cologne] / lib / cologne.js
1 'use strict';
2
3 let LogUtilities = require('./cologne/log_utilities');
4
5 /** TYPE DEFINITIONS **/
6
7 /**
8 * Main interface for Cologne Loggers
9 *
10 * @memberof Cologne
11 * @interface ILogger
12 */
13
14 /**
15 * Receives any number of cologne log objects and logs them.
16 *
17 * @memberof Cologne.ILogger
18 * @function
19 * @name log
20 * @returns {undefined}
21 */
22
23 /**
24 * Main interface for Cologne Formatters
25 *
26 * @memberof Cologne
27 * @interface IFormatter
28 */
29
30 /**
31 * Receives a cologne log object and returns a formatted string.
32 *
33 * @memberof Cologne.IFormatter
34 * @function
35 * @name format
36 * @param {Cologne.tCologneLog} logObject the log to be formatted
37 * @returns {string} the formatted log
38 */
39
40 /**
41 * The main cologne log format.
42 *
43 * @memberof Cologne
44 * @typedef {object} tCologneLog
45 * @property {Number} _timestamp the timestamp in miliseconds with decimal
46 * numbers representing fractions of miliseconds
47 * @property {String} _cologneLog main identifier, encodes the version of the
48 * cologne log format being used.
49 * @property {String} _from the origin of the log message.
50 * @property {String} _level the severity level of the log, uses syslog
51 * priorities.
52 * @property {String} _levelString the severity level keyword of the log,
53 * uses syslog priority keywords.
54 */
55
56 /**
57 * Cologne is a logger multiplexer that works mainly with a JSON format. It
58 * can be instantiated with several loggers, or they can be changed after
59 * the fact.
60 *
61 * ## Usage
62 *
63 * ```
64 * require('cologne');
65 *
66 * let co = new Cologne({
67 * from: "Special Worker Logger",
68 * loggers: [
69 * new Cologne.Logger.Console({
70 * formatter: new Cologne.Formatter.Token({
71 * formatString: '[{{_timestamp}}]{{_from}}: {{message}}'
72 * })
73 * })
74 * ]
75 * });
76 * ```
77 *
78 * @class Cologne
79 */
80 let Cologne = class Cologne {
81
82 constructor (config) {
83
84 /**
85 * The name of this logger, useful to distinguish between different
86 * loggers.
87 *
88 * @name from
89 * @instance
90 * @memberof Cologne
91 * @type String
92 * @default 'Generic Cologne Logger
93 */
94 this.from = 'Generic Cologne Logger';
95
96 /**
97 * The array containing all the loggers it will call to.
98 *
99 * @name loggers
100 * @instance
101 * @memberof Cologne
102 * @type Cologne.ILogger[]
103 * @default []
104 */
105 this.loggers = [];
106
107 Object.assign(this, config || {});
108 }
109
110 /**
111 * Adds a logger to the current instance.
112 *
113 * @function addLogger
114 * @instance
115 * @memberof Cologne
116 * @param {Cologne.ILogger} logger the logger to add
117 * @return {undefined}
118 */
119 addLogger (logger) {
120 this.loggers.push(logger);
121 }
122
123 /**
124 * Removes a logger from the current instance.
125 *
126 * @function removeLogger
127 * @instance
128 * @memberof Cologne
129 * @param {Cologne.ILogger} logger the logger to remove
130 * @return {Cologne.ILogger[]} the removed log, inside an array.
131 */
132 removeLogger (logger) {
133 let index;
134
135 index = this.loggers.indexOf(logger);
136 if (index >= 0) {
137 this.loggers.splice(index, 1);
138 }
139 }
140
141 /**
142 * Given an item, it builds a cologne log object. this is done
143 * automatically by the logger, though this is useful if you need
144 * to attach metadata before logging.
145 *
146 * @function buildLog
147 * @instance
148 * @memberof Cologne
149 * @param {*} item The item to log
150 * @return {Cologne.tCologneLog} a cologne log object
151 */
152 buildLog (item, level, meta) {
153 let logObject;
154
155 logObject = {};
156
157 if (typeof item === 'undefined' || item === null || !item._cologneLog) {
158 logObject.message = item;
159 logObject._cologneLog = this.constructor._version;
160 logObject._from = this.from;
161 logObject._level = level || 6;
162 logObject._levelString = this._levelString(logObject._level);
163 logObject._timestamp = LogUtilities.now();
164
165 if (meta && typeof meta === 'object') {
166 Object.assign(logObject, meta);
167 }
168
169 return logObject;
170 }
171
172 if (item._cologneLog) {
173 item._level = level || item._level || 6;
174 item._levelString = this._levelString(item._level);
175 }
176
177 return item;
178 }
179
180 /**
181 * Default log function. Sends arguments to loggers. If not specified in log
182 * object, it will set the severity to 6 - INFO.
183 *
184 * @function log
185 * @instance
186 * @memberof Cologne
187 * @return {undefined}
188 */
189 log () {
190 this._log.apply(this, [null].concat(Array.prototype.slice.call(arguments)));
191 }
192
193 /**
194 * Logs with debug level
195 *
196 * @function debug
197 * @instance
198 * @memberof Cologne
199 * @return {undefined}
200 */
201 debug () {
202 this._log.apply(this, [7].concat(Array.prototype.slice.call(arguments)));
203 }
204
205 /**
206 * Logs with info level
207 *
208 * @function info
209 * @instance
210 * @memberof Cologne
211 * @return {undefined}
212 */
213 info () {
214 this._log.apply(this, [6].concat(Array.prototype.slice.call(arguments)));
215 }
216
217 /**
218 * Logs with notice level
219 *
220 * @function notice
221 * @instance
222 * @memberof Cologne
223 * @return {undefined}
224 */
225 notice () {
226 this._log.apply(this, [5].concat(Array.prototype.slice.call(arguments)));
227 }
228
229 /**
230 * Logs with warn level
231 *
232 * @function warn
233 * @instance
234 * @memberof Cologne
235 * @return {undefined}
236 */
237 warn () {
238 this._log.apply(this, [4].concat(Array.prototype.slice.call(arguments)));
239 }
240
241 /**
242 * Logs with error level
243 *
244 * @function error
245 * @instance
246 * @memberof Cologne
247 * @return {undefined}
248 */
249 error () {
250 this._log.apply(this, [3].concat(Array.prototype.slice.call(arguments)));
251 }
252
253 // Private method that builds all the logs and sends them to the loggers.
254 _log (severity) {
255 let remainingArguments, logObjectArray, log, logger;
256
257 remainingArguments = Array.prototype.slice.call(arguments, 1);
258 logObjectArray = [];
259
260 for (log of remainingArguments) {
261 if (typeof log === 'undefined') {
262 logObjectArray.push(this.buildLog('undefined', severity));
263 continue;
264 }
265
266 if (log === null) {
267 logObjectArray.push(this.buildLog('null', severity));
268 continue;
269 }
270
271 logObjectArray.push(this.buildLog(log, severity));
272 }
273
274 for (logger of this.loggers) {
275 logger.log.apply(logger, logObjectArray);
276 }
277 }
278
279 // Private utility method that will return the string for any given
280 // numerical severity level
281 _levelString (level) {
282 switch(level) {
283 case 0:
284 return 'emerg';
285 case 1:
286 return 'alert';
287 case 2:
288 return 'crit';
289 case 3:
290 return 'error';
291 case 4:
292 return 'warning';
293 case 5:
294 return 'notice';
295 case 6:
296 return 'info';
297 case 7:
298 return 'debug';
299 }
300 }
301 };
302
303 // Version of the Cologne Log Format used.
304 Cologne._version = '1.0.0';
305
306 /**
307 * Namespace that includes the built-in formatters.
308 *
309 * @namespace Formatter
310 * @memberof Cologne
311 */
312 Cologne.Formatter = {};
313 Cologne.Formatter.Simple = require('./cologne/formatter/simple');
314 Cologne.Formatter.Token = require('./cologne/formatter/token');
315
316 /**
317 * Namespace that includes the built-in loggers.
318 *
319 * @namespace Logger
320 * @memberof Cologne
321 */
322 Cologne.Logger = {};
323 Cologne.Logger.Console = require('./cologne/logger/console');
324 Cologne.Logger.File = require('./cologne/logger/file');
325
326 Cologne.LogUtilities = require('./cologne/log_utilities');
327
328 module.exports = Cologne;