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.
- Clone repo:
git clone https://github.com/samsystems/logger
- Run:
npm install
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.
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
// pre-configured based on process.env.LOG_LEVEL and process.env.LOG_SILENT
// defaults to {silent: false, level: 'info'}
const logger = require('@samsystem/logger');
logger.info('Inserted Customer', { customer: 'theCustomer' });
// {"customer":"theCustomer","level":"info","message":"Inserted Customer"}
logger.error('Error inserting customer', {
error: 'the error message',
customer: 'theCustomer',
});
// {"error":"the error message","customer":"theCustomer","level":"error","message":"Error inserting customer"}
logger.warn('Customer not found with email', { email: 'the@email.com' });
// {"email":"the@email.com","level":"warn","message":"Customer not found with email"}
// LOGGING_LEVEL env variable must be set to debug in order for debug to show
logger.debug('the customer', { customer: 'theCustomer' });
// {"customer":"theCustomer","level":"debug","message":"the customer"}
const createLogger = require('@samsystem/logger/lib/utils/createLogger');
const logger = createLogger({
// winston.Logger options
});
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
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.
// tap
return getUser(username).then(
logger.tap('debug', `Retrieved user with username: ${username}`),
);
Or you can use the convenience methods for each log level.
// tapInfo
return getUser(username).then(
logger.tapInfo(`Retrieved user with username: ${username}`),
);
// tapVerbose
return getUser(username).then(
logger.tapVerbose(`Retrieved user with username: ${username}`),
);
// tapDebug
return getUser(username).then(
logger.tapDebug(`Retrieved user with username: ${username}`),
);
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.
// tapAndThrow
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.
// tapAndThrowCritical
return getUser(username)
.then(logger.tapDebug(`Retrieved user with username: ${username}`))
.catch(
logger.tapAndThrowCritical(
`Unexpected error finding user. username: ${username}`,
),
);
// tapAndThrowError
return getUser(username)
.then(logger.tapDebug(`Retrieved user with username: ${username}`))
.catch(
logger.tapAndThrowError(
`Unexpected error finding user. username: ${username}`,
),
);
// tapAndThrowWarn
return getUser(username)
.then(logger.tapDebug(`Retrieved user with username: ${username}`))
.catch(
logger.tapAndThrowWarn(
`Unexpected error finding user. username: ${username}`,
),
);