I built ReqScope — a local API request tracer for Express, because logs weren't enough

typescript dev.to

A few weeks ago I was debugging a POST /login endpoint that was occasionally taking 800ms instead of the usual 120ms. The logs told me nothing useful:

[INFO] POST /login 200 837ms
Enter fullscreen mode Exit fullscreen mode

Cool. Thanks. Which part was slow?

I added some console.time() calls. Found the slow step. Removed them. Two days later, a different endpoint had the same problem. I added the same console.time() calls again. Removed them again.

At some point I asked myself why I was doing this manually every time, and why every "real" solution (Datadog, New Relic, OpenTelemetry collectors) felt completely overkill for a local dev environment.

So I built ReqScope — a small local API request tracer for Node.js and Express.

What it actually does

You wrap the parts of your handler you care about with traceStep:

import express from "express";
import { reqscope, traceStep } from "@abdiev003/reqscope";

const app = express();
app.use(express.json());
app.use(reqscope());

app.post("/login", async (req, res, next) => {
  try {
    const user = await traceStep("findUserByEmail", () =>
      db.user.findUnique({ where: { email: req.body.email } })
    );

    const token = await traceStep("createAccessToken", () =>
      createToken(user)
    );

    res.json({ user, token });
  } catch (error) {
    next(error);
  }
});
Enter fullscreen mode Exit fullscreen mode

And then ReqScope shows you what actually happened inside the request:

POST /login 182ms

  findUserByEmail      140ms
  createAccessToken     40ms
Enter fullscreen mode Exit fullscreen mode

When something is slow or fails, you can immediately see which step was slow or failed — not just the total request duration.

What I wanted out of it

I had a short list of things that bother me when debugging APIs locally:

  • I want to see request and response bodies without piping req.body to console.log everywhere.
  • I want to see request and response headers when CORS or auth is acting weird.
  • I want to reproduce a failing request as curl so I can share it with a teammate.
  • I want sensitive fields (password, token, authorization) redacted by default so I can paste output into Slack without panicking.
  • I do not want to install an agent, run a Docker container, or sign up for anything. So that's what ReqScope does. Everything stays in memory. The data lives in your process. There is no external service.

What about production?

It's off in production by default (enabled: process.env.NODE_ENV !== "production").

ReqScope is a local development tool, not an APM. If you need distributed tracing across services, OpenTelemetry is the right answer. If you need to monitor production at scale, Datadog or Sentry is the right answer. ReqScope is for the moment when you're sitting at your laptop, something is slow, and you want to know why — without leaving your terminal.

What's there today

  • Express middleware
  • Manual step tracing with traceStep
  • Slow request and slow step thresholds (configurable)
  • Request/response body and header previews
  • Sensitive field masking
  • cURL reproduction of any captured request
  • A local dashboard (currently runs from the repo during MVP)
  • Endpoint summaries ## What's not there yet

I'm being honest about the MVP status:

  • No NestJS / Fastify / Koa adapter yet
  • No automatic ORM tracing (Prisma, TypeORM) — you wrap calls manually for now
  • No persistent storage (traces live in memory, capped at 100 by default)
  • Dashboard is not yet shipped via npm — you clone the repo to run it These are the next things I want to tackle, roughly in that order.

Try it

npm i @abdiev003/reqscope
Enter fullscreen mode Exit fullscreen mode

Thanks for reading.

Source: dev.to

arrow_back Back to Tutorials