#include <chrono>
#include <cstdio>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <map>
#include <mutex>
#include <sstream>
#include <thread>
#include <vector>
using namespace std::chrono_literals;
double value,
const std::string& team = "ops") {
alert a;
a.severity = severity;
a.state = state;
a.value = value;
a.labels.set("team", team);
a.labels.set("environment", "production");
a.annotations.summary = "Alert: " + name;
a.annotations.description = "Detailed description for " + name;
a.rule_name = name + "_rule";
return a;
}
class console_color_notifier : public alert_notifier {
public:
:
name_(std::move(notifier_name)) {}
std::string
name()
const override {
return name_; }
common::VoidResult
notify(
const alert& a)
override {
std::string reset = "\033[0m";
std::cout << color <<
"[" <<
name_ <<
"] "
<< reset << std::endl;
std::cout << " Summary: " << a.annotations.summary << std::endl;
std::cout << " Value: " << a.value << std::endl;
return common::ok();
}
common::VoidResult
notify_group(
const alert_group& group)
override {
std::cout <<
"[" <<
name_ <<
"] Alert Group: " << group.group_key
<< " (" << group.size() << " alerts)" << std::endl;
for (const auto& alert_item : group.alerts) {
auto result =
notify(alert_item);
if (!result.is_ok()) {
return result;
}
}
return common::ok();
}
bool is_ready()
const override {
return true; }
private:
switch (sev) {
default: return "\033[0m";
}
}
};
class statistics_notifier : public alert_notifier {
public:
:
name_(std::move(notifier_name)) {}
std::string
name()
const override {
return name_; }
common::VoidResult
notify(
const alert& a)
override {
std::lock_guard<std::mutex> lock(
mutex_);
return common::ok();
}
common::VoidResult
notify_group(
const alert_group& group)
override {
for (const auto& alert_item : group.alerts) {
auto result =
notify(alert_item);
if (!result.is_ok()) {
return result;
}
}
return common::ok();
}
bool is_ready()
const override {
return true; }
std::lock_guard<std::mutex> lock(
mutex_);
std::cout <<
"Statistics from " <<
name_ <<
":" << std::endl;
std::cout << " By severity:" << std::endl;
}
std::cout << " By state:" << std::endl;
}
}
std::lock_guard<std::mutex> lock(
mutex_);
}
private:
};
}
std::cout << "=== Alert Notifiers Example ===" << std::endl;
std::cout << std::endl;
const std::string temp_dir = "/tmp/alert_notifiers_example";
std::filesystem::create_directories(temp_dir);
std::cout << "1. Alert Formatters" << std::endl;
std::cout << " -----------------" << std::endl;
alert sample = create_sample_alert(
"high_cpu_usage",
alert_severity::critical,
alert_state::firing,
95.5
);
std::cout << " JSON format:" << std::endl;
std::cout <<
" " << json_fmt.
format(sample) << std::endl;
std::cout << std::endl;
std::cout << " Text format:" << std::endl;
std::cout <<
" " << text_fmt.
format(sample) << std::endl;
std::cout << std::endl;
std::cout << "2. Log Notifier" << std::endl;
std::cout << " -------------" << std::endl;
auto log_notifier_ptr = std::make_shared<log_notifier>("system_logger");
std::cout << " Notifier name: " << log_notifier_ptr->name() << std::endl;
std::cout << " Ready: " << (log_notifier_ptr->is_ready() ? "yes" : "no") << std::endl;
std::cout << " Sending alert to log notifier..." << std::endl;
if (auto result = log_notifier_ptr->notify(sample); result.is_ok()) {
std::cout << " Alert logged successfully" << std::endl;
} else {
std::cout << " Failed to log alert: " << result.error().message << std::endl;
}
std::cout << std::endl;
std::cout << "3. File Notifier" << std::endl;
std::cout << " --------------" << std::endl;
std::string alert_log_path = temp_dir + "/alerts.log";
auto file_notifier_ptr = std::make_shared<file_notifier>(
alert_log_path,
std::make_shared<text_alert_formatter>()
);
std::cout << " Notifier name: " << file_notifier_ptr->name() << std::endl;
std::cout << " Output file: " << alert_log_path << std::endl;
std::vector<alert> alerts_to_log = {
};
for (const auto& a : alerts_to_log) {
if (auto result = file_notifier_ptr->notify(a); !result.is_ok()) {
std::cout << " Failed to write alert: " << result.error().message << std::endl;
}
}
std::cout << " Wrote " << alerts_to_log.size() << " alerts to file" << std::endl;
std::cout << " File contents:" << std::endl;
std::ifstream file(alert_log_path);
std::string line;
while (std::getline(file, line)) {
std::cout << " " << line << std::endl;
}
std::cout << std::endl;
std::cout << "4. Webhook Notifier Configuration" << std::endl;
std::cout << " -------------------------------" << std::endl;
webhook_cfg.
url =
"https://hooks.example.com/alerts";
webhook_cfg.
add_header(
"Authorization",
"Bearer token-xxx")
.
add_header(
"X-Alert-Source",
"monitoring-system");
std::cout <<
" URL: " << webhook_cfg.
url << std::endl;
std::cout <<
" Method: " << webhook_cfg.
method << std::endl;
std::cout <<
" Timeout: " << webhook_cfg.
timeout.count() <<
"ms" << std::endl;
std::cout <<
" Max retries: " << webhook_cfg.
max_retries << std::endl;
std::cout << " Headers:" << std::endl;
for (
const auto& [key, value] : webhook_cfg.
headers) {
std::cout << " " << key << ": " << value << std::endl;
}
std::cout << std::endl;
auto webhook_notifier_ptr = std::make_shared<webhook_notifier>(
webhook_cfg,
std::make_shared<json_alert_formatter>()
);
std::cout << " Notifier name: " << webhook_notifier_ptr->name() << std::endl;
std::cout << " Ready: " << (webhook_notifier_ptr->is_ready() ? "yes" : "no")
<< " (no HTTP sender configured)" << std::endl;
int http_call_count = 0;
webhook_notifier_ptr->set_http_sender(
[&http_call_count](const std::string& url,
const std::string& method,
const std::unordered_map<std::string, std::string>& headers,
const std::string& body) -> kcenon::common::VoidResult {
http_call_count++;
std::cout << " [MOCK HTTP] " << method << " " << url << std::endl;
std::cout << " [MOCK HTTP] Headers: " << headers.size() << std::endl;
std::cout << " [MOCK HTTP] Body length: " << body.length() << " chars" << std::endl;
return kcenon::common::ok();
}
);
std::cout << " Ready after setting HTTP sender: "
<< (webhook_notifier_ptr->is_ready() ? "yes" : "no") << std::endl;
std::cout << " Testing webhook notification:" << std::endl;
if (auto result = webhook_notifier_ptr->notify(sample); result.is_ok()) {
std::cout << " Webhook notification sent (HTTP calls: " << http_call_count << ")" << std::endl;
}
std::cout << std::endl;
std::cout << "5. Callback Notifier" << std::endl;
std::cout << " ------------------" << std::endl;
size_t callback_count = 0;
auto callback_notifier_ptr = std::make_shared<callback_notifier>(
"custom_callback",
[&callback_count](
const alert& a) {
callback_count++;
std::cout <<
" [CALLBACK] Received: " << a.
name
<< std::endl;
},
callback_count += group.size();
std::cout << " [CALLBACK GROUP] Received group: " << group.group_key
<< " (" << group.size() << " alerts)" << std::endl;
}
);
std::cout << " Testing callback notifier:" << std::endl;
callback_notifier_ptr->notify(sample);
std::cout << " Callbacks executed: " << callback_count << std::endl;
std::cout << std::endl;
std::cout << "6. Multi Notifier (Multiple Targets)" << std::endl;
std::cout << " -----------------------------------" << std::endl;
auto multi = std::make_shared<multi_notifier>("multi_channel");
auto log_child = std::make_shared<log_notifier>("log_child");
auto stats_child = std::make_shared<statistics_notifier>("stats_child");
auto console_child = std::make_shared<console_color_notifier>("console_child");
multi->add_notifier(log_child);
multi->add_notifier(stats_child);
multi->add_notifier(console_child);
std::cout << " Added 3 child notifiers to multi_channel" << std::endl;
std::cout << " Sending alert to all channels:" << std::endl;
if (auto result = multi->notify(sample); result.is_ok()) {
std::cout << " All notifiers succeeded" << std::endl;
} else {
std::cout << " Some notifiers failed: " << result.error().message << std::endl;
}
std::cout << std::endl;
std::cout << "7. Buffered Notifier (Batching)" << std::endl;
std::cout << " -----------------------------" << std::endl;
auto inner_notifier = std::make_shared<statistics_notifier>("buffered_inner");
auto buffered = std::make_shared<buffered_notifier>(
inner_notifier,
5,
10000ms
);
std::cout << " Buffer size: 5, flush interval: 10s" << std::endl;
std::cout << " Sending alerts (will buffer until size reached):" << std::endl;
for (int i = 1; i <= 7; ++i) {
"buffered_alert_" + std::to_string(i),
alert_severity::warning,
alert_state::firing,
static_cast<double>(i * 10)
);
buffered->notify(a);
std::cout << " Sent alert " << i << ", pending: " << buffered->pending_count() << std::endl;
}
std::cout << " Forcing flush of remaining alerts..." << std::endl;
buffered->flush();
std::cout << " Pending after flush: " << buffered->pending_count() << std::endl;
inner_notifier->print_statistics();
std::cout << std::endl;
std::cout << "8. Routing Notifier (Conditional Routing)" << std::endl;
std::cout << " ---------------------------------------" << std::endl;
auto router = std::make_shared<routing_notifier>("alert_router");
auto critical_notifier = std::make_shared<console_color_notifier>("critical_channel");
auto warning_notifier = std::make_shared<console_color_notifier>("warning_channel");
auto default_notifier = std::make_shared<console_color_notifier>("default_channel");
router->route_by_severity(alert_severity::critical, critical_notifier);
router->route_by_severity(alert_severity::emergency, critical_notifier);
router->route_by_severity(alert_severity::warning, warning_notifier);
router->set_default_route(default_notifier);
std::cout << " Routing rules configured:" << std::endl;
std::cout << " - critical/emergency -> critical_channel" << std::endl;
std::cout << " - warning -> warning_channel" << std::endl;
std::cout << " - default -> default_channel" << std::endl;
std::cout << std::endl;
std::cout << " Testing routing with different severities:" << std::endl;
std::vector<alert> routing_tests = {
};
for (const auto& a : routing_tests) {
std::cout <<
" Routing '" << a.
name <<
"' (severity: "
router->notify(a);
}
std::cout << std::endl;
std::cout << " Adding label-based routing:" << std::endl;
auto ops_notifier = std::make_shared<console_color_notifier>("ops_team_channel");
router->route_by_label("team", "ops", ops_notifier);
auto ops_alert =
create_sample_alert(
"ops_alert", alert_severity::info, alert_state::firing, 60.0,
"ops");
std::cout << " Routing alert with team=ops:" << std::endl;
router->notify(ops_alert);
std::cout << std::endl;
std::cout << "9. Custom Notifier Implementation" << std::endl;
std::cout << " -------------------------------" << std::endl;
auto stats = std::make_shared<statistics_notifier>("alert_statistics");
std::vector<alert> stat_alerts = {
};
for (const auto& a : stat_alerts) {
stats->notify(a);
}
stats->print_statistics();
std::cout << std::endl;
std::cout << "10. Alert Group Notification" << std::endl;
std::cout << " -------------------------" << std::endl;
group.common_labels.set("environment", "production");
group.common_labels.set("datacenter", "us-west-2");
group.add_alert(
create_sample_alert(
"cpu_server1", alert_severity::critical, alert_state::firing, 95.0));
group.add_alert(
create_sample_alert(
"cpu_server2", alert_severity::warning, alert_state::firing, 82.0));
group.add_alert(
create_sample_alert(
"cpu_server3", alert_severity::critical, alert_state::firing, 91.0));
std::cout << " Group: " << group.group_key << std::endl;
std::cout << " Alerts: " << group.size() << std::endl;
std::cout << std::endl;
std::cout << " JSON formatted group:" << std::endl;
std::cout <<
" " << json_fmt.
format_group(group) << std::endl;
std::cout << std::endl;
auto group_stats = std::make_shared<statistics_notifier>("group_stats");
group_stats->notify_group(group);
group_stats->print_statistics();
std::cout << std::endl;
std::cout << "11. Error Handling" << std::endl;
std::cout << " ---------------" << std::endl;
fail_cfg.
url =
"https://failing.example.com/alerts";
auto failing_webhook = std::make_shared<webhook_notifier>(fail_cfg);
int retry_count = 0;
failing_webhook->set_http_sender(
[&retry_count](const std::string& ,
const std::string& ,
const std::unordered_map<std::string, std::string>& ,
const std::string& ) -> kcenon::common::VoidResult {
retry_count++;
std::cout << " HTTP attempt " << retry_count << " - simulating failure" << std::endl;
return kcenon::common::VoidResult::err(500, "Simulated server error");
}
);
std::cout << " Testing webhook with simulated failures:" << std::endl;
auto fail_result = failing_webhook->notify(sample);
if (!fail_result.is_ok()) {
std::cout << " Expected failure after " << retry_count << " attempts: "
<< fail_result.error().message << std::endl;
}
std::cout << std::endl;
std::cout << "12. Cleanup" << std::endl;
std::cout << " -------" << std::endl;
std::filesystem::remove_all(temp_dir);
std::cout << " Removed temporary directory: " << temp_dir << std::endl;
std::cout << std::endl;
std::cout << "=== Alert Notifiers Example Completed ===" << std::endl;
std::cout << std::endl;
std::cout << "Notifiers demonstrated:" << std::endl;
std::cout << " - LogNotifier (built-in logging)" << std::endl;
std::cout << " - FileNotifier (file-based alerts)" << std::endl;
std::cout << " - WebhookNotifier (HTTP webhooks)" << std::endl;
std::cout << " - CallbackNotifier (custom callbacks)" << std::endl;
std::cout << " - MultiNotifier (multiple targets)" << std::endl;
std::cout << " - BufferedNotifier (batching)" << std::endl;
std::cout << " - RoutingNotifier (conditional routing)" << std::endl;
std::cout << " - Custom implementations (color console, statistics)" << std::endl;
std::cout << " - Alert formatters (JSON, text)" << std::endl;
return 0;
}
Alert notification implementations.
Core alert data structures for the monitoring system.
console_color_notifier(std::string notifier_name)
std::string name() const override
Get notifier name.
common::VoidResult notify_group(const alert_group &group) override
Send a notification for an alert group.
bool is_ready() const override
Check if notifier is ready.
static std::string get_severity_color(alert_severity sev)
common::VoidResult notify(const alert &a) override
Send a notification for an alert.
std::map< alert_severity, size_t > severity_counts_
std::string name() const override
Get notifier name.
common::VoidResult notify_group(const alert_group &group) override
Send a notification for an alert group.
std::map< alert_state, size_t > state_counts_
void print_statistics() const
common::VoidResult notify(const alert &a) override
Send a notification for an alert.
statistics_notifier(std::string notifier_name)
bool is_ready() const override
Check if notifier is ready.
Formats alerts as human-readable text.
std::string format(const alert &a) const override
Format a single alert.
alert create_sample_alert(const std::string &name, alert_severity severity, alert_state state, double value, const std::string &team="ops")
alert_severity
Severity levels for alerts.
@ warning
Warning condition, may require attention.
@ critical
Critical condition, immediate attention required.
@ emergency
Emergency condition, system-wide impact.
@ info
Informational, no action required.
constexpr const char * alert_state_to_string(alert_state state) noexcept
Convert alert state to string.
constexpr const char * alert_severity_to_string(alert_severity severity) noexcept
Convert alert severity to string.
alert_state
State machine states for alert lifecycle.
Result pattern type definitions for monitoring system.
Group of related alerts for batch notification.
Core alert data structure.
alert_severity severity
Alert severity level.
std::string name
Alert name/identifier.
Configuration for webhook notifier.
std::chrono::milliseconds retry_delay
Delay between retries.
std::chrono::milliseconds timeout
Request timeout.
bool send_resolved
Send resolved notifications.
size_t max_retries
Maximum retry attempts.
std::string content_type
Content type header.
webhook_config & add_header(const std::string &key, const std::string &value)
Add a custom header.
std::unordered_map< std::string, std::string > headers
Custom headers.
std::string url
Webhook URL.
std::string method
HTTP method.