Skip to content

Commit d5447a0

Browse files
committed
feat(defaultHandler): Exit on error option
BREAKING CHANGE: Changes the default behaviour to exit the process on the first error logged.
1 parent a68b0c5 commit d5447a0

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

README.md

+22
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ npm install --save @stencila/logga
2323

2424
## Usage
2525

26+
### Emitting log events
27+
2628
Create a new logger by calling `getLogger` with a unique tag to identify your app and/or module. Then emit log events using the `debug`, `info`, `warn` and `error` functions. You can pass them a message string or a `LogInfo` object.
2729

2830
```js
@@ -46,6 +48,18 @@ try {
4648
}
4749
```
4850

51+
See [this post](https://reflectoring.io/logging-levels/) for advice on when to use the alternative log levels. In summary,
52+
53+
- The `ERROR` level should only be used when the application really is in trouble. Users are being affected without having a way to work around the issue.
54+
55+
- The `WARN` level should be used when something bad happened, but the application still has the chance to heal itself or the issue can wait a day or two to be fixed.
56+
57+
- The `INFO` level should be used to document state changes in the application or some entity within the application.
58+
59+
- The `DEBUG` level should be used to log any information that helps us identify what went wrong.
60+
61+
### Handling log events
62+
4963
The default log handler prints log data to `console.error`. If `stderr` is TTY log data is formatted for human consumption with emoji, colours and stack trace (for errors):
5064

5165
![](screenshot.png)
@@ -84,6 +98,14 @@ addHandler((data: LogData) => {
8498
})
8599
```
86100

101+
### Exiting the process
102+
103+
When in Node.js, the `defaultHandler` will exit the process, with code 1, on the first error event. To disable this behavior set the option `exitOnError: false` e.g.
104+
105+
```js
106+
replaceHandlers((data) => defaultHandler(data, { exitOnError: false }))
107+
```
108+
87109
## See also
88110

89111
See this [issue in `node-bunyan`](https://github.com/trentm/node-bunyan/issues/116) describing the use case for, and approaches to, a global, shared logger in Node.

index.test.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ test('logging', () => {
1414
const log = getLogger(TAG)
1515

1616
const events: LogData[] = []
17-
addHandler((data) => events.push(data))
17+
replaceHandlers((data) => events.push(data))
1818

1919
log.debug('a debug message')
2020
expect(events.length).toBe(1)
@@ -46,6 +46,7 @@ test('logging', () => {
4646

4747
test('TTY', () => {
4848
const log = getLogger('tests:tty')
49+
replaceHandlers((data) => defaultHandler(data, { exitOnError: false }))
4950

5051
// Fake that we are using a TTY device
5152
process.stderr.isTTY = true
@@ -60,6 +61,7 @@ test('TTY', () => {
6061

6162
test('non-TTY', () => {
6263
const log = getLogger('tests:non-tty')
64+
replaceHandlers((data) => defaultHandler(data, { exitOnError: false }))
6365

6466
// Fake that we are using a non-TTY device
6567
// @ts-ignore
@@ -202,6 +204,7 @@ test('defaultHandler:throttle', async () => {
202204

203205
replaceHandlers((data) =>
204206
defaultHandler(data, {
207+
exitOnError: false,
205208
throttle: { signature: '${message}', duration: 200 },
206209
})
207210
)

index.ts

+17-3
Original file line numberDiff line numberDiff line change
@@ -237,15 +237,19 @@ export function replaceHandlers(handler: LogHandler): void {
237237
const defaultHandlerHistory = new Map<string, number>()
238238

239239
/**
240-
* Default log data handler.
240+
* Default log event handler.
241241
*
242-
* Prints the data to stderr:
242+
* Prints the event data to stderr:
243243
*
244244
* - with cutesy emoji, colours and stack (for errors) if stderr is TTY (for human consumption)
245245
* - as JSON if stderr is not TTY (for machine consumption e.g. log files)
246246
*
247+
* If in Node.js, and the
248+
*
247249
* @param data The log data to handle
248-
* @param options.maxLevel The maximum log level to print. Defaults to `info`
250+
* @param options.maxLevel The maximum log level to print. Defaults to `info`.
251+
* @param options.showStack Whether or not to show any stack traces for errors. Defaults to `false`.
252+
* @param options.exitOnError Whether or not to exit the process on the first error. Defaults to `true`.
249253
* @param options.throttle.signature The log event signature to use for throttling. Defaults to '' (i.e. all events)
250254
* @param options.throttle.duration The duration for throttling (milliseconds). Defaults to 1000ms
251255
*/
@@ -254,6 +258,7 @@ export function defaultHandler(
254258
options: {
255259
maxLevel?: LogLevel
256260
showStack?: boolean
261+
exitOnError?: boolean
257262
throttle?: {
258263
signature?: string
259264
duration?: number
@@ -320,6 +325,15 @@ export function defaultHandler(
320325
if (showStack && stack !== undefined) entry += '\n ' + stack
321326
}
322327
console.error(entry)
328+
329+
const { exitOnError = true } = options
330+
if (
331+
typeof process !== 'undefined' &&
332+
exitOnError &&
333+
level === LogLevel.error
334+
) {
335+
process.exit(1)
336+
}
323337
}
324338

325339
// Enable the default handler if there no other handler

0 commit comments

Comments
 (0)