Skip to content

Commit

Permalink
feat: add output methods
Browse files Browse the repository at this point in the history
  • Loading branch information
wraithgar committed Apr 11, 2024
1 parent 6f7f5ff commit d7bd49f
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 54 deletions.
54 changes: 26 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,56 @@
# proc-log

Emits 'log' events on the process object which a log output listener can
consume and print to the terminal.
Emits events on the process object which a listener can consume and print to the terminal or log file.

This is used by various modules within the npm CLI stack in order to send
log events that can be consumed by a listener on the process object.
This is used by various modules within the npm CLI stack in order to send log events that can be consumed by a listener on the process object.

Currently emits `log` and `output` events.

## API

```js
const { log } = require('proc-log')
const { log, output } = require('proc-log')
```

#### output
* `output.standard(...args)` calls `process.emit('output', 'standard', ...args)`
This is for general standard output. Consumers will typically show this on stdout (after optionally formatting or filtering it).
* `output.error(...args)` calls `process.emit('output', 'error', ...args)`
This is for general standard output. Consumers will typically show this on stderr (after optionally formatting or filtering it).
* `output.buffer(...args)` calls `process.emit('output', 'buffer', ...args)`
This is for buffered output. Consumers will typically buffer this until they are ready to display.
* `output.LEVELS` an array of strings of all output method names

#### log
* `log.error(...args)` calls `process.emit('log', 'error', ...args)`
The highest log level. For printing extremely serious errors that
indicate something went wrong.
The highest log level. For printing extremely serious errors that indicate something went wrong.
* `log.warn(...args)` calls `process.emit('log', 'warn', ...args)`
A fairly high log level. Things that the user needs to be aware of, but
which won't necessarily cause improper functioning of the system.
A fairly high log level. Things that the user needs to be aware of, but which won't necessarily cause improper functioning of the system.
* `log.notice(...args)` calls `process.emit('log', 'notice', ...args)`
Notices which are important, but not necessarily dangerous or a cause for
excess concern.
Notices which are important, but not necessarily dangerous or a cause for excess concern.
* `log.info(...args)` calls `process.emit('log', 'info', ...args)`
Informative messages that may benefit the user, but aren't particularly
important.
Informative messages that may benefit the user, but aren't particularly important.
* `log.verbose(...args)` calls `process.emit('log', 'verbose', ...args)`
Noisy output that is more detail that most users will care about.
* `log.silly(...args)` calls `process.emit('log', 'silly', ...args)`
Extremely noisy excessive logging messages that are typically only useful
for debugging.
Extremely noisy excessive logging messages that are typically only useful for debugging.
* `log.http(...args)` calls `process.emit('log', 'http', ...args)`
Information about HTTP requests made and/or completed.
* `log.timing(...args)` calls `process.emit('log', 'timing', ...args)`
Timing information.
* `log.pause()` calls `process.emit('log', 'pause')` Used to tell
the consumer to stop printing messages.
* `log.pause()` calls `process.emit('log', 'pause')`
Used to tell the consumer to stop printing messages.
* `log.resume()` calls `process.emit('log', 'resume')`
Used to tell the consumer that it is ok to print messages again.
* `log.LEVELS` an array of strings of all log method names

## Examples

Every `log` method calls `process.emit('log', level, ...otherArgs)` internally.
So in order to consume those events you need to do `process.on('log', fn)`.
Every `log` method calls `process.emit('log', level, ...otherArgs)` internally. So in order to consume those events you need to do `process.on('log', fn)`.

### Colorize based on level

Here's an example of how to consume `proc-log` events and colorize them
based on level:
Here's an example of how to consume `proc-log` log events and colorize them based on level:

```js
const chalk = require('chalk')
Expand All @@ -63,18 +66,13 @@ process.on('log', (level, ...args) => {

### Pause and resume

`pause` and `resume` are included so you have the ability to tell your consumer
that you want to pause or resume your display of logs. In the npm CLI we use
this to buffer all logs on init until we know the correct loglevel to display.
But we also setup a second handler that writes everything to a file even if
paused.
`log.pause` and `log.resume` are included so you have the ability to tell your consumer that you want to pause or resume your display of logs. In the npm CLI we use this to buffer all logs on init until we know the correct loglevel to display. But we also setup a second handler that writes everything to a file even if paused.

```js
let paused = true
const buffer = []

// this handler will buffer and replay logs only
// after `procLog.resume()` is called
// this handler will buffer and replay logs only after `procLog.resume()` is called
process.on('log', (level, ...args) => {
if (level === 'resume') {
buffer.forEach((item) => console.log(...item))
Expand Down
10 changes: 10 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
module.exports = {
output: {
LEVELS: [
'standard',
'error',
'buffer',
],
standard: (...args) => process.emit('output', 'standard', ...args),
error: (...args) => process.emit('output', 'error', ...args),
buffer: (...args) => process.emit('output', 'buffer', ...args),
},
log: {
LEVELS: [
'notice',
Expand Down
8 changes: 8 additions & 0 deletions tap-snapshots/test/index.js.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,11 @@ Array [
"resume",
]
`

exports[`test/index.js TAP output > output levels 1`] = `
Array [
"standard",
"error",
"buffer",
]
`
54 changes: 28 additions & 26 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
const t = require('tap')
const { log } = require('../')
const { LEVELS } = log

t.test('log', t => {
t.matchSnapshot(LEVELS, 'log levels')
t.test('all log.LEVELS have a function in log', t => {
for (const level of LEVELS) {
t.test(level, t => {
t.match(log[level], Function)
process.once('log', (actual, ...args) => {
t.equal(actual, level, 'emitted log with expected level')
t.same(args, [1, 'two', [3], { 4: 4 }], 'got expected args')
t.end()
const procLog = require('../')
for (method in procLog) {

Check failure on line 3 in test/index.js

View workflow job for this annotation

GitHub Actions / Lint

'method' is not defined
t.test(method, t => {

Check failure on line 4 in test/index.js

View workflow job for this annotation

GitHub Actions / Lint

'method' is not defined
const log = procLog[method]

Check failure on line 5 in test/index.js

View workflow job for this annotation

GitHub Actions / Lint

'method' is not defined
const { LEVELS } = log
t.matchSnapshot(LEVELS, `${method} levels`)

Check failure on line 7 in test/index.js

View workflow job for this annotation

GitHub Actions / Lint

'method' is not defined
t.test(`all ${method}.LEVELS have a function in ${method}`, t => {

Check failure on line 8 in test/index.js

View workflow job for this annotation

GitHub Actions / Lint

'method' is not defined

Check failure on line 8 in test/index.js

View workflow job for this annotation

GitHub Actions / Lint

'method' is not defined
for (const level of LEVELS) {
t.test(level, t => {
t.match(log[level], Function)
process.once(method, (actual, ...args) => {

Check failure on line 12 in test/index.js

View workflow job for this annotation

GitHub Actions / Lint

'method' is not defined
t.equal(actual, level, `emitted ${method} with expected level`)

Check failure on line 13 in test/index.js

View workflow job for this annotation

GitHub Actions / Lint

'method' is not defined
t.same(args, [1, 'two', [3], { 4: 4 }], 'got expected args')
t.end()
})
log[level](1, 'two', [3], { 4: 4 })
})
log[level](1, 'two', [3], { 4: 4 })
})
}
t.end()
})
t.test('all log functions are in log.LEVELS', t => {
t.plan(LEVELS.length)
for (const fn in log) {
if (fn !== 'LEVELS') {
t.ok(LEVELS.includes(fn), `log.${fn} is in LEVELS`)
}
}
t.end()
})
t.test(`all ${method} functions are in ${method}.LEVELS`, t => {

Check failure on line 22 in test/index.js

View workflow job for this annotation

GitHub Actions / Lint

'method' is not defined

Check failure on line 22 in test/index.js

View workflow job for this annotation

GitHub Actions / Lint

'method' is not defined
t.plan(LEVELS.length)
for (const fn in log) {
if (fn !== 'LEVELS') {
t.ok(LEVELS.includes(fn), `${method}.${fn} is in ${method}.LEVELS`)
}
}
})
t.end()
})
t.end()
})
}

0 comments on commit d7bd49f

Please sign in to comment.