Skip to content

Commit 4564c06

Browse files
yhabteabjulianbrost
andcommitted
JsonRpcConnection: Log message processing time stats
Co-Authored-By: Julian Brost <julian.brost@icinga.com>
1 parent e0b053c commit 4564c06

File tree

2 files changed

+58
-11
lines changed

2 files changed

+58
-11
lines changed

lib/remote/jsonrpcconnection.cpp

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,19 @@ void JsonRpcConnection::Start()
6060

6161
void JsonRpcConnection::HandleIncomingMessages(boost::asio::yield_context yc)
6262
{
63+
namespace ch = std::chrono;
64+
65+
auto toMilliseconds ([](ch::steady_clock::duration d) {
66+
return ch::duration_cast<ch::milliseconds>(d).count();
67+
});
68+
6369
m_Stream->next_layer().SetSeen(&m_Seen);
6470

6571
while (!m_ShuttingDown) {
66-
String message;
72+
String jsonString;
6773

6874
try {
69-
message = JsonRpc::ReadMessage(m_Stream, yc, m_Endpoint ? -1 : 1024 * 1024);
75+
jsonString = JsonRpc::ReadMessage(m_Stream, yc, m_Endpoint ? -1 : 1024 * 1024);
7076
} catch (const std::exception& ex) {
7177
Log(m_ShuttingDown ? LogDebug : LogNotice, "JsonRpcConnection")
7278
<< "Error while reading JSON-RPC message for identity '" << m_Identity
@@ -76,17 +82,50 @@ void JsonRpcConnection::HandleIncomingMessages(boost::asio::yield_context yc)
7682
}
7783

7884
m_Seen = Utility::GetTime();
85+
if (m_Endpoint) {
86+
m_Endpoint->AddMessageReceived(jsonString.GetLength());
87+
}
88+
89+
String rpcMethod("UNKNOWN");
90+
ch::steady_clock::duration cpuBoundDuration(0);
91+
auto start (ch::steady_clock::now());
7992

8093
try {
8194
CpuBoundWork handleMessage (yc);
8295

96+
// Cache the elapsed time to acquire a CPU semaphore used to detect extremely heavy workloads.
97+
cpuBoundDuration = ch::steady_clock::now() - start;
98+
99+
Dictionary::Ptr message = JsonRpc::DecodeMessage(jsonString);
100+
if (String method = message->Get("method"); !method.IsEmpty()) {
101+
rpcMethod = std::move(method);
102+
}
103+
83104
MessageHandler(message);
84105

85106
l_TaskStats.InsertValue(Utility::GetTime(), 1);
107+
108+
auto total = ch::steady_clock::now() - start;
109+
110+
Log msg(total >= ch::seconds(5) ? LogWarning : LogDebug, "JsonRpcConnection");
111+
msg << "Processed JSON-RPC '" << rpcMethod << "' message for identity '" << m_Identity
112+
<< "' (took total " << toMilliseconds(total) << "ms";
113+
114+
if (cpuBoundDuration >= ch::seconds(1)) {
115+
msg << ", waited " << toMilliseconds(cpuBoundDuration) << "ms on semaphore";
116+
}
117+
msg << ").";
86118
} catch (const std::exception& ex) {
87-
Log(m_ShuttingDown ? LogDebug : LogWarning, "JsonRpcConnection")
88-
<< "Error while processing JSON-RPC message for identity '" << m_Identity
89-
<< "': " << DiagnosticInformation(ex);
119+
auto total = ch::steady_clock::now() - start;
120+
121+
Log msg(m_ShuttingDown ? LogDebug : LogWarning, "JsonRpcConnection");
122+
msg << "Error while processing JSON-RPC '" << rpcMethod << "' message for identity '"
123+
<< m_Identity << "' (took total " << toMilliseconds(total) << "ms";
124+
125+
if (cpuBoundDuration >= ch::seconds(1)) {
126+
msg << ", waited " << toMilliseconds(cpuBoundDuration) << "ms on semaphore";
127+
}
128+
msg << "): " << DiagnosticInformation(ex);
90129

91130
break;
92131
}
@@ -259,10 +298,19 @@ void JsonRpcConnection::Disconnect()
259298
}
260299
}
261300

262-
void JsonRpcConnection::MessageHandler(const String& jsonString)
301+
/**
302+
* Route the provided message to its corresponding handler (if any).
303+
*
304+
* This will first verify the timestamp of that RPC message (if any) and subsequently, rejects any message whose
305+
* timestamp is less than the remote log position of the client Endpoint; otherwise, the endpoint's remote log
306+
* position is updated to that timestamp. It is not expected to happen, but any message lacking an RPC method or
307+
* referring to a non-existent one is also discarded. Afterward, the RPC handler is then called for that message
308+
* and sends it's result back to the sender if the message contains an ID.
309+
*
310+
* @param message The RPC message you want to process.
311+
*/
312+
void JsonRpcConnection::MessageHandler(const Dictionary::Ptr& message)
263313
{
264-
Dictionary::Ptr message = JsonRpc::DecodeMessage(jsonString);
265-
266314
if (m_Endpoint && message->Contains("ts")) {
267315
double ts = message->Get("ts");
268316

@@ -281,8 +329,6 @@ void JsonRpcConnection::MessageHandler(const String& jsonString)
281329
origin->FromZone = m_Endpoint->GetZone();
282330
else
283331
origin->FromZone = Zone::GetByName(message->Get("originZone"));
284-
285-
m_Endpoint->AddMessageReceived(jsonString.GetLength());
286332
}
287333

288334
Value vmethod;

lib/remote/jsonrpcconnection.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ class JsonRpcConnection final : public Object
8888
void CheckLiveness(boost::asio::yield_context yc);
8989

9090
bool ProcessMessage();
91-
void MessageHandler(const String& jsonString);
91+
92+
void MessageHandler(const Dictionary::Ptr& message);
9293

9394
void CertificateRequestResponseHandler(const Dictionary::Ptr& message);
9495

0 commit comments

Comments
 (0)