Skip to content

Commit

Permalink
Feat: inject custom logger in options (#10)
Browse files Browse the repository at this point in the history
* feat: inject custom logger in options

* docs: injecting custom logger

* Fix old node support (#11)

Signed-off-by: Matteo Collina <hello@matteocollina.com>

---------

Signed-off-by: Matteo Collina <hello@matteocollina.com>
Co-authored-by: Matteo Collina <hello@matteocollina.com>
  • Loading branch information
bacebu4 and mcollina committed Feb 16, 2024
1 parent f6abc51 commit 26e9d8f
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 6 deletions.
22 changes: 22 additions & 0 deletions README.md
Expand Up @@ -23,6 +23,26 @@ closeWithGrace({ delay: 500 }, async function ({ signal, err, manual }) {
})
```

### Injecting custom logger

```js
const closeWithGrace = require('close-with-grace')

// delay is the number of milliseconds for the graceful close to
// finish.
closeWithGrace(
{
delay: 500,
logger: { error: (m) => console.error(`[close-with-grace] ${m}`) }
},
async function ({ signal, err, manual }) {
if (err) {
console.error(err)
}
await closeYourServer()
})
```

## API

### `closeWithGrace([opts], fn({ err, signal, manual }))`
Expand All @@ -42,6 +62,8 @@ If it is emitted again, it will terminate the process abruptly.
* `delay`: the numbers of milliseconds before abruptly close the
process. Default: `10000`.

* `logger`: instance of logger which will be used internally. Default: `10000`.

#### fn({ err, signal, manual } [, cb])

Execute the given function to perform a graceful close.
Expand Down
11 changes: 10 additions & 1 deletion index.d.ts
@@ -1,10 +1,19 @@
declare namespace closeWithGrace {
interface Logger {
error(message?: any, ...optionalParams: any[]): void
}

interface Options {
/**
* The numbers of milliseconds before abruptly close the process
* @default 10000
*/
delay: number
delay?: number
/**
* Instance of logger which will be used internally
* @default console
*/
logger?: Logger
}

type Signals = "SIGTERM" | "SIGINT"
Expand Down
9 changes: 5 additions & 4 deletions index.js
Expand Up @@ -11,6 +11,7 @@ function closeWithGrace (opts, fn) {
opts = {}
}
const delay = opts.delay ? opts.delay : 10000
const logger = opts.logger ? opts.logger : console
process.once('SIGTERM', onSignal)
process.once('SIGINT', onSignal)
process.once('uncaughtException', onError)
Expand All @@ -35,7 +36,7 @@ function closeWithGrace (opts, fn) {
}

function afterFirstSignal (signal) {
console.error(`second ${signal}, exiting`)
logger.error(`second ${signal}, exiting`)
process.exit(1)
}

Expand All @@ -44,8 +45,8 @@ function closeWithGrace (opts, fn) {
}

function afterFirstError (err) {
console.error('second error, exiting')
console.error(err)
logger.error('second error, exiting')
logger.error(err)
process.exit(1)
}

Expand Down Expand Up @@ -102,7 +103,7 @@ function closeWithGrace (opts, fn) {
process.exit(0)
}
} catch (err) {
console.error(err)
logger.error(err)
process.exit(1)
}
}
Expand Down
5 changes: 4 additions & 1 deletion index.test-d.ts
Expand Up @@ -62,7 +62,10 @@ expectAssignable<CloseWithGraceCallback>(WrongCallback)
expectAssignable<Signals>("SIGINT")
expectAssignable<Signals>("SIGTERM")

expectType<Options>({ delay: 10 })
expectAssignable<Options>({ delay: 10 })
expectAssignable<Options>({ logger: console })
expectAssignable<Options>({ logger: console, delay: 10 })
expectAssignable<Options>({ logger: { error: () => {} } })

expectAssignable<{
close: () => void
Expand Down
22 changes: 22 additions & 0 deletions test/close.test.js
Expand Up @@ -127,6 +127,28 @@ for (const signal of ['SIGTERM', 'SIGINT']) {
t.is(await err, `second ${signal}, exiting\n`)
t.is(Date.now() - now < 500, true)
})

test(`a secong signal (${signal}) calls custom logger`, async (t) => {
const child = fork(join(__dirname, 'no-resolve-custom-logger.js'), {
stdio: ['pipe', 'pipe', 'pipe', 'ipc']
})

// one line to kickstart the test
await once(child.stderr, 'readable')
child.stderr.read()
t.pass('readable emitted')

child.kill(signal)

await once(child.stdout, 'readable')

const err = all(child.stderr)
err.catch(() => {})

child.kill(signal)

t.is(await err, `[custom logger] second ${signal}, exiting\n`)
})
}

for (const event of ['uncaughtException', 'unhandledRejection']) {
Expand Down
19 changes: 19 additions & 0 deletions test/no-resolve-custom-logger.js
@@ -0,0 +1,19 @@
'use strict'

const closeWithGrace = require('..')

const customLogger = {
error (message) {
console.error(`[custom logger] ${message}`)
}
}

closeWithGrace({ delay: 500, logger: customLogger }, function ({ signal, err }) {
console.log('fn called')
// this promise never resolves, so the delay should kick in
return new Promise(() => {})
})

// to keep the process open
setInterval(() => {}, 1000)
console.error(process.pid)

0 comments on commit 26e9d8f

Please sign in to comment.