Console logs are not always well structured and eye-pleasing. Unpleasant and messy console takes away from the bliss of a developer. I recently came across a package named consola
which does exactly this — making consoles meaningful and elegant.
It has browser support, pausing and resuming logs, prompt support and other useful features.
Installation
You can install it by using npm
, yarn
or pnpm
.
npm i consola
Trying it out
Spin up a new node/express app and start exploring.
Basics
For a quick hands on experience, in your node application, throw an explicit error and then log it with the help of consola
.
import { consola } from "consola"
try {
throw Error("Unexpected error")
} catch (error) {
consola.error(error)
}
consola.error("Error...")
consola.info("Info...")
consola.warn("Warning...")
consola.log("Logged...")
New Instance
You can create a new consola instance with the help of the createConsola
method and use that instead of the default global instance.
import { createConsola } from "consola"
const logger = createConsola({
level: 0, // error/fatal logs
fancy: true,
formatOptions: {
date: true,
columns: 20
},
})
logger.info("Info...") // this WON'T work
logger.error("Error...") // this will work
Set the log level
to selectively allow only certain types of logs. Log level of 0
means only FATAL
and ERROR
logs are logged. The default log level is 3.
Reporters
Reporters are representations of logs in the terminal. Consola (v3.2.3) provides 3 reporters out of the box, namely, basic
, fancy
and browser
. They are configured based on log levels on the global consola
instance.
To add a custom reporter to your newly created instance, you can use the reporters
property which is an array of reporters.
import { LogLevels, consola, createConsola } from "consola"
const infoLogger = createConsola({
fancy: true,
formatOptions: {
date: true,
columns: 20
},
reporters: [
{
log: (log) => {
if (log.level === LogLevels.info) {
consola.info(JSON.stringify({
date: new Date().toLocaleString("default", { dateStyle: "full" }),
logs: new Array().concat(log.args.map((l, i) => `${l}${i < log.args.length - 1 ? `,` : ``}`)).join(" "),
}, null, 4))
} else {
consola.error(
new Error("invalid log method")
)
}
}
}
]
})
Now, when you use any logging method on this instance, it will only log for the info
method and throw an error for other methods. You just created a custom info message logger which you can further modify however you want.
// for the above instance
infoLogger.error("Won't work") ❌
infoLogger.info("Will work") ✔️
Multiple reporters per instance are also supported allowing you to separate logs into desired representations.
reporters: [
{
log: (log) => {
if (log.level === LogLevels.info) {
consola.info(JSON.stringify({
date: new Date().toLocaleString("default", { dateStyle: "full" }),
logs: new Array().concat(log.args.map((l, i) => `${l}${i < log.args.length - 1 ? `,` : ``}`)).join(" "),
}, null, 4))
} else {
consola.error(
new Error("invalid log method")
)
}
}
},
{
log: (log) => {
createConsola({
fancy: true,
formatOptions: {
date: false
}
}).log(log)
}
}
]
Methods such as addReporter
, setReporters
and removeReporter
are available to handle reporters for an instance.
Wrapping native console
method with consola
instance
Doing so will redirect all the native console.log
calls to the specified consola
instance.
infoLogger.wrapConsole()
// consola instance `infoLogger` will print the table
console.table(["Info", "Second Info"])
restoreConsole
will restore the native functionality of console.log
and won't redirect to consola instance.
There are several util methods present in consola/utils
which you can use to further customize the logs.
Prompts
Prompts are supported in consola with the help of clack, a tool to build command-line apps. Check this out for some prompt examples in consola.
Conclusion
Correctly and elegantly representing console logs is an important task if you want to improve developer productivity and consola
helps you with just that.