ChatGPT Designs a Health Check Tool in Node.Js to Run on Free VPS Instance


Background: Vultr has rolled out a free VPS. It is 512MB and 1 CPU Core. One idea is to run a health check tool for all your websites, and send notification in case of errors. This is to replace the CloudFlare Health-checks which are only available for Pro users ($25 per month or $20 if paid annually).

I then ask ChatGPT this: Implement a Node.Js command line tool to perform health checks to predefined URLs in config.json. Allow configuration of setting interval e.g. 60 seconds and expecting HTTP response code, content match etc.

Health Check Tool in Node.js

Within seconds, the ChatGPT gives the following code – which saves me a lot of time.

Sure, here’s an example implementation of a Node.js command line tool that performs health checks on predefined URLs in a config.json file:

First, create a config.json file with the following structure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
  "urls": [
    {
      "name": "Example Website",
      "url": "https://example.com",
      "interval": 60,
      "expectedStatusCode": 200,
      "expectedContent": "Example Domain"
    },
    {
      "name": "Google",
      "url": "https://www.google.com",
      "interval": 30,
      "expectedStatusCode": 200,
      "expectedContent": "Google"
    }
  ]
}
{
  "urls": [
    {
      "name": "Example Website",
      "url": "https://example.com",
      "interval": 60,
      "expectedStatusCode": 200,
      "expectedContent": "Example Domain"
    },
    {
      "name": "Google",
      "url": "https://www.google.com",
      "interval": 30,
      "expectedStatusCode": 200,
      "expectedContent": "Google"
    }
  ]
}

Here, we have an array of URLs with their respective properties. The name property is a string identifier for the URL, the url property is the URL itself, interval is the time (in seconds) between health checks, expectedStatusCode is the expected HTTP response code, and expectedContent is the expected content in the response body.

Next, we’ll create a Node.js script that reads the config.json file and performs health checks on each URL:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const axios = require('axios');
const config = require('./config.json');
 
// Loop through each URL in the config file
config.urls.forEach(urlConfig => {
  setInterval(() => {
    // Make a GET request to the URL
    axios.get(urlConfig.url)
      .then(response => {
        // Check if the status code and response body match the expected values
        if (response.status !== urlConfig.expectedStatusCode) {
          console.error(`${urlConfig.name} returned unexpected status code: ${response.status}`);
        }
        if (!response.data.includes(urlConfig.expectedContent)) {
          console.error(`${urlConfig.name} returned unexpected content`);
        }
      })
      .catch(error => {
        console.error(`${urlConfig.name} could not be reached: ${error}`);
      });
  }, urlConfig.interval * 1000); // Convert interval from seconds to milliseconds
});
const axios = require('axios');
const config = require('./config.json');

// Loop through each URL in the config file
config.urls.forEach(urlConfig => {
  setInterval(() => {
    // Make a GET request to the URL
    axios.get(urlConfig.url)
      .then(response => {
        // Check if the status code and response body match the expected values
        if (response.status !== urlConfig.expectedStatusCode) {
          console.error(`${urlConfig.name} returned unexpected status code: ${response.status}`);
        }
        if (!response.data.includes(urlConfig.expectedContent)) {
          console.error(`${urlConfig.name} returned unexpected content`);
        }
      })
      .catch(error => {
        console.error(`${urlConfig.name} could not be reached: ${error}`);
      });
  }, urlConfig.interval * 1000); // Convert interval from seconds to milliseconds
});

Here, we’re using the axios library to make HTTP requests to each URL. We’re also using setInterval to perform health checks on each URL at the specified interval. In each interval, we’re making a GET request to the URL and checking if the status code and response body match the expected values. If they don’t, we log an error message to the console.

To run this script, save it as healthcheck.js and run node healthcheck.js in your terminal. The script will run indefinitely, performing health checks on each URL at the specified interval. You can modify the config.json file to add, remove, or modify URLs and their properties as needed.

Adding Email Notification

Two days later, I decide to add the email notification when health checks fail – so I ask: Can you add that when health check failed, send a notification to configured email?

Sure! To send an email notification when a health check fails, we can use the nodemailer library. Here’s an updated version of the script that sends an email notification when a health check fails:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
const axios = require('axios');
const nodemailer = require('nodemailer');
const config = require('./config.json');
 
// Create a nodemailer transport
const transporter = nodemailer.createTransport({
  service: 'Gmail',
  auth: {
    user: '[email protected]',
    pass: 'your_password'
  }
});
 
// Loop through each URL in the config file
config.urls.forEach(urlConfig => {
  setInterval(() => {
    // Make a GET request to the URL
    axios.get(urlConfig.url)
      .then(response => {
        // Check if the status code and response body match the expected values
        if (response.status !== urlConfig.expectedStatusCode) {
          const errorMessage = `${urlConfig.name} returned unexpected status code: ${response.status}`;
          console.error(errorMessage);
          sendEmail(urlConfig.name, errorMessage);
        }
        if (!response.data.includes(urlConfig.expectedContent)) {
          const errorMessage = `${urlConfig.name} returned unexpected content`;
          console.error(errorMessage);
          sendEmail(urlConfig.name, errorMessage);
        }
      })
      .catch(error => {
        const errorMessage = `${urlConfig.name} could not be reached: ${error}`;
        console.error(errorMessage);
        sendEmail(urlConfig.name, errorMessage);
      });
  }, urlConfig.interval * 1000); // Convert interval from seconds to milliseconds
});
 
// Function to send email notification
function sendEmail(urlName, errorMessage) {
  const mailOptions = {
    from: '[email protected]',
    to: '[email protected]',
    subject: `Health check failed for ${urlName}`,
    text: errorMessage
  };
  
  transporter.sendMail(mailOptions, (error, info) => {
    if (error) {
      console.error(`Failed to send email notification: ${error}`);
    } else {
      console.log(`Email notification sent for ${urlName}`);
    }
  });
}
const axios = require('axios');
const nodemailer = require('nodemailer');
const config = require('./config.json');

// Create a nodemailer transport
const transporter = nodemailer.createTransport({
  service: 'Gmail',
  auth: {
    user: '[email protected]',
    pass: 'your_password'
  }
});

// Loop through each URL in the config file
config.urls.forEach(urlConfig => {
  setInterval(() => {
    // Make a GET request to the URL
    axios.get(urlConfig.url)
      .then(response => {
        // Check if the status code and response body match the expected values
        if (response.status !== urlConfig.expectedStatusCode) {
          const errorMessage = `${urlConfig.name} returned unexpected status code: ${response.status}`;
          console.error(errorMessage);
          sendEmail(urlConfig.name, errorMessage);
        }
        if (!response.data.includes(urlConfig.expectedContent)) {
          const errorMessage = `${urlConfig.name} returned unexpected content`;
          console.error(errorMessage);
          sendEmail(urlConfig.name, errorMessage);
        }
      })
      .catch(error => {
        const errorMessage = `${urlConfig.name} could not be reached: ${error}`;
        console.error(errorMessage);
        sendEmail(urlConfig.name, errorMessage);
      });
  }, urlConfig.interval * 1000); // Convert interval from seconds to milliseconds
});

// Function to send email notification
function sendEmail(urlName, errorMessage) {
  const mailOptions = {
    from: '[email protected]',
    to: '[email protected]',
    subject: `Health check failed for ${urlName}`,
    text: errorMessage
  };
  
  transporter.sendMail(mailOptions, (error, info) => {
    if (error) {
      console.error(`Failed to send email notification: ${error}`);
    } else {
      console.log(`Email notification sent for ${urlName}`);
    }
  });
}

Here, we’ve added a function sendEmail that takes the name of the URL and the error message as arguments. The function creates a mailOptions object with the sender, recipient, subject, and body of the email, and uses the transporter to send the email. If the email fails to send, we log an error message to the console. Otherwise, we log a success message.

To use this script, you’ll need to replace the [email protected] and your_password placeholders with your own email and password, and replace the [email protected] placeholder with the email address where you want to receive notifications.

Save the updated script as healthcheck.js and run node healthcheck.js in your terminal. The script will run indefinitely, performing health checks on each URL at the specified interval and sending email notifications when a health check fails.

Conclusion of using ChatGPT to Design/Implement a Health-check tool

In this post, we have shown you that the ChatGPT-4 (OpenAI) is very capable of designing and implementation based on requirements, especially it can present you the code within seconds – which is amazing. I could’ve spent hours on this because the begining is often the hardest part – no knowing where to start.

ChatGPT also remembers the session content, even after two days, it knows the context and can improve or modify according to your needs e.g. you can provide the feedbacks to ChatGPT who will tailor the solution to your needs.

The email notification is sent in a blocking way meaning the error happens, and it will send email immediately, and thus I have refactored and moved it to another “thread” although Javascript (Node.Js) is single-threaded. The notifications are pushed to a Queue, and items will be picked up separately one by one, e.g. to send a email, or just print the notification to the console.

I have also added the max notification limit per period so that you don’t get too many notifications within short amount of time.

Overall, the ChatGPT is a good tool to provide the boilerplate code from the scratch (A good start)!

Now, it is fully open source: https://github.com/DoctorLai/health-checks

ChatGPT Use Cases

ChatGPT - AGI (Artificial General Intelligence)

ChatGPT Fails to

–EOF (The Ultimate Computing & Technology Blog) —

GD Star Rating
loading...
1334 words
Last Post: Teaching Kids Programming - Split With Minimum Sum (Sort the Digits, Greedy)
Next Post: Can the Kids Beat This Simple Chinese Chess AI?

The Permanent URL is: ChatGPT Designs a Health Check Tool in Node.Js to Run on Free VPS Instance

Leave a Reply