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

@tsjam/logger

v2.1.1

Published

Vanilla TypeScript Logger with multiple output channels

Readme

@tsjam/logger

Vanilla TypeScript Logger

Not opinionated ts Logger with Multiple output channels 🍰
Useful for parallel console output & remote monitoring 👩‍🚀

MIT licensed npm version multichannel hashtags timestamps

Advantages:

  • appId (distinguish log between multiple app instances)
  • timestamps (milliseconds matter)
  • hashtags (tag child loggers, find and filter certain logs super-fast)
  • multiple channels output (add ur own output: e.g. parallel console output & remote monitoring)
  • metadata (for all log entries per appId or per call e.g. { userId: 007 })
  • buffering (useful for crash reporting)
  • fully customizable (use your own log format)
  • fair Errors serialization into string (check JSON.stringify(new Error('Oops')); // {})
  • sanitization of sensitive fields (perf optimized, Logs.sanitize({ password: 'ABC' }))
  • safe stringify payload at any moment (Logs.stringify(data))
  • trim stack to number of lines or fully cut (use config { trimStack: 2 })
  • zero third-party dependencies

Output example:
[app161125][2024-01-21T18:33:02.981Z][info][#user] Logged In: { username: Bob, password: '***' }

Installation

npm install @tsjam/logger

Usage

Out of Box

ConsoleOutput is the default output channel. Specify Ur own ones if needed...

import { jamLogger } from '@tsjam/logger';

jamLogger.info('Hello Logger!');
// [app161125][2024-01-21T18:33:02.981Z][info] Hello Logger!

Tagged Logger

Tag child loggers to easily filter logs by tags.

const logger = jamLogger.tagged('user'); // child logger with added tags

logger.info('Greetings for', { name: 'Bob' });
// [app161125][2024-01-21T18:33:02.981Z][info][#user] Greetings for { name: 'Bob' }

Bake Own Logger

const logger = JamLogger.create({
  appId: `ioApp${Date.now()}`,
  channels: [...defaultOutputChannels /* { out: MyKibanaOutput } */], // default is ConsoleOutput
});
const aiLogger = logger.tagged('ai'); // child logger with #ai tag

Custom Output Channel

const myOutput: LogOutput = {
  write: ({ appId, date, level, message, data, context }: LogEntry) => {
    // Format raw log entry and send it anywhere U wish
  },
};

const logger = JamLogger.create({
  channels: [...defaultOutputChannels, { out: myOutput }, { out: myKibanaOutput }],
});

Buffering

Use simplistic BufferOutput to buffer logs for any crash reporting or remote monitoring. Do not forget to flush after report is sent.

const logBuffer = new BufferOutput(2000);
const logger = JamLogger.create({
  channels: [...defaultOutputChannels, { out: logBuffer }],
});

Metadata

Metadata is especially useful for remote reporting & monitoring.

import { JamLogger } from '@tsjam/logger';

const logger = JamLogger.create({
  metadata: { userId: '007' }, // use it however U wish in ur output channel next to log entry
});
//...
JamLogger.updateMeta(logger.appId, { userId: '456' }); // update metadata
logger.info('Lets Play 🦑');
// [app1737064023840][2025-01-16T21:47:03.840Z][info] Lets Play 🦑
// meta: {"userId":"456"}

Pass additional meta per call.

const logger = JamLogger.create({
  metadata: { userId: '007' }, // use it however U wish in ur output channel next to log entry
});
logger.info('Whats Up?', LogMeta.bake({ drink: 'dry martini 🍸' }));
// [app170723][2025-01-16T23:10:56.102Z][info] Whats Up?
// meta: { "userId": "007", "drink": "dry martini 🍸" }

Cook per single call

Sensitive Fields Sanitization

jamLogger.debug('Logged in', Loges.sanitize({ name: 'Bob', password: 'ABC' }));
// [app170723][2024-02-06T16:47:56.398Z][debug] Logged in  { name: 'Bob', password: '***' }

Note: to always sanitize sensitive fields use sanitizeSensitiveTranslator config option.
Yet it's more perf optimized to sanitize only when needed.

Stack Visibility

Stack is shown on Error payloads (similar to console.log);

jamLogger.warn('Oops!', new Error('Something went wrong'));
// [app170723][2024-02-06T17:02:00.108Z][warn] Oops  Error: Something went wrong
//    at Object.<anonymous> (...tsjam-logger/tests/logging/log.utils.spec.ts:10:49)
//    at Promise.then.completed (...tsjam-logger/node_modules/jest-circus/build/utils.js:298:28)
//    ...

Hide stack on Error payloads for specified levels

const logger = JamLogger.create({ errorStackLevel: LogLevel.Error }); // default WARN

logger.warn('Oops!', new Error('Something went wrong'));
// [app170723][2024-02-06T17:02:00.108Z][warn] Oops  Error: Something went wrong

Trim stack to few lines

const logger = JamLogger.create({ trimStack: 2 });
logger.warn('Oops!', new Error('Spoiled the milk!'));
// [app170723][2024-02-06T17:13:59.496Z][warn] Oops! Spoiled the milk! Stack:
//   at Object.<anonymous> (...tsjam-logger/tests/logging/log.utils.spec.ts:10:15)
//   ...

Note: it's also possible to trim the stack to specified depth via trimStack


Translators

There are some built-in translators for log data u could use while baking ur own logger:

  • jsonStringifyTranslator – safely stringify log data Logs.stringify(data)
  • stringifyErrorStackTranslator – fairly serialize Error correctly Logs.stringifyError(error)
  • sanitizeSensitiveTranslator - sanitize sensitive fields defaults: ['password', 'token', 'secret', 'sessionId']

Note: These translators applied either to a Single log call or to All logs by default, U could add Ur own too.

Note: U could add custom translator if U need one for all channels transformation. Otherwise, it's recommended to process raw logEntry in Ur particular output channel.


License

@tsjam/logger is MIT licensed


TSJam Logger Documentation

NPM package

@seeAlso

TSJam API Documentation