#include #include #include #include #include #include #include #include #include #include enum QUERIES { INSTANT_QUERIES = 0, RANGE_QUERIES = 1 }; double calculateMean(std::vector vdata) { double sum = 0.0; for (auto const &iter: vdata) { sum += iter; } return sum / vdata.size(); } double calculateSD(std::vector vdata) { double mean, standardDeviation = 0.0; mean = calculateMean(vdata); for (auto const &iter: vdata) { standardDeviation += pow(iter - mean, 2); } return sqrt(standardDeviation / vdata.size()); } cpr::Response getValue(YAML::Node config, QUERIES queries, std::string strName = "") { auto prometheus_url = config["prometheus address"].as(); auto report_url = config["report address"].as(); auto interval = config["interval"].as(); auto range = config["time range"].as() - 1; auto job = config["job"].as(); auto data = config["data"].as(); spdlog::info("prometheus address : {}.", prometheus_url); spdlog::info("report address : {}.", report_url); spdlog::info("Interval of operation : {}s.", interval); spdlog::info("time range : {}s.", range); std::string str_query("{__name__=~\""); if (strName == "") { auto diagnosis = config["diagnosis"]; for (auto item: diagnosis) { if (item.IsNull() || item["name"].IsNull()) { continue; } auto name = item["name"].as(); str_query.append(name); str_query.append("|"); } str_query.pop_back(); } else { str_query.append(strName); } str_query.append("\",data=\""); str_query.append(data); str_query.append("\",job=\""); str_query.append(job); str_query.append("\"}"); spdlog::info("query: {}", str_query); QUERIES promql = queries; cpr::Response r; if (promql == INSTANT_QUERIES) { prometheus_url.append("/api/v1/query"); r = cpr::Get( cpr::Url{prometheus_url}, cpr::Parameters{{"query", str_query}} ); } else if (promql == RANGE_QUERIES) { std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); int64_t timepoint = std::chrono::duration_cast(now.time_since_epoch()).count(); prometheus_url.append("/api/v1/query_range"); r = cpr::Get( cpr::Url{prometheus_url}, cpr::Parameters{{"query", str_query}, {"start", std::to_string(timepoint - range)}, {"end", std::to_string(timepoint)}, {"step", "1s"}} ); } return r; } int main(int argc, char *argv[]) { spdlog::info("fault diagnosis"); std::string config_file_name = "./cfg.yml"; if (2 == argc) { config_file_name = argv[1]; } if (!std::filesystem::exists(config_file_name)) { spdlog::error("the config file({}) not exists.", config_file_name); return EXIT_FAILURE; } YAML::Node config = YAML::LoadFile(config_file_name); auto r = getValue(config, RANGE_QUERIES); if (200 != r.status_code) { spdlog::error("GET failed status_code: {}", r.status_code); return EXIT_FAILURE; } spdlog::info("URL: {}", r.url.str()); //spdlog::info("Response text : {}", r.text); nlohmann::json obj = nlohmann::json::parse(r.text.begin(), r.text.end(), nullptr, false); std::vector buff; double SD = 0; if (obj["status"] == "success") { spdlog::info("query success"); auto d = obj["data"]; if (d.size() > 0) { auto rt = d["resultType"]; auto r = d["result"]; if (rt == "matrix") { if (r.size() > 0) { for (auto res_iter: r) { auto metric_name = res_iter["metric"]["__name__"]; spdlog::info("metric name {}", metric_name); auto v = res_iter["values"]; if (v.size() > 0) { buff.clear(); //清除缓冲数组 for (auto const &iter: v) { if (iter.size() == 2) { auto value = iter.at(1); //spdlog::info("value: {}", value.get()); double n = atof(value.get().c_str()); //spdlog::info("value double: {}", n); buff.push_back(n); } else { spdlog::error("values size error"); return EXIT_FAILURE; } } ///计算标准差-1的绝对值 // SD = calculateSD(buff); // spdlog::info("mean: {}", calculateMean(buff)); // spdlog::info("standard deviation: {}", SD); // if (fabs(SD - 1) == 0 || fabs(SD - 1) > 1) { // spdlog::error("{} alert", metric_name); // } auto r1 = getValue(config, INSTANT_QUERIES, metric_name); if (200 != r1.status_code) { spdlog::error("GET failed status_code: {}", r1.status_code); return EXIT_FAILURE; } spdlog::warn("r1 URL: {}", r1.url.str()); spdlog::warn("r1 Response text : {}", r1.text); nlohmann::json obj1 = nlohmann::json::parse(r1.text.begin(), r1.text.end(), nullptr, false); if (obj1["status"] == "success") { spdlog::warn("query success"); auto d1 = obj1["data"]; if (d1.size() > 0) { auto rt1 = d1["resultType"]; auto re1 = d1["result"]; if (rt1 == "vector") { if (re1.size() == 1) { auto metric_name1 = re1.at(0)["metric"]["__name__"]; spdlog::warn("metric name {}", metric_name1); auto v1 = re1.at(0)["value"]; if (v1.size() == 2) { auto value1 = v1.at(1); double n1 = atof(value1.get().c_str()); SD = calculateSD(buff); spdlog::info("mean: {}", calculateMean(buff)); spdlog::info("standard deviation: {}", SD); spdlog::warn("value double: {}", n1); spdlog::warn("new value : {}",(n1-calculateMean(buff))/SD); } } else { spdlog::error("no result"); return EXIT_FAILURE; } } else { spdlog::error("resultType not vector"); return EXIT_FAILURE; } } else { spdlog::error("no data"); return EXIT_FAILURE; } } else { spdlog::error("query false"); return EXIT_FAILURE; } } else { spdlog::error("no values"); return EXIT_FAILURE; } } } else { spdlog::error("no result"); return EXIT_FAILURE; } } else { spdlog::error("resultType not matrix"); return EXIT_FAILURE; } } else { spdlog::error("no data"); return EXIT_FAILURE; } } else { spdlog::error("query false"); return EXIT_FAILURE; } // spdlog::info("json dump: {}", obj["data"]["result"].dump()); // nlohmann::json j = obj["data"]["result"].at(0); // spdlog::info("json values size: {}", j["values"].size()); // for (auto const &iter: j["values"]) { // if (iter.size() == 2) { // spdlog::info("value: {}",iter.at(1)); // } // } return 0; }