Vanilla TypeScript Logger
Not opinionated ts Logger with Multiple output channels 🍰
Useful for parallel console output & remote monitoring 👩🚀
Advantages:
{ userId: 007 }
)JSON.stringify(new Error('Oops')); // {}
)Logs.sanitize({ password: 'ABC' })
)Logs.stringify(data)
){ trimStack: 2 }
)Output example:
[app161125][2024-01-21T18:33:02.981Z][info][#user] Logged In: { username: Bob, password: '***' }
npm install @tsjam/logger
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!
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' }
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
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 }],
});
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 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 🍸" }
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 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
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.
@tsjam/logger is MIT licensed
@seeAlso