Skip to content

Commit df4e945

Browse files
committed
Add exitOn option
1 parent c3d256f commit df4e945

File tree

4 files changed

+46
-27
lines changed

4 files changed

+46
-27
lines changed

README.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ logProcessErrors(options)
3939
- [`getMessage` `{function}`](#log-message)
4040
- [`colors` `{boolean}`](#log-message) (default: `false`)
4141
- [`skipEvent` `{function}`](#skipping-events)
42+
- [`exitOn` `{string[]}`](#process-exit) (default: `['uncaughtException']`)
4243

4344
`logProcessErrors()` should be called as early as possible in the code.
4445

@@ -56,6 +57,19 @@ the
5657
[`NODE_NO_WARNINGS=1`](https://nodejs.org/api/cli.html#cli_node_no_warnings_1)
5758
environment variable to prevent warnings being logged twice.
5859

60+
# Process exit
61+
62+
The `exitOn` option specifies which event should trigger `process.exit(1)`:
63+
64+
- the default value is `['uncaughtException']`. Exiting is the default
65+
behavior of Node.js. It's also recommended by the
66+
[official documentation](https://nodejs.org/api/process.html#process_warning_using_uncaughtexception_correctly).
67+
- we recommend using `exitOn: ['uncaughtException', 'unhandledRejection']`
68+
instead since this will be the [future default behavior of Node.js](https://nodejs.org/dist/latest-v8.x/docs/api/deprecations.html#deprecations_dep0018_unhandled_promise_rejections)
69+
- to prevent any `process.exit()`, use `exitOn: []`
70+
71+
`process.exit(1)` will only be fired after successfully logging the event.
72+
5973
# Custom logging
6074

6175
By default events will be logged to the console (e.g. `console.error()`).
@@ -171,12 +185,6 @@ The following properties are also defined with the `getMessage` option:
171185
- `colors` `{object}`: [Chalk instance](https://github.com/chalk/chalk#api)
172186
to colorize strings (disabled if the option `colors` is `false`)
173187

174-
# Uncaught exceptions
175-
176-
`uncaughtException` events will fire `process.exit(1)` after being successfully
177-
logged. Exiting is the default behavior and is recommended by the
178-
[Node.js documentation](https://nodejs.org/api/process.html#process_warning_using_uncaughtexception_correctly).
179-
180188
# Stop logging
181189

182190
Logging can be stopped by firing the function returned by `logProcessErrors()`

src/default.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const DEFAULT_OPTS = {
1010
getMessage: defaultGetMessage,
1111
log: defaultLog,
1212
colors: true,
13+
exitOn: ['uncaughtException'],
1314
}
1415

1516
module.exports = {

src/exit.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict'
2+
3+
const { exit } = require('process')
4+
const { promisify } = require('util')
5+
6+
// Exit process according to `opts.exitOn` (default: ['uncaughtException']):
7+
// - `uncaughtException`: default behavior of Node.js and recommended by https://nodejs.org/api/process.html#process_warning_using_uncaughtexception_correctly
8+
// - `unhandledRejection`: possible future behavior and recommended by Node.js.
9+
// See https://nodejs.org/dist/latest-v8.x/docs/api/deprecations.html#deprecations_dep0018_unhandled_promise_rejections
10+
// By default `unhandledRejection` is opt-in so that using this library does not
11+
// decrease stability (if the application does not restart on exit).
12+
const exitProcess = async function({ eventName, opts: { exitOn } }) {
13+
if (!exitOn.includes(eventName)) {
14+
return
15+
}
16+
17+
// This is only needed as a safety measure
18+
await promisify(setTimeout)(EXIT_TIMEOUT)
19+
20+
exit(EXIT_STATUS)
21+
}
22+
23+
const EXIT_TIMEOUT = 3e3
24+
const EXIT_STATUS = 1
25+
26+
module.exports = {
27+
exitProcess,
28+
}

src/handle.js

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
'use strict'
22

3-
const { exit } = require('process')
4-
const { promisify } = require('util')
5-
63
const { getInfo } = require('./info')
74
const { getColors } = require('./colors')
85
const { getLevel } = require('./level')
96
const { getMessage } = require('./message')
7+
const { exitProcess } = require('./exit')
108

119
// Generic event handler for all events.
1210
const handleEvent = async function({
@@ -35,32 +33,16 @@ const handleEvent = async function({
3533
const level = getLevel({ opts, info })
3634
const message = getMessage({ opts, info, level, colors })
3735

38-
// We need to `await` it in case we are logging an `uncaughtException` which
39-
// will make the process exit.
36+
// We need to `await` it in case `opts.exitOn` exits the process.
4037
// Without `await` Node.js would still wait until most async tasks (including
4138
// stream draining for logging libraries like Winston) have completed.
4239
// But there are some cases where it will not. In those cases, `opts.log()`
4340
// should be either synchronous or return a promise.
4441
await opts.log(message, level, info)
4542

46-
await exitProcess({ eventName })
47-
}
48-
49-
// Exit process on `uncaughtException`
50-
// See https://nodejs.org/api/process.html#process_warning_using_uncaughtexception_correctly
51-
const exitProcess = async function({ eventName }) {
52-
if (eventName !== 'uncaughtException') {
53-
return
54-
}
55-
56-
// This is only needed as a safety measure
57-
await promisify(setTimeout)(EXIT_TIMEOUT)
58-
59-
exit(1)
43+
await exitProcess({ eventName, opts })
6044
}
6145

62-
const EXIT_TIMEOUT = 3e3
63-
6446
module.exports = {
6547
handleEvent,
6648
}

0 commit comments

Comments
 (0)