Description
This plugin instantiates and exports an instance of winston.Logger configured to follow samsystems logging conventions for logging to kibana correctly.
It also exports a logger factory function that can be used to explicitly pass options for creating winston.Logger instance as opposed to based on environment
variables.
Getting started
- Clone repo:
git clone https://github.com/samsystems/logger
- Run:
npm install
Env vars example
Package is designed to run without any necessary setup.
Just require('@samsystem/logger') and use in your service.
It will log to kibana in beta/production environments and to console otherwise.
If you need to overwrite default behaviour you can use following env variables.
-
Disable all output
LOG_SILENT=true
-
Set custom transports
LOG_TRANSPORTS=kibana,console
-
Change log level
LOG_LEVEL=info
-
MongoDB transport custom configuration
LOG_MONGODB_URI=mongodb://localhost
LOG_MONGODB_COLLECTION=logs
LOG_MONGODB_LEVEL=error
-
File transport custom configuration
LOG_FILE_FILENAME=output.log
-
Integrate with the debug Node package
LOG_USE_DEBUG=1
(and when invoking logger.debug)
logger.debug('A useful log message', {
trace: 'package:class:method',
});
-
Splunk transport custom configuration
LOG_SPLUNK_TOKEN=<token_access_splunk>
LOG_SPLUNK_URL=<url_to_splunk>
Variables follow pattern:
- General variables LOG_*
- Transport specific variables LOGTRANSPORT*
Transport specific variables overwrite general variables.
If you want to create custom logger you can use factory from lib/utils/createLogger.js to create your own logger.
How to use
Exported module is an instance of winston.Logger. If silent is false then
the returned logger instance will use a instance of winston.transport.Console
as the transport. Transports and logging-levels are able to be changed dynamically
refer to docs
Using log-level and silent-mode set by environment variables
const logger = require('@samsystem/logger');
logger.info('Inserted Customer', { customer: 'theCustomer' });
logger.error('Error inserting customer', {
error: 'the error message',
customer: 'theCustomer',
});
logger.warn('Customer not found with email', { email: 'the@email.com' });
logger.debug('the customer', { customer: 'theCustomer' });
Using createLogger method
const createLogger = require('@samsystem/logger/lib/utils/createLogger');
const logger = createLogger({
});
When using ElasticSearch transport
The ElasticSearch transport allows log data to be sent straight to ES without the need to be parsed by fluentd/logstash
allowing for a more robust set of logs to be stored. In order to make it function properly the following environment
variables need to be defined:
LOG_ELASTICSEARCH_INDEX
This specifies which index to use, as a matter of best practice the index should be named after the application
LOG_ELASTICSEARCH_HOST
The actual ES host to use, if the logger cannot connect to the ES host it will buffer a number of log messages (~5000) in
memory and then bulk write them once it can heartbeat ElasticSearch
logger.tap
tap is a curried version of the logger, making it well suited for promise chains or functional composition.
Tap methods:
- tap
- tapInfo
- tapVerbose
- tapDebug
- tapWarn
- tapError
- tapCritical
You can call tap directly, and supply the log level you wish to use.
return getUser(username).then(
logger.tap('debug', `Retrieved user with username: ${username}`),
);
Or you can use the convenience methods for each log level.
return getUser(username).then(
logger.tapInfo(`Retrieved user with username: ${username}`),
);
return getUser(username).then(
logger.tapVerbose(`Retrieved user with username: ${username}`),
);
return getUser(username).then(
logger.tapDebug(`Retrieved user with username: ${username}`),
);
logger.tapAndThrow
tapAndThrow is similar to logger.tap, but instead of returning the logged value, it throws it.
Tap and Throw methods:
- tapAndThrow
- tapAndThrowInfo
- tapAndThrowVerbose
- tapAndThrowDebug
- tapAndThrowWarn
- tapAndThrowError
- tapAndThrowCritical
You can call tapAndThrow directly, and supply the log level you wish to use.
return getUser(username)
.then(logger.tapDebug(`Retrieved user with username: ${username}`))
.catch(
logger.tapAndThrow(
'error',
`Unexpected error finding user. username: ${username}`,
),
);
Or you can use the convenience methods for each log level.
return getUser(username)
.then(logger.tapDebug(`Retrieved user with username: ${username}`))
.catch(
logger.tapAndThrowCritical(
`Unexpected error finding user. username: ${username}`,
),
);
return getUser(username)
.then(logger.tapDebug(`Retrieved user with username: ${username}`))
.catch(
logger.tapAndThrowError(
`Unexpected error finding user. username: ${username}`,
),
);
return getUser(username)
.then(logger.tapDebug(`Retrieved user with username: ${username}`))
.catch(
logger.tapAndThrowWarn(
`Unexpected error finding user. username: ${username}`,
),
);