npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

unilogr

v0.0.27

Published

Modern logger for both Node.js and Browser.

Downloads

20

Readme

UniLogr: a Universal Logger

Version npm

UniLogr is a logger for both Node.js and Browser inspired by Winston.

Motivation

This project aims to provide a simple but powerful logger that works on both Node.js and the Browser. The logger should be flexible and convenient, allowing the user to add custom outputs and create sub-loggers.

Installation

Install with NPM:

npm install unilogr

Install with Yarn:

yarn add unilogr

Install with PNPM:

pnpm add unilogr

Usage

Creating a logger

A logger is constructed with a sequence of operations that will be executed on each log. The operation writeTo is used to write a log to an output stream.

import {
  addInterval,
  addTimestamp,
  capitalizeField,
  colorizeField,
  ConsoleOutput,
  Logger,
  markSlot,
  writeTo,
} from 'unilogr';

const logger = new Logger([
  capitalizeField('level'), // Capitalize the "level" field
  colorizeField('level'), // Colorize the "level" field according to severity
  addTimestamp(), // Add the "timestamp" field
  addInterval(), // Add the "interval" field

  markSlot(), // Mark this spot for extensions

  ({ timestamp, level, message, interval }) =>
    `${timestamp} [${level}]: ${message} (${interval})`, // Format message

  writeTo(new ConsoleOutput()), // Write formatted message to console
]);

logger.info('Test'); // 2022-11-01 19:11:47 [INFO]: Test (+0ms)

Log levels

UniLogr uses the following log levels:

logger.error('Error');
logger.warn('Warn');
logger.info('Info');
logger.debug('Debug');
logger.verbose('Verbose');

The Info object

The info object is a plain JavaScript object that contains at least the following fields:

const info = {
  level: 'info', // Customizable field (colorize it, capitalize it, etc.)
  message: 'Example', // Customizable field

  [LEVEL_SYMBOL]: 'info', // Read-only field used to determine the log level
  [OUTPUT_SYMBOL]: '[INFO]: Example', // String that will be written to the output
  [ARGS_SYMBOL]: [], // Arguments for messages containing %s, %d, %o, etc.
};

String interpolation

UniLogr supports string interpolation using %s, %d, %o, etc. as placeholders. Arguments without corresponding placeholders are merged into the info object.

const logger = new Logger([
  (info) => {
    info[OUTPUT_SYMBOL] = `[${info.level}] (${info.ctx}): ${info.message}`;
  },

  writeTo(new ConsoleOutput()),
]);

logger.info('Origin is %s', 'http://localhost', { ctx: 'CORS' });
// [info] (CORS): Origin is http://localhost

Filtering logs

You can discard logs by returning false in an operation:

const logger = new Logger([
  (info) => info.ctx === 'Auth', // Accept only logs with 'Auth' context

  // ...
]);

logger.info('Server started.', { ctx: 'Startup' }); // Discarded

logger.info('Refreshing tokens...', { ctx: 'Auth' }); // Accepted

UniLogr provides the utility function discardLessSevereThan() to easily filter logs by level of severity:

const logger = new Logger([
  discardLessSevereThan('warn'), // Discard logs with level less severe than 'warn'
  // Same as: (info) => levels[info[LEVEL_SYMBOL]] <= levels['warn']

  // ...
]);

Extending a logger

A logger can be extended by inserting more operations. Operations are inserted in slots marked by markSlot().

const mainLogger = new Logger([
  addContext('Main context'),

  markSlot(), // <<< Extension operations are inserted here

  ({ timestamp, message, ctx }) =>
    `${timestamp}${ctx ? ` (${ctx})` : ''}: ${message}`,
]);

mainLogger.info('Main logger test');
// 2029-05-02 11:18:41 (Main context): Main logger test

const subLogger = mainLogger.extend([addContext('Sub context')]);

subLogger.info('Sub logger test');
// 2029-05-02 11:18:41 (Main context > Sub context): Sub logger test

The utility function logger.sub(context) helps to easily extend loggers by adding a subcontext:

const authLogger = mainLogger.sub('Auth');
// Appends the context to the field "ctx" in the info object.
// Same as mainLogger.extend([addContext('Auth')])

You can create and extend multiple slots by giving them different names.

const mainLogger = new Logger([
  // ...
  markSlot(), // name: 'defaultSlot'
  // ...
  markSlot('slot1'),

  ({ timestamp, level, message, ctx }) =>
    `${timestamp} [${level}]${ctx ? ` (${ctx})` : ''}: ${message}`,

  markSlot('slot2'),
]);

const subLogger = mainLogger.extend({
  defaultSlot: [addContext('server.ts')],

  slot1: [addTimestamp()],

  slot2: [writeTo(new FileOutput('logs.txt'))],
});

License

MIT License © 2022 Gustavo Toyota