Skip to content

Commit

Permalink
Added isLevelEnabled(string) & isXXXEnabled() (#1352)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
lutovich authored and DABH committed Aug 27, 2018
1 parent a32aa3c commit 908c300
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 1 deletion.
8 changes: 7 additions & 1 deletion lib/winston/create-logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class DerivedLogger extends Logger {
}

// Define prototype methods for each log level
// e.g. logger.log('info', msg) <––> logger.info(msg)
// e.g. logger.log('info', msg) <––> logger.info(msg) & logger.isInfoEnabled()
this[level] = (...args) => {
// Optimize the hot-path which is the single object.
if (args.length === 1) {
Expand All @@ -61,10 +61,16 @@ class DerivedLogger extends Logger {
// 2. v1/v2 API: log(level, msg, ... [string interpolate], [{metadata}], [callback])
return this.log(level, ...args);
};

this[isLevelEnabledFunctionName(level)] = () => this.isLevelEnabled(level);
});
}
}

function isLevelEnabledFunctionName(level) {
return 'is' + level.charAt(0).toUpperCase() + level.slice(1) + 'Enabled';
}

/**
* Create a new instance of a winston Logger. Creates a new
* prototype for each instance.
Expand Down
33 changes: 33 additions & 0 deletions lib/winston/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,31 @@ class Logger extends stream.Transform {
}
}

isLevelEnabled(level) {
const givenLevelValue = getLevelValue(this.levels, level);
if (givenLevelValue === null) {
return false;
}

const configuredLevelValue = getLevelValue(this.levels, this.level);
if (configuredLevelValue === null) {
return false;
}

if (!this.transports || this.transports.length === 0) {
return configuredLevelValue >= givenLevelValue;
}

const index = this.transports.findIndex(transport => {
let transportLevelValue = getLevelValue(this.levels, transport.level);
if (transportLevelValue === null) {
transportLevelValue = configuredLevelValue;
}
return transportLevelValue >= givenLevelValue;
});
return index !== -1;
}

/* eslint-disable valid-jsdoc */
/**
* Ensure backwards compatibility with a `log` method
Expand Down Expand Up @@ -511,6 +536,14 @@ class Logger extends stream.Transform {
}
}

function getLevelValue(levels, level) {
const value = levels[level];
if (!value && value !== 0) {
return null;
}
return value;
}

/**
* Represents the current readableState pipe targets for this Logger instance.
* @type {Array|Object}
Expand Down
179 changes: 179 additions & 0 deletions test/logger.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,185 @@ describe('Logger (levels)', function () {
});
});

describe('Logger (level enabled/disabled)', function () {
it('default levels', function () {
var logger = winston.createLogger({
level: 'verbose',
levels: winston.config.npm.levels,
transports: [new winston.transports.Console()]
});

assume(logger.isLevelEnabled).is.a('function');

assume(logger.isErrorEnabled).is.a('function');
assume(logger.isWarnEnabled).is.a('function');
assume(logger.isInfoEnabled).is.a('function');
assume(logger.isVerboseEnabled).is.a('function');
assume(logger.isDebugEnabled).is.a('function');
assume(logger.isSillyEnabled).is.a('function');

assume(logger.isLevelEnabled('error')).true();
assume(logger.isLevelEnabled('warn')).true();
assume(logger.isLevelEnabled('info')).true();
assume(logger.isLevelEnabled('verbose')).true();
assume(logger.isLevelEnabled('debug')).false();
assume(logger.isLevelEnabled('silly')).false();

assume(logger.isErrorEnabled()).true();
assume(logger.isWarnEnabled()).true();
assume(logger.isInfoEnabled()).true();
assume(logger.isVerboseEnabled()).true();
assume(logger.isDebugEnabled()).false();
assume(logger.isSillyEnabled()).false();
});

it('default levels, transport override', function () {
var transport = new winston.transports.Console();
transport.level = 'debug';

var logger = winston.createLogger({
level: 'info',
levels: winston.config.npm.levels,
transports: [transport]
});

assume(logger.isLevelEnabled).is.a('function');

assume(logger.isErrorEnabled).is.a('function');
assume(logger.isWarnEnabled).is.a('function');
assume(logger.isInfoEnabled).is.a('function');
assume(logger.isVerboseEnabled).is.a('function');
assume(logger.isDebugEnabled).is.a('function');
assume(logger.isSillyEnabled).is.a('function');

assume(logger.isLevelEnabled('error')).true();
assume(logger.isLevelEnabled('warn')).true();
assume(logger.isLevelEnabled('info')).true();
assume(logger.isLevelEnabled('verbose')).true();
assume(logger.isLevelEnabled('debug')).true();
assume(logger.isLevelEnabled('silly')).false();

assume(logger.isErrorEnabled()).true();
assume(logger.isWarnEnabled()).true();
assume(logger.isInfoEnabled()).true();
assume(logger.isVerboseEnabled()).true();
assume(logger.isDebugEnabled()).true();
assume(logger.isSillyEnabled()).false();
});

it('default levels, no transports', function () {
var logger = winston.createLogger({
level: 'verbose',
levels: winston.config.npm.levels,
transports: []
});

assume(logger.isLevelEnabled).is.a('function');

assume(logger.isErrorEnabled).is.a('function');
assume(logger.isWarnEnabled).is.a('function');
assume(logger.isInfoEnabled).is.a('function');
assume(logger.isVerboseEnabled).is.a('function');
assume(logger.isDebugEnabled).is.a('function');
assume(logger.isSillyEnabled).is.a('function');

assume(logger.isLevelEnabled('error')).true();
assume(logger.isLevelEnabled('warn')).true();
assume(logger.isLevelEnabled('info')).true();
assume(logger.isLevelEnabled('verbose')).true();
assume(logger.isLevelEnabled('debug')).false();
assume(logger.isLevelEnabled('silly')).false();

assume(logger.isErrorEnabled()).true();
assume(logger.isWarnEnabled()).true();
assume(logger.isInfoEnabled()).true();
assume(logger.isVerboseEnabled()).true();
assume(logger.isDebugEnabled()).false();
assume(logger.isSillyEnabled()).false();
});

it('custom levels', function () {
var logger = winston.createLogger({
level: 'test',
levels: {
bad: 0,
test: 1,
ok: 2
},
transports: [new winston.transports.Console()]
});

assume(logger.isLevelEnabled).is.a('function');

assume(logger.isBadEnabled).is.a('function');
assume(logger.isTestEnabled).is.a('function');
assume(logger.isOkEnabled).is.a('function');

assume(logger.isLevelEnabled('bad')).true();
assume(logger.isLevelEnabled('test')).true();
assume(logger.isLevelEnabled('ok')).false();

assume(logger.isBadEnabled()).true();
assume(logger.isTestEnabled()).true();
assume(logger.isOkEnabled()).false();
});

it('custom levels, no transports', function () {
var logger = winston.createLogger({
level: 'test',
levels: {
bad: 0,
test: 1,
ok: 2
},
transports: []
});

assume(logger.isLevelEnabled).is.a('function');

assume(logger.isBadEnabled).is.a('function');
assume(logger.isTestEnabled).is.a('function');
assume(logger.isOkEnabled).is.a('function');

assume(logger.isLevelEnabled('bad')).true();
assume(logger.isLevelEnabled('test')).true();
assume(logger.isLevelEnabled('ok')).false();

assume(logger.isBadEnabled()).true();
assume(logger.isTestEnabled()).true();
assume(logger.isOkEnabled()).false();
});

it('custom levels, transport override', function () {
var transport = new winston.transports.Console();
transport.level = 'ok';

var logger = winston.createLogger({
level: 'bad',
levels: {
bad: 0,
test: 1,
ok: 2
},
transports: [transport]
});

assume(logger.isLevelEnabled).is.a('function');

assume(logger.isBadEnabled).is.a('function');
assume(logger.isTestEnabled).is.a('function');
assume(logger.isOkEnabled).is.a('function');

assume(logger.isLevelEnabled('bad')).true();
assume(logger.isLevelEnabled('test')).true();
assume(logger.isLevelEnabled('ok')).true();

assume(logger.isBadEnabled()).true();
assume(logger.isTestEnabled()).true();
assume(logger.isOkEnabled()).true();
});
});

describe('Logger (stream semantics)', function () {
it(`'finish' event awaits transports to emit 'finish'`, function (done) {
const transports = [
Expand Down

0 comments on commit 908c300

Please sign in to comment.