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.
NOTE
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:
updateStatus()
- Updates the load using the random generator.
- Assigns availability with an 80% chance of being “online” (
randomGen.generate() > 0.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:
- Formatted Output
TheupdateDisplay()
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 |
- Alerts System
TheshowAlert()
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.
- Thread Safety
ThealertMutex
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:
- Updating Server Statuses
Continuously refreshes load and availability for all servers. - Alert Generation
Checks each server’s status and raises appropriate alerts. - Concurrent Execution
Runs monitoring operations in a separate thread to allow real-time updates without blocking the main program.
Key Methods:
startMonitoring()
- Activates the monitoring process in a new thread.
- Uses
std::atomic<bool>
(running
) to control the thread’s lifecycle.
monitorLoop()
- Periodically updates each server.
- Calls
checkForAlerts()
to identify potential issues. - Displays server statuses using
DashboardController
.
checkForAlerts()
- Identifies critical and warning conditions based on load and availability.
- Calls
showAlert()
to notify users.
- Thread Safety
- Uses a mutex (
outputMutex
) to synchronize updates and alerts, preventing garbled output from concurrent threads.
- Uses a mutex (
Monitoring Example:
monitor.startMonitoring(); // Begins monitoring in a separate thread
How the System Works Together
- Initialization
The main function creates a list of servers and initializes theDashboardController
andServerMonitor
. - Monitoring
TheServerMonitor
begins monitoring in a new thread.- Every 5 seconds, server statuses are updated, alerts are raised, and the dashboard is refreshed.
- Alerts
Alerts are raised dynamically based on server load and availability. - Continuous Operation
The system runs indefinitely (std::this_thread::sleep_for(std::chrono::hours(1))
) or until terminated.
Output Walkthrough
Example Console Output:
- Status Update: Displays the load and availability for each server.
- Critical Alert: Server B’s load exceeds 90%.
- 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
Therunning
flag can be set tofalse
to safely stop the monitoring loop.
Real-World Use Cases
- IT Infrastructure: Monitor server clusters for performance and availability.
- Simulations: Test server behavior under varying conditions.
- 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;
}