22#include <unordered_map>
69 void set(
const std::string& key,
const std::string& value) {
82 std::unordered_map<std::string, std::string> vars;
85 vars[
"name"] = a.
name;
95 vars[
"labels." + key] = value;
105 vars[
"annotations." + key] = value;
130 std::regex pattern(R
"(\$\{[^}]*$)");
139 std::ostringstream oss;
140 oss << std::fixed << std::setprecision(2) << value;
145 const std::string& input,
146 const std::unordered_map<std::string, std::string>& vars) {
147 std::string result = input;
148 std::regex pattern(R
"(\$\{([^}]+)\})");
150 std::string::const_iterator start = result.cbegin();
154 while (std::regex_search(start, result.cend(), match, pattern)) {
155 output += std::string(start, match[0].first);
157 std::string var_name = match[1].str();
158 auto it = vars.find(var_name);
159 if (it != vars.end()) {
160 output += it->second;
162 output += match[0].str();
165 start = match[0].second;
167 output += std::string(start, result.cend());
207 std::unordered_map<std::string, std::string>
labels;
229 if (def.
name.empty()) {
230 return common::make_error<std::shared_ptr<alert_rule>>(
232 "Rule name is required");
235 return common::make_error<std::shared_ptr<alert_rule>>(
237 "Metric name is required");
240 auto rule = std::make_shared<alert_rule>(def.
name);
243 if (!def.
group.empty()) {
244 rule->set_group(def.
group);
252 if (!severity.is_ok()) {
253 return common::make_error<std::shared_ptr<alert_rule>>(
255 severity.error().message);
257 rule->set_severity(severity.value());
260 rule->set_enabled(def.
enabled);
264 if (!trigger.is_ok()) {
265 return common::make_error<std::shared_ptr<alert_rule>>(
267 trigger.error().message);
269 rule->set_trigger(trigger.value());
272 rule->set_evaluation_interval(
274 rule->set_for_duration(
276 rule->set_repeat_interval(
280 for (
const auto& [key, value] : def.
labels) {
281 rule->add_label(key, value);
286 rule->set_summary(def.
summary);
295 return common::ok(std::move(rule));
300 if (str.empty() || str ==
"warning") {
306 if (str ==
"critical") {
309 if (str ==
"emergency") {
312 return common::make_error<alert_severity>(
314 "Unknown severity: " + str);
319 if (cfg.
type.empty() || cfg.
type ==
"threshold") {
322 return common::make_error<std::shared_ptr<alert_trigger>>(
326 return common::ok(std::shared_ptr<alert_trigger>(
327 std::make_shared<threshold_trigger>(cfg.
threshold, op.value())));
330 if (cfg.
type ==
"rate") {
331 return common::ok(std::shared_ptr<alert_trigger>(
332 std::make_shared<rate_of_change_trigger>(
337 if (cfg.
type ==
"anomaly") {
338 return common::ok(std::shared_ptr<alert_trigger>(
339 std::make_shared<anomaly_trigger>(
344 if (cfg.
type ==
"absent") {
345 return common::ok(std::shared_ptr<alert_trigger>(
346 std::make_shared<absent_trigger>(
350 return common::make_error<std::shared_ptr<alert_trigger>>(
352 "Unknown trigger type: " + cfg.
type);
355 static common::Result<comparison_operator>
parse_operator(
const std::string& str) {
356 if (str.empty() || str ==
">") {
368 if (str ==
"==" || str ==
"=") {
371 if (str ==
"!=" || str ==
"<>") {
374 return common::make_error<comparison_operator>(
376 "Unknown operator: " + str);
390 const std::string& rule_name,
391 const std::shared_ptr<alert_rule>& rule,
404 std::lock_guard<std::mutex> lock(
mutex_);
406 std::string name = rule->name();
411 callback(name, rule,
false);
423 std::lock_guard<std::mutex> lock(
mutex_);
425 auto it =
rules_.find(name);
428 "Rule not found: " + name);
431 auto rule = it->second;
436 callback(name, rule,
true);
445 std::shared_ptr<alert_rule>
get_rule(
const std::string& name)
const {
446 std::lock_guard<std::mutex> lock(
mutex_);
447 auto it =
rules_.find(name);
448 return it !=
rules_.end() ? it->second :
nullptr;
455 std::lock_guard<std::mutex> lock(
mutex_);
456 std::vector<std::shared_ptr<alert_rule>> result;
457 result.reserve(
rules_.size());
458 for (
const auto& [name, rule] :
rules_) {
459 result.push_back(rule);
468 const std::string& group)
const {
469 std::lock_guard<std::mutex> lock(
mutex_);
470 std::vector<std::shared_ptr<alert_rule>> result;
471 for (
const auto& [name, rule] :
rules_) {
472 if (rule->group() == group) {
473 result.push_back(rule);
483 std::lock_guard<std::mutex> lock(
mutex_);
491 std::lock_guard<std::mutex> lock(
mutex_);
502 std::vector<std::string> errors;
504 for (
const auto& def : definitions) {
506 if (rule_result.is_ok()) {
508 if (reg_result.is_ok()) {
511 errors.push_back(def.name +
": " + reg_result.error().message);
514 errors.push_back(def.name +
": " + rule_result.error().message);
518 if (!errors.empty() && loaded == 0) {
519 return common::make_error<size_t>(
521 "Failed to load any rules: " + errors.front());
524 return common::ok(loaded);
531 std::lock_guard<std::mutex> lock(
mutex_);
533 for (
const auto& [name, rule] :
rules_) {
535 callback(name, rule,
true);
544 std::unordered_map<std::string, std::shared_ptr<alert_rule>>
rules_;
Alert rule configuration and evaluation.
Alert trigger implementations for various condition types.
Core alert data structures for the monitoring system.
Template engine for alert messages.
static std::string format_value(double value)
const std::string & template_string() const
Get template string.
std::string template_str_
static std::string substitute_variables(const std::string &input, const std::unordered_map< std::string, std::string > &vars)
common::VoidResult validate() const
Validate template syntax.
void set(const std::string &key, const std::string &value)
Set a custom variable value.
std::string render(const alert &a) const
Render template with alert data.
std::unordered_map< std::string, std::string > custom_vars_
alert_template(std::string template_str)
Construct with template string.
Builds alert_rule from rule_definition.
static common::Result< std::shared_ptr< alert_rule > > build(const rule_definition &def)
Build alert_rule from definition.
static common::Result< comparison_operator > parse_operator(const std::string &str)
static common::Result< std::shared_ptr< alert_trigger > > build_trigger(const rule_definition::trigger_config &cfg)
static common::Result< alert_severity > parse_severity(const std::string &str)
Dynamic registry for alert rules with hot-reload support.
std::function< void( const std::string &rule_name, const std::shared_ptr< alert_rule > &rule, bool is_removal)> rule_change_callback
common::VoidResult unregister_rule(const std::string &name)
Unregister a rule.
void on_rule_change(rule_change_callback callback)
Register callback for rule changes.
size_t rule_count() const
Get rule count.
common::VoidResult register_rule(std::shared_ptr< alert_rule > rule)
Register a rule.
std::unordered_map< std::string, std::shared_ptr< alert_rule > > rules_
std::vector< std::shared_ptr< alert_rule > > get_rules_by_group(const std::string &group) const
Get rules in a group.
std::vector< std::shared_ptr< alert_rule > > get_all_rules() const
Get all registered rules.
common::Result< size_t > load_definitions(const std::vector< rule_definition > &definitions)
Load rules from definitions.
void clear()
Clear all rules.
std::vector< rule_change_callback > change_callbacks_
std::shared_ptr< alert_rule > get_rule(const std::string &name) const
Get a rule by name.
@ equal
value == threshold (with epsilon)
@ less_or_equal
value <= threshold
@ less_than
value < threshold
@ not_equal
value != threshold (with epsilon)
@ greater_or_equal
value >= threshold
@ greater_than
value > threshold
@ configuration_parse_error
@ 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.
Result pattern type definitions for monitoring system.
std::string description
Detailed description.
std::unordered_map< std::string, std::string > custom
Custom annotations.
std::string summary
Brief description.
std::optional< std::string > runbook_url
Link to runbook.
std::unordered_map< std::string, std::string > labels
Core alert data structure.
alert_state state
Current state.
double value
Current metric value.
alert_severity severity
Alert severity level.
std::string rule_name
Name of triggering rule.
std::string group_key
Grouping key for dedup.
std::string name
Alert name/identifier.
alert_labels labels
Identifying labels.
alert_annotations annotations
Descriptive annotations.
std::string fingerprint() const
Get alert fingerprint for deduplication.
Extended error information with context.
Structured definition for alert rule configuration.
int repeat_interval_seconds
int evaluation_interval_seconds
struct kcenon::monitoring::rule_definition::trigger_config trigger
std::unordered_map< std::string, std::string > labels