initial commit
[urlittler] / src / logger.js
1 'use strict';
2
3 /**
4 * Log as JSON to stdout/stderr.
5 */
6
7 const common = require('./common');
8
9 // This is uncomfortable, but is the simplest way to let logging work for BigInts.
10 // TODO: revisit with better solution
11 BigInt.prototype.toJSON = function() {
12 return this.toString();
13 }
14
15 // Also uncomfortable
16 Object.defineProperty(Error.prototype, 'toJSON', {
17 configurable: true,
18 value: function () {
19 const result = {};
20 const dupKey = function (key) {
21 // eslint-disable-next-line security/detect-object-injection
22 result[key] = this[key];
23 };
24 Object.getOwnPropertyNames(this).forEach(dupKey, this);
25 return result;
26 },
27 });
28
29 const defaultOptions = {
30 ignoreBelowLevel: 'debug',
31 backend: console,
32 };
33
34 class Logger {
35 constructor(options = {}) {
36 common.setOptions(this, defaultOptions, options);
37
38 this.logLevels = [
39 'error',
40 'warn',
41 'info',
42 'log',
43 'debug',
44 ];
45
46 const ignoreLevelIdx = this.logLevels.indexOf(this.ignoreBelowLevel);
47 this.logLevels.forEach((level) => {
48 // eslint-disable-next-line security/detect-object-injection
49 this[level] = (this.logLevels.indexOf(level) > ignoreLevelIdx) ?
50 () => {} :
51 Logger.levelTemplateFn(this.backend, level);
52 });
53 }
54
55 static levelTemplateFn(backend, level) {
56 return function (...args) {
57 // eslint-disable-next-line security/detect-object-injection
58 backend[level](Logger.payload(level, ...args));
59 };
60 }
61
62 static payload(level, scope, message, data, ...other) {
63 return JSON.stringify({
64 timestamp: Date.now(),
65 level: level,
66 scope: scope || '[unknown]',
67 message: message || '',
68 data: data || {},
69 ...(other.length && { other }),
70 });
71 }
72 }
73
74 module.exports = Logger;