<p align="center">
  <a href="https://github.com/mocks-server/main/actions?query=workflow%3Abuild+branch%3Amaster"><img src="https://github.com/mocks-server/main/workflows/build/badge.svg?branch=master" alt="Build Status"></a>
  <a href="https://codecov.io/gh/mocks-server/main"><img src="https://codecov.io/gh/mocks-server/main/branch/master/graph/badge.svg?token=2S8ZR55AJV" alt="Coverage"></a>
  <a href="https://sonarcloud.io/project/overview?id=mocks-server_main_logger"><img src="https://sonarcloud.io/api/project_badges/measure?project=mocks-server_main_logger&metric=alert_status" alt="Quality Gate"></a>
  <a href="https://www.npmjs.com/package/@mocks-server/logger"><img src="https://img.shields.io/npm/dm/@mocks-server/logger.svg" alt="Downloads"></a>
  <a href="https://renovatebot.com"><img src="https://img.shields.io/badge/renovate-enabled-brightgreen.svg" alt="Renovate"></a>
  <a href="https://github.com/mocks-server/main/blob/master/packages/logger/LICENSE"><img src="https://img.shields.io/npm/l/@mocks-server/logger.svg" alt="License"></a>
</p>

---

# Logger

[Winston](https://github.com/winstonjs/winston)-based logger allowing to create nested namespaces. It provides:

* Nested namespaces
* Each namespace includes its "path" in the logs generated by it (the path is formed by its label appended to all its parent labels).
* Coloured logs, with format: `HH:mm:ss:SS [level][...parentLabel:parentLabel:label?] message`
* Store logs from each different namespace in a different array.
* Store logs from all namespaces in a global store.
* Each namespace log level can be set separately, and child namespaces can inherit the change or not.
* Emit events whenever a log is added to any store.

## Usage

A brief example:

```js
const { Logger } = require("@mocks-server/logger");

// Create root logger
const logger = new Logger();

logger.setLevel("debug");

logger.info("Hello world");
// 18:41:43:16 [info] Hello world

const dbLogger = logger.namespace("db");

dbLogger.verbose("Hello from database component");
// 18:41:43:16 [verbose][db] Hello from database component

const dbConnectionLogger = dbLogger.namespace("connection");

dbConnectionLogger.debug("Connecting");
// 18:41:43:16 [debug][db:connection] Connecting

console.log(dbConnectionLogger.store);
/*
[ '18:41:43:16 [debug][db:connection] Connecting' ]
*/

console.log(logger.globalStore);
/*
[
  '18:41:43:16 [info] Hello world',
  '18:41:43:16 [verbose][db] Hello from database component',
  '18:41:43:16 [debug][db:connection] Connecting'
]
*/
```

## API

### Logger constructor

```js
const logger = new Logger();
``` 

* __`Logger(label?, options?)`__. Returns a `logger` instance.
  * __`label`__ _(String)_: Label for the root namespace. Optional.
  * __`options`__ _(Object)_: Optional.
    * __`level`__ _(String)_: - Initial level, can be one of `silent`, `error`, `warn`, `info`, `verbose`, `debug` or `silly`.
    * __`storeLimit`__ _(Number)_: - Limit of logs to store in the root namespace `store` array. The option will be inherited by all children namespaces. Default is 1000.
    * __`globalStoreLimit`__ _(Number)_: - Limit of logs to store in the global `store` array, which stores logs from all nested namespaces. Default is 1000.

### logger instance

* __`error(message)`__: The message will be logged always except if the current `level` is `silent`.
* __`warn(message)`__: The message will be logged always except if the current `level` is `error` or `silent`.
* __`info(message`__: The message will be logged whenever the current `level` is not `error`, `warn` or `silent`.
* __`verbose(message)`__: The message will be logged whenever the current `level` is upper or equal than `verbose`.
* __`debug(message)`__: The message will be logged whenever the current `level` is upper or equal than `debug`.
* __`silly(message)`__: The message will be logged whenever the current `level` is upper or equal than `silly`.
* __`setLevel(level, [options])`__: Sets the logger current log level for the current namespace and all children namespaces recursively.
  * `level` _(String)_: Level can be one of `silent`, `error`, `warn`, `info`, `verbose`, `debug` or `silly`.
  * `options` _(Object)_:
    * `transport` _(String)_: The `Winston` transport in which the level has to be set. Can be one of `console` or `store`. If not provided, the level is set to all transports. In the root logger, changes in the `store` transport will be applied also to the `globalStore` transport.
    * `propagate` _(Boolean)_: Propagates the level change to all children namespaces recursively or not. Default is `true`.
    * `pinned` _(Boolean)_: When `true`, next level changes coming from propagations will be ignored and the transport/transports will keep the defined `level`. Default is `false`.
    * `forcePropagation` _(Boolean)_: When `true`, the propagation will ignore `pinned` levels and will always override them.
* __`namespace(label)`__: Creates and returns a new child namespace or returns an already existent one when the `label` already exists. The returned namespace has the same `Logger` methods described here. The created namespace will inherit the current namespace level.
  * `label` _(String)_: Label for the new namespace. It will be displayed as part of the log `[label]`, appended to parent namespaces labels.
* __`cleanStore()`__ Empties the namespace store array.
* __`onChangeStore(callback)`__: Allows to add a listener that will be executed whenever a log is added to the current namespace store. __It returns a function that removes the listener once executed__.
  * `callback()` _(Function)_: Callback to be executed.
* __`onChangeGlobalStore(callback)`__: Allows to add a listener that will be executed whenever a log is added to the global store. __It returns a function that removes the listener once executed__.
  * `callback()` _(Function)_: Callback to be executed.
* __`store`__: Returns an array with logs stored in the current namespace.
* __`globalStore`__: Returns an array with logs stored in all namespaces, including those from the ancestors. There is only one global namespace for each `Logger` instance, no matter the amount of namespaces it has.
* __`label`__: Getter returning the namespace label.
* __`level`__: Getter returning the current namespace level.
* __`root`__: Getter returning the root namespace instance.
