Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added documentation for MultiStreamRes, StreamEntry, DestinationStream and Level #1342

Merged
merged 2 commits into from
Feb 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
64 changes: 62 additions & 2 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
* [pino.stdTimeFunctions](#pino-stdtimefunctions)
* [pino.symbols](#pino-symbols)
* [pino.version](#pino-version)
* [Interfaces](#interfaces)
* [MultiStreamRes](#multistreamres)
* [StreamEntry](#streamentry)
* [DestinationStream](#destinationstream)
* [Types](#types)
* [Level](#level-1)

<a id="export"></a>
## `pino([options], [destination]) => logger`
Expand Down Expand Up @@ -1164,9 +1170,10 @@ finalLogger.info('exiting...')

<a id="pino-multistream"></a>

### `pino.multistream(options) => Stream`
### `pino.multistream(streamsArray, opts) => MultiStreamRes`

Create a stream composed by multiple destination streams:
Create a stream composed by multiple destination streams and returns an
object implementing the [MultiStreamRes](#multistreamres) interface.

```js
var fs = require('fs')
Expand Down Expand Up @@ -1272,3 +1279,56 @@ for general use.
Exposes the Pino package version. Also available on the logger instance.

* See [`logger.version`](#version)

## Interfaces
<a id="pino-multistreamres"></a>

### `MultiStreamRes`
Properties:

* `write(data)`
- `data` Object | string
- Returns: void

Write `data` onto the streams held by the current instance.
* `add(dest)`
- `dest` [StreamEntry](#streamentry) | [DestinationStream](#destinationstream)
- Returns: [MultiStreamRes](#multistreamres)

Add `dest` stream to the array of streams of the current instance.
* `flushSync()`
- Returns: `undefined`

Call `flushSync` on each stream held by the current instance.
* `minLevel`
- number

The minimum level amongst all the streams held by the current instance.
* `streams`
- Returns: [StreamEntry[]](#streamentry)

The array of streams currently held by the current instance.
* `clone(level)`
- `level` [Level](#level-1)
- Returns: [MultiStreamRes](#multistreamres)

Returns a cloned object of the current instance but with the the provided `level`.

### `StreamEntry`
Properties:

* `stream`
- DestinationStream
* `level`
- Optional: [Level](#level-1)

### `DestinationStream`
Properties:

* `write(msg)`
- `msg` string

## Types
### `Level`

* Values: `"fatal"` | `"error"` | `"warn"` | `"info"` | `"debug"` | `"trace"`
42 changes: 30 additions & 12 deletions lib/multistream.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ const { levels } = require('./levels')
const defaultLevels = Object.create(levels)
defaultLevels.silent = Infinity

const DEFAULT_INFO_LEVEL = levels.info

function multistream (streamsArray, opts) {
let counter = 0

streamsArray = streamsArray || []
opts = opts || { dedupe: false }

Expand Down Expand Up @@ -77,22 +78,39 @@ function multistream (streamsArray, opts) {
}

function add (dest) {
if (!dest) {
return res
}

// Check that dest implements either StreamEntry or DestinationStream
const isStream = typeof dest.write === 'function' || dest.stream
const stream_ = dest.write ? dest : dest.stream
// This is necessary to provide a meaningful error message, otherwise it throws somewhere inside write()
if (!isStream) {
throw Error('stream object needs to implement either StreamEntry or DestinationStream interface')
}

const { streams } = this
if (typeof dest.write === 'function') {
return add.call(this, { stream: dest })
} else if (typeof dest.levelVal === 'number') {
return add.call(this, Object.assign({}, dest, { level: dest.levelVal, levelVal: undefined }))

let level
if (typeof dest.levelVal === 'number') {
level = dest.levelVal
} else if (typeof dest.level === 'string') {
return add.call(this, Object.assign({}, dest, { level: levels[dest.level] }))
} else if (typeof dest.level !== 'number') {
// we default level to 'info'
dest = Object.assign({}, dest, { level: 30 })
level = levels[dest.level]
} else if (typeof dest.level === 'number') {
level = dest.level
} else {
dest = Object.assign({}, dest)
level = DEFAULT_INFO_LEVEL
}

const dest_ = {
stream: stream_,
level,
levelVal: undefined,
id: counter++
}
dest.id = counter++

streams.unshift(dest)
streams.unshift(dest_)
streams.sort(compareByLevel)

this.minLevel = streams[0].level
Expand Down
4 changes: 2 additions & 2 deletions pino.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,10 +261,10 @@ declare namespace pino {

interface MultiStreamRes {
write: (data: any) => void,
add: (dest: Record<string, any>) => MultiStreamRes,
add: (dest: StreamEntry | DestinationStream) => MultiStreamRes,
flushSync: () => void,
minLevel: number,
streams: ({ stream: DestinationStream, level: number, id: number })[],
streams: StreamEntry[],
clone(level: Level): MultiStreamRes,
}

Expand Down
39 changes: 38 additions & 1 deletion test/multistream.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ test('no stream', function (t) {
t.end()
})

test('add a stream', function (t) {
test('one stream', function (t) {
let messageCount = 0
const stream = writeStream(function (data, enc, cb) {
messageCount += 1
Expand All @@ -497,6 +497,43 @@ test('add a stream', function (t) {
t.end()
})

test('add a stream', function (t) {
let messageCount = 0
const stream = writeStream(function (data, enc, cb) {
messageCount += 1
cb()
})

const log = pino({
level: 'trace'
}, multistream().add(stream))
log.info('info stream')
log.debug('debug stream')
log.fatal('fatal stream')
t.equal(messageCount, 2)
t.end()
})

test('multistream.add throws if not a stream', function (t) {
try {
pino({
level: 'trace'
}, multistream().add({}))
} catch (_) {
t.end()
}
})

test('multistream throws if not a stream', function (t) {
try {
pino({
level: 'trace'
}, multistream({}))
} catch (_) {
t.end()
}
})

test('flushSync', function (t) {
const tmp = join(
os.tmpdir(),
Expand Down
1 change: 1 addition & 0 deletions test/types/pino-multistream.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ expectType<pino.MultiStreamRes>(pino.multistream(streams))
expectType<pino.MultiStreamRes>(pino.multistream(streams, {}))
expectType<pino.MultiStreamRes>(pino.multistream(streams, { levels: { 'info': 30 } }))
expectType<pino.MultiStreamRes>(pino.multistream(streams, { dedupe: true }))
expectType<pino.MultiStreamRes>(pino.multistream(streams[0]).add(streams[1]))

expectType<pino.MultiStreamRes>(multistream(process.stdout));