Skip to content

Commit cf4ae62

Browse files
authored
Create winston-transports.md
1 parent de8c6fa commit cf4ae62

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
+++
2+
ShowToc = true
3+
date = 2022-09-06T18:30:00Z
4+
description = "Brief intro to winston transports and how to create custom ones."
5+
tags = ["webdev", "winston", "logging", "custom"]
6+
title = "Winston Transports??"
7+
[cover]
8+
alt = "winston transport blog post cover"
9+
image = "/blog/uploads/winston-transport-cover.png"
10+
+++
11+
12+
### Brief Introduction to what is `winston`?
13+
14+
> Winston is a node package that provides a simple and universal logging library. It supports **multiple transports**, such as file, console, and syslog. Winston is easy to use and can be **customized** to meet your specific needs.
15+
>
16+
17+
Did you see the words `multiple transports` and `customized` in the above definition of `winston` (that I asked Google Bard to write)? Yeah, `winston` is probable the most sophisticated and customizable logger out there.
18+
19+
### What are transports?
20+
21+
So we know that `winston` supports multiple transports, but what is a transport anyway?
22+
23+
> In `winston`, transport is essentially a storage device for your logs. Each instance of a `winston` logger can have multiple transports configured at different levels.
24+
>
25+
26+
So transport is basically like where you want to store your logs.
27+
28+
There are some most basic ones like:
29+
30+
- **The Console**
31+
32+
```tsx
33+
import winston from "winston"
34+
35+
export const logger = winston.createLogger(
36+
{
37+
transports: [
38+
new winston.transports.Console()
39+
],
40+
}
41+
)
42+
```
43+
44+
- **Files**
45+
46+
```tsx
47+
...
48+
new winston.transports.File({ filename: "logs/all.log" })
49+
...
50+
```
51+
52+
53+
Console and file are like the most basic ones, Console basically prints your logs to the console and file one just stores your log in the defined file. You can go crazy with the options and do a lot more stuff, like storing logs of only a specific `level`, let’s say `error` or something.
54+
55+
The default ones are great, and they make for the most basic use cases, but if youre going into production and logs are just more than something youll use to debug and get HTTP status codes.
56+
57+
There are a lot of platforms that allows you to store your logs and do crazy things with them (basically alerts and analytics). Some of them are [Logtail](https://betterstack.com/logtail), and an open source one is [Highstorm](https://highstorm.app).
58+
59+
To upload your logs to them, youll need custom transport. `winston` give you the power to create custom transports pretty easily with the `winston-transport` package, and heres how you do it
60+
61+
### Custom Transports
62+
63+
So basically custom transports are to upload your logs to some sort of storage or maybe do something else with it, like creating alerts and stuff.
64+
65+
Heres how you create basic custom transport for `winston`:
66+
67+
```tsx
68+
// my-transport.ts
69+
70+
import Transport, { TransportStreamOptions } 'winston-transport';
71+
import type { LogEntry } from "winston";
72+
73+
export class MyTransport extends Transport {
74+
constructor(
75+
opts: TransportStreamOptions
76+
) {
77+
super(opts);
78+
79+
/*
80+
* Consume any custom options here. e.h:
81+
* Connection information for databases
82+
* Authentication information for APIs
83+
*/
84+
}
85+
86+
// this functions run when something is logged so here's where you can add you custom logic to do stuff when something is logged.
87+
log(info: LogEntry, callback: any) {
88+
// make sure you installed `@types/node` or this will give a typerror
89+
// this is the basic default behavior don't forget to add this.
90+
setImmediate(() => {
91+
this.emit("logged", info);
92+
});
93+
94+
const { level, message, ...meta } = info;
95+
96+
// here you can add your custom logic, e.g. ingest data into database etc.
97+
98+
// don't forget this one
99+
callback();
100+
}
101+
}
102+
```
103+
104+
Now you can add your custom transport very easily as:
105+
106+
```tsx
107+
// logger.ts
108+
109+
import {MyTransport} from "./my-transport.ts"
110+
111+
const options = {
112+
// custom transport options
113+
}
114+
115+
const myTransport = new MyTransport(options)
116+
117+
export const logger = winston.createLogger({
118+
...
119+
transports: [
120+
...
121+
mytransport,
122+
...
123+
]
124+
});
125+
```
126+
127+
Pretty easy to write, yup, thanks to `winston` being the best logger out there with this level of customization. With the above example, you can create any custom transport you want with whatever fancy logic you want.
128+
129+
Check out these to dive deeper:
130+
131+
[npm: winston-transport](https://www.npmjs.com/package/winston-transport)
132+
133+
[npm: winston](https://www.npmjs.com/package/winston)
134+
135+
Here are some packages that provide transports to do various things (mostly upload to their service):
136+
137+
[npm: @logtail/winston](https://www.npmjs.com/package/@logtail/winston)
138+
139+
[npm: winston-transport-sentry-node](https://www.npmjs.com/package/winston-transport-sentry-node)
140+
141+
[npm: winston-kafka-transport](https://www.npmjs.com/package/winston-kafka-transport)
142+
143+
[npm: @shelf/winston-datadog-logs-transport](https://www.npmjs.com/package/@shelf/winston-datadog-logs-transport)

0 commit comments

Comments
 (0)