diff --git a/eqpalg/algs/bound_alg.cpp b/eqpalg/algs/bound_alg.cpp new file mode 100644 index 0000000..8f78086 --- /dev/null +++ b/eqpalg/algs/bound_alg.cpp @@ -0,0 +1,66 @@ +#include +#include +#include +#include + +BoundAlg::BoundAlg(const std::string& name, const mix_cc::json& rule_json, + const std::string& ruleId, size_t exp_type) + : ExpBase(name, rule_json, ruleId, exp_type) { + logger_.reset(new LOG("BoundAlg:" + rule_name_, AUTO_CATCH_PID)); +} + +BoundAlg::~BoundAlg() = default; + +int BoundAlg::init() { + int ret = ExpBase::init(); + if (ret == 0) { + exp_is_wrong_ = false; + } + return ret; +} + +void BoundAlg::doInitExtend() { + // BoundAlg 额外的初始化:上下限 + reload_config_up_down(); + reload_ci_dist(); + last_load_time_ = std::chrono::system_clock::now(); + stat_collector_.configure(rule_id_, rule_name_, dist_mode_, is_learning_); +} + +bool BoundAlg::checkFilter() { + if (!expr_engine_->exps_.count("feedback")) { + return true; // 无筛选表达式,所有数据参与 + } + try { + return expr_engine_->evaluateBool("feedback"); + } catch (...) { + return false; + } +} + +AlarmInfo BoundAlg::doMonProc() { + double result_value = expr_engine_->evaluate("act"); + filter_flag_ = false; + + // 数据筛选 + filter_flag_ = checkFilter(); + + // 自学习统计 + if (is_learning_ && filter_flag_) { + rule_stat_.current_value = result_value; + SingletonTemp::GetInstance().add_stat_values(rule_id_, result_value); + } + + // 超限检测 + if (filter_flag_ && bound_checker_.isOutOfBounds(result_value)) { + rule_stat_.alarm_value = result_value; + auto msg = error_str_ + ":" + DAA::double2str(result_value) + unit_ + + ",合理区间:[" + DAA::double2strLimit(bound_checker_.limitDown()) + + "," + DAA::double2strLimit(bound_checker_.limitUp()) + "]" + unit_; + query_time_range_.set_left(query_time_range_.get_right() - delay_time_); + expr_engine_->markFunVarsNeedReset(); + return utility::build_alarm_info(MsgLevel::ERROR, rule_id_, rule_name_, + "EXP2", msg, get_alarm_time()); + } + return AlarmInfo{}; +} diff --git a/eqpalg/algs/bound_alg.h b/eqpalg/algs/bound_alg.h new file mode 100644 index 0000000..dfa7abc --- /dev/null +++ b/eqpalg/algs/bound_alg.h @@ -0,0 +1,19 @@ +#pragma once +#include + +class BoundAlg : public ExpBase { +public: + BoundAlg(const std::string& name, const mix_cc::json& rule_json, + const std::string& ruleId, + size_t exp_type = ExpType::Bound); + ~BoundAlg() override; + + int init() override; + +protected: + AlarmInfo doMonProc() override; + void doInitExtend() override; + + // 数据筛选检查 + bool checkFilter(); +}; diff --git a/eqpalg/algs/bound_hold_alg.cpp b/eqpalg/algs/bound_hold_alg.cpp new file mode 100644 index 0000000..2a28e50 --- /dev/null +++ b/eqpalg/algs/bound_hold_alg.cpp @@ -0,0 +1,62 @@ +#include +#include +#include + +BoundHoldAlg::BoundHoldAlg(const std::string& name, const mix_cc::json& rule_json, + const std::string& ruleId) + : BoundAlg(name, rule_json, ruleId, ExpType::BoundHoldTime) { + logger_.reset(new LOG("BoundHoldAlg:" + rule_name_, AUTO_CATCH_PID)); +} + +BoundHoldAlg::~BoundHoldAlg() = default; + +int BoundHoldAlg::init() { + int ret = BoundAlg::init(); + if (ret == 0) { + reload_config_up_down_hold_time(); + } + return ret; +} + +AlarmInfo BoundHoldAlg::doMonProc() { + double result_value = expr_engine_->evaluate("act"); + filter_flag_ = checkFilter(); + + if (is_learning_ && filter_flag_) { + rule_stat_.current_value = result_value; + SingletonTemp::GetInstance().add_stat_values(rule_id_, result_value); + } + + bool is_over = bound_checker_.isOutOfBounds(result_value); + + if (!filter_flag_) { + act_start_time_ = now_time_; + act_started_ = false; + } else { + if (is_over) { + if (!act_started_) { + act_started_ = true; + act_start_time_ = now_time_; + } + if ((hold_time_ <= delay_time_) || + (now_time_ - act_start_time_ > hold_time_)) { + rule_stat_.alarm_value = result_value; + auto msg = error_str_ + ":" + DAA::double2str(result_value) + unit_ + + ",合理区间:[" + DAA::double2strLimit(bound_checker_.limitDown()) + + "," + DAA::double2strLimit(bound_checker_.limitUp()) + "]" + unit_; + query_time_range_.set_left(query_time_range_.get_right() - delay_time_); + expr_engine_->markFunVarsNeedReset(); + act_start_time_ = now_time_; + act_started_ = false; + return utility::build_alarm_info( + utility::get_msg_level(bound_checker_.limitDown(), + bound_checker_.limitUp(), result_value), + rule_id_, rule_name_, "EXP5", msg, get_alarm_time()); + } + } else { + act_start_time_ = now_time_; + act_started_ = false; + } + } + return AlarmInfo{}; +} diff --git a/eqpalg/algs/bound_hold_alg.h b/eqpalg/algs/bound_hold_alg.h new file mode 100644 index 0000000..66e5452 --- /dev/null +++ b/eqpalg/algs/bound_hold_alg.h @@ -0,0 +1,14 @@ +#pragma once +#include + +class BoundHoldAlg : public BoundAlg { +public: + BoundHoldAlg(const std::string& name, const mix_cc::json& rule_json, + const std::string& ruleId); + ~BoundHoldAlg() override; + + int init() override; + +protected: + AlarmInfo doMonProc() override; +}; diff --git a/eqpalg/algs/exp_base.cpp b/eqpalg/algs/exp_base.cpp index 758fb40..cbc9f3f 100644 --- a/eqpalg/algs/exp_base.cpp +++ b/eqpalg/algs/exp_base.cpp @@ -44,16 +44,7 @@ int ExpBase::init() { fb_fsm_.configure(keep_mode_, time_out_); } - if (exp_type_ == ExpType::Bound || exp_type_ == ExpType::CondBound || - exp_type_ == ExpType::BoundHoldTime) { - ret += this->reload_config_up_down(); /*7.上下限*/ - this->reload_ci_dist(); - this->last_load_time_ = chrono::system_clock::now(); - stat_collector_.configure(rule_id_, rule_name_, dist_mode_, is_learning_); - } - if (exp_type_ == ExpType::BoundHoldTime) { - ret += this->reload_config_up_down_hold_time(); /*8.上下限-保持时间*/ - } + doInitExtend(); } catch (const std::exception &e) { logger_->Debug() << e.what() << ".location:" << BOOST_CURRENT_LOCATION << endl; @@ -268,195 +259,13 @@ std::vector ExpBase::exec_task(mix_cc::time_range_t time_range) { } AlarmInfo ExpBase::mon_proc() { - // 监控基本过程 - double result_value; - filter_flag_ = false; expr_engine_->autoResetFunVars(); try { - // 获得是否满足前提条件表达式 - result_value = expr_engine_->evaluate("act"); - if (exp_type_ == ExpType::Bound || exp_type_ == ExpType::BoundHoldTime) { - try { - /*有数据筛选*/ - filter_flag_ = expr_engine_->evaluateBool("feedback"); - } catch (...) { - /*无数据筛选*/ - logger_->Debug() << "ruleid:" << rule_id_ << ",feedback evaluate ERROR!" - << endl; - filter_flag_ = true; - } - if (is_learning_ && filter_flag_ == true) { - rule_stat_.current_value = result_value; - SingletonTemp::GetInstance().add_stat_values(this->rule_id_, - result_value); - } - } - - bool act_triggered = static_cast(result_value); - // 如果是反馈模式 - if (feedback_mode_) { - // === 使用 FbStateMachine === - auto [fbState, needFunReset] = fb_fsm_.update( - act_triggered, now_time_, expr_engine_->vars(), m_tags.size()); - - if (needFunReset) { - expr_engine_->markFunVarsNeedReset(); - } - - if (fbState == FbState::Started) { - // 刚启动,下周期继续 - // query_time_range 左边界设为动作开始时间 - query_time_range_.set_left(now_time_); - return AlarmInfo{}; - } - - if (fbState == FbState::NotHold) { - return AlarmInfo{}; - } - - if (fbState == FbState::InProgress) { - // 检查反馈条件 - bool fbCond = expr_engine_->evaluateBool("feedback"); - bool done = fb_fsm_.checkFeedback(fbCond, now_time_, expr_engine_->vars()); - if (done) { - // 动作完成,计算结果 - query_time_range_.set_left( - query_time_range_.get_right() - - milliseconds(static_cast(expr_engine_->vars()["time"]))); - result_value = expr_engine_->evaluate("result"); - expr_engine_->markFunVarsNeedReset(); - rule_stat_.limit_down = limit_down_; - rule_stat_.limit_up = limit_up_; - rule_stat_.current_value = result_value; - - if (exp_type_ == ExpType::CondBound) { - if (is_learning_) { - SingletonTemp::GetInstance().add_stat_values( - rule_id_, result_value); - } - if (bound_checker_.isOutOfBounds(result_value)) { - rule_stat_.alarm_value = result_value; - std::string msg = ""; - if (fb_fsm_.isTimeMode()) { - msg = error_str_ + ":" + DAA::double2str(result_value) + - "ms,时间范围:[0," + DAA::double2str(bound_checker_.limitUp()) + "] ms"; - } else { - msg = error_str_ + ":" + DAA::double2str(result_value) + unit_ + - ",合理区间:[" + DAA::double2strLimit(bound_checker_.limitDown()) + "," + - DAA::double2strLimit(bound_checker_.limitUp()) + "]" + unit_; - } - return utility::build_alarm_info( - utility::get_msg_level(bound_checker_.limitDown(), bound_checker_.limitUp(), result_value), - rule_id_, rule_name_, "EXP4", msg, get_alarm_time()); - } - } else { - if (result_value) { - rule_stat_.alarm_value = result_value; - auto msg = rule_name_ + " " + error_str_; - return utility::build_alarm_info(MsgLevel::ERROR, rule_id_, - rule_name_, "EXP3", msg, - get_alarm_time()); - } - } - } - // fbCondition 不满足,继续 InProgress - return AlarmInfo{}; - } - - if (fbState == FbState::Timeout) { - if (!fb_fsm_.isTimeMode()) { - return AlarmInfo{}; - } - string msg = - rule_name_ + " 反馈超时:" + std::to_string(time_out_.count()) + " ms"; - logger_->Debug() << msg << endl; - return utility::build_alarm_info(MsgLevel::ERROR, rule_id_, rule_name_, - "EXPACT", msg, query_time_range_); - } - - // Idle state (from terminal auto-reset) — nothing to do - return AlarmInfo{}; - } - // 不是动作反馈 - else { - if (exp_type_ == ExpType::Bound) { - if (filter_flag_ == true && bound_checker_.isOutOfBounds(result_value)) { - rule_stat_.alarm_value = result_value; - auto msg = error_str_ + ":" + DAA::double2str(result_value) + unit_ + - ",合理区间:[" + DAA::double2strLimit(bound_checker_.limitDown()) + "," + - DAA::double2strLimit(bound_checker_.limitUp()) + "]" + unit_; - logger_->Debug() << msg << endl; - this->query_time_range_.set_left(query_time_range_.get_right() - - delay_time_); - expr_engine_->markFunVarsNeedReset(); - return utility::build_alarm_info(MsgLevel::ERROR, rule_id_, - rule_name_, "EXP2", msg, - this->get_alarm_time()); - } - } - else if (exp_type_ == ExpType::BoundHoldTime) { - - bool is_over_up_down = - bound_checker_.isOutOfBounds(result_value); - if (!filter_flag_) { - /*前提条件不满足*/ - act_start_time_ = this->now_time_; - act_started_ = false; - } else { - /*前提条件满足*/ - /*检查范围*/ - if (is_over_up_down) { - /*超范围*/ - if (!act_started_) { - // 首次检测到异常,记录开始时间 - act_started_ = true; - act_start_time_ = this->now_time_; - } - /*检查时间*/ - if ((hold_time_ <= delay_time_) || - (now_time_ - act_start_time_ > hold_time_)) { - rule_stat_.alarm_value = result_value; - auto msg = error_str_ + ":" + DAA::double2str(result_value) + - unit_ + ",合理区间:[" + - DAA::double2strLimit(bound_checker_.limitDown()) + "," + - DAA::double2strLimit(bound_checker_.limitUp()) + "]" + unit_; - expr_engine_->printVars(); - this->query_time_range_.set_left(query_time_range_.get_right() - - delay_time_); - expr_engine_->markFunVarsNeedReset(); - act_start_time_ = - this->now_time_; - act_started_ = false; - return utility::build_alarm_info( - utility::get_msg_level(bound_checker_.limitDown(), bound_checker_.limitUp(), result_value), - rule_id_, rule_name_, "EXP5", msg, this->get_alarm_time()); - } - } else { - act_start_time_ = this->now_time_; - act_started_ = false; - } - } - } - else { - if (act_triggered) { - rule_stat_.alarm_value = act_triggered; - expr_engine_->printVars(); - auto msg = rule_name_ + " " + error_str_; - logger_->Debug() << msg << endl; - this->query_time_range_.set_left(query_time_range_.get_right() - - delay_time_); - expr_engine_->markFunVarsNeedReset(); - return utility::build_alarm_info(MsgLevel::ERROR, rule_id_, - rule_name_, "EXP1", msg, - this->get_alarm_time()); - } - } - } + return doMonProc(); } catch (const std::exception &e) { gb_logger_->log_error("rule_name:" + rule_name_ + ",error:" + e.what()); return AlarmInfo{}; } - return AlarmInfo{}; } bool ExpBase::get_cycled_cron() { auto now = system_clock::now(); diff --git a/eqpalg/algs/exp_base.h b/eqpalg/algs/exp_base.h index 48a8a40..0766b26 100644 --- a/eqpalg/algs/exp_base.h +++ b/eqpalg/algs/exp_base.h @@ -103,6 +103,17 @@ public: bool get_prr() override; protected: + /** + * @brief 子类实现的具体算法逻辑 + * @return AlarmInfo + */ + virtual AlarmInfo doMonProc() = 0; + + /** + * @brief 子类扩展初始化(钩子) + */ + virtual void doInitExtend() {} + /** * @brief 重新载入数据源信息 * @return int @@ -120,7 +131,6 @@ protected: */ bool get_cycled_cron(); -private: /** * @brief 载入上下限 * @return int @@ -128,7 +138,7 @@ private: int reload_config_up_down(); /** - * @brief载入上、下限及保持时间 + * @brief 载入上、下限及保持时间 * @return int */ int reload_config_up_down_hold_time(); diff --git a/eqpalg/algs/feedback_alg.cpp b/eqpalg/algs/feedback_alg.cpp new file mode 100644 index 0000000..707e54e --- /dev/null +++ b/eqpalg/algs/feedback_alg.cpp @@ -0,0 +1,116 @@ +#include +#include +#include +#include + +FeedbackAlg::FeedbackAlg(const std::string& name, const mix_cc::json& rule_json, + const std::string& ruleId, size_t exp_type) + : ExpBase(name, rule_json, ruleId, exp_type), + hasBoundCheck_(exp_type == ExpType::CondBound) { + logger_.reset(new LOG("FeedbackAlg:" + rule_name_, AUTO_CATCH_PID)); +} + +FeedbackAlg::~FeedbackAlg() = default; + +void FeedbackAlg::doInitExtend() { + if (hasBoundCheck_) { + reload_config_up_down(); + reload_ci_dist(); + last_load_time_ = std::chrono::system_clock::now(); + stat_collector_.configure(rule_id_, rule_name_, dist_mode_, is_learning_); + } +} + +AlarmInfo FeedbackAlg::doMonProc() { + double result_value = expr_engine_->evaluate("act"); + + // CondBound: filter + statistics + if (hasBoundCheck_) { + bool filter_ok = true; + try { + filter_ok = expr_engine_->evaluateBool("feedback"); + } catch (...) {} + if (is_learning_ && filter_ok) { + rule_stat_.current_value = result_value; + SingletonTemp::GetInstance().add_stat_values(rule_id_, result_value); + } + } + + bool triggered = static_cast(result_value); + + // === FbStateMachine === + auto [fbState, needFunReset] = fb_fsm_.update( + triggered, now_time_, expr_engine_->vars(), m_tags.size()); + + if (needFunReset) { + expr_engine_->markFunVarsNeedReset(); + } + + if (fbState == FbState::Started) { + query_time_range_.set_left(now_time_); + return AlarmInfo{}; + } + + if (fbState == FbState::NotHold) { + return AlarmInfo{}; + } + + if (fbState == FbState::InProgress) { + bool fbCond = expr_engine_->evaluateBool("feedback"); + bool done = fb_fsm_.checkFeedback(fbCond, now_time_, expr_engine_->vars()); + if (done) { + query_time_range_.set_left( + query_time_range_.get_right() - + std::chrono::milliseconds(static_cast(expr_engine_->vars()["time"]))); + result_value = expr_engine_->evaluate("result"); + expr_engine_->markFunVarsNeedReset(); + rule_stat_.limit_down = bound_checker_.limitDown(); + rule_stat_.limit_up = bound_checker_.limitUp(); + rule_stat_.current_value = result_value; + + if (hasBoundCheck_) { + if (is_learning_) { + SingletonTemp::GetInstance().add_stat_values( + rule_id_, result_value); + } + if (bound_checker_.isOutOfBounds(result_value)) { + rule_stat_.alarm_value = result_value; + std::string msg; + if (fb_fsm_.isTimeMode()) { + msg = error_str_ + ":" + DAA::double2str(result_value) + + "ms,时间范围:[0," + DAA::double2str(bound_checker_.limitUp()) + "] ms"; + } else { + msg = error_str_ + ":" + DAA::double2str(result_value) + unit_ + + ",合理区间:[" + DAA::double2strLimit(bound_checker_.limitDown()) + + "," + DAA::double2strLimit(bound_checker_.limitUp()) + "]" + unit_; + } + return utility::build_alarm_info( + utility::get_msg_level(bound_checker_.limitDown(), + bound_checker_.limitUp(), result_value), + rule_id_, rule_name_, "EXP4", msg, get_alarm_time()); + } + } else { + if (static_cast(result_value)) { + rule_stat_.alarm_value = result_value; + auto msg = rule_name_ + " " + error_str_; + return utility::build_alarm_info(MsgLevel::ERROR, rule_id_, + rule_name_, "EXP3", msg, + get_alarm_time()); + } + } + } + return AlarmInfo{}; + } + + if (fbState == FbState::Timeout) { + if (fb_fsm_.isTimeMode()) { + std::string msg = rule_name_ + " 反馈超时:" + + std::to_string(time_out_.count()) + " ms"; + return utility::build_alarm_info(MsgLevel::ERROR, rule_id_, rule_name_, + "EXPACT", msg, query_time_range_); + } + return AlarmInfo{}; + } + + return AlarmInfo{}; +} diff --git a/eqpalg/algs/feedback_alg.h b/eqpalg/algs/feedback_alg.h new file mode 100644 index 0000000..df7fdf1 --- /dev/null +++ b/eqpalg/algs/feedback_alg.h @@ -0,0 +1,16 @@ +#pragma once +#include + +class FeedbackAlg : public ExpBase { +public: + FeedbackAlg(const std::string& name, const mix_cc::json& rule_json, + const std::string& ruleId, size_t exp_type); + ~FeedbackAlg() override; + +protected: + AlarmInfo doMonProc() override; + void doInitExtend() override; + +private: + bool hasBoundCheck_; // CondBound (exp_type 4) vs Logic (exp_type 3) +}; diff --git a/eqpalg/algs/logic_alg.cpp b/eqpalg/algs/logic_alg.cpp new file mode 100644 index 0000000..1fa406a --- /dev/null +++ b/eqpalg/algs/logic_alg.cpp @@ -0,0 +1,24 @@ +#include +#include + +LogicAlg::LogicAlg(const std::string& name, const mix_cc::json& rule_json, + const std::string& ruleId) + : ExpBase(name, rule_json, ruleId, ExpType::Logic) { + logger_.reset(new LOG("LogicAlg:" + rule_name_, AUTO_CATCH_PID)); +} + +LogicAlg::~LogicAlg() = default; + +AlarmInfo LogicAlg::doMonProc() { + double result_value = expr_engine_->evaluate("act"); + + if (static_cast(result_value)) { + rule_stat_.alarm_value = result_value; + auto msg = rule_name_ + " " + error_str_; + query_time_range_.set_left(query_time_range_.get_right() - delay_time_); + expr_engine_->markFunVarsNeedReset(); + return utility::build_alarm_info(MsgLevel::ERROR, rule_id_, rule_name_, + "EXP1", msg, get_alarm_time()); + } + return AlarmInfo{}; +} diff --git a/eqpalg/algs/logic_alg.h b/eqpalg/algs/logic_alg.h new file mode 100644 index 0000000..7a4be64 --- /dev/null +++ b/eqpalg/algs/logic_alg.h @@ -0,0 +1,12 @@ +#pragma once +#include + +class LogicAlg : public ExpBase { +public: + LogicAlg(const std::string& name, const mix_cc::json& rule_json, + const std::string& ruleId); + ~LogicAlg() override; + +protected: + AlarmInfo doMonProc() override; +};