npm package: @jrh-works/log
Description: Combined local and remote logging for Node.js applications.
Latest version: 1.0.0

# @jrh-works/log

Combined local and remote logging (via [LogDNA](https://logdna.com)) for Node.js applications.

## Installation

`npm install @jrh-works/log`

## The Configuration Function

### Usage

`const configureLogger = require('@jrh-works/log')`

### Syntax

```
configureLogger(options)
```

### Arguments

| Name | Type | Description |
| :-- | :-- | :-- |
| options | [Object: Options](#the-options-object) | Configures the loggers which are generated by [the factory function](#the-factory-function). |

### Returns

| Type | Description |
| :-- | :-- |
| Function | A [factory function](#the-factory-function) which can be used to create loggers. |

### Exceptions

Throws a standard `Error` if all configuration options are not present.

---

### The Options Object

| Property | Type | Description |
| :-- | :-- | :-- |
| application | String | The name of the application. |
| key | String | The LogDNA API key. |
| mode | String | The mode of the running application (i.e. `production`). When the mode is set to `testing`, remote logs are disabled. |
| source | String | The source of the log line. |
| fetch | [Function: Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) *(optional)* | A [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) implementation to be used for remote requests. Defaults to [`node-fetch`](https://github.com/node-fetch/node-fetch). |

---

## The Factory Function

### Usage

```javascript
const createLogger = require('@jrh-works/log')(options)
const log = createLogger('logger-one')
```

### Syntax

```
createLogger(name)
```

### Arguments

| Name | Type | Description |
| :-- | :-- | :-- |
| name | String | A name which will be prepended to output from this logger. |

### Returns

| Type | Description |
| :-- | :-- |
| Function | A [logging function](#the-logging-function). |

### Exceptions

Throws a standard `Error` if a name is not present.

## The Logging Function

### Syntax

```
log(message, [metadata], notes)
```

### Example Usage

```javascript
const createLogger = require('@jrh-works/log')(options)
const log = createLogger('logger-one')

await log('Hello world!')
```

### Arguments

| Name | Type | Description |
| :-- | :-- | :-- |
| message | String | A message to log. |
| metadata | Object *(optional)* | Metadata to be included in the logging output. |
| notes | [Object: Notes](#the-notes-object) *(optional)* | [Notes](#the-notes-object) to append to the log message. |

### Returns

| Type | Description |
| :-- | :-- |
| Object: Promise | A preconfigured call to `fetch`. |

### Exceptions

Throws a standard `Error` if called without a message.

### Effects

- Logs will appear in the local console and in LogDNA.
- The log level will be `info`.

---

#### The Notes Object

| Attribute | Type | Description |
| :-- | :-- | :-- |
| [note] | Boolean | A note to be appended to the log message if the value is `true`. |

##### Example Usage

```javascript
await log('My message.', null, {
  'dry run': true,
  'limit: 1': true,
  'production mode': false
})

// Logs:
// "My message. (dry run, limit: 1)"
```

---

## Logging Errors

### Syntax

```
log.error(messageOrError, [metadata])
```

### Example Usage

```javascript
const createLogger = require('@jrh-works/log')(options)
const log = createLogger('logger-two')

await log.error(new Error())
```

### Arguments

| Name | Type | Description |
| :-- | :-- | :-- |
| messageOrError | String \| Error | An error message or error object to be logged. |
| metadata | Object *(optional)* | Metadata to be included in the logging output. |

### Returns

| Type | Description |
| :-- | :-- |
| Object: Promise | A preconfigured call to `fetch`. |

### Exceptions

Throws a standard `Error` if no message or error is present.

### Effects

- Logs will appear in the local console and in LogDNA.
- When given a string, the error message will be logged with optional metadata. 
- When given an error object, the error message will be logged. The error object and stacktrace will be included in the metadata.
- In all cases, the log level will be `error`.

## Logging HTTP Requests

### Usage

```javascript
const createLogger = require('@jrh-works/log')(options)

// An example serverless function.
module.exports = async (request, response) => {
  const log = createLogger('logger-two')
  await log.request(request)
}
```

### Syntax

```
log.request(request)
```

### Arguments

| Name | Type | Description |
| :-- | :-- | :-- |
| request | [Object: HTTP Request](https://nodejs.org/api/http.html#http_class_http_incomingmessage) | A standard Node.js [HTTP Request](https://nodejs.org/api/http.html#http_class_http_incomingmessage) object. |

### Returns

| Type | Description |
| :-- | :-- |
| Object: Promise | A preconfigured call to `fetch`. |

### Exceptions

Throws a standard `Error` if no request is present.

### Effects

- Logs will appear in the local console and in LogDNA.
- The URL and HTTP method will be logged (`GET /hello`) as the message, with the request body as metadata.
- The log level will be `info`.

## Composing Loggers

### Syntax

```
log.append()
```

### Arguments

| Name | Type | Description |
| :-- | :-- | :-- |
| name | String | A name which will be added to the previous logger's name. |

### Returns

| Type | Description |
| :-- | :-- |
| Function | A [logging function](#the-logging-function). |

### Exceptions

Throws a standard `Error` if a name is not present.