
Security News
npm ‘is’ Package Hijacked in Expanding Supply Chain Attack
The ongoing npm phishing campaign escalates as attackers hijack the popular 'is' package, embedding malware in multiple versions.
jlog-facade
Advanced tools
Logger façade that focusing on creating a JSON output for typescript projects
This is a simple logger façade that focusing on creating a JSON output for typescript projects.
A LoggerFactory is used to create a new instance of a JLogger which doesn't output any log until a log destination is set:
const logger = LoggerFactory.create('my-logger');
// or alternatively
const logger = LoggerFactory.getLogger('my-logger');
Note that .getLogger
was created for compatibility with other logger classes but it is not strictly correct. Every call to .getLogger
will create a new instance of JLogger.
To write a log entry, it works like any other logger:
logger.debug('This is a debug message');
logger.info(`Process started at port $PORT`);
logger.error('Failed to processing incoming request', err);
npm i jlog-facade
To facilitate generation of JSON output, JLogger accept IJson as additional attributes to be added to the output:
logger.info('The process has started', {processId: 123456});
The log methods also support a callback method that would handle any potential error when generating the message.
logger.info(() => 'The process has started', {processId: 123456});
Logger methods also accept an AbstractLoggable which exposes .toJson
method allowing any custom object to be written to the log. All the entries are merged before the log and by default, duplicated keys are resolved by first key having priority over any subsquent keys.
AbstractKeyValue is an implementation of AbstractLoggable that creates a simple key/value pair object where value can be any data type. A sample implementation is KV which enforces the value to be instance of TLoggableValue:
logger.info('The process has started', KV.of('processId', 123456), new KV.of('processId', 888));
The value of the processId
key in above example is 123456
as it's the first value set.
Another built-in AbstractLoggable is Label that allow caller to pass a key and one or more values. Please note that value of the Label is always a list, even if only one value is passed to the constructor. The duplicate keys of Label passed are merged instead of overwriten:
logger.info('The process has started', Label.of('processId', 123456), Label.of('processId', 888));
The value of the processId
key in above example is [123456, 888]
.
A Loggable is a special implementation of AbstractLoggable that accept any data type as value. However, if value passed contains any attributes that cannot be processed by JSON.stringify()
, the result will be a string of [object Object]
. As result, it's recommend the use of KV instead.
logger.info('The process has started', Loggable.of('date', new Date('2023-03-24')));
The value of the date
key in above example would be 2023-03-24T00:00:00.000Z
.
2 simple destinations are available in this package:
The class above serve mostly for debug or test purposes. It is expected that a separate platform specific destination is used in an actual project. A log destination really is just a formatter for a IJLogEntry and LoggerFactory. It accepts 3 type of log destination:
If one must ensure that last async log has been written, the following promise can be used:
await logger.logWritten();
At starting point of your application, add desire destinations using A LoggerFactory:
SimpleJsonDestination.use();
// or
LoggerFactory.addLogDestination(new SimpleJsonDestination());
Log destination allow you to add a log interceptor by calling setLogInterceptor
:
SimpleTextDestination.use(LogLevel.DEBUG).setLogInterceptor((entry: IJLogEntry, loggerLevel?: LogLevel, defaultPayload?: IJson) => {
// Do something with log entry
});
This is often used by unit testing to ensure that correct data are logged.
You should be able to create your own version of Log Destination AbstractLogDestination. However, you must make sure that:
public static use
method so that all Log Destination follow the same interface._write(entry, loggerLevel, defaultPayload)
in your .write
method to ensure that log interceptor worksJSON.stringify
to address
error that would result from logging an object with circular reference.A logger.json
can be placed under ./etc/${FP8_ENV}/logger.json
or ./config/${FP8_ENV}/logger.json
with the following content:
{
// This is default logger level
"severity": "info",
// This overrides the log level for a specific loggerName
"logger": {
"my-logger": "debug"
},
// This overrides the logger name filter for a destination
"destination": {
"TestSimpleTextDestination": {
"severity": "warn",
"filters": ["test-zEd7efJ0Pr"]
}
}
}
The configuration set in logger.json
override what's done in code. The next level of setting is using destination:
// Only write .warn logs
SimpleJsonDestination.use(LogLevel.WARNING);
// Only output log if logger is 'my-logger-A' or 'logger-B'
SimpleJsonDestination.use('my-logger-A', 'logger-B');
// Only output log if logger is 'my-logger' and if level is ERROR or above
SimpleJsonDestination.use(LogLevel.ERROR, 'my-logger');
The level can also be set by upon logger creation but this is not recommended as it should really be set in the logger.json
or in a destination.
const logger = LoggerFactory.create('my-logger', LogLevel.ERROR);
The content of the loaded logger.json
can be accessed via LoggerFactory.loadedConfig property.
It's often difficult to read json when doing local development. The logger.json
configuration allows you to enable multiple logger and activate a specific
logger for given env. To accomplish this, set multiple destination as desired but set those destination using LogLevel.OFF
:
SimpleTextDestination.use(LogLevel.OFF);
SimpleJsonDestination.use(LogLevel.OFF);
Add the following logger.json
to activate only the SimpleTextDestination
:
{
"destination": {
"SimpleTextDestination": {
"severity": "info"
}
}
}
Working with project in both Kotlin and Typescript, I have come to miss the abstraction allowed by slf4j in the JVM world. Another challenge I face is the need to produce a JSON based output for cloud service provider.
The problem above is simple to address on a project by project basis but it becomes an complicated mess when trying to create reusable components.
The objectives of jlog-facade
are therefore:
FAQs
Logger façade that focusing on creating a JSON output for typescript projects
We found that jlog-facade demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
The ongoing npm phishing campaign escalates as attackers hijack the popular 'is' package, embedding malware in multiple versions.
Security News
A critical flaw in the popular npm form-data package could allow HTTP parameter pollution, affecting millions of projects until patched versions are adopted.
Security News
Bun 1.2.19 introduces isolated installs for smoother monorepo workflows, along with performance boosts, new tooling, and key compatibility fixes.