
Company News
Socket Named Top Sales Organization by RepVue
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.
@bebrasmell/mono-logger
Advanced tools
A simple logger module with topics and side-effects capabilities. It comes pretty useful when need to share common loggers across multiple modules or to nest loggers with different topics (e.g. function executors for debugging purposes).
Default logs format:
7/26/2024, 20:54:26 [DBG] hello, world
Please see CHANGELOG for latest changes.
yarn add @bebrasmell/mono-logger
Or
npm i @bebrasmell/mono-logger
You can create a new child logger with a specific topic. This way you can filter logs by topic.
import { Logger } from '@bebrasmell/mono-logger';
const logger = new Logger();
const subLogger = logger.topic('sub-topic');
const deepSubLogger = subLogger.topic('deep-sub-topic');
deepSubLogger.log('hello, world');
// Output:
// 7/26/2024, 21:11:09 [DBG] sub-topic:deep-sub-topic hello, world
You can also access parent logger from a child logger.
import { Logger } from '@bebrasmell/mono-logger';
const logger = new Logger();
const subLogger = logger.topic('sub-topic');
const deepSubLogger = subLogger.topic('deep-sub-topic');
deepSubLogger._parent?.log('hello, world');
// Output:
// 7/26/2024, 21:11:09 [DBG] sub-topic hello, world
Configuration can be set for the root logger or specific topic and its descendants. It means, that topic configuration will be inherited from it's parent. When you provide options for a new topic, it's going to override its parent configuration entirely.
Example:
const root_logger = new Logger("root", {
level: "info",
});
const sub_logger = root_logger.topic("leaf", {});
sub_logger.debug("I am still here!");
// Output:
// 7/26/2024, 21:11:09 [DBG] root:leaf I am still here!
You can configure the logger with:
level: (e.g. debug) The minimum log level to be displayed.prefix: (function) A prefix to be added to each log record before topics.date_format: (function) The date formatter function to be used in logs.effect: (function) A side-effect function to be called on each log record. It receives log level, list of topics and spread raw data array passed to logger.transform: (function) A function to transform log records before being displayed.force_effect: (boolean) If true, side-effects will be called even if log level is below the minimum level.import { Logger } from '@bebrasmell/mono-logger';
const ex_logger = new Logger('example', {
level: 'debug',
prefix: () => 'my-app',
date_format: (date) => date.toISOString(),
effect: (level, topics, ...data) => console.log(level, topics, ...data),
transform: (m) => `yes, ${m}`,
force_effect: true,
});
ex_logger.log('hello', 'world');
// Output:
// 2024-07-26T18:47:01.978Z [DBG] my-app example yes, hello yes, world
// debug [ 'example' ] hello world
You can assign any side effect you want to any topic and it's descendants (see Configuration). So each time you log something, the logger fires the effect function with parameters:
level - log leveltopics (array, root to leaf)...raw data you passed to loggerBy default, when you log something below the minimum log level specified in Topic Configuration, effect is not fired. You can force logger to fire it by passing force_effect.
By default, every child logger will inherit configuration from it's parent, but if you'd like to customize a specific parameter, you can access parent's configuration as a readonly object:
const parent = logger.topic("parent", {
/* ... */
});
const child = root.topic("child", {
...parent._config,
effect: () => { /* do something else */ },
});
![note] You should not modify or override existing configuration. That is done on purpose to preserve verbosity and functional consistency.
MonoEffect is a wrapper around your effect function with minimum log level check. Imagine this:
info level;warn, error and fatal logs that are generated by the module;In such situations, you can use MonoEffect:
import { MonoEffect } from "@bebrasmell/mono-logger";
const handleWarnings = (lvl, topics, ...messages) => {
/*
* ...
* your custom warn, error and fatal handler
* ...
*/
console.warn("Warning has been recorded and saved");
};
const warnings_effect = new MonoEffect(handleWarnings, "warn");
const logger = root_logger.topic("target_module_name", {
level: "info",
effect: warnings_effect,
});
logger.warn("Example warning");
// Output:
// 2024-07-26T18:47:01.978Z [WRN] target_module_name Example warning
// Warning has been recorded and saved
PolyEffect simply concatenates your effects and fires them one after another.
import { MonoEffect, PolyEffect } from "@bebrasmell/mono-logger";
const handleWarnings = (lvl, topics, ...messages) => {
/*
* ...
* your custom warn, error and fatal handler
* ...
*/
console.warn("Warning has been recorded and saved");
};
const handleFatal = (lvl, topics, ...messages) => {
/*
* ...
* your custom fatal handler
* ...
*/
console.error("x_x");
};
const warnings_effect = new MonoEffect(handleWarnings, "warn");
const fatal_effect = new MonoEffect(handleFatal, "fatal");
const poly_effect = new PolyEffect();
poly_effect.add(warnings_effect);
poly_effect.add(fatal_effect);
const logger = root_logger.topic("target_module_name", {
level: "info",
effect: poly_effect,
});
logger.warn("Example warning");
logger.fatal("Nope, I'm dead");
// Output:
// 2024-07-26T18:47:01.978Z [WRN] target_module_name Example warning
// Warning has been recorded and saved
// 2024-07-26T18:47:01.978Z [FTL] target_module_name Nope, I'm dead
// Warning has been recorded and saved
// x_x
You can use PolyEffect to execute both parent and current effects. This will allow you to bypass the configuration inheritance limitation:
const poly_effect = new PolyEffect();
if (parent._config.effect) poly_effect.add(parent._config.effect);
poly_effect.add(() => { /* New effect */ });
const child = parent.topic("child", {
...parent._config,
effect: poly_effect,
});
MIT
FAQs
A simple topic-based logger with side effects
We found that @bebrasmell/mono-logger demonstrated a not healthy version release cadence and project activity because the last version was released 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.

Company News
Socket won two 2026 Reppy Awards from RepVue, ranking in the top 5% of all sales orgs. AE Alexandra Lister shares what it's like to grow a sales career here.

Security News
NIST will stop enriching most CVEs under a new risk-based model, narrowing the NVD's scope as vulnerability submissions continue to surge.

Company News
/Security News
Socket is an initial recipient of OpenAI's Cybersecurity Grant Program, which commits $10M in API credits to defenders securing open source software.