#pragma once /** * @file eqpalg/algs/exp_sample.h * @brief 表达式-样本的实现 基类 * 这个类只会载入样本相关的信息,与前提表达式无关 * @author Cat (null.null.null@qq.com) * @version 0.1 * @date 2021-09-13 * * Copyright: Baosight Co. Ltd. * DO NOT COPY/USE WITHOUT PERMISSION * */ #include #include #include #include #include #include #include #include #include #include #include "mix_cc/ihyper_db/utility.h" #include "mix_cc/json.h" #include "mix_cc/type/mix_time.h" /** * @brief 表达式-样本类的实现 * @tparam dims 样本的维度 * 为什么使用template dims确定样本的维度? * 因为目前程序维度较低且相对固定 * 这样可以减少运行时开销 * 如果维度较高或不固定,请更改这个策略 */ class ExpSample : public Exp { public: /** * @brief 构建表达式样本类 * @param name My Param doc * @param rule_json My Param doc * @param ruleId My Param doc */ ExpSample(const string& name, const mix_cc::json& rule_json, const string& ruleId, size_t dims, double padding_low, double padding_up) : Exp(name, rule_json, ruleId, dims), last_load_time_(system_clock::now()), padding_low_(padding_low), padding_up_(padding_up) { logger_.reset(new LOG("ExpSample:" + rule_name_, AUTO_CATCH_PID)); } virtual ~ExpSample() {} public: /** * @brief 重新载入样本表达式中样本相关的配置 * @return int */ int init() override; protected: /** * @brief 执行监控 * @return AlarmInfo */ AlarmInfo exec_mon() override; /** * @brief cron 根据ihd的速度数据检查机组状态 * @return true * @return false */ bool cron_check_is_line_start(); protected: /** * @brief 重新载入样本相关配置信息 * @return int */ int reload_config_sample(); /** * @brief 打印动作开始行为 * @param result_value My Param doc * @return int */ int log_action_info(double result_value); /** * @brief 重载定时任务函数 * @return mix_cc::json */ mix_cc::json exec_cron() override; /** * @brief 重写exec_normal_task */ AlarmInfo exec_normal_task(mix_cc::time_range_t time_range) override; /** * @brief 最小的单元过程 * @tparam T * @tparam ReturnType * @return ReturnType */ template ReturnType base_proc() { double result_value; try { act_triggered_ = static_cast(exp_act_->evaluate()); // 检测是否是表达式-反馈模式 if (feedback_mode_) { // 如果是表达式反馈-模式,检测是否满足反馈条件 if (act_start_done() || act_not_hold()) { if constexpr (is_same_v) { return AlarmInfo{}; } else if constexpr (is_same_v) { return std::nullopt; } } feedback_triggered_ = static_cast(exp_feedback_->evaluate()); // 如果所有前提动作和条件均满足 if (act_done()) { result_value = exp_result_->evaluate(); this->log_action_info(result_value); // 刷 mv2 for (size_t i = 0; i < m_tags.size(); i++) { mm_vars["mv2_tag" + std::to_string(i + 1)] = 0; } // 并且数据合法 if (result_value != 0 && !std::isnan(result_value)) { if constexpr (is_same_v) { // 检查是否满足报警条件 auto alarm_info = this->sample_stat_->auto_detect_and_save( SamplePoint{result_value}, now_time_); // 如果报警,则把报警新返回 if (alarm_info) { return utility::build_alarm_info( MsgLevel::ERROR, rule_id_, rule_name_, "EXPSMP", error_str_ + alarm_info.alarm_str, alarm_info.value, alarm_info.range, query_time_range_); } } else if constexpr (is_same_v) { return std::make_optional(SamplePoint{result_value}); } } } else if (act_timeout()) { // 如果超时,则返回 this->get_timeout_alarm(); // 如果有必要,可以返回超时报警信息 } } // 表达式-样本,无需反馈,act_triggered_即为报警条件 2021-10-27 else if (act_triggered_) { // 同上,唯一不同 是这里无需假设反馈的条件 result_value = exp_result_->evaluate(); if (result_value != 0 && !std::isnan(result_value)) { if constexpr (is_same_v) { auto alarm_info = this->sample_stat_->auto_detect_and_save( SamplePoint{result_value}, now_time_); if (alarm_info) { return utility::build_alarm_info( MsgLevel::ERROR, rule_id_, rule_name_, "EXPSMP", error_str_ + alarm_info.alarm_str, alarm_info.value, alarm_info.range, query_time_range_); } } else if constexpr (is_same_v) { return std::make_optional(SamplePoint{result_value}); } } } } catch (const std::exception& e) { std::throw_with_nested( mix_cc::Exception(-1, "calc_once error", BOOST_CURRENT_LOCATION)); } if constexpr (is_same_v) { return AlarmInfo{}; } else if constexpr (is_same_v) { return std::nullopt; } } AlarmInfo mon_proc() override { return base_proc(); } virtual std::optional cron_proc_sample() { return base_proc>(); } protected: TimePoint last_load_time_; ///< 上一次载入的时间 ///< ExpSample构造时,初始化为构造时的时间 double judge_diff_; ///< 评判的数据差值 double padding_up_, padding_low_; ///< 数据浮动 stat_tools::TestMode test_mode_; ///< 0: absolute difference, 1: error ///< percentage (%), 2: normal TimePoint start_date_; ///< 取样开始时间 TimePoint end_date_; ///< 取样结束时间 bool is_no_down_limit_ = false; ///< 是否是无下限算法 int archive_interval_day_; ///< 归档间隔时间 std::unique_ptr sample_stat_; ///< 样本统计 };