DEV Community

Cover image for Monitoring using Proxy Design Pattern with Node.js
Kneonix
Kneonix

Posted on

9 1 1 1 1

Monitoring using Proxy Design Pattern with Node.js

Introduction

why we need monitoring?
Imagine you have multiple machines (servers) running simultaneously, each located in a different place. To ensure they operate smoothly without issues, we need access to their logs and performance data.

This is where a good monitoring system comes handy.

What Will We Cover?
In this article, we’ll see how to use the Proxy pattern in Node.js to enhance monitoring and performance tracking.

What is Proxy design pattern?

Proxy categories as a structural and object-relational design pattern.
You might known Proxies to move a method calls over the internet.

The Proxy provides a surrogate or placeholder for another object to control access to it.

For example, imagine you have an object A on a server located across the world and you want to access to that. Instead of interacting with A directly, you create another object in your system call it B. Object B then takes responsibility for managing and controlling access to A for you.

Image description

Why Use Proxy for Monitoring?

The Proxy design pattern is great choice for monitoring because

  • Its lets you perform actions before and after send the request, that make your code decouple and maintainable.

  • Its allows you to logging every request that send to the object service and record them too.

  • By placing monitoring logic within the proxy, you can centralize monitoring functionality. This avoids scattering monitoring code throughout the client or the service object, making the monitoring implementation easier to manage and maintain.

Implementation

  • setup our project

First, you need to install Node.js and npm on your device.

After that, create a directory for your service server and name it service.

Inside the directory, run the following command to initial NPM and install the Express package:

npm init -y
npm install express
Enter fullscreen mode Exit fullscreen mode
  • create service

Next, create file inside the folder and name it service.js. In this file create simple express app with POST /monitoring route.

In the same file, implement class for your data you want monitor. we'll call it ObjectService and create object from it named service.

The ObjectService class should store data related to the machine and include a monitoring method that returns its data.

Our /monitoring route will expect data in req.body, which is in our example is the city we want to monitor. Using this value, the route will call .monitoring(data) and return the result to the client.

const express = require('express');
const app = express();
app.use(express.json());

class ObjectService {
  location = 'Madrid';
  state = 'state one'
  monitoring(data) {
    console.log(`Real Service monitoring data: ${data}`);
    return `the location is ${this.location},
    the state is ${this.state}`
  }
}


const service = new ObjectService();

app.post('/monitoring', (req, res) => {
  const { data } = req.body;
  const result = service.monitoring(data);
  res.send({ result });
});

app.listen(3000, () => {
  console.log('Service running on port 3000');
});
Enter fullscreen mode Exit fullscreen mode

At the end to run our service we use this command:

node service.js
Enter fullscreen mode Exit fullscreen mode
  • create proxy

Navigate to the main directory and then create folder named monitoring. Inside that create a file named monitoring.js

Javascript has built-in proxy object. in order to use that, we first create class with a property to carrying our proxy instance. We also define a monitoring method to call the proxy’s getter method and log the result.

To create proxy we use new proxy(target, handler)

  1. Target (The Object to Proxy): This is the object that the proxy will wrap. It can be an object, array, or even another proxy.

  2. Handler (The Object with Trap Methods): This is an object that defines traps (interceptor methods) to customize operations on the target.

    Some common traps include:

    • get – Intercepts property access
    • set – Intercepts property assignments
    • apply – Intercepts function calls
    • construct – Intercepts object instantiation
    • deleteProperty – Intercepts property deletion
class MachineMonitor {
    proxy;
    constructor(location) {
        this.proxy = new Proxy({ location }, proxyHandler);
    }
    async monitoring() {
        console.log(await this.proxy.monitoring);
    }
}
const machineMonitor = new MachineMonitor("Madrid");
Enter fullscreen mode Exit fullscreen mode

Now we should create the proxyHandler object which has getter method inside that.

The get method takes two argument:

  1. Target Object: The object passed to the proxy.
  2. Property: The property being accessed. For example, if we call this.proxy.x, the property is "x".

Finally after we add the proxyHandler object to our code it will look like this:

const proxyHandler = {
    async get(target, property) {
        // check the getter property
        if (property === "monitoring") {
            // call the service
            const response = await fetch("http://localhost:5000/monitoring", {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                },
                // get location from the target object
                body: JSON.stringify({ data: target.location }),
            });
            const res = await response.json();
            return res;
        }
    },
};

class MachineMonitor {
    proxy;
    constructor(location) {
        this.proxy = new Proxy({ location }, proxyHandler);
    }
    async monitoring() {
        console.log(await this.proxy.monitoring);
    }
}

const machineMonitor = new MachineMonitor("Madrid");
await machineMonitor.monitoring();
Enter fullscreen mode Exit fullscreen mode

Now open up a new terminal then navigate to monitoring folder and run this command

node monitoring.js
Enter fullscreen mode Exit fullscreen mode

Then you will see the request send to our service and in our monitoring terminal we see

{ result: 'the location is Madrid,\n    the state is state one' }
Enter fullscreen mode Exit fullscreen mode

Also in our other terminal which we run the express service, we can see this:

Service running on port 3000
Real Service monitoring data: Madrid
Enter fullscreen mode Exit fullscreen mode

Use Cases and Trade-offs

One of the main use cases of the Proxy pattern with monitoring is when you decide to create a distributed system with multiple servers.

Some trade-offs are:

  • Performance Overhead
  • Complexity
  • Limited Control Over the Target
  • Decoupled Code
  • Scalability Concerns

Conclusion

In this article, we've explored how the Proxy design pattern can be used in Node.js for monitoring. By acting as an intermediary between clients and the actual service, the Proxy pattern provides a clean way to manage monitoring tasks, ensuring that your code remains decoupled and modular.

While there are trade-offs, such as potential performance overhead and increased complexity, the benefits of easier management and centralized control make this approach a valuable tool in this type of scenario. Ultimately, choosing to implement the Proxy pattern depends on your specific requirements and the scale of your application.

Quadratic AI

Quadratic AI – The Spreadsheet with AI, Code, and Connections

  • AI-Powered Insights: Ask questions in plain English and get instant visualizations
  • Multi-Language Support: Seamlessly switch between Python, SQL, and JavaScript in one workspace
  • Zero Setup Required: Connect to databases or drag-and-drop files straight from your browser
  • Live Collaboration: Work together in real-time, no matter where your team is located
  • Beyond Formulas: Tackle complex analysis that traditional spreadsheets can't handle

Get started for free.

Watch The Demo 📊✨

Top comments (14)

Collapse
 
sg_milad profile image
milad

🔥

Collapse
 
smhkneonix profile image
Kneonix

🫡

Collapse
 
_mohamadmohamadi profile image
Mohamad

Amazing👏

Collapse
 
smhkneonix profile image
Kneonix

I'm glad it was helpful❤️

Collapse
 
mohammad_taslimi_ea912903 profile image
Mohammad Taslimi

😍

Collapse
 
black_m_5efe0ba524382db41 profile image
Black M

Can you share your contact for DM?

Collapse
 
smhkneonix profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
Kneonix • Edited

I just added in my profile. you can check that out

Collapse
 
amir_taslimi_45ee82ef7a47 profile image
Amir Taslimi

The Best.

Collapse
 
smhkneonix profile image
Kneonix

Appreciate that

Collapse
 
rahjerdy profile image
Mohammad

Wowwwww❤️‍🔥❤️‍🔥❤️‍🔥

Collapse
 
smhkneonix profile image
Kneonix

I'm glad you like it❤️

Collapse
 
facelessfk profile image
fardin

Wow, so helpful for me.

Collapse
 
smhkneonix profile image
Kneonix

Thank you, glad you like it

Collapse
 
mohamad_hosein_6b8bc9cd74 profile image
Mohamad Hosein

Perfect

Some comments may only be visible to logged-in visitors. Sign in to view all comments.

Image of DataStax

AI Agents Made Easy with Langflow

Connect models, vector stores, memory and other AI building blocks with the click of a button to build and deploy AI-powered agents.

Get started for free

👋 Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay