Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(level): Separate concerns for the "level" parameter #35

Merged
merged 2 commits into from
Sep 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,12 @@ logger.info({
## Custom Log Levels

As per the Winston documentation, [custom log levels](https://github.com/winstonjs/winston#using-custom-logging-levels) may be used. In order to use such
levels in LogDNA, [custom levels must be defined](https://github.com/logdna/logger-node#custom-log-levels) for that logger as well.
levels in LogDNA, [custom levels must be defined](https://github.com/logdna/logger-node#custom-log-levels) for that logger as well. If `levels` is passed to this transport, they
will **automatically** be configured as custom levels for the LogDNA logger.

Similarly, if no custom winston levels are used, then the Winston [default of "npm" levels](https://github.com/winstonjs/winston#logging-levels) will be automatically configured for LogDNA to understand.

**NOTE:** The "levels" parameter is in the context of Winston, thus it should be an object where the keys are the level names, and the values are a numeric priority.

```javascript
const levels = {
Expand All @@ -95,7 +100,6 @@ levels in LogDNA, [custom levels must be defined](https://github.com/logdna/logg

const logdna_options = {
key: 'abc123'
, levels: Object.keys(levels)
}
logger.add(new logdnaWinston(logdna_options))

Expand All @@ -110,6 +114,38 @@ levels in LogDNA, [custom levels must be defined](https://github.com/logdna/logg
})
```

## The `maxLevel` Parameter

Both the Winston logger and the LogDNA logger accept a `level` parameter, but they mean different things:

* For Winston, `level` represents the maximum log level by priority. In other words, anything "higher" in priority number WILL NOT be logged.
* In LogDNA, `level` represents a default log level which is used in the absence of a level being defined for each log entry. Since Winston always passed a log level, this parameter is not usable in this transport.

To disambiguate the two `level` parameters (even though the LogDNA one cannot be used), this custom transport will accept the `maxLevel` parameter to be used as Winston's `level` parameter. This is **only needed if** `level` has not been defined during Winston's `createLogger` call prior to adding this custom transport.

```js
const winston = require('winston')
const logdnaTransport = require('logdna-winston')

const logger = winston.createLogger({
level: 'verbose'
, transports:[new logdnaTransport({key: 'abc123'})]
})
logger.silly('This will not be logged')
logger.verbose('This will be logged')

// ...is the same as this
const logger = winston.createLogger({
transports:[
new logdnaTransport({
key: 'abc123'
, maxLevel: 'verbose'
})
]
})
logger.silly('This will not be logged')
logger.verbose('This will be logged')
```
## Contributors ✨

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
Expand Down
27 changes: 24 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,32 @@ const pkg = require('./package.json')
*/
module.exports = class LogDNATransport extends Transport {
constructor(options) {
super(options)
const {levels, maxLevel, key, ...opts} = options
super({
...opts
, levels
, level: maxLevel
})

let custom_levels = levels
if (!custom_levels) {
// Per the winston docs, their 'npm' levels will be used, and those must be
// set up as custom levels in LogDNA.
// @see https://github.com/winstonjs/winston#logging-levels
custom_levels = {
error: 0
, warn: 1
, info: 2
, http: 3
, verbose: 4
, debug: 5
, silly: 6
}
}
// Create an instance of @logdna/logger
this.logger = createLogger(options.key, {
...options
this.logger = createLogger(key, {
...opts
, levels: Object.keys(custom_levels)
, UserAgent: `${pkg.name}/${pkg.version}`
})
}
Expand Down
92 changes: 91 additions & 1 deletion test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ test('Call .log() with a message payload and custom level', (t) => {
, mac: '9e:a0:f8:20:86:3d'
, url: 'http://localhost:35870'
, app: 'LogDNA'
, levels: Object.keys(levels)
, levels
}
logger.add(new logdnaWinston(logdna_options))

Expand Down Expand Up @@ -303,3 +303,93 @@ test('Error will still be processed if there is no stack trace', (t) => {
, error
})
})

test('If no "levels", then use winston defaults and pass LogDNA custom levels', (t) => {
const logger = winston.createLogger()

const logdna_options = {
key: 'abc123'
, hostname: 'My-Host'
, ip: '192.168.2.100'
, mac: '9e:a0:f8:20:86:3d'
, url: 'http://localhost:35870'
, app: 'LogDNA'
, maxLevel: 'silly' // Required for this test since 'info' is the max log level by default
}
logger.add(new logdnaWinston(logdna_options))

t.plan(4)
t.on('end', async () => {
nock.cleanAll()
})

nock(logdna_options.url)
.post('/', (body) => {
for (const {level} of body.ls) {
switch (level) {
case 'ERROR':
case 'INFO':
case 'VERBOSE':
case 'SILLY':
t.pass(`${level} level received`)
continue
default:
t.fail(`${level} is not configured for this test`)
}
}
return true
})
.query(() => {
return true
})
.reply(200, 'Ingester response')

logger.error('This is an error')
logger.info('This is an info')
logger.verbose('This is verbose, which is supported via LogDNA custom levels')
logger.silly('This is silly, which is supported via LogDNA custom levels')
})

test('Winston is passed "level" when the "maxLevel" param is used', (t) => {
const logger = winston.createLogger()

const logdna_options = {
key: 'abc123'
, hostname: 'My-Host'
, ip: '192.168.2.100'
, mac: '9e:a0:f8:20:86:3d'
, url: 'http://localhost:35870'
, app: 'LogDNA'
, maxLevel: 'warn'
}
logger.add(new logdnaWinston(logdna_options))

t.plan(2)
t.on('end', async () => {
nock.cleanAll()
})

nock(logdna_options.url)
.post('/', (body) => {
for (const {level} of body.ls) {
switch (level) {
case 'ERROR':
case 'WARN':
t.pass(`${level} level received`)
continue
default:
t.fail(`${level} is not configured for this test`)
}
}
return true
})
.query(() => {
return true
})
.reply(200, 'Ingester response')

logger.error('This error will be logged')
logger.warn('This warning will be logged')
logger.info('This is an info, but will be ignored due to maxLevel')
logger.verbose('This is verbose, but will be ignored due to maxLevel')
})