Skip to content

Commit 908c300

Browse files
lutovichDABH
authored andcommitted
Added isLevelEnabled(string) & isXXXEnabled() (#1352)
Make logger expose functions to check if a particular level is enabled. This could be useful if either message or parameter creation is an expensive operation, which should be avoided when log level is disabled. Logger will contain `isLevelEnabled(level: string)` function and multiple `isXXXEnabled()` where "XXX" is the capitalized name of the configured log level. E.g. `isDebugEnabled()`, `isInfoEnabled()`, etc.
1 parent a32aa3c commit 908c300

File tree

3 files changed

+219
-1
lines changed

3 files changed

+219
-1
lines changed

lib/winston/create-logger.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class DerivedLogger extends Logger {
4444
}
4545

4646
// Define prototype methods for each log level
47-
// e.g. logger.log('info', msg) <––> logger.info(msg)
47+
// e.g. logger.log('info', msg) <––> logger.info(msg) & logger.isInfoEnabled()
4848
this[level] = (...args) => {
4949
// Optimize the hot-path which is the single object.
5050
if (args.length === 1) {
@@ -61,10 +61,16 @@ class DerivedLogger extends Logger {
6161
// 2. v1/v2 API: log(level, msg, ... [string interpolate], [{metadata}], [callback])
6262
return this.log(level, ...args);
6363
};
64+
65+
this[isLevelEnabledFunctionName(level)] = () => this.isLevelEnabled(level);
6466
});
6567
}
6668
}
6769

70+
function isLevelEnabledFunctionName(level) {
71+
return 'is' + level.charAt(0).toUpperCase() + level.slice(1) + 'Enabled';
72+
}
73+
6874
/**
6975
* Create a new instance of a winston Logger. Creates a new
7076
* prototype for each instance.

lib/winston/logger.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,31 @@ class Logger extends stream.Transform {
9595
}
9696
}
9797

98+
isLevelEnabled(level) {
99+
const givenLevelValue = getLevelValue(this.levels, level);
100+
if (givenLevelValue === null) {
101+
return false;
102+
}
103+
104+
const configuredLevelValue = getLevelValue(this.levels, this.level);
105+
if (configuredLevelValue === null) {
106+
return false;
107+
}
108+
109+
if (!this.transports || this.transports.length === 0) {
110+
return configuredLevelValue >= givenLevelValue;
111+
}
112+
113+
const index = this.transports.findIndex(transport => {
114+
let transportLevelValue = getLevelValue(this.levels, transport.level);
115+
if (transportLevelValue === null) {
116+
transportLevelValue = configuredLevelValue;
117+
}
118+
return transportLevelValue >= givenLevelValue;
119+
});
120+
return index !== -1;
121+
}
122+
98123
/* eslint-disable valid-jsdoc */
99124
/**
100125
* Ensure backwards compatibility with a `log` method
@@ -511,6 +536,14 @@ class Logger extends stream.Transform {
511536
}
512537
}
513538

539+
function getLevelValue(levels, level) {
540+
const value = levels[level];
541+
if (!value && value !== 0) {
542+
return null;
543+
}
544+
return value;
545+
}
546+
514547
/**
515548
* Represents the current readableState pipe targets for this Logger instance.
516549
* @type {Array|Object}

test/logger.test.js

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,185 @@ describe('Logger (levels)', function () {
360360
});
361361
});
362362

363+
describe('Logger (level enabled/disabled)', function () {
364+
it('default levels', function () {
365+
var logger = winston.createLogger({
366+
level: 'verbose',
367+
levels: winston.config.npm.levels,
368+
transports: [new winston.transports.Console()]
369+
});
370+
371+
assume(logger.isLevelEnabled).is.a('function');
372+
373+
assume(logger.isErrorEnabled).is.a('function');
374+
assume(logger.isWarnEnabled).is.a('function');
375+
assume(logger.isInfoEnabled).is.a('function');
376+
assume(logger.isVerboseEnabled).is.a('function');
377+
assume(logger.isDebugEnabled).is.a('function');
378+
assume(logger.isSillyEnabled).is.a('function');
379+
380+
assume(logger.isLevelEnabled('error')).true();
381+
assume(logger.isLevelEnabled('warn')).true();
382+
assume(logger.isLevelEnabled('info')).true();
383+
assume(logger.isLevelEnabled('verbose')).true();
384+
assume(logger.isLevelEnabled('debug')).false();
385+
assume(logger.isLevelEnabled('silly')).false();
386+
387+
assume(logger.isErrorEnabled()).true();
388+
assume(logger.isWarnEnabled()).true();
389+
assume(logger.isInfoEnabled()).true();
390+
assume(logger.isVerboseEnabled()).true();
391+
assume(logger.isDebugEnabled()).false();
392+
assume(logger.isSillyEnabled()).false();
393+
});
394+
395+
it('default levels, transport override', function () {
396+
var transport = new winston.transports.Console();
397+
transport.level = 'debug';
398+
399+
var logger = winston.createLogger({
400+
level: 'info',
401+
levels: winston.config.npm.levels,
402+
transports: [transport]
403+
});
404+
405+
assume(logger.isLevelEnabled).is.a('function');
406+
407+
assume(logger.isErrorEnabled).is.a('function');
408+
assume(logger.isWarnEnabled).is.a('function');
409+
assume(logger.isInfoEnabled).is.a('function');
410+
assume(logger.isVerboseEnabled).is.a('function');
411+
assume(logger.isDebugEnabled).is.a('function');
412+
assume(logger.isSillyEnabled).is.a('function');
413+
414+
assume(logger.isLevelEnabled('error')).true();
415+
assume(logger.isLevelEnabled('warn')).true();
416+
assume(logger.isLevelEnabled('info')).true();
417+
assume(logger.isLevelEnabled('verbose')).true();
418+
assume(logger.isLevelEnabled('debug')).true();
419+
assume(logger.isLevelEnabled('silly')).false();
420+
421+
assume(logger.isErrorEnabled()).true();
422+
assume(logger.isWarnEnabled()).true();
423+
assume(logger.isInfoEnabled()).true();
424+
assume(logger.isVerboseEnabled()).true();
425+
assume(logger.isDebugEnabled()).true();
426+
assume(logger.isSillyEnabled()).false();
427+
});
428+
429+
it('default levels, no transports', function () {
430+
var logger = winston.createLogger({
431+
level: 'verbose',
432+
levels: winston.config.npm.levels,
433+
transports: []
434+
});
435+
436+
assume(logger.isLevelEnabled).is.a('function');
437+
438+
assume(logger.isErrorEnabled).is.a('function');
439+
assume(logger.isWarnEnabled).is.a('function');
440+
assume(logger.isInfoEnabled).is.a('function');
441+
assume(logger.isVerboseEnabled).is.a('function');
442+
assume(logger.isDebugEnabled).is.a('function');
443+
assume(logger.isSillyEnabled).is.a('function');
444+
445+
assume(logger.isLevelEnabled('error')).true();
446+
assume(logger.isLevelEnabled('warn')).true();
447+
assume(logger.isLevelEnabled('info')).true();
448+
assume(logger.isLevelEnabled('verbose')).true();
449+
assume(logger.isLevelEnabled('debug')).false();
450+
assume(logger.isLevelEnabled('silly')).false();
451+
452+
assume(logger.isErrorEnabled()).true();
453+
assume(logger.isWarnEnabled()).true();
454+
assume(logger.isInfoEnabled()).true();
455+
assume(logger.isVerboseEnabled()).true();
456+
assume(logger.isDebugEnabled()).false();
457+
assume(logger.isSillyEnabled()).false();
458+
});
459+
460+
it('custom levels', function () {
461+
var logger = winston.createLogger({
462+
level: 'test',
463+
levels: {
464+
bad: 0,
465+
test: 1,
466+
ok: 2
467+
},
468+
transports: [new winston.transports.Console()]
469+
});
470+
471+
assume(logger.isLevelEnabled).is.a('function');
472+
473+
assume(logger.isBadEnabled).is.a('function');
474+
assume(logger.isTestEnabled).is.a('function');
475+
assume(logger.isOkEnabled).is.a('function');
476+
477+
assume(logger.isLevelEnabled('bad')).true();
478+
assume(logger.isLevelEnabled('test')).true();
479+
assume(logger.isLevelEnabled('ok')).false();
480+
481+
assume(logger.isBadEnabled()).true();
482+
assume(logger.isTestEnabled()).true();
483+
assume(logger.isOkEnabled()).false();
484+
});
485+
486+
it('custom levels, no transports', function () {
487+
var logger = winston.createLogger({
488+
level: 'test',
489+
levels: {
490+
bad: 0,
491+
test: 1,
492+
ok: 2
493+
},
494+
transports: []
495+
});
496+
497+
assume(logger.isLevelEnabled).is.a('function');
498+
499+
assume(logger.isBadEnabled).is.a('function');
500+
assume(logger.isTestEnabled).is.a('function');
501+
assume(logger.isOkEnabled).is.a('function');
502+
503+
assume(logger.isLevelEnabled('bad')).true();
504+
assume(logger.isLevelEnabled('test')).true();
505+
assume(logger.isLevelEnabled('ok')).false();
506+
507+
assume(logger.isBadEnabled()).true();
508+
assume(logger.isTestEnabled()).true();
509+
assume(logger.isOkEnabled()).false();
510+
});
511+
512+
it('custom levels, transport override', function () {
513+
var transport = new winston.transports.Console();
514+
transport.level = 'ok';
515+
516+
var logger = winston.createLogger({
517+
level: 'bad',
518+
levels: {
519+
bad: 0,
520+
test: 1,
521+
ok: 2
522+
},
523+
transports: [transport]
524+
});
525+
526+
assume(logger.isLevelEnabled).is.a('function');
527+
528+
assume(logger.isBadEnabled).is.a('function');
529+
assume(logger.isTestEnabled).is.a('function');
530+
assume(logger.isOkEnabled).is.a('function');
531+
532+
assume(logger.isLevelEnabled('bad')).true();
533+
assume(logger.isLevelEnabled('test')).true();
534+
assume(logger.isLevelEnabled('ok')).true();
535+
536+
assume(logger.isBadEnabled()).true();
537+
assume(logger.isTestEnabled()).true();
538+
assume(logger.isOkEnabled()).true();
539+
});
540+
});
541+
363542
describe('Logger (stream semantics)', function () {
364543
it(`'finish' event awaits transports to emit 'finish'`, function (done) {
365544
const transports = [

0 commit comments

Comments
 (0)