Caterpillar
Caterpillar is the ultimate logging system for Deno, Node.js, and Web Browsers. Log levels are implemented to the RFC standard. Log entries can be filtered and piped to various streams, including coloured output to the terminal, the browser's console, and debug files. You can even write your own transforms.
Install / Use
/learn @bevry/CaterpillarREADME
Caterpillar
<!-- /TITLE --> <!-- BADGES/ --><span class="badge-githubworkflow"><a href="https://github.com/bevry/caterpillar/actions?query=workflow%3Abevry" title="View the status of this project's GitHub Workflow: bevry"><img src="https://github.com/bevry/caterpillar/workflows/bevry/badge.svg" alt="Status of the GitHub Workflow: bevry" /></a></span> <span class="badge-npmversion"><a href="https://npmjs.org/package/caterpillar" title="View this project on NPM"><img src="https://img.shields.io/npm/v/caterpillar.svg" alt="NPM version" /></a></span> <span class="badge-npmdownloads"><a href="https://npmjs.org/package/caterpillar" title="View this project on NPM"><img src="https://img.shields.io/npm/dm/caterpillar.svg" alt="NPM downloads" /></a></span> <br class="badge-separator" /> <span class="badge-githubsponsors"><a href="https://github.com/sponsors/balupton" title="Donate to this project using GitHub Sponsors"><img src="https://img.shields.io/badge/github-donate-yellow.svg" alt="GitHub Sponsors donate button" /></a></span> <span class="badge-thanksdev"><a href="https://thanks.dev/u/gh/bevry" title="Donate to this project using ThanksDev"><img src="https://img.shields.io/badge/thanksdev-donate-yellow.svg" alt="ThanksDev donate button" /></a></span> <span class="badge-patreon"><a href="https://patreon.com/bevry" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span> <span class="badge-liberapay"><a href="https://liberapay.com/bevry" title="Donate to this project using Liberapay"><img src="https://img.shields.io/badge/liberapay-donate-yellow.svg" alt="Liberapay donate button" /></a></span> <span class="badge-buymeacoffee"><a href="https://buymeacoffee.com/balupton" title="Donate to this project using Buy Me A Coffee"><img src="https://img.shields.io/badge/buy%20me%20a%20coffee-donate-yellow.svg" alt="Buy Me A Coffee donate button" /></a></span> <span class="badge-opencollective"><a href="https://opencollective.com/bevry" title="Donate to this project using Open Collective"><img src="https://img.shields.io/badge/open%20collective-donate-yellow.svg" alt="Open Collective donate button" /></a></span> <span class="badge-crypto"><a href="https://bevry.me/crypto" title="Donate to this project using Cryptocurrency"><img src="https://img.shields.io/badge/crypto-donate-yellow.svg" alt="crypto donate button" /></a></span> <span class="badge-paypal"><a href="https://bevry.me/paypal" title="Donate to this project using Paypal"><img src="https://img.shields.io/badge/paypal-donate-yellow.svg" alt="PayPal donate button" /></a></span> <br class="badge-separator" /> <span class="badge-discord"><a href="https://discord.gg/nQuXddV7VP" title="Join this project's community on Discord"><img src="https://img.shields.io/discord/1147436445783560193?logo=discord&label=discord" alt="Discord server badge" /></a></span> <span class="badge-twitch"><a href="https://www.twitch.tv/balupton" title="Join this project's community on Twitch"><img src="https://img.shields.io/twitch/status/balupton?logo=twitch" alt="Twitch community badge" /></a></span>
<!-- /BADGES --> <!-- DESCRIPTION/ -->Caterpillar is the ultimate logging system for Deno, Node.js, and Web Browsers. Log levels are implemented to the RFC standard. Log entries can be filtered and piped to various streams, including coloured output to the terminal, the browser's console, and debug files. You can even write your own transforms.
<!-- /DESCRIPTION -->Usage
Examples
Overview
The RFC Log Levels are provided by the rfc-log-levels package which follows RFC 3164 - The BSD Syslog Protocol.
Log Entries that are within the lineLevel range, will have their line information fetched using the get-current-line package.
The Logger is what you write your log messages to, which you then pipe to destinations and transforms.
The Filter transport is used to filter out log levels that we do not want to pass onto the next destination.
The Human transport is used to convert the Log Entries into a human readable and colourful output.
The Browser transport is used to send the human output, including colours, to the Web Browser console.
The Transform is used to write your own transforms, and is what all the others are based from.
Node.js Guide
To get started for Node.js, setup a new Node.js project for this guide and install Caterpillar.
mkdir caterpillar-guide
cd caterpillar-guide
npm init
npm install --save caterpillar
touch index.js
Then edit our index.js file with the following, that will output all the log messages in JSON format to stdout, and can be run via node index.js:
const { Logger } = require('caterpillar')
const logger = new Logger()
logger.pipe(process.stdout)
logger.log('warn', 'this is a warning, which is level', 4)
logger.warn('this is a warning, which is level', 4)
logger.log('debug', 'this is a debug message, which is level', 7)
logger.warn('this is a debug message, which is level', 7)
Outputting in JSON format is not a nice experience, instead we can do better by using the Human transport such that it is human readable.
const { Logger, Human } = require('caterpillar')
const logger = new Logger()
logger.pipe(new Human()).pipe(process.stdout)
logger.log('warn', 'this is a warning, which is level', 4)
logger.warn('this is a warning, which is level', 4)
logger.log('debug', 'this is a debug message, which is level', 7)
logger.warn('this is a debug message, which is level', 7)
However, perhaps we want to still store the JSON format for querying later. We can pipe the human format to stdout as before, but we can pipe the raw output to a debug file.
const { Logger, Human } = require('caterpillar')
const logger = new Logger()
const { createWriteStream } = require('fs')
logger.pipe(createWriteStream('./debug.log'))
logger.pipe(new Human()).pipe(process.stdout)
logger.log('warn', 'this is a warning, which is level', 4)
logger.warn('this is a warning, which is level', 4)
logger.log('debug', 'this is a debug message, which is level', 7)
logger.warn('this is a debug message, which is level', 7)
Now let's stay for some reason, we want to capitalise all the log messages that are warning levels and higher, we can do this by making our own transport by extending the Transform.
const { Logger, Transform, Human } = require('caterpillar')
const logger = new Logger()
const { createWriteStream } = require('fs')
logger.pipe(createWriteStream('./debug.log'))
class Uppercase extends Transform {
format(entry) {
if (entry.levelNumber <= 4) {
entry.args.forEach(function (value, index) {
if (typeof value === 'string') {
entry.args[index] = value.toUpperCase()
}
})
}
return entry
}
}
logger.pipe(new Uppercase()).pipe(new Human()).pipe(process.stdout)
logger.log('warn', 'this is a warning, which is level', 4)
logger.warn('this is a warning, which is level', 4)
logger.log('debug', 'this is a debug message, which is level', 7)
logger.warn('this is a debug message, which is level', 7)
Futhermore, the user probably doesn't need to see debug messages, even though they are useful for debugging. We can filter out the debug messages for the user, but maintain them for the debug.log file by applying the Filter transport to the pipe that goes to stdout.
const { Logger, Transform, Filter, Human } = require('caterpillar')
const logger = new Logger()
const { createWriteStream } = require('fs')
logger.pipe(createWriteStream('./debug.log'))
class Uppercase extends Transform {
format(entry) {
if (entry.levelNumber <= 4) {
entry.args.forEach(function (value, index) {
if (typeof value === 'string') {
entry.args[index] = value.toUpperCase()
}
})
}
return entry
}
}
logger
.pipe(new Filter({ filterLevel: 5 }))
.pipe(new Uppercase())
.pipe(new Human())
.pipe(process.stdout)
logger.log('warn', 'this is a warning, which is level', 4)
logger.warn('this is a warning, which is level', 4)
logger.log('debug', 'this is a debug message, which is level', 7)
logger.warn('this is a debug message, which is level', 7)
As fetching line information is computationally expensive process, for large applications for performance we probably only want to fetch the line information for messages that we actually show to the user. As such, we should make the [filterLevel](http://master.caterpillar.bevry.surge.sh/docs/classes/filter.h
