Skip to content

Commit

Permalink
✨improve(patch): consoleBuffer service (#1776)
Browse files Browse the repository at this point in the history
- fix: log deduplication
- improve: formatting
- improve: docblocks
- optim: logger footprint

refers:

- none

## Type of change

**PATCH: backwards compatible change**



This PR includes breaking changes to the following core packages:

- none

This PR includes breaking changes to the follow extensions:

- none

## Dependencies

### Adds

- none

### Removes

- none
  • Loading branch information
kellymears committed Oct 14, 2022
1 parent 40e3fa7 commit 266b811
Showing 1 changed file with 90 additions and 14 deletions.
104 changes: 90 additions & 14 deletions sources/@roots/bud-framework/src/services/console.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,112 @@ import patchConsole from '@roots/bud-support/patch-console'

import {Service} from '../service.js'

/**
* Received messages
*
* @public
*/
interface Messages {
stdout: string[]
stderr: string[]
}

/**
* Map stream name to logging function name
*
* @public
*/
const streamDictionary = {
stdout: `log`,
stderr: `error`,
}

/**
* ConsoleBuffer service class
*
* @remarks
* Intercepts console function calls and emits them using the bud logger.
* Deduplicates and trims console output.
*
* @public
*/
export default class ConsoleBuffer extends Service {
/**
* Service label
* @public
*/
public static label = `consoleBuffer`

public messages: {stdout: string[]; stderr: string[]} = {
stdout: [],
stderr: [],
}
/**
* Received messages
* @public
*/
public messages: Messages = {stdout: [], stderr: []}

/**
* Restore console function
*
* @remarks
* Returned from {@link patchConsole} call. This is called to restore
* the normal {@link console} behavior.
*
* @public
*/
public restore: () => any

/**
* `boot` callback
*
* @public
* @decorator `@bind`
*/
@bind
public async boot() {
// Don't mess with console if --ci flag is `true`
if (this.app.context?.args?.ci) return

// Overwrite service logger with a specially configured `Signale` instance
this.logger = this.app.logger.makeInstance({
disabled: this.app.context.args?.log === false,
config: {
displayLabel: false,
displayBadge: false,
displayTimestamp: true,
},
// Unlike the main bud.logger, emit everything
logLevel: `info`,
})

// Patch the console, and assign the restore function
this.restore = patchConsole((stream, data) => {
const message = data.trim()
/**
* Clean up log message whitespace, etc.
*/
const message = data
.split(`\n`)
.map(line => line.trim())
.filter(Boolean)
.join(`\n`)
.trim()

// Ignore empty messages
if (!message) return

// Ignore messages that have been logged before
if (this.messages[stream].some(stale => stale === message)) return

if (!message || message.length === 0) return
if (this.messages[stream].some(message => message === data)) return
// Add message to buffer
this.messages[stream].push(message)

this.app.logger
.makeInstance({
disabled: this.app.context.args?.log === false,
config: {displayLabel: false},
logLevel: `info`,
})
// Log message to console
this.logger
.scope(...this.app.logger.scope, stream)
[stream === `stdout` ? `log` : `error`](message)
[streamDictionary[stream]](message)
})

/**
* On compiler close event, restore {@link console} methods
*/
this.app.hooks.action(`compiler.close`, this.restore)
}
}

0 comments on commit 266b811

Please sign in to comment.