Log
A lightweight and extendable logging library.
For further insights, read on.
Installation
To install this library use your favorite package manager. No additional steps are required to start using the library.
npm install @n7e/log
This library is implemented in TypeScript but can be used with JavaScript without any additional steps.
Logger
Loggers has the ability to send messages of varying severity to a wide range of targets.
All loggers implement the Logger
interface. To reference it simply import it
and use it as a type.
import type { Logger } from "@n7e/log";
function someFunction(logger: Logger): void {
// ...
}
Logger
is just an interface describing the functionality of a logger. To
create a logger instance you need to reference a specific
implementation.
Logger Implementations
This library provides the following loggers:
- ConsoleLogger
- Logs messages to the global JavaScript console object.
- StreamLogger
- Logs messages to any writable stream.
- AggregateLogger
-
Delegates the logging procedure to a set of registered loggers.
To create an aggregate logger use the aggregate logger builder.
Log Levels
Log messages are assigned a severity level to enable filtering and specific actions to be taken on certain severity levels.
A defined set of log levels are available through an enum and can be accessed like so:
import { LogLevel } from "@n7e/log";
logger.log(LogLevel.INFO, "This is an informational message");
The available log levels are:
- Emergency
- System is unusable.
- Alert
-
Action must be taken immediately.
Example: Entire website down, database unavailable, etc. This should trigger the SMS alerts and wake you up. - Critical
-
Critical conditions.
Example: Application component unavailable, unexpected exception. - Error
- Runtime errors that do not require immediate action but should typically be logged and monitored.
- Warning
-
Exceptional occurrences that are not errors.
Example: Use of deprecated APIs, poor use of an API, undesirable things that are not necessarily wrong. - Notice
- Normal but significant events.
- Info
-
Interesting events.
Example: User logs in, SQL logs. - Debug
- Detailed debug information.
Logging Messages
To produce log messages the Logger
interface provides a dedicated method for
each log level as well as a log()
method to log messages with a provided log
level. Although it's ultimately up to the implementation either method should
produce the same result. The following lines should essentially be equal in
functionality.
import { LogLevel } from "@n7e/log";
logger.info("This is an informative message");
logger.log(LogLevel.INFO, "This is an informative message");
Since implementations can send log messages to any number of remote resources
all methods of the Logger
interface returns a promise. If it's important to
ensure the message has been received by the target the promise should be
awaited.
await logger.info("This is an informative message");
Message Context
Every logged message can have an optional associated context object. The significance of the context is up to the logger implementation and/or log formatters used by the logger.
logger.info("This is an informative message", {key: "value"});
The log message may or may not be affected by the passed context object.
Log Formatters
Some logger implementations accept a log formatter to format the message being
logged. All log formatters implement the LogFormat
interface and can be
imported from the @n7e/log/format
module.
import type { LogFormatter } from "@n7e/log/format";
function someFunction(formatter: LogFormatter): void {
// ...
}
LogFormatter
is just an interface describing the functionality of a log
formatter. To create a log formatter instance you need to reference a specific
implementation.
This library provides the following log formatters:
- InterpolationFormatter
- Replaces log message tokens with context values. Tokens are context property names surrounded by curly braces. e.g. `{name}`.
- LogLevelFormatter
- Prepends the log level to the log message.
- AggregateLogFormatter
- Delegates the format procedure to a set of registered log formatters.
Logger Builder
Logger builders has the ability to create logger instances.
All logger builders implement the LoggerBuilder
interface. To reference it
simply import it and use it as a type.
import type { LoggerBuilder } from "@n7e/log";
function someFunction(loggerBuilder: LoggerBuilder): void {
// ...
}
LoggerBuilder
is just an interface describing the functionality of a logger
builder. To create a logger builder instance you need to reference a specific
implementation.
Aggregate Logger Builder
To create an aggregate logger instance import and use the provided
AggregateLoggerBuilder
logger builder.
import { AggregateLoggerBuilder } from "@n7e/log";
const loggerBuilder = new AggregateLoggerBuilder();
To configure the build aggregate logger instance any number of loggers can be provided to the builder.
loggerBuilder.addLogger(new ConsoleLogger());
If a logger should log records for and above a certain log level the desired log level can be provided.
loggerBuilder.addLogger(new ConsoleLogger(), LogLevel.WARNING);
The console logger will now only log messages with log level: warning, error, critical, alert or emergency.
If you need to customize the delegation behaviour you can configure the logger
to use a custom predicate to determine whether to delegate to a logger. The
provided predicate must conform to the AggregateLoggerDelegationPredicate
interface.
loggerBuilder.useDelegationPredicate(() => true);
To produce an aggregate logger instance simply call the build()
method when
all desired loggers have been configured.
const logger = loggerBuilder.build();