Interactive Server Monitoring Dashboard in C++

Interactive Server Monitoring Dashboard in C++: This project is a real-time monitoring flow in C++. It combines threading, randomness, formatted output, and concurrency management to track and report the status of multiple servers. Explore the details of each component and how they work together.


RandomGenerator Class: Adding Realism

The RandomGenerator class simulates randomness in server load and availability.

  • Purpose: Mimics unpredictable server behavior, making the system dynamic.
  • Implementation: Uses <random> for generating floating-point numbers between 0.0 and 1.0.
  • A Mersenne Twister engine (std::mt19937) ensures high-quality random numbers.
  • Usage: This class is used to assign random values to the server’s load and availability status.

Key Method:

double generate();  // Returns a random value between 0.0 and 1.0

Example:
When a server updates its load, it calls randomGen.generate() to get a new value, simulating fluctuations in workload.


You can get the code of Interactive Server Monitoring Dashboard in C++ from my GitHub repository

You can also get the code for checking Server Health in C++ by downloading the Zip File

Server Class: Representing Individual Servers

Each server is modeled as an instance of the Server class.

Attributes:

  • Name: Unique identifier (e.g., “Server A”).
  • Load: A floating-point number representing server usage (0.0 to 1.0).
  • Availability: A boolean indicating whether the server is operational.

Methods:

  1. updateStatus()
    • Updates the load using the random generator.
    • Assigns availability with an 80% chance of being “online” (randomGen.generate() > 0.2).
  2. Getters:
    • getName(): Returns the server’s name.
    • getLoad(): Returns the server’s current load.
    • isAvailable(): Returns whether the server is online.

DashboardController Class: Managing Output and Alerts

The DashboardController is responsible for displaying server information and generating alerts when needed.

Key Features:

  1. Formatted Output
    The updateDisplay() method organizes server details into a neat, readable format. It uses <iomanip> to ensure uniform spacing and load values with two decimal places. Example Display:
   | Server A   | Load: 0.72 | Available: YES |
  1. Alerts System
    The showAlert() method highlights critical conditions:
  • Critical Load: Load > 90%.
  • High Load: Load > 70%.
  • Unavailable: Server is offline. Alerts are color-coded using ANSI escape codes for terminal emphasis:
  • Red (\033[1;31m) for critical issues.
  • Bold formatting for better visibility.
  1. Thread Safety
    The alertMutex ensures that alerts are displayed correctly even when multiple threads attempt to output messages simultaneously.

ServerMonitor Class: The Monitoring Engine

This is the heart of the application, responsible for:

  1. Updating Server Statuses
    Continuously refreshes load and availability for all servers.
  2. Alert Generation
    Checks each server’s status and raises appropriate alerts.
  3. Concurrent Execution
    Runs monitoring operations in a separate thread to allow real-time updates without blocking the main program.

Key Methods:

  1. startMonitoring()
    • Activates the monitoring process in a new thread.
    • Uses std::atomic<bool> (running) to control the thread’s lifecycle.
  2. monitorLoop()
    • Periodically updates each server.
    • Calls checkForAlerts() to identify potential issues.
    • Displays server statuses using DashboardController.
  3. checkForAlerts()
    • Identifies critical and warning conditions based on load and availability.
    • Calls showAlert() to notify users.
  4. Thread Safety
    • Uses a mutex (outputMutex) to synchronize updates and alerts, preventing garbled output from concurrent threads.

Monitoring Example:

monitor.startMonitoring();  // Begins monitoring in a separate thread

How the System Works Together

  1. Initialization
    The main function creates a list of servers and initializes the DashboardController and ServerMonitor.
  2. Monitoring
    The ServerMonitor begins monitoring in a new thread.
    • Every 5 seconds, server statuses are updated, alerts are raised, and the dashboard is refreshed.
  3. Alerts
    Alerts are raised dynamically based on server load and availability.
  4. Continuous Operation
    The system runs indefinitely (std::this_thread::sleep_for(std::chrono::hours(1))) or until terminated.

Output Walkthrough

Example Console Output:

Interactive Server Monitoring Dashboard in C++
  1. Status Update: Displays the load and availability for each server.
  2. Critical Alert: Server B’s load exceeds 90%.
  3. Error Alert: Server C is unavailable.

Concurrency Considerations

  • Why Threads?
    The monitoring loop runs in its own thread, allowing the main application to remain responsive.
  • Thread-Safe Output
    Using mutexes ensures that no two threads write to the console simultaneously, preventing mixed or corrupted output.
  • Stopping the Monitor
    The running flag can be set to false to safely stop the monitoring loop.

Real-World Use Cases

  1. IT Infrastructure: Monitor server clusters for performance and availability.
  2. Simulations: Test server behavior under varying conditions.
  3. Prototyping: Serve as a basis for developing full-fledged server monitoring solutions.

Potential Enhancements

  • Database Logging: Store server data and alerts for analysis.
  • Real Server Integration: Replace simulated data with real metrics via APIs.
  • Web Dashboard: Create a web-based GUI using a framework like Flask or React.
  • Customizable Alerts: Allow users to define thresholds for warnings and critical alerts.

Conclusion of code for checking Server Health in C++

This server monitoring project demonstrates the power Real-Time Monitoring Flow in C++. It combines threading, formatted output, randomness, and concurrency handling into a cohesive system. With some additional enhancements, it could evolve into a sophisticated server management tool suitable for production environments.

Source Code of Interactive Server Monitoring Dashboard in C++

#include <iostream>
#include <vector>
#include <string>
#include <random>
#include <thread>
#include <chrono>
#include <atomic>
#include <mutex>
#include <iomanip> // For output formatting

// Random number generator utility
class RandomGenerator {
private:
    std::random_device rd;
    std::mt19937 gen;
    std::uniform_real_distribution<> dis;

public:
    RandomGenerator() : gen(rd()), dis(0.0, 1.0) {}

    double generate() {
        return dis(gen);
    }
};

RandomGenerator randomGen; // Global random generator

// Server Class
class Server {
private:
    std::string name;
    double load;
    bool available;

public:
    Server(const std::string& name)
        : name(name), load(randomGen.generate()), available(true) {}

    const std::string& getName() const { return name; }
    double getLoad() const { return load; }
    bool isAvailable() const { return available; }

    void updateStatus() {
        load = randomGen.generate();             // Randomly update load
        available = randomGen.generate() > 0.2; // 80% chance to be available
    }
};

// DashboardController Class
class DashboardController {
public:
    void updateDisplay(const Server& server) {
        std::cout << std::fixed << std::setprecision(2); // Format load to 2 decimal places
        std::cout << "| " << std::setw(10) << server.getName()
            << " | Load: " << std::setw(5) << server.getLoad()
            << " | Available: " << (server.isAvailable() ? "YES" : "NO")
            << " |" << std::endl;
    }

    void showAlert(const std::string& message) {
        std::lock_guard<std::mutex> lock(alertMutex); // Thread-safe alerts
        std::cerr << "\033[1;31mALERT: " << message << "\033[0m" << std::endl; // Red color for alerts
    }

private:
    std::mutex alertMutex; // To synchronize alert messages
};

// ServerMonitor Class
class ServerMonitor {
private:
    std::vector<Server>& servers;
    DashboardController& controller;
    std::atomic<bool> running;
    std::mutex outputMutex;

    void checkForAlerts(Server& server) {
        if (server.getLoad() > 0.9) {
            controller.showAlert("CRITICAL: " + server.getName() + " load exceeds 90%!");
        }
        else if (server.getLoad() > 0.7) {
            controller.showAlert("WARNING: " + server.getName() + " load exceeds 70%.");
        }

        if (!server.isAvailable()) {
            controller.showAlert("ERROR: " + server.getName() + " is unavailable!");
        }
    }

    void monitorLoop() {
        while (running.load()) {
            std::cout << "\n\033[1;34m=== Server Status Update ===\033[0m" << std::endl; // Blue header
            std::cout << "| " << std::setw(10) << "Server"
                << " | " << std::setw(10) << "Details" << " |" << std::endl;
            std::cout << "-------------------------------------" << std::endl;

            for (auto& server : servers) {
                server.updateStatus();
                {
                    std::lock_guard<std::mutex> lock(outputMutex); // Ensure thread-safe output
                    checkForAlerts(server);
                    controller.updateDisplay(server);
                }
            }
            std::this_thread::sleep_for(std::chrono::seconds(5));
        }
    }

public:
    ServerMonitor(std::vector<Server>& servers, DashboardController& controller)
        : servers(servers), controller(controller), running(false) {}

    void startMonitoring() {
        running.store(true);
        std::thread(&ServerMonitor::monitorLoop, this).detach(); // Run monitoring in a separate thread
    }

    void stopMonitoring() {
        running.store(false);
    }
};

// Main Function
int main() {
    DashboardController controller;

    std::vector<Server> servers = {
        Server("Server A"),
        Server("Server B"),
        Server("Server C"),
        Server("Server D")
    };

    ServerMonitor monitor(servers, controller);
    monitor.startMonitoring();

    // Run indefinitely (or until manually terminated)
    std::this_thread::sleep_for(std::chrono::hours(1)); // Simulates long-running process

    return 0;
}

Leave a comment