Product
Introducing Socket Optimize
We're excited to introduce Socket Optimize, a powerful CLI command to secure open source dependencies with tested, optimized package overrides.
@visulima/pail
Advanced tools
Highly configurable Logger for Node.js, Edge and Browser, built on top of
@visulima/fmt, @visulima/colorize, ansi-escapes, safe-stable-stringify, string-length, terminal-size and wrap-ansi
Daniel Bannert's open source work is supported by the community on GitHub Sponsors
Pretty
or JSON
outputnpm install @visulima/pail
yarn add @visulima/pail
pnpm add @visulima/pail
Most importantly,
pail
adheres to the log levels defined in RFC 5424 extended withtrace
level. This means that you can use the log levels to filter out messages that are not important to you.
Pail supports the logging levels described by RFC 5424.
DEBUG
: Detailed debug information.
INFO
: Interesting events. Examples: User logs in, SQL logs.
NOTICE
: Normal but significant events.
TRACE
: Very detailed and fine-grained informational events.
WARNING
: Exceptional occurrences that are not errors. Examples: Use of deprecated APIs, poor use of an API, undesirable things that are not necessarily wrong.
ERROR
: Runtime errors that do not require immediate action but should typically be logged and monitored.
CRITICAL
: Critical conditions. Example: Application component unavailable, unexpected exception.
ALERT
: Action must be taken immediately. Example: Entire website down, database unavailable, etc. This should trigger the SMS alerts and wake you up.
EMERGENCY
: Emergency: system is unusable.
Reporters are responsible for writing the log messages to the console or a file. pail
comes with a few built-in reporters:
Browser (console.{function}) | Server (stdout or stderr) |
---|---|
JsonReporter | JsonReporter |
PrettyReporter | PrettyReporter |
x | SimpleReporter |
x | FileReporter |
Processors are responsible for processing the log message (Meta Object) before it's written to the console or a file.
This usually means that they add some metadata to the record's context
property.
A processor can be added to a logger directly (and is subsequently applied to log records before they reach any handler).
pail
comes with a few built-in processors:
CallerProcessor
- adds the caller information to the log message
RedactProcessor
- redacts sensitive information from the log message (Soon)MessageFormatterProcessor
- formats the log message (Util.format-like unescaped string formatting utility) @visulima/fmtErrorProcessor
- serializes the error with cause object to a std error object that can be serialized.import { pail } from "@visulima/pail";
pail.success("Operation successful");
pail.debug("Hello", "from", "L59");
pail.pending("Write release notes for %s", "1.2.0");
pail.fatal(new Error("Unable to acquire lock"));
pail.watch("Recursively watching build directory...");
pail.complete({
prefix: "[task]",
message: "Fix issue #59",
suffix: "(@prisis)",
});
To create a custom logger define an options
object yielding a types field with the logger data and pass it as argument to the createPail function.
import { createPail } from "@visulima/pail";
const custom = createPail({
types: {
remind: {
badge: "**",
color: "yellow",
label: "reminder",
logLevel: "info",
},
santa: {
badge: "🎅",
color: "red",
label: "santa",
logLevel: "info",
},
},
});
custom.remind("Improve documentation.");
custom.santa("Hoho! You have an unused variable on L45.");
Here is an example where we override the default error
and success
loggers.
import { pail, createPail } from "@visulima/pail";
pail.error("Default Error Log");
pail.success("Default Success Log");
const custom = createPail({
scope: "custom",
types: {
error: {
badge: "!!",
label: "fatal error",
},
success: {
badge: "++",
label: "huge success",
},
},
});
custom.error("Custom Error Log");
custom.success("Custom Success Log");
To create a scoped logger from scratch, define the scope
field inside the options object and pass it as argument to the createPail function.
import { createPail } from "@visulima/pail";
const mayAppLogger = createPail({
scope: "my-app",
});
mayAppLogger.info("Hello from my app");
To create a scoped logger based on an already existing one, use the scope()
function, which will return a new pail instance, inheriting all custom loggers, timers, secrets, streams, configuration, log level, interactive mode & disabled statuses from the initial one.
import { pail } from "@visulima/pail";
const global = pail.scope("global scope");
global.success("Hello from the global scope");
function foo() {
const outer = global.scope("outer", "scope");
outer.success("Hello from the outer scope");
setTimeout(() => {
const inner = outer.scope("inner", "scope");
inner.success("Hello from the inner scope");
}, 500);
}
foo();
To initialize an interactive logger, create a new pail instance with the interactive
attribute set to true
.
While into the interactive mode, previously logged messages originating from an interactive logger, will be overridden only by new ones originating from the same or a different interactive logger.
Note that regular messages originating from regular loggers are not overridden by the interactive ones.
import { createPail } from "@visulima/pail";
console.log("\n");
const pail = createPail();
const interactive = createPail({ interactive: true });
pail.info("This is a log message 1");
setTimeout(() => {
interactive.await("[%d/4] - Process A", 1);
setTimeout(() => {
interactive.success("[%d/4] - Process A", 2);
setTimeout(() => {
interactive.await("[%d/4] - Process B", 3);
setTimeout(() => {
interactive.error("[%d/4] - Process B", 4);
}, 1000);
}, 1000);
}, 1000);
});
pail.info("This is a log message 2");
pail.info("This is a log message 3");
pail.info("This is a log message 4");
For a more complex example, use can use the getInteractiveManager
function, see the following code:
import { createPail } from "@visulima/pail";
const interactive = createPail({ interactive: true });
const TICKS = 60;
const TIMEOUT = 80;
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
const messages = ["Swapping time and space...", "Have a good day.", "Don't panic...", "Updating Updater...", "42"];
let ticks = TICKS;
let i = 0;
const interactiveManager = interactive.getInteractiveManager();
interactiveManager.hook();
// eslint-disable-next-line no-console
console.log(" - log message");
// eslint-disable-next-line no-console
console.error(" - error message");
// eslint-disable-next-line no-console
console.warn(" - warn message");
const id = setInterval(() => {
if (--ticks < 0) {
clearInterval(id);
interactiveManager.update(["✔ Success", "", "Messages:", "this line will be deleted!!!"]);
interactiveManager.erase(1);
interactiveManager.unhook(false);
} else {
const frame = frames[(i = ++i % frames.length)];
const index = Math.round(ticks / 10) % messages.length;
const message = messages[index];
if (message) {
interactiveManager.update([`${frame} Some process...`, message]);
}
}
}, TIMEOUT);
Timer are managed by the time()
, timeLog()
and timeEnd()
functions.
A unique label can be used to identify a timer on initialization, though if none is provided the timer will be assigned one automatically.
In addition, calling the timeEnd()
function without a specified label will have as effect the termination of the most recently initialized timer, that was created without providing a label.
import { pail } from "@visulima/pail";
pail.time("test");
pail.time();
pail.timeLog("default", "Hello");
setTimeout(() => {
pail.timeEnd();
pail.timeEnd("test");
}, 500);
Its also possible to change the text inside time()
and timeEnd()
by using the options object.
import { createPail } from "@visulima/pail";
const pail = createPail({
messages: {
timerStart: "Start Timer:",
timerEnd: "End Timer:",
},
});
pail.time("test");
pail.timeEnd("test");
To disable a logger, use the disable()
function, which will prevent any log messages from being written to the console or a file.
import { pail } from "@visulima/pail";
pail.disable();
pail.success("This message will not be logged");
To enable a logger, use the enable()
function, which will allow log messages to be written to the console or a file.
import { pail } from "@visulima/pail";
pail.disable();
pail.success("This message will not be logged");
pail.enable();
pail.success("This message will be logged");
Libraries in this ecosystem make the best effort to track Node.js’ release schedule. Here’s a post on why we think this is important.
If you would like to help take a look at the list of issues and check our Contributing guild.
Note: please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
The visulima pail is open-sourced software licensed under the MIT
FAQs
Find a file or directory by walking up parent directories.
The npm package @visulima/pail receives a total of 817 weekly downloads. As such, @visulima/pail popularity was classified as not popular.
We found that @visulima/pail demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
We're excited to introduce Socket Optimize, a powerful CLI command to secure open source dependencies with tested, optimized package overrides.
Product
We're excited to announce that Socket now supports the Java programming language.
Security News
Socket detected a malicious Python package impersonating a popular browser cookie library to steal passwords, screenshots, webcam images, and Discord tokens.