@chax-at/log-sink
v2.0.0
Published
A Log Service
Downloads
129
Keywords
Readme
LogSink
LogSink is a simple logging package that allows logs to be sent to multiple destinations. These destinations are called "drains".
Usage
The package provides a singleton instance of LogSink as a default export:
import LogSink from '@chax-at/log-sink';
Before use the LogSink instance must be configured with at least one drain:
LogSink.registerDrain(new ConsoleLogDrain(), {
enabled: true,
minLevel: LOGGING_CONSOLE_MINLEVEL,
maxLevel: LOGGING_CONSOLE_MAXLEVEL,
});
The singleton instance can then be imported in any file and used for logging:
import LogSink from '@chax-at/log-sink';
LogSink.info('This is an info message');
Log Levels
LogSink only differentiates between four log levels. This is less than other logging solution, but is intended to make it clearer when to use each level. The numeric value of each level adheres to the syslog standard.
| Level | Numeric | Description | |-------|---------|----------------------------------------------------------------------------| | Error | 3 | An error occurred. Will trigger an alert. (depending on the drain) | | Warn | 4 | A warning message. Will not trigger an alert but is visible on dashboards. | | Info | 6 | An informational message, visible in production logs. | | Debug | 7 | A debug message, typically filtered out in production environments. |
In projects where exceptions are also used for non-serve errors, such as for token-expired exceptions, each exception should be associated with the appropriate error level. That is,
token expired
would be a debug messagevalidation failed
would be a warning messagePDF generation failed
would be an error message
LogSink.error('This is an error message');
LogSink.warning('This is a warning message');
LogSink.info('This is an info message');
LogSink.debug('This is a debug message'); // Level 7
Tags, Attributes and Timestamps
In addition to a message, each of these methods takes an optional tag, attribute object and timestamp:
enum LogTags {
Database = 'database',
}
LogSink.info('This is an info message', LogTags.Database, {attr1: 'value1', attr2: 'value2'}, new Date());
If the log level is not known at compile time, the log
method can be used:
LogSink.log(LogLevel.Info, 'This is an info message');
If needed, you can create additional LogSink instances:
import {LogSink} from '@chax-at/log-sink';
const logSink = new LogSink();
Drains
The package provides two built-in drains: ConsoleLogDrain
and GelfLogDrain
.
New drains can be added by implementing the ILogDrain
interface.
Drains are registered using the registerDrain
method.
Using minLevel
and maxLevel
, the severity levels can be filtered on each drain.
Additionally, logs can be filtered using the filter
method and transformed using the transform
method.
LogSink.registerDrain(new ConsoleLogDrain(), {
enabled: true,
minLevel: LOGGING_CONSOLE_MINLEVEL,
maxLevel: LOGGING_CONSOLE_MAXLEVEL,
filter: (options: LogOptions) => {
return options.tag === LogTags.Database;
},
transform: (options: LogOptions) => {
return {
...options,
message: options.message.toUpperCase(),
};
},
});
ConsoleLogDrain
The ConsoleLogDrain
logs messages to the console. It can be configured to log attributes and use color.
new ConsoleLogDrain({logAttributes: true, useColor: true});
GelfLogDrain
The GelfLogDrain
logs messages to any GELF-capable server, such as Graylog.
It uses @chax-at/gelf-client under the hood.
new GelfLogDrain(new SecureTCPTransport({
host: GELF_HOST,
port: GELF_PORT,
ca: GELF_SERVER_CA_CERT, // CA certificate string or buffer
cert: GELF_CLIENT_CERT, // Client certificate string or buffer
key: GELF_CLIENT_KEY, // CLient key string or buffer
}));
new GelfLogDrain(new TCPTransport({
host: GELF_HOST,
port: GELF_PORT,
}));
new GelfLogDrain(new UDPTransport({
host: GELF_HOST,
port: GELF_PORT,
timeout: GELF_TIMEOUT, // optional timeout (default 1000ms)
protocol: GELF_PROTOCOL, // udp4 (default) or udp6
}));
FilesystemLogDrain
The FilesystemLogDrain
logs messages to a file on the filesystem.
new FilesystemLogDrain({
fileName? : string; // optional filename (default log.txt)
formatFunction? : LogFormatFunction; // optional formatting function for the logged message
indentation? : number; // optional indentation for nested newlines (default 4)
logAttributes? : boolean; // whether to log embedded attributes (default true)
outDir: string; // the path of the directory the log file will be created
separateWithEmptyLine? : boolean; // whether to add an additional newline after each log message to improve readability (default false)
});
OpenTelemetryLogDrain
The OpenTelemetryLogDrain
logs messages via OpenTelemetry.
First, install the necessary packages in your project:
npm i "@opentelemetry/sdk-node" "@opentelemetry/api" "@opentelemetry/sdk-logs" "@opentelemetry/exporter-logs-otlp-proto"
then use it the following way
import {NodeSDK} from "@opentelemetry/sdk-node";
import {SimpleLogRecordProcessor} from "@opentelemetry/sdk-logs";
import {logs} from '@opentelemetry/api-logs';
import {OTLPLogExporter} from "@opentelemetry/exporter-logs-otlp-proto";
import LogSink, {LogLevel, OpenTelemetryLogDrain} from '@chax-at/log-sink';
const exporter = new OTLPLogExporter({
//url: defaults to 'http://localhost:4318/v1/logs',
});
const sdk = new NodeSDK({
logRecordProcessor: new SimpleLogRecordProcessor(exporter),
});
sdk.start();
const logger = logs.getLoggerProvider().getLogger("default");
LogSink.registerDrain(new OpenTelemetryLogDrain(logger), {
enabled: true,
minLevel: LogLevel.Error,
maxLevel: LogLevel.Debug
});
LogSink.info("This is a log");
More info can be found in the OpenTelemetry info or the official open-telemetry documentation.