Repository: pinojs/pino
Pull request #320 (2017-10-29 03:53:55)

Added isLevelEnabled function
Adds a function to the Pino object that returns true if its argument is the current level or higher, false otherwise. The use case is to be able to put costly log computations behind a an `if` statement and only calculate them if a certain log level is enabled. e.g.

```javascript
if (logger.isLevelEnabled('debug')) {
  logger.debug(fetchLargeDocument())
}
```

Currently to do this I have to wrap the logger and include a function similar to the one this PR adds.

jsumners: What's wrong with `if (logger.level > 30) logger.debug('something')`?
Epitrochoid: @jsumners in my case we use this pattern pretty often and we would end up with a lot of magic numbers throughout the code base. It gets even hairier because we have a shared library adding a bunch of company wide standard log levels as custom log levels to pino. Someone else using the library would have to pull the repo and look at the `pino.addLevel()` calls to figure out what integer they need to reference for a log name they already know. This seems like standard functionality in other logging libraries with Bunyan returning true or false on an empty call (e.g. `bunyan.debug() == true`) and raptor-logging providing `logging.isDebugEnabled()` for each of its standard levels.

Patch:
diff --git a/pino.js b/pino.js
index 5b09b5d..3378991 100644
--- a/pino.js
+++ b/pino.js
@@ -250,6 +250,15 @@ Object.defineProperty(pinoPrototype, 'addLevel', {
   value: addLevel
 })
 
+function isLevelEnabled (logLevel) {
+  var logLevelVal = this.levels.values[logLevel]
+  return logLevelVal && (logLevelVal >= this._levelVal)
+}
+Object.defineProperty(pinoPrototype, 'isLevelEnabled', {
+  enumerable: true,
+  value: isLevelEnabled
+})
+
 function pino (opts, stream) {
   var iopts = opts
   var istream = stream


Test patch:
diff --git a/test/islevelenabled.test.js b/test/islevelenabled.test.js
new file mode 100644
index 0000000..34992f3
--- /dev/null
+++ b/test/islevelenabled.test.js
@@ -0,0 +1,53 @@
+'use strict'
+
+var test = require('tap').test
+var pino = require('../')
+
+test('can check if current level enabled', function (t) {
+  t.plan(1)
+
+  var log = pino({level: 'debug'})
+  t.is(true, log.isLevelEnabled('debug'))
+})
+
+test('can check if level enabled after level set', function (t) {
+  t.plan(2)
+
+  var log = pino()
+  t.is(false, log.isLevelEnabled('debug'))
+  log.level = 'debug'
+  t.is(true, log.isLevelEnabled('debug'))
+})
+
+test('can check if higher level enabled', function (t) {
+  t.plan(1)
+
+  var log = pino({level: 'debug'})
+  t.is(true, log.isLevelEnabled('error'))
+})
+
+test('can check if lower level is disabled', function (t) {
+  t.plan(1)
+
+  var log = pino({level: 'error'})
+  t.is(false, log.isLevelEnabled('trace'))
+})
+
+test('can check if child has current level enabled', function (t) {
+  t.plan(3)
+
+  var log = pino().child({level: 'debug'})
+  t.is(true, log.isLevelEnabled('debug'))
+  t.is(true, log.isLevelEnabled('error'))
+  t.is(false, log.isLevelEnabled('trace'))
+})
+
+test('can check if custom level is enabled', function (t) {
+  t.plan(3)
+
+  var log = pino({level: 'debug'})
+  log.addLevel('foo', 35)
+  t.is(true, log.isLevelEnabled('foo'))
+  t.is(true, log.isLevelEnabled('error'))
+  t.is(false, log.isLevelEnabled('trace'))
+})