npm package: @nuskin/logger
Description: Logger for ...
Latest version: 1.1.4

# logger

Logger library for Nu Skin serverless applications.

@nuskin/logger is a logger library to aid in the development of Nu Skin serverless applications. 
**CONTENTS**

- [@nuskin/logger](#@nuskin/logger)
  - [NPM and Github Repo](#npm-and-github-repo)
  - [Installation](#installation)
  - [Usage](#usage)
    - [Logging](#logging)
      - [Logging Data](#logging-data)
      - [Setting the Logging Level](#setting-the-logging-level)
      - [Scrubbing Sensitive Data](#scrubbing-sensitive-data)
      - [Tags](#tags)
    - [Correlation IDs](#correlation-ids)
    - [Text Scrubbing](#text-scrubbing)

## NPM and Github Repo

https://www.npmjs.com/package/@nuskin/logger


## Installation

Using npm:

```bash
$ npm install @nuskin/logger
```

## Usage



### Logging

The `logger` module provides logging utilities.

This module can
* log data
* set logging levels
* add tags to logs
* scrub sensitive data from logs
* add tracing tags to logs, to aid in debugging

#### Logging Data

The `logging` module exposes `debug`, `info`, `warn`, and `error` methods for logging data.

Log entries take the following form:

```
{"level":"...","msg":{...}}
```

If the message argument passed to the logging function is a string, the log's `msg` property takes the following form:
```
"msg":{"message":"<YOUR MESSAGE HERE>"}
```

The logging functions support JSON objects as messages. This is often recommended in practice. If the message object is a JSON object, the log's `msg` takes the following form:

```
"msg": { // YOUR OBJECT HERE // }
```

**Examples:**

```javascript
const { logger: log } = require("@nuskin/logger");

// === Logging strings:

log.debug("Hello debug");
// LOGS: {"level":"debug","msg":{"message":"hello debug"}}

log.info("Hello info");
// LOGS: {"level":"info","msg":{"message":"hello info"}}

log.warn("Hello warn");
// LOGS: {"level":"warn","msg":{"message":"hello warn"}}

log.error("Hello error");
// LOGS: {"level":"error","msg":{"message":"hello error"}}

// === Logging an object:

log.info({ attr1: "it is cool", attr2: 42 });
// LOGS: {"level":"info","msg":{"attr1":"it is cool","attr2":42}}
```

#### Setting the Logging Level

The logging level can be set by calling `logger.setLevel()`. Logging calls made that are below the set logging level will not be written to the logs.

**Example:**

```javascript
const { logger } = require("@nuskin/logger");

logger.setLevel("off"); // no logs are written

logger.setLevel("error"); // only error logs are written

logger.setLevel("warn"); // warn and error logs are written

logger.setLevel("info"); // info, warn, and error logs are written

logger.setLevel("debug"); // debug, info, warn, and error logs are written
```

#### Scrubbing Sensitive Data

The `logger` module can scrub sensitive data from your logs. This scrubbing is turned *on* by default. You can disable it by calling `logger.setScrubbing()`.

```javascript
logger.setScrubbing(false);
```

See the [scrubber section](#text-scrubbing) for information on how to configure log scrubbing.

#### Tags

You can include a function-specific tag in your logs. Call `logger.setTag()` to set this tag. All logs written by your function will include your tag.

Tagged log entries take the following form:

```
{"level":"...", "tag": {...}, "msg": {...}}
```

If the provided tag is a string, the `tag` property takes the following form:

```
"tag":{"key":"<YOUR STRING HERE>"}
```

If the provided tag is a JSON object, the `tag` property takes the following form:

```
"tag":{ // YOUR OBJECT HERE // }
```

**Examples:**

```javascript
const { logger: log } = require("@nuskin/logger");

// set the tag as a string
log.setTag("My new tag"); 
log.info({ myMessage: "message 1" });
// LOGS: {"level":"info","tag":{"key":"My new tag"},"msg":{"myMessage":"message 1"}}

// set the tag as an object
log.setTag({ requestId: "some Id", resourceId: "12345" }); 
log.info({ myMessage: "message 2" });
// LOGS: {"level":"info","tag":{"requestId":"some Id","resourceId":"12345"},"msg":{"myMessage":"message 2"}}
```

To clear the tag, call `logger.setTag()` with no arguments.

```javascript
log.setTag();
```

Additional data can be merged into the current tag by calling `logger.addTag()`.

```javascript
log.setTag({ key1: "abc" });
log.addTag({ key2: "xyz" });
log.info({ myMessage: "message 1" });
// LOGS: {"level":"info","tag":{"key1":"abc","key2":"xyz"},"msg":{"myMessage":"message 1"}}
```
### Correlation IDs

The log correlation ID is a special tag that can be applied to logs to correlate transactions between applications, and is especially useful when debugging execution chains that span multiple applications. The `correlate` module provides methods for extracting an already-set correlation ID from incoming HTTP events, batchEvents and lambda to lambda calls. If a correlation ID is not found in the incoming message a correlation ID is generated.

An incoming HTTP request or lambda to lambda call is inspected for a correlaton ID in the following order. If one is not found, a uuid is generated and provided.

1. The `x-correlation-id` header on an HTTP request
2. The `x-request-id` header on an HTTP request
3. The 'correlationId' top level attribute in the body of the request. This is for a lambda to lambda call.
4. The `X_AMZN_TRACE_ID` environment variable
5. The `x-amzn-trace-id` header on an HTTP request
6. The `awsRequestID` property of the Lambda context parameter passed to your handler function


**Usage example:**
For HTTP and Lambda events, call `correlate.captureCorrelationID()`, passing in the event and context parameters passed to your function, to retrieve or generate the correlation ID. This correlation ID should then be added as a logging tag with the key `nse.correlation_id`.

```javascript
const { correlate, logger } = require("@nuskin/logger");

// Lambda handler function
exports.handler = async function(event, context) {
    // capture or generate the correlation ID
    const correlationID = correlate.captureCorrelationId(event, context);

    // Tag all logging messages with the correlation ID
    logger.addTag({ "nse.correlation_id": correlationID });

    // ... handler code continues ... //
};
```

**Usage example:**
For processing batch records, call `correlate.captureRecordCorrelationID()`, passing in the each record in the batch. This correlation ID should then be added as a logging tag with the key `nse.correlation_id`.

```javascript
const { correlate, logger } = require("@nuskin/logger");

async function snsHandler(event) {
    for (const record of event.Records) {
        // capture or generate the correlation ID
        const correlationID = correlate.captureRecordCorrelationId(record);

        // Tag subsequent logging messages with this correlation ID
        logger.addTag({ "nse.correlation_id": correlationID });

        // ... code continues ... //
```

| :warning: WARNING          |
|:---------------------------|
| This library uses a single global value to store the correlation ID. If you are processing batch records concurrently, it is likely the correlation and the associated tag will not be reliable.       |
&nbsp;   

If needed, an already-captured correlation ID can be retrieved by calling `correlate.retrieveCorrelationId()`.

```javascript
const savedCorrelationID = correlate.retrieveCorrelationId();
```
### Text Scrubbing

The `scrubber` module provides text scrubbing features. It also provides configuration for the log scrubbing described in [Scrubbing Sensitive Data](#scrubbing-sensitive-data). When a value is scrubbed, an md5 hash is created from the value being scrubbed. In the case of self referencing objects,
the reference is replaced with a replacement string.

The scrubber can be configured to scrub particular object keys or to scrub any keys matching a regular expression. The scrubber module has a built-in list of common sensitive keys that it can include in a list of keys to scrub.

```javascript
const { scrubber } = require("@nuskin/logger");

// Set scrubber to scrub specific keys
scrubber.setKeysToScrub(["sensitiveKey1", "Private_Data_Key"]);

// Set scrubber to scrub specific keys, and include default key list
scrubber.setKeysWithDefaultToScrub(["sensitiveKey1", "Private_Data_Key"]);

// Set scrubber to scrub any keys matching a pattern
scrubber.setPattern(/(my)?-sensitive-key-\d{2}/);
```

To change the replacement value for self referencing objects use `scrubber.setReplacement()` to set the value of this replacement string.

```javascript
// Any self referenced object found will be replaced with "AAAAAAAAAA"
scrubber.setReplacement("AAAAAAAAAA");
```

The scrubber can be called directly on a JSON object to scrub sensitive data by calling `scrubber.scrub()`. Scrubbing is applied recursively, in other words any key at any level of the object that matches the scrubber's settings will have its value scrubbed.

```javascript
const obj = {
    "key-01": "sensitive data here",
    "details": {
        "normal-stuff": "hello",
        "my-key-02": "more sensitive data"
    }
};
obj.b = obj

scrubber.setPattern(/(my)?-key-\d{2}/);
scrubber.setReplacement("...---...");

const scrubbedObj = scrubber.scrub(obj);
/* 
scrubbedObj:
{
    "key-01": "{HASHED VALUE}",
    "details": {
        "normal-stuff": "hello",
        "my-key-02": "{HASHED VALUE}"
    },
    b: "...---..."
}
 */
```

Any configuration settings provided to the `scrubber` module are used to scrub logs written by the `logger` module.

```javascript
const { logger, scrubber } = require("@nuskin/logger");

// Set scrubber to scrub specific keys
scrubber.setKeysToScrub(["pi", "myPassword"]);
scrubber.setReplacement("::::::");

logger.info({"pi": "3.14159", "user": {"name":"Bob","myPassword": "password1"}});
// LOGS: {"level":"info","msg":{"pi":"::::::","user": {"name":"Bob","myPassword": "::::::"}}}
```