Просмотр исходного кода

Z991239-5462 #comment fea: guiconsole send entity status through thread in duration

chenliangyu 1 год назад
Родитель
Сommit
d2e7bc9c38

+ 6 - 0
Module/include/EventCode.h

@@ -704,6 +704,12 @@ ERROR_ACCESSAUTH_CONNECT_ACS_x}
 #define WARN_GUICONSOLE_PERFORMANCE_PROCESS32FIRST	0x50820402
 //openLogSender not vaild input
 #define WARN_GUICONSOLE_LOGSENDER_UNVAILD_INPUT	0x50820501
+//entity monitor get entity info failed
+#define WARN_GUICONSOLE_ENTITYMONITOR_GETINFO_FAILED	0x50820601
+//entityMonitor failed:thread already existed
+#define WARN_GUICONSOLE_ENTITYMONITOR_EXISTED		0x50820602
+//entityMonitor failed:thread not exist
+#define WARN_GUICONSOLE_ENTITYMONITOR_NOTEXISTED		0x50820603
 
 
 

+ 49 - 0
Module/mod_guiconsole/GUIConsole_client_g.h

@@ -499,6 +499,55 @@ public:
 		return Error;
 	}
 
+	ErrorCodeEnum GetBasicInformation(GUIConsoleService_GetBasicInformation_Req &Req, CSmartPointer<IAsynWaitSp> &spAsyncWait, DWORD dwTimeout)
+	{
+		CSmartPointer<IClientSessionFunction> pFunc = GetFunction();
+		CAutoBuffer Buf = SpObject2Buffer(Req);
+		if (m_context.checkEmpty())
+		{
+			m_context.AutoGenerate();
+			DbgToBeidou(m_context, m_pEntityBase != NULL ? m_pEntityBase->GetEntityName() : "")();
+			m_context = m_context.upgradeLink();
+		}
+		auto ret = pFunc->AsyncRequest(GUIConsoleService_Method_GetBasicInformation, GUIConsoleService_MethodSignature_GetBasicInformation, Buf, spAsyncWait, m_context, dwTimeout);
+		m_context.clear();
+		return ret;
+	}
+	ErrorCodeEnum GetBasicInformation(GUIConsoleService_GetBasicInformation_Req &Req, GUIConsoleService_GetBasicInformation_Ans &Ans, DWORD dwTimeout)
+	{
+		CSmartPointer<IAsynWaitSp> spAsyncWait;
+		ErrorCodeEnum Error = GetBasicInformation(Req, spAsyncWait, dwTimeout);
+		if (Error == Error_Succeed) {
+			bool bEnd = false;
+			Error = SpWaitAnswerObject(spAsyncWait, Ans, bEnd, dwTimeout);
+			LOG_ASSERT(Error || bEnd);
+		}
+		return Error;
+	}
+	ErrorCodeEnum GetBasicInformation(GUIConsoleService_GetBasicInformation_Req &Req, GUIConsoleService_GetBasicInformation_Ans &Ans, DWORD dwTimeout, DWORD &dwUserError, CSimpleString &str)
+	{
+		CSmartPointer<IAsynWaitSp> spAsyncWait;
+		ErrorCodeEnum Error = GetBasicInformation(Req, spAsyncWait, dwTimeout);
+		if (Error == Error_Succeed) {
+			bool bEnd = false;
+			Error = SpWaitAnswerObject(spAsyncWait, Ans, bEnd, dwUserError, str, dwTimeout);
+			LOG_ASSERT(Error || bEnd);
+		}
+		return Error;
+	}
+	ErrorCodeEnum GetBasicInformation(GUIConsoleService_GetBasicInformation_Req &Req, GUIConsoleService_GetBasicInformation_Ans &Ans, DWORD dwTimeout, DWORD &dwUserError)
+	{
+		CSmartPointer<IAsynWaitSp> spAsyncWait;
+		ErrorCodeEnum Error = GetBasicInformation(Req, spAsyncWait, dwTimeout);
+		if (Error == Error_Succeed) {
+			bool bEnd = false;
+			CSimpleString str;
+			Error = SpWaitAnswerObject(spAsyncWait, Ans, bEnd, dwUserError, str, dwTimeout);
+			LOG_ASSERT(Error || bEnd);
+		}
+		return Error;
+	}
+
 
 	bool SafeDelete()
 	{

+ 31 - 3
Module/mod_guiconsole/GUIConsole_def_g.h

@@ -21,6 +21,7 @@ namespace GUIConsole {
 #define GUIConsoleService_Method_VTMSystemControl 6
 #define GUIConsoleService_Method_VTM_controlEntity 7
 #define GUIConsoleService_Method_GetAllEntityList 8
+#define GUIConsoleService_Method_GetBasicInformation 9
 
 #define GUIConsoleService_MethodSignature_OpenLogSender -744778557
 #define GUIConsoleService_MethodSignature_CloseLogSender -1838250527
@@ -31,6 +32,7 @@ namespace GUIConsole {
 #define GUIConsoleService_MethodSignature_VTMSystemControl -1084584417
 #define GUIConsoleService_MethodSignature_VTM_controlEntity -580226164
 #define GUIConsoleService_MethodSignature_GetAllEntityList 1179841316
+#define GUIConsoleService_MethodSignature_GetBasicInformation 217932562
 
 #define GUIConsoleService_LogCode_OpenLogSender "QLR040250800"
 #define GUIConsoleService_LogCode_CloseLogSender "QLR040250801"
@@ -41,6 +43,7 @@ namespace GUIConsole {
 #define GUIConsoleService_LogCode_VTMSystemControl "QLR040250806"
 #define GUIConsoleService_LogCode_VTM_controlEntity "QLR040250807"
 #define GUIConsoleService_LogCode_GetAllEntityList "QLR040250808"
+#define GUIConsoleService_LogCode_GetBasicInformation "QLR040250809"
 
 struct GUIConsoleService_OpenLogSender_Req
 {
@@ -94,13 +97,13 @@ struct GUIConsoleService_CloseLogSender_Ans
 
 struct GUIConsoleService_OpenEntityMonitor_Req
 {
-	int reserved1;
-	int reserved2;
+	int longestFrequence;
+	int leastFrequence;
 	CSimpleStringA reserved3;
 
 	void Serialize(SpBuffer &Buf)
 	{
-		auto & buf = Buf & reserved1 & reserved2 & reserved3;
+		auto & buf = Buf & longestFrequence & leastFrequence & reserved3;
 	}
 
 };
@@ -274,6 +277,31 @@ struct GUIConsoleService_GetAllEntityList_Ans
 
 };
 
+struct GUIConsoleService_GetBasicInformation_Req
+{
+	int reserved1;
+	int reserved2;
+	CSimpleStringA reserved3;
+
+	void Serialize(SpBuffer &Buf)
+	{
+		auto & buf = Buf & reserved1 & reserved2 & reserved3;
+	}
+
+};
+
+struct GUIConsoleService_GetBasicInformation_Ans
+{
+	bool result;
+	CSimpleStringA additionalMsg;
+
+	void Serialize(SpBuffer &Buf)
+	{
+		auto & buf = Buf & result & additionalMsg;
+	}
+
+};
+
 
 ///////////////////////////
 

+ 8 - 6
Module/mod_guiconsole/GUIConsole_msg_g.h

@@ -19,15 +19,17 @@ namespace GUIConsole {
 
 struct EntityStatus
 {
-	CSimpleStringA entityName;
-	CSimpleStringA status;
-	CSimpleStringA processId;
-	CSimpleStringA versionNo;
-	CSimpleStringA lastStartTime;
+	bool result;
+	CSimpleStringA additionalMsg;
+	CAutoArray<CSimpleStringA> entityName;
+	CAutoArray<CSimpleStringA> status;
+	CAutoArray<CSimpleStringA> processId;
+	CAutoArray<CSimpleStringA> versionNo;
+	CAutoArray<CSimpleStringA> lastStartTime;
 
 	void Serialize(SpBuffer &Buf)
 	{
-		auto & buf = Buf & entityName & status & processId & versionNo & lastStartTime;
+		auto & buf = Buf & result & additionalMsg & entityName & status & processId & versionNo & lastStartTime;
 	}
 
 };

+ 27 - 0
Module/mod_guiconsole/GUIConsole_server_g.h

@@ -93,6 +93,13 @@ public:
 				Error = Error_MethodSignatureFailed;
 			}
 			break;
+		case GUIConsoleService_Method_GetBasicInformation:
+			if (dwSignature == GUIConsoleService_MethodSignature_GetBasicInformation) {
+				bOverlap = true;
+			} else {
+				Error = Error_MethodSignatureFailed;
+			}
+			break;
 		default:
 			Error = Error_MethodNotFound;
 			break;
@@ -149,6 +156,11 @@ public:
 				Error = Error_MethodSignatureFailed;
 			}
 			break;
+		case GUIConsoleService_Method_GetBasicInformation:
+			if (dwSignature != GUIConsoleService_MethodSignature_GetBasicInformation) {
+				Error = Error_MethodSignatureFailed;
+			}
+			break;
 		default:
 			Error = Error_MethodNotFound;
 			break;
@@ -201,6 +213,11 @@ public:
 	/// override by user
 	}
 
+	virtual void Handle_GetBasicInformation(SpReqAnsContext<GUIConsoleService_GetBasicInformation_Req, GUIConsoleService_GetBasicInformation_Ans>::Pointer ctx)
+	{
+	/// override by user
+	}
+
 	virtual void OnRequest(CSmartPointer<ITransactionContext> pTransactionContext)
 	{
 		CAutoBuffer Buf;
@@ -307,6 +324,16 @@ public:
 						Handle_GetAllEntityList(ctx);
 					}
 					break;
+				case GUIConsoleService_Method_GetBasicInformation:
+					{
+						SpReqAnsContext<GUIConsoleService_GetBasicInformation_Req,GUIConsoleService_GetBasicInformation_Ans>::Pointer ctx;
+						ctx.Attach(new SpReqAnsContext<GUIConsoleService_GetBasicInformation_Req,GUIConsoleService_GetBasicInformation_Ans>(pTransactionContext));
+						SpBuffer2Object(Buf, ctx->Req);
+						pTransactionContext->GetLinkContext(ctx->link);
+						EntityResource::setLink(ctx->link);
+						Handle_GetBasicInformation(ctx);
+					}
+					break;
 				default:
 					assert(0);
 					break;

+ 20 - 23
Module/mod_guiconsole/GuiConsole.xml

@@ -40,10 +40,10 @@
 		<!-- 定义一个名为 OpenEntityMonitor 的双向通信,用于打开实体监控功能,我认为这个一直发会比较消耗内网资源,因为需要一直有状态更新,只在ST环境打开 -->
 		<twoway name="OpenEntityMonitor" overlap="true" simpleret="true">
 			<req>
-				<!-- 预留参数1,类型为整数 -->
-				<param name="reserved1" type="int"/>
-				<!-- 预留参数2,类型为整数 -->
-				<param name="reserved2" type="int"/>
+				<!-- 最大发送频率-秒,类型为整数,建议为60s, 意思为最长更新一次时间为60s -->
+				<param name="longestFrequence" type="int"/>
+				<!-- 最小发送频率-秒,类型为整数,建议为2s, 意思为最短更新一次时间为2s,避免启动时因为很多实体同时更新状态,引发的频发更新 -->
+				<param name="leastFrequence" type="int"/>
 				<!-- 预留参数3,类型为字符串 -->
 				<param name="reserved3" type="string"/>
 			</req>
@@ -161,15 +161,7 @@
 				<!-- 实体名称数组,类型为字符串数组 -->
 				<param name="entityName" type="array_string"/>
 				<!-- 状态数组,类型为字符串数组, 有效值包含
-				"NoStart",
-			"Starting",
-			"Idle",
-			"Busy",
-			"Pause",
-			"UnLoading",
-			"Lost",
-			"Close",
-			"Killed",-->
+				"NoStart",			"Starting",			"Idle",	"Busy",			"Pause",			"UnLoading"		"Lost",	"Close",	"Killed",-->
 				<param name="status" type="array_string"/>
 				<!-- 进程ID数组,类型为字符串数组 -->
 				<param name="processId" type="array_string"/>
@@ -199,16 +191,21 @@
 	</class>
 	<!-- 定义一个名为 EntityStatus 的消息,用于发送实体状态信息, 与OpenEntityMonitor,CloseEntityMonitor配合使用 -->
 	<message name="EntityStatus" simpleret="true">
-		<!-- 实体名称,类型为字符串 -->
-		<param name="entityName" type="string"/>
-		<!-- 状态,类型为字符串 -->
-		<param name="status" type="string"/>
-		<!-- 进程ID,类型为字符串 -->
-		<param name="processId" type="string"/>
-		<!-- 版本号,类型为字符串 -->
-		<param name="versionNo" type="string"/>
-		<!-- 最后启动时间,类型为字符串 -->
-		<param name="lastStartTime" type="string"/>
+		<!-- 操作结果,类型为布尔值 -->
+		<param name="result" type="bool"/>
+		<!-- 附加消息,类型为字符串 -->
+		<param name="additionalMsg" type="string"/>
+		<!-- 实体名称数组,类型为字符串数组 -->
+		<param name="entityName" type="array_string"/>
+		<!-- 状态数组,类型为字符串数组, 有效值包含
+				"NoStart",			"Starting",			"Idle",	"Busy",			"Pause",			"UnLoading"		"Lost",	"Close",	"Killed",-->
+		<param name="status" type="array_string"/>
+		<!-- 进程ID数组,类型为字符串数组 -->
+		<param name="processId" type="array_string"/>
+		<!-- 版本号数组,类型为字符串数组 -->
+		<param name="versionNo" type="array_string"/>
+		<!-- 最后启动时间数组,类型为字符串数组 -->
+		<param name="lastStartTime" type="array_string"/>
 	</message>
 	<!-- 定义一个名为 LogInfo 的消息 与OpenLogSender, CloseLogSender配合使用-->
 	<message name="LogInfo" simpleret="true">

+ 78 - 0
Module/mod_guiconsole/guiconsole_define.cpp

@@ -78,6 +78,84 @@ void PollMemInfo(memInfo& info)
 	info.UpTime = GetTickCount64();
 }
 
+/* Linux reference
+	timer->stop();
+
+	ui->performTableWidget->clearContents();
+
+	process->start("/bin/bash");
+	if(process->waitForStarted(3000)) {
+		process->write(cmd.toLatin1());
+		process->closeWriteChannel();
+		process->waitForFinished(3000);
+		QString result = process->readAllStandardOutput();
+		QRegularExpression reg;
+		reg.setPattern(" +");
+		result = result.replace(reg," ");
+		QStringList elemList = result.split("\n");
+		elemList.removeFirst();
+		elemList.removeLast();
+		ui->performTableWidget->setRowCount(elemList.length());
+		for(int i=0;i< elemList.length();i++) {
+			QString line = elemList.at(i);
+			QStringList elems = line.split(" ");
+			QString strPID = elems.at(RAW_PID_INDEX);
+			bool root = false, related = false;
+			for(int j=0; j<ui->performTableWidget->columnCount(); j++) {
+				QTableWidgetItem* item = new QTableWidgetItem;
+				item->setBackground((i % 2 != 0) ? QColor("#f5f5f5") : QColor("#ffffff"));
+				if(j== COLUMN_NAME_INDEX) {
+					item->setWhatsThis(strPID);
+					line = elems.at(RAW_COMMAND_INDEX);
+					if (line.compare("spshell", Qt::CaseInsensitive) == 0
+						|| line.compare("sphost", Qt::CaseInsensitive) == 0
+						|| line.compare("cefclient", Qt::CaseInsensitive) == 0
+						|| line.compare("guardian", Qt::CaseInsensitive) == 0) {
+						related = true;
+						item->setForeground(QBrush(Qt::red));
+
+						if (line.compare("sphost", Qt::CaseInsensitive) == 0 && elems.count() > 7 && elems.at(7).startsWith("mod_")) {
+							line = elems.at(7);
+						}
+					}
+
+					item->setToolTip(line);
+					item->setText(line);
+				}
+				else if (j == COLUMN_PID_INDEX) {
+					item->setTextAlignment(Qt::AlignHCenter);
+					item->setText(elems.at(RAW_PID_INDEX));
+				}
+				else if (j == COLUMN_CPU_INDEX) {
+					item->setTextAlignment(Qt::AlignHCenter);
+					item->setText(elems.at(RAW_CPU_INDEX));
+				}
+				else if (j == COLUMN_MEM_INDEX) {
+					item->setTextAlignment(Qt::AlignHCenter);
+					item->setText(elems.at(RAW_MEM_INDEX));
+				}
+				else if(j== COLUMN_COMMAND_INDEX)
+				{
+					line = elems.mid(5).join(" ");
+					item->setText(line);
+					item->setToolTip(line);
+				} else if(j == COLUMN_FDS_INDEX) {
+					if (related) {
+						int fds = GetProcessFdsImpl(pro, strPID.toInt());
+						item->setText(QString::number(fds));
+					} else {
+						item->setText("NA");
+					}
+
+				}
+				ui->performTableWidget->setItem(i, j, item);
+			}
+		}
+	}
+
+	timer->start();
+
+	*/
 
 std::pair<long, std::string> PollProcessList(long UpdateTime, system_monitor_status& curStatus)
 {

+ 11 - 2
Module/mod_guiconsole/mod_GuiConsole.h

@@ -5,6 +5,9 @@ using namespace GUIConsole;
 #include "SpBase.h"
 #include "guiconsole_define.h"
 #include <thread>
+#include <condition_variable>
+#include <mutex>
+#include <chrono>
 
 // 本地控制台 GUIConsole	0x508
 class CGUIConsoleEntity;
@@ -60,7 +63,7 @@ public:
 
 	std::pair<DWORD, std::string> openLogSender(SpReqAnsContext<GUIConsoleService_OpenLogSender_Req, GUIConsoleService_OpenLogSender_Ans>::Pointer ctx);
 	std::pair<DWORD, std::string> closeLogSender();
-	std::pair<DWORD, std::string> openEntityMonitor();
+	std::pair<DWORD, std::string> openEntityMonitor(SpReqAnsContext<GUIConsoleService_OpenEntityMonitor_Req, GUIConsoleService_OpenEntityMonitor_Ans>::Pointer ctx);
 	std::pair<DWORD, std::string> closeEntityMonitor();
 	std::pair<DWORD, std::string> openPerformanceSender(SpReqAnsContext<GUIConsoleService_OpenPerformanceSender_Req, GUIConsoleService_OpenPerformanceSender_Ans>::Pointer ctx);
 	std::pair<DWORD, std::string> closePerformanceSender();
@@ -102,6 +105,12 @@ private:
 	bool m_isOpenLogSender, m_isOpenEntityMonitor, m_isOpenPerformanceSender;
 	int m_performanceSenderFrequence, m_sendLogType;
 	CUUID m_logSubID;
-	std::thread *thread_performanceSend;
+	std::thread *thread_performanceSend, *thread_entityMonitor;
+
+	int m_longestEntityMonitor, m_leastEntityMonitor;
+	std::condition_variable m_entityMonitor_cv;
+	std::mutex m_entityMonitro_lock;
+	bool m_entityMonitor_shouldwork;
+	std::chrono::steady_clock::time_point m_entityMonitorlast_notify_time;
 };
 

+ 146 - 101
Module/mod_guiconsole/mod_guiconsole.cpp

@@ -50,29 +50,32 @@ void CGUIConsoleEntity::OnLog(const CAutoArray<CUUID>& SubIDs, const CUUID nLogI
 void CGUIConsoleEntity::OnEntityStateHook(const char* pszEntityName, const char* pszTriggerEntity, EntityStateEnum eState, EntityStateEnum eLastState)
 {
 	//did not open log sender
-	if (!m_isOpenLogSender)
-		return;
-
-	LogInfo msg;
-	if (eLastState == EntityState_Idle && eState != EntityState_Idle)
-	{
-		msg.sysError = ErrorCodeEnum::Error_Closed;
-		msg.userCode = ErrorCodeEnum::Error_Closed;
-		msg.message = CSimpleString::Format("%s实体异常,重新启动...", pszEntityName);
-	}
-	else
+	if (m_isOpenLogSender)
 	{
-		msg.sysError = ErrorCodeEnum::Error_Succeed;
-		msg.userCode = ErrorCodeEnum::Error_Succeed;
-		if (eState == EntityState_Starting)
-			msg.message = CSimpleString::Format("正在启动实体%s...", pszEntityName);
-		else if(eState == EntityState_Idle)
-			msg.message = CSimpleString::Format("%s 实体启动成功", pszEntityName);
-	}
+		LogInfo msg;
+		if (eLastState == EntityState_Idle && eState != EntityState_Idle)
+		{
+			msg.sysError = ErrorCodeEnum::Error_Closed;
+			msg.userCode = ErrorCodeEnum::Error_Closed;
+			msg.message = CSimpleString::Format("%s实体异常,重新启动...", pszEntityName);
+		}
+		else
+		{
+			msg.sysError = ErrorCodeEnum::Error_Succeed;
+			msg.userCode = ErrorCodeEnum::Error_Succeed;
+			if (eState == EntityState_Starting)
+				msg.message = CSimpleString::Format("正在启动实体%s...", pszEntityName);
+			else if (eState == EntityState_Idle)
+				msg.message = CSimpleString::Format("%s 实体启动成功", pszEntityName);
+		}
+
+		msg.timeStr = GenerateTimeStr().c_str();
+		msg.entityName = pszEntityName;
+		SpSendBroadcast(GetFunction(), eMsg_LogInfo, eMsgSig_LogInfo, msg);
+	}	
 
-	msg.timeStr = GenerateTimeStr().c_str();
-	msg.entityName = pszEntityName;
-	SpSendBroadcast(GetFunction(), eMsg_LogInfo, eMsgSig_LogInfo, msg);
+	if (m_isOpenEntityMonitor)
+		PostEntityVary(pszEntityName);//if registered, while entity status changed, send to web
 }
 
 
@@ -101,6 +104,9 @@ std::pair<DWORD, std::string> CGUIConsoleEntity::openLogSender(SpReqAnsContext<G
 		else
 			m_sendLogType = logType;
 		auto rc = GetFunction()->SubscribeLog(m_logSubID, this, (LogTypeEnum)m_sendLogType, Severity_None, Error_IgnoreAll, -1, NULL, false);
+		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("openLogSender SubscribeLog %s %s", ctx->Req.LogType.GetData(), 
+			(rc == ErrorCodeEnum::Error_Succeed ? "success" : "failed"));
+
 		m_isOpenLogSender = (rc == ErrorCodeEnum::Error_Succeed);
 		return std::pair<DWORD, std::string>(rc, "");
 	}
@@ -121,98 +127,99 @@ std::pair<DWORD, std::string> CGUIConsoleEntity::closeLogSender()
 		auto rc = GetFunction()->UnsubscribeLog(m_logSubID);
 		if(rc == ErrorCodeEnum::Error_Succeed)
 			m_logSubID = 0;
+
+		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("closeLogSender UnsubscribeLog %s", (rc == ErrorCodeEnum::Error_Succeed ? "success" : "failed"));
+
 		m_isOpenLogSender = !(rc == ErrorCodeEnum::Error_Succeed);
 		return std::pair<DWORD, std::string>(rc, "");
 	}
 }
 
-std::pair<DWORD, std::string> CGUIConsoleEntity::openEntityMonitor()
+std::pair<DWORD, std::string> CGUIConsoleEntity::openEntityMonitor(SpReqAnsContext<GUIConsoleService_OpenEntityMonitor_Req, GUIConsoleService_OpenEntityMonitor_Ans>::Pointer ctx)
 {
 	m_isOpenEntityMonitor = true;
-	/*
-	timer->stop();
-
-    ui->performTableWidget->clearContents();
-
-    process->start("/bin/bash");
-    if(process->waitForStarted(3000)) {
-        process->write(cmd.toLatin1());
-        process->closeWriteChannel();
-        process->waitForFinished(3000);
-        QString result = process->readAllStandardOutput();
-        QRegularExpression reg;
-        reg.setPattern(" +");
-        result = result.replace(reg," ");
-        QStringList elemList = result.split("\n");
-        elemList.removeFirst();
-        elemList.removeLast();
-        ui->performTableWidget->setRowCount(elemList.length());
-        for(int i=0;i< elemList.length();i++) {
-            QString line = elemList.at(i);
-            QStringList elems = line.split(" ");
-            QString strPID = elems.at(RAW_PID_INDEX);
-            bool root = false, related = false;
-            for(int j=0; j<ui->performTableWidget->columnCount(); j++) {
-                QTableWidgetItem* item = new QTableWidgetItem;
-                item->setBackground((i % 2 != 0) ? QColor("#f5f5f5") : QColor("#ffffff"));
-                if(j== COLUMN_NAME_INDEX) {
-                    item->setWhatsThis(strPID);
-                    line = elems.at(RAW_COMMAND_INDEX);
-                    if (line.compare("spshell", Qt::CaseInsensitive) == 0 
-                        || line.compare("sphost", Qt::CaseInsensitive) == 0
-                        || line.compare("cefclient", Qt::CaseInsensitive) == 0
-                        || line.compare("guardian", Qt::CaseInsensitive) == 0) {
-                        related = true;
-                        item->setForeground(QBrush(Qt::red));
-
-                        if (line.compare("sphost", Qt::CaseInsensitive) == 0 && elems.count() > 7 && elems.at(7).startsWith("mod_")) {
-                            line = elems.at(7);
-                        }
-                    }
-
-                    item->setToolTip(line);
-                    item->setText(line);
-                }
-                else if (j == COLUMN_PID_INDEX) {
-                    item->setTextAlignment(Qt::AlignHCenter);
-                    item->setText(elems.at(RAW_PID_INDEX));
-                }
-                else if (j == COLUMN_CPU_INDEX) {
-                    item->setTextAlignment(Qt::AlignHCenter);
-                    item->setText(elems.at(RAW_CPU_INDEX));
-                }
-                else if (j == COLUMN_MEM_INDEX) {
-                    item->setTextAlignment(Qt::AlignHCenter);
-                    item->setText(elems.at(RAW_MEM_INDEX));
-                }
-                else if(j== COLUMN_COMMAND_INDEX)
-                {
-                    line = elems.mid(5).join(" ");
-                    item->setText(line);
-                    item->setToolTip(line);
-                } else if(j == COLUMN_FDS_INDEX) {
-                    if (related) {
-                        int fds = GetProcessFdsImpl(pro, strPID.toInt());
-                        item->setText(QString::number(fds));
-                    } else {
-                        item->setText("NA");
-                    }
-
-                }
-                ui->performTableWidget->setItem(i, j, item);
-            }
-        }
-    }
-
-    timer->start();
+	if (ctx->Req.longestFrequence <= 1)
+		m_longestEntityMonitor = 1;
+	else
+		m_longestEntityMonitor = ctx->Req.longestFrequence;
+	if (ctx->Req.leastFrequence <= 1)
+		m_leastEntityMonitor = 1;
+	else
+		m_leastEntityMonitor = ctx->Req.leastFrequence;
+
+	m_entityMonitor_shouldwork = true;
+
+	auto entityMonitorSender = [this] {
+		while (m_isOpenEntityMonitor)
+		{
+			std::unique_lock<std::mutex> guard(m_entityMonitro_lock);
+			m_entityMonitor_cv.wait(guard, [this] {
+				return m_entityMonitor_shouldwork || (std::chrono::steady_clock::now() - m_entityMonitorlast_notify_time >=  std::chrono::seconds(m_longestEntityMonitor));
+				});
+
+			m_entityMonitorlast_notify_time = std::chrono::steady_clock::now();
+			m_entityMonitor_shouldwork = false;
+			EntityStatus cur;
+			CAutoArray<EntityEntry> Entities;
+			auto ret = GetAllEntity(Entities);
+			if (ret.first != ErrorCodeEnum::Error_Succeed)
+			{
+				LogWarn(SeverityLevelEnum::Severity_Middle, ErrorCodeEnum::Error_AlreadyExist, WARN_GUICONSOLE_ENTITYMONITOR_GETINFO_FAILED,
+					CSimpleStringA::Format("openEntityMonitor - GetAllEntity failed, %d", ret.first));
+				continue;
+			}
+			cur.entityName.Init(Entities.GetCount());
+			cur.status.Init(Entities.GetCount());
+			cur.processId.Init(Entities.GetCount());
+			cur.versionNo.Init(Entities.GetCount());
+			cur.lastStartTime.Init(Entities.GetCount());
+
+			for (int i = 0; i < Entities.GetCount(); ++i) {
+				cur.entityName[i] = Entities[i].Name;
+				cur.status[i] = EntityEntry::GetStateName(Entities[i].State);
+				cur.processId[i] = std::to_string(Entities[i].Pid).c_str();
+				cur.versionNo[i] = getRunVersion();
+				cur.lastStartTime[i] = Entities[i].lastStartTime.ToTimeString();
+			}
+
+			SpSendBroadcast(GetFunction(), eMsg_EntityStatus, eMsgSig_EntityStatus, cur);
+
+			
+
+			std::this_thread::yield();
+		}
+	};
+
+	if (thread_entityMonitor != NULL)
+	{
+		LogWarn(SeverityLevelEnum::Severity_Middle, ErrorCodeEnum::Error_AlreadyExist, WARN_GUICONSOLE_ENTITYMONITOR_EXISTED,
+			"openEntityMonitor, thread_entityMonitor already existed");
+		return std::pair<DWORD, std::string>(WARN_GUICONSOLE_ENTITYMONITOR_EXISTED, "");
+	}
 	
-	*/
+	thread_entityMonitor = new std::thread(entityMonitorSender);
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("openEntityMonitor create entityMonitor sender thread %s,  leastFrequence:%d, m_longestEntityMonitor:%d",
+		(thread_entityMonitor != NULL ? "success" : "failed"), m_leastEntityMonitor, m_longestEntityMonitor);
+
 	return std::pair<DWORD, std::string>(Error_Succeed, "");
 }
 
 std::pair<DWORD, std::string> CGUIConsoleEntity::closeEntityMonitor()
 {
 	m_isOpenEntityMonitor = false;
+
+	if (thread_entityMonitor == NULL)
+	{
+		LogWarn(SeverityLevelEnum::Severity_Middle, ErrorCodeEnum::Error_NotExist, WARN_GUICONSOLE_ENTITYMONITOR_NOTEXISTED,
+			"closeEntityMonitor, thread_entityMonitor not exist");
+		return std::pair<DWORD, std::string>(WARN_GUICONSOLE_ENTITYMONITOR_NOTEXISTED, "");
+	}
+
+	thread_entityMonitor->join();
+	delete thread_entityMonitor;
+	thread_entityMonitor = NULL;
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("closeEntityMonitor close entityMonitor sender thread success");
+
 	return std::pair<DWORD, std::string>(Error_Succeed, "");
 }
 
@@ -260,6 +267,9 @@ std::pair<DWORD, std::string> CGUIConsoleEntity::openPerformanceSender(SpReqAnsC
 
 	thread_performanceSend = new std::thread(performanceSender);
 
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("openPerformanceSender create performance sender thread %s,  sendFrequence:%d",
+		(thread_performanceSend != NULL ? "success" : "failed"), m_performanceSenderFrequence);
+
 	return std::pair<DWORD, std::string>(Error_Succeed, "");
 }
 
@@ -277,6 +287,8 @@ std::pair<DWORD, std::string> CGUIConsoleEntity::closePerformanceSender()
 	delete thread_performanceSend;
 	thread_performanceSend = NULL;
 
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("closePerformanceSender close performance sender thread success");
+
 	return std::pair<DWORD, std::string>(Error_Succeed, "");
 }
 
@@ -339,7 +351,8 @@ std::pair<DWORD, std::string> CGUIConsoleEntity::VTM_controlEntity(SpReqAnsConte
 
 CGUIConsoleEntity::CGUIConsoleEntity()
 	:m_isOpenLogSender(false), m_isOpenEntityMonitor(false), m_isOpenPerformanceSender(false),
-	m_sendLogType(LogTypeEnum::Log_Warning), thread_performanceSend(NULL)
+	m_sendLogType(LogTypeEnum::Log_Warning), thread_performanceSend(NULL), thread_entityMonitor(NULL),
+	m_longestEntityMonitor(60), m_leastEntityMonitor(2)
 {
 }
 
@@ -355,59 +368,74 @@ CGUIConsoleEntity::~CGUIConsoleEntity()
 		thread_performanceSend = NULL;
 	}
 
+	if (thread_entityMonitor)
+	{
+		thread_entityMonitor->detach();
+		delete thread_entityMonitor;
+		thread_entityMonitor = NULL;
+	}
 }
 
 
 void CGUIConsoleSession::Handle_OpenLogSender(SpReqAnsContext<GUIConsoleService_OpenLogSender_Req, GUIConsoleService_OpenLogSender_Ans>::Pointer ctx)
 {
+	DbgToBeidou(ctx->link, __FUNCTION__)();
 	auto ret = m_pEntity->openLogSender(ctx);
 	ctx->Answer((ErrorCodeEnum)ret.first, (ErrorCodeEnum)ret.first);
 }
 
 void CGUIConsoleSession::Handle_CloseLogSender(SpReqAnsContext<GUIConsoleService_CloseLogSender_Req, GUIConsoleService_CloseLogSender_Ans>::Pointer ctx)
 {
+	DbgToBeidou(ctx->link, __FUNCTION__)();
 	auto ret = m_pEntity->closeLogSender();
 	ctx->Answer((ErrorCodeEnum)ret.first, (ErrorCodeEnum)ret.first);
 }
 
 void CGUIConsoleSession::Handle_OpenEntityMonitor(SpReqAnsContext<GUIConsoleService_OpenEntityMonitor_Req, GUIConsoleService_OpenEntityMonitor_Ans>::Pointer ctx)
 {
-	auto ret = m_pEntity->openEntityMonitor();
+	DbgToBeidou(ctx->link, __FUNCTION__)();
+	auto ret = m_pEntity->openEntityMonitor(ctx);
 	ctx->Answer((ErrorCodeEnum)ret.first, (ErrorCodeEnum)ret.first);
 }
 
 void CGUIConsoleSession::Handle_CloseEntityMonitor(SpReqAnsContext<GUIConsoleService_CloseEntityMonitor_Req, GUIConsoleService_CloseEntityMonitor_Ans>::Pointer ctx)
 {
+	DbgToBeidou(ctx->link, __FUNCTION__)();
 	auto ret = m_pEntity->closeEntityMonitor();
 	ctx->Answer((ErrorCodeEnum)ret.first, (ErrorCodeEnum)ret.first);
 }
 
 void CGUIConsoleSession::Handle_OpenPerformanceSender(SpReqAnsContext<GUIConsoleService_OpenPerformanceSender_Req, GUIConsoleService_OpenPerformanceSender_Ans>::Pointer ctx)
 {
+	DbgToBeidou(ctx->link, __FUNCTION__)();
 	auto ret = m_pEntity->openPerformanceSender(ctx);
 	ctx->Answer((ErrorCodeEnum)ret.first, (ErrorCodeEnum)ret.first);
 }
 
 void CGUIConsoleSession::Handle_ClosePerformanceSender(SpReqAnsContext<GUIConsoleService_ClosePerformanceSender_Req, GUIConsoleService_ClosePerformanceSender_Ans>::Pointer ctx)
 {
+	DbgToBeidou(ctx->link, __FUNCTION__)();
 	auto ret = m_pEntity->closePerformanceSender();
 	ctx->Answer((ErrorCodeEnum)ret.first, (ErrorCodeEnum)ret.first);
 }
 
 void CGUIConsoleSession::Handle_VTMSystemControl(SpReqAnsContext<GUIConsoleService_VTMSystemControl_Req, GUIConsoleService_VTMSystemControl_Ans>::Pointer ctx)
 {
+	DbgToBeidou(ctx->link, __FUNCTION__)();
 	auto ret = m_pEntity->VTMSystemControl(ctx);
 	ctx->Answer((ErrorCodeEnum)ret.first, (ErrorCodeEnum)ret.first);
 }
 
 void CGUIConsoleSession::Handle_VTM_controlEntity(SpReqAnsContext<GUIConsoleService_VTM_controlEntity_Req, GUIConsoleService_VTM_controlEntity_Ans>::Pointer ctx)
 {
+	DbgToBeidou(ctx->link, __FUNCTION__)();
 	auto ret = m_pEntity->VTM_controlEntity(ctx);
 	ctx->Answer((ErrorCodeEnum)ret.first, (ErrorCodeEnum)ret.first);
 }
 
 void CGUIConsoleSession::Handle_GetAllEntityList(SpReqAnsContext<GUIConsoleService_GetAllEntityList_Req, GUIConsoleService_GetAllEntityList_Ans>::Pointer ctx)
 {
+	DbgToBeidou(ctx->link, __FUNCTION__)();
 	CAutoArray<EntityEntry> Entities;
 	auto ret = m_pEntity->GetAllEntity(Entities);
 	if (ret.first != ErrorCodeEnum::Error_Succeed)
@@ -572,6 +600,7 @@ ErrorCodeEnum CGUIConsoleEntity::GetEntity(const char* entity_name, EntityEntry&
 
 void CGUIConsoleEntity::PostEntityVary(const char* entity_name)
 {
+	DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("PostEntityVary %s ", entity_name);
 	EntityEntry ret;
 	DWORD rc;
 	if (ErrorCodeEnum::Error_Succeed != (rc = GetEntity(entity_name, ret)))
@@ -581,6 +610,21 @@ void CGUIConsoleEntity::PostEntityVary(const char* entity_name)
 		return;
 	}
 
+	
+	auto now = std::chrono::steady_clock::now();
+	if (now - m_entityMonitorlast_notify_time < std::chrono::seconds(m_leastEntityMonitor)) {
+		return; // m_leastEntityMonitor seconds not passed, ignore this notification
+	}
+
+	{
+		std::lock_guard<std::mutex> guard(m_entityMonitro_lock);
+		m_entityMonitor_shouldwork = true;
+	}//release lock this time
+
+
+	m_entityMonitor_cv.notify_one();
+
+	/*
 	EntityStatus cur;
 	cur.entityName = entity_name;
 	cur.status = EntityEntry::GetStateName(ret.State);
@@ -588,6 +632,7 @@ void CGUIConsoleEntity::PostEntityVary(const char* entity_name)
 	cur.versionNo = getRunVersion();
 	cur.lastStartTime = ret.lastStartTime.ToTimeString();
 	SpSendBroadcast(GetFunction(), eMsg_EntityStatus, eMsgSig_EntityStatus, cur);
+	*/
 }