mirror of
				https://github.com/Icinga/icinga2.git
				synced 2025-10-31 11:14:10 +01:00 
			
		
		
		
	JsonRpcConnection: Log message processing time stats
Co-Authored-By: Julian Brost <julian.brost@icinga.com>
This commit is contained in:
		
							parent
							
								
									e0b053cbe1
								
							
						
					
					
						commit
						4564c068fe
					
				| @ -60,13 +60,19 @@ void JsonRpcConnection::Start() | |||||||
| 
 | 
 | ||||||
| void JsonRpcConnection::HandleIncomingMessages(boost::asio::yield_context yc) | void JsonRpcConnection::HandleIncomingMessages(boost::asio::yield_context yc) | ||||||
| { | { | ||||||
|  | 	namespace ch = std::chrono; | ||||||
|  | 
 | ||||||
|  | 	auto toMilliseconds ([](ch::steady_clock::duration d) { | ||||||
|  | 		return ch::duration_cast<ch::milliseconds>(d).count(); | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
| 	m_Stream->next_layer().SetSeen(&m_Seen); | 	m_Stream->next_layer().SetSeen(&m_Seen); | ||||||
| 
 | 
 | ||||||
| 	while (!m_ShuttingDown) { | 	while (!m_ShuttingDown) { | ||||||
| 		String message; | 		String jsonString; | ||||||
| 
 | 
 | ||||||
| 		try { | 		try { | ||||||
| 			message = JsonRpc::ReadMessage(m_Stream, yc, m_Endpoint ? -1 : 1024 * 1024); | 			jsonString = JsonRpc::ReadMessage(m_Stream, yc, m_Endpoint ? -1 : 1024 * 1024); | ||||||
| 		} catch (const std::exception& ex) { | 		} catch (const std::exception& ex) { | ||||||
| 			Log(m_ShuttingDown ? LogDebug : LogNotice, "JsonRpcConnection") | 			Log(m_ShuttingDown ? LogDebug : LogNotice, "JsonRpcConnection") | ||||||
| 				<< "Error while reading JSON-RPC message for identity '" << m_Identity | 				<< "Error while reading JSON-RPC message for identity '" << m_Identity | ||||||
| @ -76,17 +82,50 @@ void JsonRpcConnection::HandleIncomingMessages(boost::asio::yield_context yc) | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		m_Seen = Utility::GetTime(); | 		m_Seen = Utility::GetTime(); | ||||||
|  | 		if (m_Endpoint) { | ||||||
|  | 			m_Endpoint->AddMessageReceived(jsonString.GetLength()); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		String rpcMethod("UNKNOWN"); | ||||||
|  | 		ch::steady_clock::duration cpuBoundDuration(0); | ||||||
|  | 		auto start (ch::steady_clock::now()); | ||||||
| 
 | 
 | ||||||
| 		try { | 		try { | ||||||
| 			CpuBoundWork handleMessage (yc); | 			CpuBoundWork handleMessage (yc); | ||||||
| 
 | 
 | ||||||
|  | 			// Cache the elapsed time to acquire a CPU semaphore used to detect extremely heavy workloads.
 | ||||||
|  | 			cpuBoundDuration = ch::steady_clock::now() - start; | ||||||
|  | 
 | ||||||
|  | 			Dictionary::Ptr message = JsonRpc::DecodeMessage(jsonString); | ||||||
|  | 			if (String method = message->Get("method"); !method.IsEmpty()) { | ||||||
|  | 				rpcMethod = std::move(method); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			MessageHandler(message); | 			MessageHandler(message); | ||||||
| 
 | 
 | ||||||
| 			l_TaskStats.InsertValue(Utility::GetTime(), 1); | 			l_TaskStats.InsertValue(Utility::GetTime(), 1); | ||||||
|  | 
 | ||||||
|  | 			auto total = ch::steady_clock::now() - start; | ||||||
|  | 
 | ||||||
|  | 			Log msg(total >= ch::seconds(5) ? LogWarning : LogDebug, "JsonRpcConnection"); | ||||||
|  | 			msg << "Processed JSON-RPC '" << rpcMethod << "' message for identity '" << m_Identity | ||||||
|  | 				<< "' (took total " << toMilliseconds(total) << "ms"; | ||||||
|  | 
 | ||||||
|  | 			if (cpuBoundDuration >= ch::seconds(1)) { | ||||||
|  | 				msg << ", waited " << toMilliseconds(cpuBoundDuration) << "ms on semaphore"; | ||||||
|  | 			} | ||||||
|  | 			msg << ")."; | ||||||
| 		} catch (const std::exception& ex) { | 		} catch (const std::exception& ex) { | ||||||
| 			Log(m_ShuttingDown ? LogDebug : LogWarning, "JsonRpcConnection") | 			auto total = ch::steady_clock::now() - start; | ||||||
| 				<< "Error while processing JSON-RPC message for identity '" << m_Identity | 
 | ||||||
| 				<< "': " << DiagnosticInformation(ex); | 			Log msg(m_ShuttingDown ? LogDebug : LogWarning, "JsonRpcConnection"); | ||||||
|  | 			msg << "Error while processing JSON-RPC '" << rpcMethod << "' message for identity '" | ||||||
|  | 				<< m_Identity << "' (took total " << toMilliseconds(total) << "ms"; | ||||||
|  | 
 | ||||||
|  | 			if (cpuBoundDuration >= ch::seconds(1)) { | ||||||
|  | 				msg << ", waited " << toMilliseconds(cpuBoundDuration) << "ms on semaphore"; | ||||||
|  | 			} | ||||||
|  | 			msg << "): " << DiagnosticInformation(ex); | ||||||
| 
 | 
 | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -259,10 +298,19 @@ void JsonRpcConnection::Disconnect() | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void JsonRpcConnection::MessageHandler(const String& jsonString) | /**
 | ||||||
|  |  * Route the provided message to its corresponding handler (if any). | ||||||
|  |  * | ||||||
|  |  * This will first verify the timestamp of that RPC message (if any) and subsequently, rejects any message whose | ||||||
|  |  * timestamp is less than the remote log position of the client Endpoint; otherwise, the endpoint's remote log | ||||||
|  |  * position is updated to that timestamp. It is not expected to happen, but any message lacking an RPC method or | ||||||
|  |  * referring to a non-existent one is also discarded. Afterward, the RPC handler is then called for that message | ||||||
|  |  * and sends it's result back to the sender if the message contains an ID. | ||||||
|  |  * | ||||||
|  |  * @param message The RPC message you want to process. | ||||||
|  | */ | ||||||
|  | void JsonRpcConnection::MessageHandler(const Dictionary::Ptr& message) | ||||||
| { | { | ||||||
| 	Dictionary::Ptr message = JsonRpc::DecodeMessage(jsonString); |  | ||||||
| 
 |  | ||||||
| 	if (m_Endpoint && message->Contains("ts")) { | 	if (m_Endpoint && message->Contains("ts")) { | ||||||
| 		double ts = message->Get("ts"); | 		double ts = message->Get("ts"); | ||||||
| 
 | 
 | ||||||
| @ -281,8 +329,6 @@ void JsonRpcConnection::MessageHandler(const String& jsonString) | |||||||
| 			origin->FromZone = m_Endpoint->GetZone(); | 			origin->FromZone = m_Endpoint->GetZone(); | ||||||
| 		else | 		else | ||||||
| 			origin->FromZone = Zone::GetByName(message->Get("originZone")); | 			origin->FromZone = Zone::GetByName(message->Get("originZone")); | ||||||
| 
 |  | ||||||
| 		m_Endpoint->AddMessageReceived(jsonString.GetLength()); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	Value vmethod; | 	Value vmethod; | ||||||
|  | |||||||
| @ -88,7 +88,8 @@ private: | |||||||
| 	void CheckLiveness(boost::asio::yield_context yc); | 	void CheckLiveness(boost::asio::yield_context yc); | ||||||
| 
 | 
 | ||||||
| 	bool ProcessMessage(); | 	bool ProcessMessage(); | ||||||
| 	void MessageHandler(const String& jsonString); | 
 | ||||||
|  | 	void MessageHandler(const Dictionary::Ptr& message); | ||||||
| 
 | 
 | ||||||
| 	void CertificateRequestResponseHandler(const Dictionary::Ptr& message); | 	void CertificateRequestResponseHandler(const Dictionary::Ptr& message); | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user