Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
@tinkoff/logger
Advanced tools
Logging library
Install using package manager, e.g. for npm:
npm i --save @tinkoff/logger
for yarn:
yarn add @tinkoff/logger
You can create child loggers using method .child
of the current logger instance. Child logger will inherit parent logger settings and can override these settings.
:::info
Logger name always will be in lower case, e.g. myLogger
will be converted to mylogger
:::
const log = logger({ name: 'test' });
const childLog = log.child('child'); // as this logger is child logger the result name will be 'test.child'
const childLogWithDefaults = log.child({
name: 'with-defaults',
defaults: {
// defaults might be used to specify properties which will be merged to log objects logged with this logger
child: true,
},
});
const childLogWithOverrides = log.child({
name: 'override',
reporters: [], // may override settings of the parent logger
filters: [],
extensions: [],
});
Library allows to specify used logging level, show/hide logs for specific instances of the logger, reset display settings.
By default, error
level is used for every logger.
Settings display level higher than error
for single logger, e.g. logger.enable('info', 'my-logger')
, overrides logging level only for my-logger
.
It is impossible to set logging level lower than common level, e.g. when using common logging level equal to error
calls to logger.enable('fatal', 'my-logger')
changes nothing.
All subsequent setup for log displaying are preserved, e.g. subsequent calls logger.enable('info', 'my-logger')
and logger.enable('trace', 'yet-another-logger')
will enable logs to both logger according to their settings.
For control of displaying logs on server environment variables LOG_LEVEL
, LOG_ENABLE
and LOG_DEFAULT_REPORTER_DEPTH
are used:
LOG_LEVEL=info
then all logs of levels info, warn, error, fatal will be showed.${name}
| ${level}:${name}
- let to enable displaying logs for a specific name and level. It can accept several entries that are passed as comma-separated. E.g.:
LOG_ENABLE=server
then all logs for name server
will be displayedLOG_ENABLE=trace:server*
then for logs with name server only trace
level will be showedLOG_ENABLE=info:server,client,trace:shared
then displaying logs will be enabled for specified loggers using rules above${number}
- specifies how deep the objects will be displayed in the logs. E.g.:
LOG_DEFAULT_REPORTER_DEPTH=3
we will see the values in the log objects up to object.a.b.c
In browser display settings are stored in localStorage, so it will work even after page reloads. In order to reset settings you may clear localStorage. For convenient usage a special object logger
is added to window object in the browser.
logger === window.logger;
logger.setLevel('warn'); // enable displaying log for level `warn` and higher
logger.enable('info', 'test'); // enable displaying logs for logger `test` with level `info` также отображать вывод логгера test уровня info
logger.enable('my-logger'); // show all logs for logger `my-logger`
logger.enable('perf*'); // enable all logs with name starting with `perf`
logger.disable('my-logger'); // disable displaying logs for `my-logger`
logger.clear(); // reset all settings
import { logger } from '@tinkoff/logger';
const log = logger({ name: 'my-logger' }); // name is required field in order to identify logs
const log = logger('my-logger'); // same as above
const log = logger({
name: 'remote-logger',
defaults: {
remote: true,
},
});
Options:
name[='log']
- name of the new logger@tinkoff/logger
might be extended using next entities:
Filters can disable logging for specific logs base on inner conditions
import { logger } from '@tinkoff/logger';
interface Filter {
filter(logObj: LogObj): boolean;
}
logger.addFilter(filter as Filter); // add new filter to list of previously added filters
logger.setFilters([filter1, filter2]); // replace current filters with passed list. that allows to override default settings
Extensions can extend or override log object before making actual logging
import { logger } from '@tinkoff/logger';
interface Extension {
extend(logObj: LogObj): LogObj;
}
logger.addExtension(extension as Extension); // add new extension to list of previously added extensions
logger.setExtensions([extension1, extension2]); // replace current extensions with passed list. that allows to override default settings
Reporters can change the way logs are showed (json, fancy logs in browser, send logs to remote api).
Be default, enabled only reporters for displaying logs in console based on display logs settings
Reporters are depends of logger level settings as reporters will not be called if level of the current log are lower than display logs setting (except reporters with emitLevels property).
import { logger } from '@tinkoff/logger';
interface Reporter {
log(logObj: LogObj): void;
emitLevels?: {
trace?: boolean;
debug?: boolean;
info?: boolean;
warn?: boolean;
error?: boolean;
fatal?: boolean;
};
}
logger.addReporter(reporter as Reporter); // add new reporter to list of previously added reporters
logger.setReporters([reporter1, reporter2]); // replace current reporters with passed list. that allows to override default settings
Reporters with emitLevels
property will be called independently of display logs settings.
By default, bundled RemoteReporter use this property for logs filter.
Standard reporter to show logs in browser
Standard reporter to showing logs in the server console with handy formatting
Used by default in dev-mode or if environment variable process.env.DEBUG_PLAIN
is specified.
Minimal reporter to showing logs in the server console.
Show logs in json format.
Sends logs on remote api.
import { logger, RemoteReporter } from '@tinkoff/logger';
const remote = new RemoteReporter({
requestCount: 1, // number of parallel request
emitLevels: { error: true, fatal: true }, // log levels which will be send to api
async makeRequest(logObj) {
// function that accepts log object and sends data to api
return await request();
},
});
logger.addReporter(remote);
const log = logger({ name: 'test-remote' }); // settings for remote will be inherited from RemoteReporter itself
log.error('error'); // will be sent to api
log.info('test'); // will not be sent to api
const remoteLog = logger({ name: 'remote-for-all', defaults: { remote: true } }); // `remote` allows to override settings from RemoteReporter and send logs unconditionally
remoteLog.info('test'); // will be sent to api
remoteLog.debug('test'); // will be sent to api
const traceLog = logger({
name: 'log-trace',
defaults: { remote: { emitLevels: { trace: true } } },
}); // override RemoteReporter settings
traceLog.trace('test'); // will be sent to api
traceLog.error('test'); // will not be sent to api
import logger from '@tinkoff/logger'; // import logger
const log = logger('my-component'); // create new logger with an id `my-component`. This id will be added for every log at field `name`. Using unique ids will help to find source of the logs
// logs can be created with different levels
log.trace('trace');
log.debug('debug');
log.info({ event: 'client-visited', message: 'client visited tinkoff.ru' });
log.warn('warn');
log.error({ event: 'form-send-error', error: new Error('form') });
log.fatal('fatal error');
More about logging level and what do they mean in the article.
To log properly it is suitable to use next format:
interface Log {
event?: string; // unique id of event which is might be easily found in log management tool
message?: string; // log description
error?: Error; // error if appropriate
[key]: any; // any other data
}
message
props.logger.info('hello logger'); // identical to logger.info({ message: 'hello logger' });
logger.warn({
message: 'be warn',
event: 'my-warning',
...obj1,
...obj2,
a: 1,
b: 2,
});
error
or pass it to logger as only argumentlogger.error({
error: new Error('message'),
});
logger.error(new Error('message'));
logger.error(new Error('typeError'), 'custom error message'); // a special format to redefine error message
args
propslogger.debug(
{
event: 'watch',
data: 'some data',
},
'arg2',
'arg3'
);
These formatting rules are handful to connect logging to external tools like kibana, splunk. So it is desirable to follow these rules, otherwise it may lead to troubles with searching and analyzing your logs.
Be sure that you set all required environment variable (LOG_LEVEL
and LOG_ENABLE
) before app initialization. If you set all variable in .env
and parse them via Nest.js's ConfigModule, they will not be available in the logger initialization phase. ConfigModule
parses .env
-file later.
Also, check here that DEBUG_PLAIN
or NODE_ENV
variables are available.
FAQs
Logging library
We found that @tinkoff/logger demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers 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.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.