DEV Community

Cover image for I replaced Morgan with reqlog and never looked back
FirasLatrech
FirasLatrech

Posted on

I replaced Morgan with reqlog and never looked back

Let me describe a debugging session I had six months ago.

It is 11pm. A client is reporting that their order confirmation emails are not sending. I am staring at a NestJS backend with 12 services and I have no idea which request is failing or what payload it is carrying when it does. My terminal is a wall of Morgan output that looks like this:

POST /api/orders 200 43ms
GET /api/users/17 200 12ms
POST /api/orders 500 8ms
GET /api/notifications 200 29ms
Enter fullscreen mode Exit fullscreen mode

Something sent a POST /api/orders and got a 500. That is all I know. What was in the body? What did the response say? Which user triggered it? Morgan has no idea. Morgan does not care. Morgan logged a status code and went home.

I spent 45 minutes adding console.log(req.body) statements across three files, redeploying, asking the client to reproduce the issue, and squinting at my terminal. I found the bug — a malformed recipientEmail field — in the most embarrassing way possible.

That night I started building reqlog.


What is wrong with Morgan

Nothing is wrong with Morgan. That is almost the problem.

Morgan was built in 2014 for a world where request logging meant writing a line to stdout so your sysadmin could grep it later. It is a solved problem, executed cleanly, and then frozen in time. The last meaningful commit was years ago. It does exactly what it was designed to do.

But we do not debug like it is 2014 anymore. We have live dashboards for everything — database queries, frontend performance, infrastructure metrics. Our request logging is somehow still a stream of text in a terminal that disappears when you close the tab.

The gap between what we have and what we need has always been there. I just finally got annoyed enough to fill it.


What reqlog actually is

reqlog is a drop-in middleware for NestJS, Express and Fastify that does two things Morgan does not.

It captures everything. Not just the method, path and status. The full request body. The full response body. Headers. Duration. All of it, structured, stored in memory.

It gives you a live local dashboard. Open localhost:9000 while your server is running and you get a real-time feed of every request — with a payload diff viewer, a replay button, and slow request highlighting. It is Postman for your running server, without the Postman.


Setup takes 90 seconds

NestJS:

import { ReqlogModule } from 'reqlog-nestjs';

@Module({
  imports: [
    ReqlogModule.forRoot({
      port: 9000,
      maxRequests: 200,
    }),
  ],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

Express:

import { reqlog } from 'reqlog-express';

app.use(reqlog());
Enter fullscreen mode Exit fullscreen mode

Fastify:

import reqlogPlugin from 'reqlog-fastify';

await fastify.register(reqlogPlugin);
Enter fullscreen mode Exit fullscreen mode

Go (net/http, Gin, Chi):

import reqlog "github.com/reqlog/reqlog-go"

rl := reqlog.New(reqlog.Options{Port: 9000})
rl.Start()
defer rl.Stop()

http.ListenAndServe(":3000", rl.Middleware()(mux))
Enter fullscreen mode Exit fullscreen mode

reqlog only runs when NODE_ENV is not production. There is a hard guard. It will never ship to prod by accident.


The features that changed how I debug

The payload diff

When you hit the same endpoint twice, reqlog shows you exactly what changed between the two requests field by field in a color coded diff view. Old value in red. New value in green. Unchanged fields in gray.

I was working on a checkout flow last month where a field was being sent correctly on the first attempt and then silently dropped on retry. With Morgan I would have needed to manually log both request bodies and diff them myself. With reqlog I just looked at the diff panel and saw it immediately.

The replay button

Every request in the feed has a replay button. One click resends the exact request — same headers, same body, same everything — against your local server.

This sounds minor until you are trying to reproduce a bug that requires a specific sequence of requests. Now you just hit replay.

Slow request highlighting

Any request that takes longer than your configured threshold gets highlighted in amber in the feed. Last week I discovered a database query that was taking 340ms on every call. It had been there for months. reqlog caught it because it was amber in my feed every single time.

Zero persistence

reqlog stores nothing to disk. No SQLite file, no log files. When your server restarts the request history is gone. This makes reqlog safe with any data including personally identifiable information or auth tokens.


The Morgan migration

// Before
import morgan from 'morgan';
app.use(morgan('dev'));

// After
import { reqlog } from 'reqlog-express';
app.use(reqlog());
Enter fullscreen mode Exit fullscreen mode

Remove morgan from your dependencies:

npm uninstall morgan @types/morgan
npm install reqlog-express
Enter fullscreen mode Exit fullscreen mode

That is the whole migration.


Try it

npm install reqlog-nestjs
# or
npm install reqlog-express
# or
go get github.com/reqlog/reqlog-go
Enter fullscreen mode Exit fullscreen mode

GitHub: github.com/FirasLatrech/reqlog

If you have ever added a console.log at 11pm in frustration this one is for you.


reqlog is MIT licensed and free forever. If it saves you a debugging session a GitHub star goes a long way.


That is the complete post. Copy everything from the title down, paste into DEV.to, add the tags #node #nestjs #webdev #opensource #go and hit publish.

Come back and send me the link when it is live. 👀

Top comments (0)