Okay, so there I was, knee-deep in this * project. And you know what my logging solution was? Good old . Everywhere. I mean, literally spammed all over the code. It was a total disaster. Anytime something went sideways, trying to find the useful bit of info in that flood of messages was a nightmare. Just a wall of text staring back at me. Useless.

I grumbled about it for a while, probably to anyone who would listen. Then I think I was just browsing, maybe some forum, or a blog post, and the name ‘Winston’ popped up. Someone said it was pretty decent for logging in Node. Didn’t know much about it, but heck, anything had to be better than my * mess, right?
So, I Gave It a Whirl
First thing, I jumped into my terminal. Typed that familiar command: npm install winston. That part was easy, thankfully. Always a good start when the install doesn’t throw a hundred errors at you.
Then came the “now what?” moment. Stared at my editor. Okay, it’s installed. How do I actually use this thing? I poked around their docs, or maybe some examples I found online. The first thing that caught my eye was this ‘transports’ business. Sounded complicated, but it’s basically just telling Winston where to send the logs. Like, to a file, or to the console, or somewhere else.
My main goal was simple:
- Get logs into a file. So they wouldn’t just vanish when I closed the terminal.
- Still see logs on my console while I was developing, ’cause that’s handy.
- And maybe, just maybe, make them look a bit less chaotic.
So I started tinkering. Found out I needed to create a logger instance. Something like . Inside that, I started adding transports. For file logging, it was something like new *({ filename: '*' })
. Threw that in. Then for the console, new *()
. Seemed straightforward enough.

Took a bit of fiddling to get the syntax right, you know how it is. Copied a bit, typed a bit, ran it, saw an error, tweaked it. The usual dance. But then, bam! It worked. I ran my app, and a shiny new `*` file appeared. And stuff was printing to my console too. Felt like a mini-victory, I tell ya.
Next up, I wanted to make the logs more, well, useful. Just plain messages weren’t enough. I saw stuff about log levels – like `info`, `warn`, `error`. So instead of `*(‘Something happened’)`, I could do `*(‘Something happened’)` or `*(‘Big problem here!’)`. That was neat. Helps you filter things later, or just quickly see the bad stuff.
And the formatting! `*` just dumps text. With Winston, I found I could control how the log messages looked. There was this `*` thing. I played with `*()` for a bit, which was, well, simple. Then I saw `*()`. Tried that too. JSON is good if you want to send logs to some system later, but for just reading them, simple text with a timestamp was fine for me at that stage. I think I ended up combining a timestamp, the level, and the message. Looked way more professional than my old logs, ha!
So, after an afternoon of messing around, I had it. My logs were going to a file, they were on my console, they had levels, and they had timestamps. It wasn’t perfect, I’m sure there’s a ton more Winston can do, but for a first pass? Huge improvement.
Honestly, it made looking at what my app was doing so much easier. No more scrolling through endless, meaningless `*` outputs. I could actually find errors, see the sequence of events. It wasn’t as scary as I thought it would be to set up a ‘proper’ logger. Winston seemed to do the job without too much fuss, once I got past the initial “what are all these options?” phase. Definitely better than living in the dark ages of print statements. Never going back to that, if I can help it.
