Monitoring System 0.1.0
System resource monitoring with pluggable collectors and alerting
Loading...
Searching...
No Matches
platform_metrics_example.cpp

This example shows how to use the unified platform metrics collector:

// BSD 3-Clause License
// Copyright (c) 2021-2025, 🍀☀🌕🌥 🌊
// See the LICENSE file in the project root for full license information.
#include <iostream>
#include <thread>
#include <chrono>
#include <iomanip>
using namespace kcenon::monitoring;
using namespace std::chrono_literals;
std::cout << "\n=== Platform Information ===" << std::endl;
if (info.available) {
std::cout << "Platform: " << info.name << std::endl;
std::cout << "Version: " << info.version << std::endl;
std::cout << "Architecture: " << info.architecture << std::endl;
} else {
std::cout << "Platform information not available" << std::endl;
}
}
std::cout << "\n=== Uptime Metrics ===" << std::endl;
if (uptime.available) {
// Convert seconds to days, hours, minutes
int64_t seconds = uptime.uptime_seconds;
int64_t days = seconds / (24 * 3600);
seconds %= (24 * 3600);
int64_t hours = seconds / 3600;
seconds %= 3600;
int64_t minutes = seconds / 60;
seconds %= 60;
std::cout << "System Uptime: " << days << "d " << hours << "h "
<< minutes << "m " << seconds << "s" << std::endl;
std::cout << "Total Uptime: " << uptime.uptime_seconds << " seconds" << std::endl;
std::cout << "Idle Time: " << uptime.idle_seconds << " seconds" << std::endl;
// Display boot timestamp as ISO 8601 format if available
if (uptime.boot_timestamp > 0) {
auto boot_time = std::chrono::system_clock::from_time_t(uptime.boot_timestamp);
auto boot_tt = std::chrono::system_clock::to_time_t(boot_time);
std::tm boot_tm{};
#ifdef _MSC_VER
localtime_s(&boot_tm, &boot_tt);
#else
localtime_r(&boot_tt, &boot_tm);
#endif
std::cout << "Boot Time: " << std::put_time(&boot_tm, "%Y-%m-%d %H:%M:%S") << std::endl;
}
} else {
std::cout << "Uptime metrics not available on this platform" << std::endl;
}
}
std::cout << "\n=== Context Switch Statistics ===" << std::endl;
if (switches.available) {
std::cout << "Total Switches: " << switches.total_switches << std::endl;
std::cout << "Voluntary Switches: " << switches.voluntary_switches << std::endl;
std::cout << "Involuntary Switches: " << switches.involuntary_switches << std::endl;
std::cout << "Switches Per Second: " << std::fixed << std::setprecision(2)
<< switches.switches_per_second << std::endl;
} else {
std::cout << "Context switch statistics not available on this platform" << std::endl;
}
}
std::cout << "\n=== TCP Connection States ===" << std::endl;
if (tcp.available) {
std::cout << "ESTABLISHED: " << tcp.established << std::endl;
std::cout << "SYN_SENT: " << tcp.syn_sent << std::endl;
std::cout << "SYN_RECV: " << tcp.syn_recv << std::endl;
std::cout << "FIN_WAIT1: " << tcp.fin_wait1 << std::endl;
std::cout << "FIN_WAIT2: " << tcp.fin_wait2 << std::endl;
std::cout << "TIME_WAIT: " << tcp.time_wait << std::endl;
std::cout << "CLOSE_WAIT: " << tcp.close_wait << std::endl;
std::cout << "LISTEN: " << tcp.listen << std::endl;
std::cout << "Total Connections: " << tcp.total << std::endl;
} else {
std::cout << "TCP state information not available on this platform" << std::endl;
}
}
std::cout << "\n=== Socket Buffer Information ===" << std::endl;
if (socket.available) {
std::cout << "RX Buffer Size: " << (socket.rx_buffer_size / 1024.0) << " KB" << std::endl;
std::cout << "TX Buffer Size: " << (socket.tx_buffer_size / 1024.0) << " KB" << std::endl;
std::cout << "RX Buffer Used: " << (socket.rx_buffer_used / 1024.0) << " KB ("
<< std::fixed << std::setprecision(1)
<< (socket.rx_buffer_size > 0 ? (socket.rx_buffer_used * 100.0 / socket.rx_buffer_size) : 0.0)
<< "%)" << std::endl;
std::cout << "TX Buffer Used: " << (socket.tx_buffer_used / 1024.0) << " KB ("
<< (socket.tx_buffer_size > 0 ? (socket.tx_buffer_used * 100.0 / socket.tx_buffer_size) : 0.0)
<< "%)" << std::endl;
} else {
std::cout << "Socket buffer information not available on this platform" << std::endl;
}
}
std::cout << "\n=== Interrupt Statistics ===" << std::endl;
if (interrupts.available) {
std::cout << "Total Interrupts: " << interrupts.total_interrupts << std::endl;
} else {
std::cout << "Interrupt statistics not available on this platform" << std::endl;
}
}
std::cout << "\n=== Platform-Specific Feature Detection ===" << std::endl;
// Collect platform info first
auto info = collector.get_platform_info();
std::cout << "\nDetected Platform: " << info.name << std::endl;
// Demonstrate feature availability checks before collection
std::cout << "\nFeature Availability:" << std::endl;
// Display feature availability
std::cout << " Platform Available: " << (collector.is_platform_available() ? "Yes" : "No") << std::endl;
std::cout << " Collector Health: " << (collector.is_available() ? "Healthy" : "Unhealthy") << std::endl;
std::cout << "\nNote: The Strategy pattern abstracts platform-specific implementations." << std::endl;
std::cout << " Features not supported on a platform return empty/unavailable values." << std::endl;
#if defined(__linux__)
std::cout << "\nLinux-specific features:" << std::endl;
std::cout << " - Reading /proc/stat for context switches" << std::endl;
std::cout << " - Reading /proc/net/tcp for TCP state info" << std::endl;
std::cout << " - Reading /proc/uptime for system uptime" << std::endl;
#elif defined(__APPLE__)
std::cout << "\nmacOS-specific features:" << std::endl;
std::cout << " - Using sysctl for system metrics" << std::endl;
std::cout << " - Limited TCP state information" << std::endl;
std::cout << " - Using kern.boottime for uptime" << std::endl;
#elif defined(_WIN32)
std::cout << "\nWindows-specific features:" << std::endl;
std::cout << " - Using GetTickCount64 for uptime" << std::endl;
std::cout << " - Using Performance Counters for metrics" << std::endl;
std::cout << " - Limited context switch information" << std::endl;
#else
std::cout << "\nUnknown platform - limited feature support" << std::endl;
#endif
}
void demonstrate_metric_normalization(const std::vector<metric>& metrics) {
std::cout << "\n=== Cross-Platform Metric Normalization ===" << std::endl;
std::cout << "\nAll metrics use standardized naming conventions:" << std::endl;
std::cout << " platform.uptime.* - Uptime metrics" << std::endl;
std::cout << " platform.context_switches.* - Context switch metrics" << std::endl;
std::cout << " platform.tcp.* - TCP state metrics" << std::endl;
std::cout << " platform.socket.* - Socket buffer metrics" << std::endl;
std::cout << " platform.interrupts.* - Interrupt metrics" << std::endl;
std::cout << "\nCollected Metrics (" << metrics.size() << " total):" << std::endl;
// Display metrics directly without grouping to avoid compilation issues
for (const auto& m : metrics) {
std::cout << " " << m.name << ": ";
std::visit([](const auto& val) { std::cout << val; }, m.value);
auto unit_it = m.tags.find("unit");
if (unit_it != m.tags.end() && !unit_it->second.empty()) {
std::cout << " " << unit_it->second;
}
std::cout << std::endl;
}
}
int main() {
std::cout << "=== Platform Metrics Example ===" << std::endl;
try {
// Step 1: Create platform_metrics_collector with configuration
std::cout << "\n1. Creating platform_metrics_collector..." << std::endl;
config.collect_uptime = true;
config.collect_context_switches = true;
config.collect_tcp_states = true;
config.collect_socket_buffers = true;
config.collect_interrupts = true;
platform_metrics_collector collector(config);
// Initialize the collector
std::unordered_map<std::string, std::string> init_config;
if (!collector.initialize(init_config)) {
std::cerr << "Failed to initialize platform_metrics_collector" << std::endl;
return 1;
}
std::cout << " Initialized: " << collector.name() << std::endl;
std::cout << " Health: " << (collector.is_available() ? "OK" : "UNHEALTHY") << std::endl;
// Step 2: Display platform information
std::cout << "\n2. Retrieving platform information..." << std::endl;
auto platform_info = collector.get_platform_info();
// Step 3: Demonstrate platform-specific feature detection
std::cout << "\n3. Demonstrating platform-specific features..." << std::endl;
// Step 4: Collect and display metrics (3 iterations)
std::cout << "\n4. Collecting platform metrics (3 iterations)..." << std::endl;
for (int i = 0; i < 3; ++i) {
std::cout << "\n--- Iteration " << (i + 1) << "/3 ---" << std::endl;
// Collect all platform metrics
auto metrics = collector.collect();
std::cout << "Metrics collected: " << metrics.size() << std::endl;
// Get last collected metrics for detailed display
auto last_metrics = collector.get_last_metrics();
// Display each metric category
display_uptime_metrics(last_metrics.uptime);
display_context_switch_stats(last_metrics.context_switches);
display_tcp_info(last_metrics.tcp);
display_socket_info(last_metrics.socket);
display_interrupt_info(last_metrics.interrupts);
// Wait before next collection
if (i < 2) {
std::cout << "\nWaiting 2 seconds before next collection..." << std::endl;
std::this_thread::sleep_for(2s);
}
}
// Step 5: Demonstrate metric normalization
std::cout << "\n5. Demonstrating cross-platform metric normalization..." << std::endl;
auto final_metrics = collector.collect();
// Step 6: Display collector statistics
std::cout << "\n6. Collector Statistics:" << std::endl;
auto stats = collector.get_statistics();
for (const auto& [key, value] : stats) {
std::cout << " " << key << ": " << value << std::endl;
}
// Step 7: Demonstrate dynamic configuration updates
std::cout << "\n7. Configuration note:" << std::endl;
std::cout << " Platform metrics collector configuration is set at initialization." << std::endl;
std::cout << " To change configuration, recreate the collector with new config." << std::endl;
std::cout << "\n=== Example completed successfully ===" << std::endl;
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
return 1;
}
return 0;
}
Unified platform-agnostic metrics collector.
auto is_available() const -> bool override
bool initialize(const config_map &config) override
auto name() const -> std::string_view override
auto get_statistics() const -> stats_map override
auto collect() -> std::vector< metric > override
@ info
Informational, no action required.
Unified platform-agnostic metrics collector.
void display_platform_info(const platform_info &info)
void display_interrupt_info(const platform_interrupt_info &interrupts)
void demonstrate_metric_normalization(const std::vector< metric > &metrics)
void display_uptime_metrics(const platform_uptime &uptime)
void display_tcp_info(const platform_tcp_info &tcp)
void display_context_switch_stats(const platform_context_switches &switches)
void demonstrate_platform_features(platform_metrics_collector &collector)
void display_socket_info(const platform_socket_info &socket)
double switches_per_second
Context switches per second.
uint64_t voluntary_switches
Voluntary context switches.
uint64_t involuntary_switches
Involuntary context switches.
Platform identification information.
Configuration for platform metrics collection.
bool collect_context_switches
Collect context switch metrics.
bool collect_socket_buffers
Collect socket buffer metrics.
Platform TCP connection state information.
uint64_t established
ESTABLISHED connections.
int64_t boot_timestamp
Unix timestamp of last boot.
int64_t idle_seconds
Total idle time in seconds.
int64_t uptime_seconds
System uptime in seconds.
bool available
Whether uptime info is available.