Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: document transformers feature #17

Merged
merged 2 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ lerna-debug.log*
!.vscode/extensions.json

# Temp files
*.temp
*.temp

.vscode
201 changes: 186 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@ A logger module for [Nestjs](https://github.com/nestjs/nest), built on top of [n

# Features

* A gloabl bunyan logger provider can be used in the controllers/services.
* Automatically log request/response with `request-id`, `timestamp`, `status-code`, etc.
- A gloabl bunyan logger provider can be used in the controllers/services.
- Automatically log request/response with `request-id`, `timestamp`, `status-code`, etc.

# Usage

## Installation

### Yarn

```
yarn add @wiredcraft/nestjs-bunyan-logger
```

### NPM

```
npm install @wiredcraft/nestjs-bunyan-logger --save
```
Expand Down Expand Up @@ -48,34 +50,203 @@ export class AppModule {}
```

A sample configuration file is as below,

```typescript
export default () => ({
logger: {
name: 'awesome-app',
streamType: 'FILE' | 'STDOUT',
path: './logs/app.log', // only available for `FILE` streamType
excludeReqPath: '/health', // the path that you want to skip logging
}
name: 'awesome-app',
streamType: 'FILE' | 'STDOUT',
path: './logs/app.log', // only available for `FILE` streamType
excludeReqPath: '/health', // the path that you want to skip logging
},
});

```


2. Inject the logger instance to your service and use it as you want.

```typescript
import { Injectable } from '@nestjs/common';
import { Logger, Bunyan } from '@wiredcraf/nestjs-bunyan-logger';
import { Logger, Bunyan } from '@wiredcraf/nestjs-bunyan-logger';

@Injectable()
export class CatService {
constructor(
@Logger() private logger: Bunyan,
) {
}
constructor(@Logger() private logger: Bunyan) {}
}
```

## Transformers Option

![image](./docs/images/transformers-workflow.png)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it mean the transformers have to be in the order of constant -> clone -> map?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good point, we don't have such rules for orders, and let me redraw the picture to make it more accurate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the latest commit.


`transformers` is a config option that could allow the user to specify a list of customized transform rules to apply to each log entry. The current library supports three types of transformers: `constant`, `clone` and `map`.

### Constant

`constant` type allows the user to copy a **object type** constant directly to the log entry. An example is as follows:

```js
const options: LoggerConfig = {
name: 'test-app',
streamType: 'STDOUT',
transformers: [{ constant: { customField: '123' } }],
};

logger.info({ originalField: 'abc' });

// The above will generate the following log entry:
// {
// originalField: 'abc',
// customField: '123'
// }
```

### Clone

`clone` type allows the user to copy value from one fieldname to the specified fieldname with the following rules:

- The original field is not removed from the log entry
- Only one embed level is allowed in new Fieldname specification

An example is as follows:

```js
const options: LoggerConfig = {
name: 'test-app',
streamType: 'STDOUT',
transformers: [{ clone: { originalField: 'newField' } }],
};

logger.info({ originalField: 'abc' });

// The above will generate the following log entry:
// {
// originalField: 'abc',
// newField: 'abc'
// }
```

An one embed level example is as follows:

```js
const options: LoggerConfig = {
name: 'test-app',
streamType: 'STDOUT',
transformers: [{ clone: { originalField: 'newParent.newField' } }],
};

logger.info({ originalField: 'abc' });

// The above will generate the following log entry:
// {
// originalField: 'abc',
// newParent: {
// {
// newField: 'abc'
// }
// }
// }
```

### Map

`map` type allows the user to apply a map value or a map function to the target field and replace the field value with the mapped value with the following rules:

- only one embed level is allowed for original field name specification

An example of simple map value is as follows:

```js
const options: LoggerConfig = {
name: 'test-app',
streamType: 'STDOUT',
transformers: [{ map: { originalField: 'new-value' } }],
};

logger.info({ originalField: 'abc' });

// The above will generate the following log entry:
// {
// originalField: 'new-value',
// }
```

An example of map function is as follows:

```js
const options: LoggerConfig = {
name: 'test-app',
streamType: 'STDOUT',
transformers: [
{ map: { originalField: (oldValue) => oldValue + 'transformed' } },
],
};

logger.info({ originalField: 'abc' });

// The above will generate the following log entry:
// {
// originalField: 'abctransformed',
// }
```

An one embed level example is as follows:

```js
const options: LoggerConfig = {
name: 'test-app',
streamType: 'STDOUT',
transformers: [
{ map: { ['originalParentField.originalField']: 'new-value' } },
],
};

logger.info({
originalParentField: {
originalField: 'abc',
},
});

// The above will generate the following log entry:
// {
// originalParentField: {
// originalField: 'new-value',
// },
// }
```

### Multiple transformers

Multiple transformers are applied in the order as they are specified in the `transformers` option. An example is as follows:

```js
const transformers = [
{
constant: { customField: 'custom-value' },
},
{
clone: { originalField: 'backupField' },
},
{
map: { originalField: (oldValue) => oldValue + 'transformed' },
},
];

const options: LoggerConfig = {
name: 'test-app',
streamType: 'STDOUT',
transformers,
};

logger.info({ originalField: 'original-value' });

// The above will generate the following log entry:
// {
// originalField: 'original-value-transformed',
// backupField: 'original-value',
// customField: 'custom-value'
// }
```

# Development

## Installation
Expand All @@ -86,7 +257,7 @@ $ yarn install

## Publish

``` bash
```bash
$ npm version major|minor|patch
$ npm publish
```
Expand Down
Binary file added docs/images/transformers-workflow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/logger.providers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Provider } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import * as Bunyan from 'bunyan';
import Bunyan from 'bunyan';

import { LOGGER, LOGGER_OPTIONS } from './constants';
import { RequestInterceptor } from './logger.interceptor';
Expand Down
Loading
Loading