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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@knev/bitlogr

v2.0.11

Published

**BitLOGR** is a lightweight, bitwise logging library for JavaScript, designed for modular applications with no label dependencies between compilation units. It leverages bit flags for efficient, granular logging control, offering zero performance overhea

Readme

BitLOGR

BitLOGR is a lightweight, bitwise logging library for JavaScript, designed for modular applications with no label dependencies between compilation units. It leverages bit flags for efficient, granular logging control, offering zero performance overhead in production through lazy evaluation (thunks) and build-time optimizations.

The idea behind BitLOGR is to label execution paths, not INFO, WARN, DEBUG, ERROR, CRITICAL.

Key Features (USPs)

  • No Label Dependency: Each compilation unit can independently define, ignore, inherit, overwrite, or rename labels from submodules.
  • Flexible Label Management: Supports custom label sets with bitwise operations for combining and toggling logs.
  • Custom Logging Handler: It is possible to specify your own handler (e.g., console.log, custom function) for output flexibility.
  • Zero Performance Hit: Use thunks, to defer argument evaluation, and static functions to, ensuring no overhead when logging is disabled.

Installation

Install via npm:

npm install @knev/bitlogr

Overview

Singleton Class

BitLOGR is implemented as a singleton, meaning there is only one instance of the LOGR class across your application. This ensures consistent logging behavior but requires careful label management when shared across modules.

import { LOGR } from '@knev/bitlogr';

const LOGR1_ = LOGR.instance();
const LOGR2_ = LOGR.instance();
console.log(LOGR1_ === LOGR2_); // true (same instance)

Initializing BitLOGR

To use BitLOGR, initialize the singleton instance with labels and toggle settings:

  1. Labels: Define categories as an object mapping names to bit values (powers of 2).
  2. Toggled: Specify which labels are active using a key-value object with boolean values.
import { LOGR, l_array } from '@knev/bitlogr';

// Define labels
const l_ = l_array(['EVENT', 'CXN', 'HANDLERS']); // { EVENT: 1, CXN: 2, HANDLERS: 4 }

// Get the logger instance
const LOGR_ = LOGR.instance();
LOGR_.labels = l_;

// Enable specific logs
LOGR_.toggled = { EVENT: true, CXN: true }; // Bitmask: 0b101 (5)

Label and Toggle Formats

  • Labels: An object where keys are strings and values are unique powers of 2 (e.g., 1, 2, 4, 8). These represent log categories and align with bits for efficient checking.

    • Example: { EVENT: 1, CXN: 2, HANDLERS: 4 } → Bit positions 0, 1, 2.
  • Toggled: An object where keys match label names and values are booleans (true/false). Internally, this creates a bitmask.

    • Example: { EVENT: true, CXN: false, HANDLERS: true } → Bitmask 0b101 (5).

The toggled bitmask is compared with the log statement’s bit value using bitwise AND (&) to determine if logging occurs.

Log Statement Format

The log method takes two arguments:

  1. nr_logged: A number (bitmask) representing the log categories (e.g., l_.EVENT | l_.CXN).

  2. argsFn: A thunk (function returning an array) that lazily provides log arguments.

LOGR_.log(l_.EVENT, () => ['Debug message']); // Logs if EVENT is toggled

Return Value:

  • Logging occurs only if labels are toggled true; the log function returns true/false in development (i.e., LOGR_ENABLED is true).
  • undefined: in production mode, the log function returns undefined.

Using OR for Labels

Combine labels with the bitwise OR (|) operator to log under multiple categories:

LOGR_.toggled = { EVENT: true, CXN: true }; // 0b101 (5)
LOGR_.log(l_.EVENT | l_.CXN, () => ['Debug or Info']);
// Logs because 0b101 & (0b001 | 0b100) = 0b101 & 0b101 = 0b101 !== 0

Utility Functions

BitLOGR provides helper functions to manage labels:

l_array(labels, start = 1)

Creates a label object from an array, assigning sequential bit values.

const l_ = l_array(['A', 'B', 'C']); // { A: 1, B: 2, C: 4 }
const l_shifted_ = l_array(['X', 'Y'], 4); // { X: 4, Y: 8 }

l_length(obj)

Returns the next power of 2 based on the maximum value in the object.

const l_len_= l_length({ a: 1, b: 4 }); // 8 (next power of 2 after 4)

l_concat(base, additional)

Combines label sets, appending new labels with next available bits.

const l_ = l_array(['A', 'B']); // { A: 1, B: 2 }
const l_more_ = l_concat(l_, ['C', 'D']); // { A: 1, B: 2, C: 4, D: 8 }

l_merge(obj1, obj2)

Merges label sets, shifting conflicting values to unique bits.

const l1_ = { A: 1, B: 4 };
const l2_ = { C: 1, D: 8 };
const l_merged_ = l_merge(l1_, l2_); // { A: 1, B: 4, C: 16, D: 8 }

l_LL(obj, shift)

Left-shifts all values in a label object.

const l_ = { A: 1, B: 2 };
const l_shifted_ = l_LL(l_, 2); // { A: 4, B: 8 }

l_RR(obj, shift)

Right-shifts all values in a label object.

const l_ = { A: 4, B: 8 };
const l_shifted_ = l_RR(l_, 2); // { A: 1, B: 2 }

Examples

Setting Labels

// Simple label set
const l_ = l_array(['EVENT', 'CXNS']);
LOGR_.labels = l_;

Importing Labels from Submodules

import { l as l_subm_ } from './submodule.mjs'; // e.g., { EVENTS: 8, HANDLERS: 16 }
// Merge with local labels
const l_local_ = l_array(['EVENT', 'CXNS']); // { EVENT: 1, CXNS: 2 }
const l_= l_merge(l_subm_, l_local_); // { EVENTS: 8, HANDLERS: 16, EVENT: 1, CXNS: 2 }

LOGR_.labels = l_;

Custom Handler

LOGR_.handler = (...args) => console.warn('WARN:', ...args);
LOGR_.toggled = { EVENT: true };
LOGR_.log(l_.EVENT, () => ['Debug warning']); // "WARN: Debug warning"

Development vs. Production

Development Mode

Set LOGR_ENABLED = true (default or via build config) to enable logging:

LOGR_.toggled = { EVENT: true };
LOGR_.log(l_.EVENT, () => ['Dev log']); // Logs "Dev log"
LOGR_.log(l_.CXNS, () => ['No log']); // Skipped

Production Mode

Set LOGR_ENABLED = false (e.g., via Webpack DefinePlugin) to disable logging with no performance cost:

// In production with LOGR_ENABLED = false
LOGR_.log(l_.EVENT, () => ['Expensive computation']); // No-op, thunk not evaluated

Use a build tool to replace LOGR_ENABLED at compile time:

// webpack.config.js
const webpack = require('webpack');
module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      LOGR_ENABLED: JSON.stringify(false),
    }),
  ],
};

Performance Optimization with Static Functions

For critical paths, bind the log method to a static function to avoid repeated property lookups:

const log_ = LOGR_.log.bind(LOGR);
function criticalPath() {
  log_(l_.EVENT, () => ['Fast log']); // Slightly faster than logger.log
}

Limitations

  • 32-Bit Limit: Supports up to 31 labels before overflow (JavaScript’s 32-bit integer limit).
  • Singleton Scope: Shared instance requires label consistency across modules.