225 lines
7.9 KiB
C++
225 lines
7.9 KiB
C++
|
|
|
|||
|
|
#include <base/BitTool.h>
|
|||
|
|
#include <eqpalg/algs/roller.h>
|
|||
|
|
#include <eqpalg/feature_extraction/daa.h>
|
|||
|
|
#include <eqpalg/utility/build_alarm_info.h>
|
|||
|
|
#include <algorithm>
|
|||
|
|
#include <limits>
|
|||
|
|
#include <string>
|
|||
|
|
#include <utility>
|
|||
|
|
#include <vector>
|
|||
|
|
#include "mix_cc/ihyper_db.h"
|
|||
|
|
// 炉辊组算法无需额外的算法初始化步骤
|
|||
|
|
int Roller::init() {
|
|||
|
|
int res = 0;
|
|||
|
|
try {
|
|||
|
|
res += AlgBase::init();
|
|||
|
|
this->n_tags_ = m_tags.size();
|
|||
|
|
if (this->delay_time_ > 3min) {
|
|||
|
|
this->interval_time_ = this->delay_time_;
|
|||
|
|
} else {
|
|||
|
|
this->interval_time_ = 3min;
|
|||
|
|
}
|
|||
|
|
this->data_source_ = DataSource::IHDB;
|
|||
|
|
this->error_name_ =
|
|||
|
|
rule_json_.at("output").at("reason").at("value").get<std::string>();
|
|||
|
|
this->error_diff_ = std::stod(rule_json_.at("function")
|
|||
|
|
.at("result")
|
|||
|
|
.at("param")
|
|||
|
|
.at("limit_over")
|
|||
|
|
.at("value")
|
|||
|
|
.get<std::string>());
|
|||
|
|
this->error_content_ =
|
|||
|
|
rule_json_.at("output").at("error").at("value").get<std::string>();
|
|||
|
|
|
|||
|
|
print_load_content();
|
|||
|
|
} catch (const std::exception& e) {
|
|||
|
|
std::throw_with_nested(
|
|||
|
|
mix_cc::Exception(-1, "load error", BOOST_CURRENT_LOCATION));
|
|||
|
|
}
|
|||
|
|
return res;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Roller::Roller(const string name, const mix_cc::json& rule_json,
|
|||
|
|
const string ruleId)
|
|||
|
|
: AlgBase(name, rule_json, ruleId) {
|
|||
|
|
logger_.reset(new LOG("Roller:" + rule_name_, AUTO_CATCH_PID));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Roller::~Roller() {
|
|||
|
|
// AlgBase::~AlgBase();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
AlarmInfo Roller::exec_mon() {
|
|||
|
|
AlarmInfo now_alarm{};
|
|||
|
|
this->refresh_now_time();
|
|||
|
|
this->query_time_range_.set_left(this->now_time_ - this->interval_time_);
|
|||
|
|
this->query_time_range_.set_right(this->now_time_);
|
|||
|
|
auto ihd_result = this->refresh_mmean_tags_ihd();
|
|||
|
|
if (ihd_result == -1) {
|
|||
|
|
return now_alarm;
|
|||
|
|
}
|
|||
|
|
while (1) {
|
|||
|
|
auto result_base = exec_mon_base();
|
|||
|
|
if (result_base == 0 || result_base == -1) {
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (this->tags_errors_.size() != 0) {
|
|||
|
|
std::string msg = {};
|
|||
|
|
for (auto iter = this->tags_errors_.begin();
|
|||
|
|
iter != this->tags_errors_.end(); iter++) {
|
|||
|
|
msg = msg + " tag" + std::to_string(iter->first + 1) + ":" +
|
|||
|
|
DAA::double2str(this->mmean_tags_[iter->first]) + "," +
|
|||
|
|
BIG_SMALL[iter->second];
|
|||
|
|
}
|
|||
|
|
std::string error_info = this->error_name_ + this->error_content_ + msg;
|
|||
|
|
this->logger_->Debug() << "报警!" << this->rule_name_ << error_info
|
|||
|
|
<< std::endl;
|
|||
|
|
now_alarm =
|
|||
|
|
utility::build_alarm_info(MsgLevel::ERROR, rule_id_, rule_name_,
|
|||
|
|
"Roller", error_info, query_time_range_);
|
|||
|
|
} else {
|
|||
|
|
this->rule_stat_.limit_down = 0;
|
|||
|
|
this->rule_stat_.limit_up = 0;
|
|||
|
|
this->rule_stat_.current_value = 0;
|
|||
|
|
}
|
|||
|
|
this->logger_->Debug()
|
|||
|
|
<< this->rule_name_ << "执行完成 时间段"
|
|||
|
|
<< mix_cc::mix_time_t(this->query_time_range_.get_left())
|
|||
|
|
.to_formatted_time()
|
|||
|
|
<< "~"
|
|||
|
|
<< mix_cc::mix_time_t(this->query_time_range_.get_right())
|
|||
|
|
.to_formatted_time()
|
|||
|
|
<< std::endl;
|
|||
|
|
logger_->Debug() << "区间:[" << this->rule_stat_.limit_down << ","
|
|||
|
|
<< this->rule_stat_.limit_up
|
|||
|
|
<< "],当前值:" << this->rule_stat_.current_value << endl;
|
|||
|
|
return now_alarm;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int Roller::exec_mon_base() {
|
|||
|
|
int flag = 0;
|
|||
|
|
int n_tags = this->comparison_tags_.size();
|
|||
|
|
//计算均值
|
|||
|
|
int result = minmaxsum_get(this->comparison_tags_);
|
|||
|
|
double sum_mmean = this->min_max_sum_[2];
|
|||
|
|
double m_ave = sum_mmean / n_tags;
|
|||
|
|
if (n_tags > 2) {
|
|||
|
|
m_ave = (sum_mmean - this->min_max_sum_[0] - this->min_max_sum_[1]) /
|
|||
|
|
(n_tags - 2);
|
|||
|
|
}
|
|||
|
|
//寻找异常
|
|||
|
|
this->logger_->Debug() << "result=" << result << ",n_tags=" << n_tags
|
|||
|
|
<< std::endl;
|
|||
|
|
if (m_ave < std::numeric_limits<double>::epsilon() || result == -1) {
|
|||
|
|
return -1;
|
|||
|
|
} else {
|
|||
|
|
double diff_max = std::max(fabs(this->min_max_sum_[1] - m_ave),
|
|||
|
|
fabs(this->min_max_sum_[0] - m_ave));
|
|||
|
|
|
|||
|
|
for (auto iter = this->comparison_tags_.begin();
|
|||
|
|
iter != this->comparison_tags_.end();) {
|
|||
|
|
auto value_avg_diff = fabs(this->mmean_tags_[*iter] - m_ave);
|
|||
|
|
|
|||
|
|
if (fabs(diff_max - value_avg_diff) <
|
|||
|
|
std::numeric_limits<double>::epsilon() &&
|
|||
|
|
flag == 0 && fabs(100 * value_avg_diff / m_ave) > this->error_diff_) {
|
|||
|
|
flag++;
|
|||
|
|
this->rule_stat_.limit_down =
|
|||
|
|
fabs(m_ave) * (1 - this->error_diff_ / 100.0);
|
|||
|
|
this->rule_stat_.limit_up =
|
|||
|
|
fabs(m_ave) * (1 + this->error_diff_ / 100.0);
|
|||
|
|
this->rule_stat_.current_value = this->mmean_tags_[*iter];
|
|||
|
|
this->rule_stat_.alarm_value = this->rule_stat_.current_value;
|
|||
|
|
logger_->Debug() << rule_name_ << ",diff_max:" << diff_max
|
|||
|
|
<< ",value_avg_diff:" << value_avg_diff
|
|||
|
|
<< ",error_diff_:" << error_diff_ << ",m_ave:" << m_ave
|
|||
|
|
<< ",min:" << this->min_max_sum_[0]
|
|||
|
|
<< ",max:" << this->min_max_sum_[1]
|
|||
|
|
<< ",sum:" << this->min_max_sum_[2]
|
|||
|
|
<< ",n_tag2:" << n_tags << std::endl;
|
|||
|
|
if (this->mmean_tags_[*iter] > m_ave) {
|
|||
|
|
tags_errors_[*iter] = 0; ///<过大
|
|||
|
|
} else {
|
|||
|
|
tags_errors_[*iter] = 1; ///<过小
|
|||
|
|
}
|
|||
|
|
iter = this->comparison_tags_.erase(iter);
|
|||
|
|
this->logger_->Debug() << "flag=" << flag << std::endl;
|
|||
|
|
} else {
|
|||
|
|
iter++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return flag;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* @brief 获取待检查tag值的 min max sum
|
|||
|
|
* @param comparison_tags My Param doc
|
|||
|
|
* @return int
|
|||
|
|
*/
|
|||
|
|
int Roller::minmaxsum_get(std::vector<int> comparison_tags) {
|
|||
|
|
if (comparison_tags.size() < 3) {
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
this->min_max_sum_ = {this->mmean_tags_[comparison_tags[0]],
|
|||
|
|
this->mmean_tags_[comparison_tags[0]], 0};
|
|||
|
|
for (int i = 0; i < comparison_tags.size(); i++) {
|
|||
|
|
this->min_max_sum_[0] =
|
|||
|
|
std::min(this->min_max_sum_[0], this->mmean_tags_[comparison_tags[i]]);
|
|||
|
|
this->min_max_sum_[1] =
|
|||
|
|
std::max(this->min_max_sum_[1], this->mmean_tags_[comparison_tags[i]]);
|
|||
|
|
this->min_max_sum_[2] += this->mmean_tags_[comparison_tags[i]];
|
|||
|
|
}
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
std::vector<AlarmInfo> Roller::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();
|
|||
|
|
result.push_back(rr1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* @brief
|
|||
|
|
* 初始化map和vector:1.mmean_tags_ 更新查询的结果;
|
|||
|
|
* 2.comparison_tags_ 初始化待检查的tag(map的key)
|
|||
|
|
* 3. tags_errors_ = {}; 异常tag及对应的异常结果(map的key,0-1)置空
|
|||
|
|
* @return int
|
|||
|
|
*/
|
|||
|
|
int Roller::refresh_mmean_tags_ihd() {
|
|||
|
|
this->comparison_tags_ = {};
|
|||
|
|
this->tags_errors_ = {};
|
|||
|
|
for (unsigned int i = 0; i < this->n_tags_; i++) {
|
|||
|
|
auto ave_maybe = mix_cc::ihd::read_data_stats_maybe(
|
|||
|
|
m_tags[i], this->query_time_range_, HD3_STATS_TYPE_ARITH_MEAN);
|
|||
|
|
if (ave_maybe.is_nothing()) {
|
|||
|
|
this->logger_->Debug() << this->rule_name_ << ":ihd查询失败" << std::endl;
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
this->mmean_tags_[i] = ave_maybe.unsafe_get_just();
|
|||
|
|
this->comparison_tags_.push_back(i);
|
|||
|
|
}
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void Roller::print_load_content() {
|
|||
|
|
this->logger_->Debug()
|
|||
|
|
<< "执行周期:"
|
|||
|
|
<< std::to_string(
|
|||
|
|
std::chrono::duration_cast<std::chrono::seconds>(this->delay_time_)
|
|||
|
|
.count())
|
|||
|
|
<< "s,均值查询时间段:"
|
|||
|
|
<< std::to_string(std::chrono::duration_cast<std::chrono::seconds>(
|
|||
|
|
this->interval_time_)
|
|||
|
|
.count())
|
|||
|
|
<< "s,报警名称:" << this->error_name_
|
|||
|
|
<< ",阈值:" << std::to_string(this->error_diff_)
|
|||
|
|
<< ",报警内容:" << this->error_content_ << std::endl;
|
|||
|
|
}
|