#include "pch.h" #include #include #include #include "DingDing.h" #include "HttpClient.h" #include "ConfigFile.h" typedef struct PushRecord { std::string strType; // 类型,消息内容也可以 std::int64_t nFirstTime; // 最近一次消息时间戳,秒 std::int32_t nTimeOut; // 超时时间,单位秒 std::int16_t nTotalCount; // 总需累积次数 std::int16_t nCurCount; // 当前累积次数 PushRecord(const std::string& strType, const std::int32_t& nTimeOut, const std::int16_t& nTotalCount) { this->strType = strType; this->nFirstTime = time(NULL); this->nTimeOut = nTimeOut; this->nTotalCount = nTotalCount; this->nCurCount = 0; } bool IsPush() { this->nCurCount++; if ((time(NULL) - this->nFirstTime) < nTimeOut && this->nCurCount >= this->nTotalCount) { // 该条件满足, 重置计数,便于下次计算 this->nFirstTime = time(NULL); this->nCurCount = 0; return true; } return false; } }CPushRecord; bool CDingDing::Push(const std::string & strInfo) { auto cfig = CConfigFile::getInstance(); if (!cfig->isPush()) return false; std::string content = cfig->projectName() + "\n[" + strInfo + "]"; Json::Value root; Json::Value child; Json::Value third; Json::StreamWriterBuilder builder; const std::unique_ptr writer(builder.newStreamWriter()); third["isAtAll"] = true; child["at"] = third; third.clear(); child["msgtype"] = "text"; third["content"] = ansi_to_utf8(content); child["text"] = third; root = child; content = Json::writeString(builder, root); std::string resp; auto eCode = CHttpClient::GetInStance()->curl_post_req(cfig->pushUrl().c_str(), content.c_str(), resp); return CURLE_OK == eCode ? true : false; } bool CDingDing::PushHeart(const std::string & strDev) { std::string strPushInfo = ""; strPushInfo = "[" + strDev + "] 心跳超时,请尽快检测程序是否运行正常"; return Push(strPushInfo); } bool CDingDing::PushHeart(const std::string & strDev, const bool & bIsPush, const bool& bIsRm) { auto cfig = CConfigFile::getInstance(); if (!cfig->isPush()) return false; static std::map mapDev; static std::mutex mut; std::stringstream ssPushInfo; std::unique_locklock(mut); if (bIsRm) { // 是否移除监听 mapDev.erase(strDev); } else { if (bIsPush) { // 更新时间戳 mapDev[strDev] = time(NULL); } else { // 不移除,不更新,说明在需要遍历是否心跳超时 // 遍历当前设备列表每个设备最近的消息时间 std::list ltPushInfo; // 待推送消息 std::int64_t lTimeStamp = 0; std::int64_t lCurTime = time(NULL); auto it = mapDev.begin(); while (it != mapDev.end()) { ssPushInfo.str(""); ssPushInfo.clear(); lTimeStamp = lCurTime - it->second; if (lTimeStamp > cfig->heartTimeOut()) { ssPushInfo << "[" << it->first << "] 心跳超时,请尽快检测程序是否运行正常;\n"; ssPushInfo << "当前配置超时时间为:" << cfig->heartTimeOut() << "秒;\n"; ssPushInfo << "实际超时时间为:" << lTimeStamp << "秒;\n"; ltPushInfo.emplace_back(ssPushInfo.str()); it = mapDev.erase(it); } else { ++it; } } lock.unlock(); // 推送到钉钉 for (auto pushInfo : ltPushInfo) { Push(pushInfo); } } } return true; } bool CDingDing::PushDisConn(const std::string & strDev) { std::string strPushInfo = ""; strPushInfo = "[" + strDev + "] 网络连接断开,请尽快检测程序是否运行正常"; return Push(strPushInfo); } bool CDingDing::PushIVRCellTimeOut() { // 60秒内触发5次就提醒 static CPushRecord pushRecord("IVR-流程超时提醒", 60, 5); if (pushRecord.IsPush()) { return Push(pushRecord.strType); } return true; } bool CDingDing::PushFailSQL(const std::string & strSql, const std::string& strErrInfo) { std::string strPushInfo = ""; strPushInfo = "SQL执行失败,错误信息:[" + strErrInfo + "];SQL=[" + strSql + "]"; return Push(strPushInfo); } bool CDingDing::PushFindFailChan() { // 60秒内触发5次就提醒 static CPushRecord pushRecord("处理通道事件时查找对应通道失败", 60, 5); if (pushRecord.IsPush()) { return Push(pushRecord.strType); } return true; } CDingDing CDingDing::instance; extern "C" DINGDING_API IDingDing* GetDingDing() { return CDingDing::GetInstance(); } //extern "C" DINGDING_API IDingDing* GetInstance() { // return CDingDing::GetInstance(); //};