@tsjam/logger v2.0.5
@tsjam/logger
Vanilla TypeScript Logger
Not opinionated ts Logger with Multiple output channels 🍰
Useful for parallel console output & remote monitoring 👩🚀
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 dataLogs.stringify(data)
stringifyErrorStackTranslator
– fairly serialize Error correctlyLogs.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
@seeAlso