npm package: @samsystem/logger
Description: Winston logging for samsystems projects. Env-loaded transports: console and elasticsearch only; restore deps from _inactiveTransportDependencies to re-enable other transports.
Author: Joe Luis Borrero Senciales
Latest version: 1.5.2

## 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.

1. Disable all output

    ```bash
    LOG_SILENT=true
    ```

1. Set custom transports

    ```bash
    LOG_TRANSPORTS=elasticsearch,console
    ```

1. Change log level

    ```bash
    LOG_LEVEL=info
    ```

1. MongoDB transport custom configuration

    ```bash
    LOG_MONGODB_URI=mongodb://localhost
    LOG_MONGODB_COLLECTION=logs
    LOG_MONGODB_LEVEL=error
    ```

1. File transport custom configuration

    ```bash
    LOG_FILE_FILENAME=output.log
    ```

1. Integrate with the [debug](https://github.com/visionmedia/debug) Node package

    ```bash
    LOG_USE_DEBUG=1
    ```

    (and when invoking `logger.debug`)

    ```javascript 1.6
    logger.debug('A useful log message', {
        trace: 'package:class:method',
    });
    ```

1. Splunk transport custom configuration
    ```bash
    LOG_SPLUNK_TOKEN=<token_access_splunk>
    LOG_SPLUNK_URL=<url_to_splunk>
    ```

Variables follow pattern:

1. General variables LOG\_\*
1. Transport specific variables LOG*TRANSPORT*\*
   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][winston-docs]

### Using log-level and silent-mode set by environment variables

```javascript
// 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"}
```

### Using createLogger method

```javascript
const createLogger = require('@samsystem/logger/lib/utils/createLogger');
const logger = createLogger({
    // winston.Logger options
});
```

### 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:

1. `LOG_ELASTICSEARCH_INDEX`
   This specifies which index to use, as a matter of best practice the index should be named after the application
2. `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.

```javascript
// tap
return getUser(username).then(
    logger.tap('debug', `Retrieved user with username: ${username}`),
);
```

Or you can use the convenience methods for each log level.

```javascript
// 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}`),
);
```

### 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.

```javascript
// 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.

```javascript
// 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}`,
        ),
    );
```

[winston-docs]: https://github.com/winstonjs/winston