@wnqueiroz/ecs-winston
Version:
A formatter for the winston logger compatible with Elastic Common Schema (ECS) 🚀
221 lines (170 loc) • 5.7 kB
Markdown
<h1 align="center">@wnqueiroz/ecs-winston</h1>
<h3 align="center">
A formatter for the <a href="https://github.com/winstonjs/winston">winston</a> logger compatible with <a href="https://www.elastic.co/guide/en/ecs-logging/overview/master/intro.html"> Elastic Common Schema (ECS) 🚀</a>
</h3>
<div align="center">
[](http://commitizen.github.io/cz-cli/)
[](https://github.com/wnqueiroz/ecs-winston/actions/workflows/ci-cd.yml)
[](https://codecov.io/gh/wnqueiroz/ecs-winston)
<a href="https://twitter.com/wnqueiroz" alt="Twitter Follow">
<img src="https://img.shields.io/twitter/follow/wnqueiroz?style=social">
</a>
</div>
## Table Of Contents
- [Key Features ✨](#key-features-)
- [Install](#install)
- [Usage](#usage)
- [Basic Usage](#basic-usage)
- [Converting Express `req` and `res`](#converting-express-req-and-res)
- [Removing ECS fields from the log](#removing-ecs-fields-from-the-log)
- [Roadmap 🚧](#roadmap-)
- [License](#license)
## Key Features ✨
- ECS version [1.12](https://www.elastic.co/guide/en/ecs/1.12/index.html) support.
- IntelliSense of ECS fields in writing logs.
- Automatic field conversion when using [Express](https://expressjs.com/) `req` and `res`. 😍
- Overwrite and omit the values of the ECS fields that you find necessary.
## Install
With NPM:
```sh
npm install @wnqueiroz/ecs-winston
```
Or using Yarn:
```sh
yarn add @wnqueiroz/ecs-winston
```
> 💡 Make sure you are using the [winston@3](https://www.npmjs.com/package/winston).
## Usage
### Basic Usage
```ts
import * as winston from 'winston'
import { ecsWinstonFormat, ECSLog, LogMetadata } from '@wnqueiroz/ecs-winston'
const logger = winston.createLogger({
level: 'info',
format: ecsWinstonFormat(),
transports: [new winston.transports.Console()],
})
const ecs: ECSLog = {
// IntelliSense here 😍
labels: {
application: 'foo',
},
tags: ['api'],
}
const log: LogMetadata = {
ecs,
}
logger.info(log)
logger.info('This is amazing!!', log)
```
```sh
# logger.info(log)
{"@timestamp":"2021-10-08T20:56:37.643Z","labels":{"application":"foo"},"message":"","tags":["api"],"log":{"level":"info"},"ecs":{"version":"1.12.0"}}
# logger.info('This is amazing!!', log)
{"@timestamp":"2021-10-08T20:56:37.649Z","labels":{"application":"foo"},"message":"This is amazing!!","tags":["api"],"log":{"level":"info"},"ecs":{"version":"1.12.0"}}
```
### Converting Express `req` and `res`
Let's configure a simple express application that, when finalizing a HTTP Request, an access log will be created:
```ts
import { ecsWinstonFormat, LogMetadata } from '@wnqueiroz/ecs-winston'
import * as winston from 'winston'
import express, { Request, Response } from 'express'
const app = express()
const logger = winston.createLogger({
level: 'info',
format: ecsWinstonFormat(),
transports: [new winston.transports.Console()],
})
app.get('/', (req: Request, res: Response) => {
const payload = {
data: 'foo',
}
res.locals.body = payload // will be injected into http.response.body.content
req.on('end', () => {
const log: LogMetadata = {
req,
res,
}
logger.info('access log', log)
})
res.json(payload)
})
const port = 3000
app.listen(port, () => {
logger.info(`app listening at http://localhost:${port}`)
})
```
When making the HTTP Request `GET http://localhost:3000`, the log displayed will look something like:
```json
{
"@timestamp": "2021-10-09T20:31:08.828Z",
"message": "access log",
"log": {
"level": "info"
},
"ecs": {
"version": "1.12.0"
},
"http": {
"version": "1.1",
"request": {
"id": "",
"method": "GET",
"headers": {
"user-agent": "Thunder Client (https://www.thunderclient.io)",
"accept": "*/*",
"accept-encoding": "gzip, deflate, br",
"host": "localhost:3000",
"connection": "close"
},
"body": {}
},
"response": {
"status_code": 200,
"mime_type": "application/json; charset=utf-8",
"body": {
"bytes": 14,
"content": {
"data": "foo"
}
}
}
},
"user_agent": {
"original": "Thunder Client (https://www.thunderclient.io)"
}
}
```
### Removing ECS fields from the log
It's possible to configure the formatter to exclude ECS properties by default (from all written logs):
```ts
import { ecsWinstonFormat, LogMetadata } from '@wnqueiroz/ecs-winston'
import * as winston from 'winston'
const logger = winston.createLogger({
level: 'info',
format: ecsWinstonFormat({
exclude: ['http.request.headers.authorization'], // will remove this property from all logs by default.
}),
transports: [new winston.transports.Console()],
})
```
Or delete the property from that log only:
```ts
const log: LogMetadata = {
ecs: {
message: 'exclude example',
labels: {
application: 'foo', // will be removed
foo: 'bar',
},
},
exclude: ['labels.application'],
}
logger.info(log)
// {"@timestamp":"2021-10-11T14:40:35.163Z","labels":{"foo":"bar"},"message":"exclude example","log":{"level":"info"},"ecs":{"version":"1.12.0"}}
```
> 💡 It is possible to combine the two strategies: excluding properties by default (at configuration) and from a specific log.
## Roadmap 🚧
- Integration with [Elastic APM](https://www.elastic.co/apm/).
## License
This software is licensed under the [MIT license](./LICENSE).