log-process-errors
log-process-errors copied to clipboard
Show some ❤️ to Node.js process errors
Show some ❤️ to Node.js process errors.
Node.js prints process errors
(uncaughtException
,
warning
,
unhandledRejection
,
rejectionHandled
)
on the console which is very useful. Unfortunately those errors:
- do not show stack traces for
warning
andrejectionHandled
making them hard to debug. - are inconvenient to log to an external service.
- are hard to test.
- cannot be conditionally skipped.
- are printed each time an error is repeated (except for
warning
). - are not human-friendly.
log-process-errors
fixes all those issues.
Without log-process-errors
:
With log-process-errors
:
Use cases
- Proper logging of process errors in production.
- Debugging of process errors in development.
- Automated testing of process errors.
Demo
You can try this library:
- either directly in your browser.
- or by executing the
examples
files in a terminal.
Install
Production code (e.g. a server) can install this either as a production or development dependency:
npm install log-process-errors
However, libraries should install this as a development dependency:
npm install -D log-process-errors
This is because logging is modified globally and libraries users might not expect this side-effect. Also, this might lead to conflicts between libraries.
This package is an ES module and must be loaded using
an import
or import()
statement,
not require()
.
API
logProcessErrors(options?)
options
object?
Return value: () => void
Initializes log-process-errors
. Should be called as early as possible in the
code, before other import
statements.
import logProcessErrors from 'log-process-errors'
logProcessErrors(options)
Returns a function that can be fired to restore Node.js default behavior.
import logProcessErrors from 'log-process-errors'
const restore = logProcessErrors(options)
restore()
Options
log
Type: function(error, level, originalError)
By default process errors will be logged to the console using console.error()
,
console.warn()
, etc.
This behavior can be overridden with the log
option. For example to log
process errors with Winston instead:
import logProcessErrors from 'log-process-errors'
logProcessErrors({
log(error, level, originalError) {
winstonLogger[level](error.stack)
},
})
The function's arguments are error
, level
and
originalError
.
If logging is asynchronous, the function should return a promise (or use
async
/await
). This is not necessary if logging is buffered (like
Winston).
Duplicate process errors are only logged once (whether the log
option is
defined or not).
error
Type: Error
The log
and level
options receive as argument an error
instance.
This error is generated based on the original process error but with an improved
name
, message
and stack
. However the original process error is still
available as a third argument to log
.
error.name
Type: string
Value: 'UncaughtException'
,
'UnhandledRejection'
,
'RejectionHandled'
or 'Warning'
error.stack
error
is prettified when using
console
or
util.inspect()
:
console.log(error)
But not when using error.stack
instead:
console.log(error.stack)
level
Type: object
Default: { warning: 'warn', default: 'error' }
Which log level to use.
Object keys are the error names:
uncaughtException
,
warning
,
unhandledRejection
,
rejectionHandled
or default
.
Object values are the log level: 'debug'
, 'info'
, 'warn'
, 'error'
,
'silent'
or 'default'
. It can also be a function using
error
as argument and returning one of those log levels.
import logProcessErrors from 'log-process-errors'
logProcessErrors({
level: {
// Use `debug` log level for `uncaughtException` instead of `error`
uncaughtException: 'debug',
// Skip some logs based on a condition
default(error) {
return shouldSkip(error) ? 'silent' : 'default'
},
},
})
exitOn
Type: string[]
Value: array of 'uncaughtException'
,
'unhandledRejection'
,
'rejectionHandled'
or 'warning'
Default: ['uncaughtException', 'unhandledRejection']
for Node >= 15.0.0
,
['uncaughtException']
otherwise.
Which process errors should trigger process.exit(1)
:
-
['uncaughtException', 'unhandledRejection']
is Node.js default behavior since Node.js15.0.0
. Before, onlyuncaughtException
was enabled. - use
[]
to prevent anyprocess.exit(1)
. Recommended if your process is long-running and does not automatically restart on exit.
process.exit(1)
will only be fired after successfully logging the process
error.
import logProcessErrors from 'log-process-errors'
logProcessErrors({ exitOn: ['uncaughtException', 'unhandledRejection'] })
testing
Type: string
Value: 'ava'
, 'mocha'
, 'jasmine'
, 'tape'
or 'node_tap'
Default: undefined
When running tests, makes them fail if there are any process errors.
Example with Ava:
import logProcessErrors from 'log-process-errors'
// Should be initialized before requiring other dependencies
logProcessErrors({ testing: 'ava' })
import test from 'ava'
// Tests will fail because a warning is triggered
test('Example test', (t) => {
process.emitWarning('Example warning')
t.pass()
})
To ignore specific process errors, use the level
option:
import logProcessErrors from 'log-process-errors'
// Should be initialized before requiring other dependencies
logProcessErrors({ testing: 'ava', level: { warning: 'silent' } })
import test from 'ava'
// Tests will not fail because warnings are `silent`
test('Example test', (t) => {
process.emitWarning('Example warning')
t.pass()
})
colors
Type: boolean
Default: true
if the output is a terminal.
Colorizes messages.
import logProcessErrors from 'log-process-errors'
logProcessErrors({ colors: false })
Related projects
-
modern-errors
: Handle errors like it's 2022 🔮 -
create-error-types
: Create multiple error types -
error-type
: Create one error type -
error-serializer
: Convert errors to/from plain objects -
normalize-exception
: Normalize exceptions/errors -
merge-error-cause
: Merge an error with itscause
-
error-cause-polyfill
: Polyfillerror.cause
-
handle-cli-error
: 💣 Error handler for CLI applications 💥
Support
For any question, don't hesitate to submit an issue on GitHub.
Everyone is welcome regardless of personal background. We enforce a Code of conduct in order to promote a positive and inclusive environment.
Contributing
This project was made with ❤️. The simplest way to give back is by starring and sharing it online.
If the documentation is unclear or has a typo, please click on the page's Edit
button (pencil icon) and suggest a correction.
If you would like to help us fix a bug or add a new feature, please check our guidelines. Pull requests are welcome!
Thanks go to our wonderful contributors:
ehmicky 💻 🎨 🤔 📖 |
Steven Vachon 💬 |
Hongarc 📖 💻 |
Andy Brenneke 🐛 |