2026-05-09 11:23:45 +08:00
|
|
|
|
|
|
|
|
|
|
#include "mix_cc/ihyper_db/read_data_stats.h"
|
|
|
|
|
|
#include <base/BitTool.h>
|
|
|
|
|
|
#include <eqpalg/algs/trend_slope2.h>
|
|
|
|
|
|
#include <eqpalg/feature_extraction/daa.h>
|
|
|
|
|
|
#include <eqpalg/utility/build_alarm_info.h>
|
|
|
|
|
|
#include <limits>
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
#include <utility/StringHelper.h>
|
|
|
|
|
|
#include <vector>
|
2026-05-09 13:30:09 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-05-09 11:23:45 +08:00
|
|
|
|
|
|
|
|
|
|
TrendSlope2::TrendSlope2(const string name, const mix_cc::json &rule_json,
|
|
|
|
|
|
const string ruleId)
|
|
|
|
|
|
: AlgBase(name, rule_json, ruleId) {
|
|
|
|
|
|
logger_.reset(new LOG("TrendSlope2:" + rule_name_, AUTO_CATCH_PID));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TrendSlope2::~TrendSlope2() {
|
2026-05-09 13:30:09 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-05-09 11:23:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int TrendSlope2::init() {
|
|
|
|
|
|
int res = 0;
|
|
|
|
|
|
try {
|
|
|
|
|
|
res += AlgBase::init();
|
|
|
|
|
|
double interval_time = std::stod(rule_json_.at("function")
|
|
|
|
|
|
.at("limit_error")
|
|
|
|
|
|
.at("param")
|
|
|
|
|
|
.at("interval_time")
|
|
|
|
|
|
.at("value")
|
|
|
|
|
|
.get<std::string>());
|
2026-05-09 13:30:09 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-05-09 11:23:45 +08:00
|
|
|
|
limit_time_interval_ = seconds(int(interval_time));
|
|
|
|
|
|
if (limit_time_interval_ < seconds(1)) {
|
|
|
|
|
|
limit_time_interval_ = seconds(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
limit_slope_ = std::stod(rule_json_.at("function")
|
|
|
|
|
|
.at("limit_error")
|
|
|
|
|
|
.at("param")
|
|
|
|
|
|
.at("diff")
|
|
|
|
|
|
.at("value")
|
|
|
|
|
|
.get<std::string>());
|
|
|
|
|
|
string need_tag = rule_json_.at("function")
|
|
|
|
|
|
.at("limit_error")
|
|
|
|
|
|
.at("value")
|
|
|
|
|
|
.get<std::string>();
|
|
|
|
|
|
need_tag_seq_ = std::stoi(need_tag.substr(3)) - 1;
|
|
|
|
|
|
|
|
|
|
|
|
double deltaX = std::stod(rule_json_.at("function")
|
|
|
|
|
|
.at("limit_error")
|
|
|
|
|
|
.at("param")
|
|
|
|
|
|
.at("deltaX")
|
|
|
|
|
|
.at("value")
|
|
|
|
|
|
.get<std::string>());
|
|
|
|
|
|
deltaX_ = seconds(int(deltaX * 60));
|
|
|
|
|
|
CS_AVG_SIZE_ = std::stoi(rule_json_.at("function")
|
|
|
|
|
|
.at("limit_error")
|
|
|
|
|
|
.at("param")
|
|
|
|
|
|
.at("CS_AVG_SIZE")
|
|
|
|
|
|
.at("value")
|
|
|
|
|
|
.get<std::string>());
|
|
|
|
|
|
|
2026-05-09 13:30:09 +08:00
|
|
|
|
this->rule_stat_.limit_down = 0;
|
|
|
|
|
|
this->rule_stat_.limit_up = 0;
|
2026-05-09 11:23:45 +08:00
|
|
|
|
error_content_ =
|
|
|
|
|
|
rule_json_.at("output").at("error").at("value").get<std::string>();
|
|
|
|
|
|
logger_->Debug() << "查询均值时间[s]:"
|
|
|
|
|
|
<< limit_time_interval_.count() / 1000
|
|
|
|
|
|
<< ",监控量变化率:" << limit_slope_ << ",单位间隔时间:"
|
|
|
|
|
|
<< deltaX_.count() << "ms,连续出现次数:" << CS_AVG_SIZE_
|
|
|
|
|
|
<< ",报警内容:" << error_content_ << endl;
|
|
|
|
|
|
this->data_source_ = DataSource::IHDB;
|
|
|
|
|
|
|
|
|
|
|
|
} catch (const std::exception &e) {
|
|
|
|
|
|
std::throw_with_nested(
|
|
|
|
|
|
mix_cc::Exception(-1, "load error", BOOST_CURRENT_LOCATION));
|
|
|
|
|
|
}
|
|
|
|
|
|
return res;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AlarmInfo TrendSlope2::exec_mon() {
|
|
|
|
|
|
AlarmInfo out_alarm{};
|
|
|
|
|
|
int count_error = 0;
|
2026-05-09 13:30:09 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-05-09 11:23:45 +08:00
|
|
|
|
now_time_ =
|
2026-05-09 13:30:09 +08:00
|
|
|
|
system_clock::now() - 60s;
|
2026-05-09 11:23:45 +08:00
|
|
|
|
vector<double> avg;
|
|
|
|
|
|
double f_slope = 0.0;
|
2026-05-09 13:30:09 +08:00
|
|
|
|
double f_slope_max = 0;
|
2026-05-09 11:23:45 +08:00
|
|
|
|
try {
|
|
|
|
|
|
/* before --> now*/
|
|
|
|
|
|
// 检查6个周期的时间内数据的斜率是否小于目标斜率
|
|
|
|
|
|
auto start_time = now_time_ - this->deltaX_ * CS_AVG_SIZE_;
|
|
|
|
|
|
for (int i = 0; i < CS_AVG_SIZE_ + 1; i++) {
|
|
|
|
|
|
query_time_range_.set_left(start_time - limit_time_interval_);
|
|
|
|
|
|
query_time_range_.set_right(start_time);
|
|
|
|
|
|
if (!query_time_range_.valid()) {
|
|
|
|
|
|
logger_->Error() << "时间数据 不合法" << std::endl;
|
|
|
|
|
|
return out_alarm;
|
|
|
|
|
|
}
|
|
|
|
|
|
logger_->Debug() << "时间范围"
|
|
|
|
|
|
<< mix_cc::mix_time_t(query_time_range_.get_left())
|
|
|
|
|
|
.to_formatted_time()
|
|
|
|
|
|
<< " "
|
|
|
|
|
|
<< mix_cc::mix_time_t(query_time_range_.get_right())
|
|
|
|
|
|
.to_formatted_time()
|
|
|
|
|
|
<< std::endl;
|
2026-05-09 13:30:09 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-05-09 11:23:45 +08:00
|
|
|
|
if (refresh_ihd_cache(query_time_range_) != 0) {
|
|
|
|
|
|
logger_->Error() << rule_name_ << ":ihd查询异常!" << std::endl;
|
|
|
|
|
|
return out_alarm;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!get_prr2()) {
|
|
|
|
|
|
logger_->Error() << rule_name_ << ":不满足前提表达式" << std::endl;
|
|
|
|
|
|
return out_alarm;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double avgi = queried_data_.col(need_tag_seq_).mean();
|
|
|
|
|
|
avg.push_back(avgi);
|
|
|
|
|
|
logger_->Debug() << "avg[" << i << "]:" << avgi << endl;
|
|
|
|
|
|
start_time = start_time + this->deltaX_;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string msgslope;
|
|
|
|
|
|
for (int i = 0; i < CS_AVG_SIZE_ + 1; i++) {
|
|
|
|
|
|
if (i > 0) {
|
|
|
|
|
|
f_slope = static_cast<int>(1000.0 * (avg[i] - avg[i - 1]) + 0.5);
|
|
|
|
|
|
f_slope = f_slope / 1000;
|
|
|
|
|
|
f_slope_max = (abs(f_slope_max) > abs(f_slope)) ? f_slope_max : f_slope;
|
|
|
|
|
|
if ((limit_slope_ > 0 && f_slope > limit_slope_) ||
|
|
|
|
|
|
(limit_slope_ < 0 && f_slope < limit_slope_)) {
|
|
|
|
|
|
msgslope += " " + DAA::double2str(f_slope, 3);
|
|
|
|
|
|
count_error++;
|
|
|
|
|
|
logger_->Debug() << msgslope << endl;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
msgslope = "";
|
|
|
|
|
|
count_error = 0;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (count_error == CS_AVG_SIZE_) {
|
|
|
|
|
|
rule_stat_.current_value = 1;
|
|
|
|
|
|
rule_stat_.alarm_value = f_slope_max;
|
|
|
|
|
|
string msg = error_content_ + " 斜率变化量:" + msgslope;
|
|
|
|
|
|
logger_->Debug() << msg << endl;
|
|
|
|
|
|
|
|
|
|
|
|
query_time_range_.set_right(now_time_);
|
|
|
|
|
|
query_time_range_.set_left(
|
|
|
|
|
|
now_time_ - (deltaX_ * (CS_AVG_SIZE_)-limit_time_interval_));
|
|
|
|
|
|
return utility::build_alarm_info(MsgLevel::ERROR, rule_id_, rule_name_,
|
|
|
|
|
|
"SLOPE", msg, query_time_range_);
|
|
|
|
|
|
}
|
|
|
|
|
|
rule_stat_.current_value = 0;
|
|
|
|
|
|
} catch (const std::exception &e) {
|
|
|
|
|
|
std::throw_with_nested(
|
|
|
|
|
|
mix_cc::Exception(-1, "calc error", BOOST_CURRENT_LOCATION));
|
|
|
|
|
|
}
|
|
|
|
|
|
return out_alarm;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<AlarmInfo> TrendSlope2::exec_task(mix_cc::time_range_t time_range) {
|
|
|
|
|
|
std::vector<AlarmInfo> result;
|
|
|
|
|
|
for (auto now_time = time_range.get_left();
|
|
|
|
|
|
now_time <= time_range.get_right(); now_time += delay_time_) {
|
|
|
|
|
|
this->now_time_ = now_time;
|
|
|
|
|
|
auto rr1 = this->exec_mon();
|
|
|
|
|
|
if (rr1.alarmed) {
|
|
|
|
|
|
result.push_back(rr1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool TrendSlope2::get_prr2() {
|
|
|
|
|
|
if (this->prr_ == 1) {
|
|
|
|
|
|
exp_mpdule_ptr_->update(queried_data_, queried_time_);
|
|
|
|
|
|
bool prr_result = (bool)exp_mpdule_ptr_->get_value("pre_result");
|
|
|
|
|
|
this->now_prr_ = prr_result;
|
|
|
|
|
|
logger_->Debug() << "ruleid:" << this->rule_id_
|
|
|
|
|
|
<< ",rulename:" << this->rule_name_
|
|
|
|
|
|
<< " get_prr():" << prr_result << std::endl;
|
|
|
|
|
|
return prr_result;
|
|
|
|
|
|
}
|
|
|
|
|
|
this->now_prr_ = true;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|