debugNEXT -- A feature-enhanced TypeScript drop-in replacement for a very popular and simple-to-use [debug][https://www.npmjs.com/package/debug] module.
Your logs are always either nothing, or flooded.
The simple yet elegant solution is namespacing so that you can have granular control over which parts of your code to log.
The original debug
module exists in many popular frameworks, but it never grew in functionality. debug-next
is a drop-in replacement that adds new features.
One problem that the original debug
module had was that it indiscriminately log everything to error logs (process.stderr
for Node environments / console.error
for non-node environments). debug-next
has new debuggers that follows mainstream conventions (log
, logDebug
, logWarn
, logError
, logFatal
), and will log to normal or error logs depending on which is used:
log('This is equivalent to console.log / process.stdout.write')
logError('This is equivalent to console.error / process.stderr.write')
npm install --save debug-next
// or
yarn add debug-next
import { debug } from 'debug-next'
const log = debug('namespace')
const logFoo = debug('namespace:foo')
const logBar = debug('namespace:bar')
const logBarChild = debug('namespace:bar:child')
log('Output from log.')
logFoo('Output from logFoo.')
logBar('Output from logBar.')
logBarChild('Output from logBarChild.')
Your folder structure is your natural namespace. debug-next
uses that by default to generate namespacing.
Say you have 2 files index.js
and foo.js
:
src/index.ts:
import { Log, LogBase } from 'debug-next'
import * as foo from './foo'
// do this once in index/app/server.ts
LogBase.init('my-awesome-app', __dirname) // __dirname is a node global
const { log } = Log()
log('output from index')
foo.ts:
import { Log } from 'debug-next'
const { log } = Log()
log('output from foo')
DEBUG=my-awesome-app* node .
// Outputs:
my-awesome-app:index output from index
my-awesome-app:foo output from foo
$ DEBUG=namespace* node .
// logs
Output from log.
Output from logFoo.
Output from logBar.
Output from logBarChild.
DEBUG=namespace:bar:* node .
// logs
Output from logBarChild.
DEBUG=namespace*,-namespace:bar:child node .
// logs
Output from log.
Output from logFoo.
Output from logBar.
// logBarChild is de-matched.
Run any hooks with your debugging:
// src/index.js
import { LogBase, Log } from 'debug-next'
const { log } = Log()
LogBase.init('myHookExampleApp', __dirname)
// adding hook too all loggers
LogBase.addHook('all', 'myHook', args => {
// do something with the args they are passed into #log
console.log('myHook is running...', ...args)
})
log('FOO')
// outputs: myHookExampleApp:src:index FOO
// outputs: myHook is running... FOO
You can use this to run any hooks you like, for example, capturing message and transporting to Sentry:
LogBase.addHook('log', 'Sentry', (args, loggerType, isEnabled, scope, hookName) => {
Sentry.captureMessage(
`Captured messaged with arguments: ${args} ${loggerType} ${isEnabled} ${scope} ${hookName}`,
)
})
Smaller logs files will always help developers to debug faster. For logs that can generate multiple lines, use logVerbose
:
// simulating a data from API
const result = {
id: '89dnk-5jkl6',
success: true,
// objects containing a lot of data
payload: { ... },
data: { ... },
}
logVerbose(`Log everything important in first argument. ID[${result.id}] success[${result.success}]`, result)
When in default mode (non-verbose mode), logVerbose
will output:
app-name:filename.js Log everything important in first argument. ID[89dnk-5jkl6] success[true]| Verbose debugger available for: an object with keys [id,success,payload,data]
When in verbose mode (DEBUG_VERBOSE=true), logVerbose
will output:
app-name:filename.js Log everything important in first argument. ID[89dnk-5jkl6] success[true] {
id: '89dnk-5jkl6',
success: true,
payload: {
// many
// many
// lines
},
data: {
// many
// many
// lines
},
}
Please see https://github.com/calvintwr/debug-next/blob/master/src/types/node.process.env.d.ts for a full list of ENV options and their explanation.
DEBUG_VERBOSE=true
DEBUG_ERROR=true
DEBUG_DEPTH=5
DEBUG_SHOW_HIDDEN=true
DEBUG_GETTERS=true
debug-next
should run without settings in production.
Occassionally, you would want to only turn on namespaces for latest code changes:
DEBUG=namespace:with:latest-code-changes*
- Browser compatibility.
- Support Winston transportation methodology.
- Out-of-box support for Sentry.