Skip to content
Santekno.com | Tech Tutorials and Trends
EN
📖 0%
26 Oct 2025 · 5 min read ·Article 118 / 125
Go

118 Resolver Middleware for Logging and Monitoring

IH
Ihsan Arif
Writer at Santekno · Backend Engineer

118 Resolver Middleware for Logging and Monitoring

Middleware has become the backbone of the modern web ecosystem, especially in applications built on a microservices architecture or a complex monolith. One powerful approach in the world of Node.js API development is the use of a resolver middleware for managing logging and monitoring. In this article, I’ll take a deep dive into the implementation of resolver middleware number 118, a pattern I’ve found to be very effective for building a logging and monitoring pipeline. We’ll also walk through an example implementation, a simulation, and a performance analysis based on real-world experience.


What Is a Resolver Middleware?

A resolver middleware is a function, or a series of functions, that runs a particular process (such as logging, authentication, monitoring, and so on) before or after the main request is handled by the server. This concept is very commonly used in frameworks like Express.js and Koa, and even in GraphQL middleware.

The advantage of a resolver middleware is how easily it lets you manage cross-cutting concerns such as logging and monitoring without polluting your core business logic. You simply attach the resolver to a specific route or endpoint, and all the logging-related logic runs automatically.


Logging and Monitoring: Why Do They Matter?

Before we dive into the middleware itself, let’s remind ourselves: why do we care about logging and monitoring?

  • Logging: Helps with debugging, auditing, and tracing the request/response flow.
  • Monitoring: Detects problems early, provides performance insights, and enables precise scaling efforts.

In real-world scenarios, good logging can reduce downtime, and many “small incidents” can be diagnosed before they escalate into a major crisis.


Resolver Middleware #118: A Practical Pattern

Once I reached the hundreds in terms of resolver count, I noticed a specific pattern in resolver #118 that I’ve used across several Angular backend and Node.js projects. This pattern:

  • Separates request/response logging in detail.
  • Measures the processing time of each request (performance monitoring).
  • Is flexible: it can plug into a variety of stacks (Express, Koa, Fastify, and so on).
  • Supports optional telemetry pushes to external services like Datadog or Grafana.

Let’s take a look at the flow diagram for this logging middleware.

MERMAID
flowchart LR
    A[Incoming Request] --> B[Middleware #118]
    B --> C{Logging Mode?}
    C --Yes--> D[Log Request]
    C --No--> E[Skip Logging]
    D --> F[Start Timer]
    E --> F
    F --> G[Process Handler]
    G --> H[Stop Timer & Log Response]
    H --> I[Push Metric to Monitoring]
    I --> J[Send Response]

Example Implementation in Express.js

Here is an example of resolver middleware #118 for logging and monitoring. The core code is simple yet powerful.

javascript
 1const fs = require('fs');
 2const path = require('path');
 3
 4function middleware118(options = {}) {
 5  return function (req, res, next) {
 6    const {
 7      logRequest = true,
 8      logResponse = true,
 9      monitorTime = true,
10      telemetryPush = false
11    } = options;
12    const startTime = Date.now();
13
14    if (logRequest) {
15      console.log(`[REQ] ${req.method} ${req.url} @ ${new Date().toISOString()}`);
16    }
17
18    // Simulate pushing to external monitoring
19    function pushTelemetry(durationMs) {
20      if (telemetryPush) {
21        // Example: push to a file as a dummy
22        fs.appendFileSync(
23          path.join(__dirname, "metrics.log"),
24          `endpoint=${req.url},duration=${durationMs}ms\n`
25        );
26      }
27    }
28
29    // Listen for the response to finish
30    res.on('finish', () => {
31      const duration = Date.now() - startTime;
32      if (logResponse) {
33        console.log(
34          `[RES] ${req.method} ${req.url} -> ${res.statusCode} in ${duration}ms`
35        );
36      }
37
38      // Monitoring
39      if (monitorTime) {
40        pushTelemetry(duration);
41      }
42    });
43
44    next();
45  };
46}
47
48// Usage in Express
49const express = require('express');
50const app = express();
51
52app.use(middleware118({ logRequest: true, telemetryPush: true }));
53
54app.get('/hello', (req, res) => {
55  setTimeout(() => {
56    res.json({ message: "World!", time: Date.now() });
57  }, Math.floor(Math.random() * 150));
58});
59
60app.listen(3000, () => {
61  console.log('Server running at http://localhost:3000');
62});

Simulation and Analysis

Let’s run a simulation of 3 requests to the /hello endpoint.

RequestResponse Time (ms)StatusLog RequestLog ResponseTelemetry Push
#152200YesYesYes
#2101200YesYesYes
#337200YesYesYes

For each request, the following output will appear in the console:

text
1[REQ] GET /hello @ 2024-06-15T08:00:00.000Z
2[RES] GET /hello -> 200 in 52ms
3[REQ] GET /hello @ 2024-06-15T08:00:01.000Z
4[RES] GET /hello -> 200 in 101ms
5[REQ] GET /hello @ 2024-06-15T08:00:02.000Z
6[RES] GET /hello -> 200 in 37ms

And the metrics.log file will contain:

text
1endpoint=/hello,duration=52ms
2endpoint=/hello,duration=101ms
3endpoint=/hello,duration=37ms

Middleware #118 Feature Table

FeatureDescriptionCustomizable
Log RequestRecords the method, endpoint, and request arrival timeYes
Log ResponseLogs the status and response timeYes
Performance TimerMeasures the processing time of each endpointYes
Telemetry PushSaves metrics to a file/log/monitoring serviceYes
Plug & PlayWorks with Express, Koa, Fastify, and GraphQLYes

Conclusion

In my opinion, resolver middleware #118 is one of those patterns that is essential to have in any modern Node.js project, especially as the need for observability and auditing continues to grow. With this pattern, implementing logging and monitoring becomes cleaner, more flexible, and more scalable without adding complexity to your core API.

Here are a few tips from using it in real-world projects:

  • Make sure the middleware is loaded before your main routes for comprehensive logging.
  • Don’t forget to disable telemetry pushes in the development environment.
  • Extend the middleware with a traceID for distributed tracing (if you need it).

Don’t hesitate to fork and modify this middleware to suit your team’s and project’s needs. Happy experimenting, and may your application’s observability level up another notch!


Related Articles

💬 Comments