Skip to content

Commit c8832b5

Browse files
committed
JsonRpcConnection: Log message processing stats
1 parent f85f9a3 commit c8832b5

File tree

2 files changed

+57
-12
lines changed

2 files changed

+57
-12
lines changed

lib/remote/jsonrpcconnection.cpp

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,15 @@ void JsonRpcConnection::Start()
6060

6161
void JsonRpcConnection::HandleIncomingMessages(boost::asio::yield_context yc)
6262
{
63+
namespace ch = std::chrono;
64+
6365
m_Stream->next_layer().SetSeen(&m_Seen);
6466

6567
for (;;) {
66-
String message;
68+
String jsonString;
6769

6870
try {
69-
message = JsonRpc::ReadMessage(m_Stream, yc, m_Endpoint ? -1 : 1024 * 1024);
71+
jsonString = JsonRpc::ReadMessage(m_Stream, yc, m_Endpoint ? -1 : 1024 * 1024);
7072
} catch (const std::exception& ex) {
7173
Log(m_ShuttingDown ? LogDebug : LogNotice, "JsonRpcConnection")
7274
<< "Error while reading JSON-RPC message for identity '" << m_Identity
@@ -76,20 +78,55 @@ void JsonRpcConnection::HandleIncomingMessages(boost::asio::yield_context yc)
7678
}
7779

7880
m_Seen = Utility::GetTime();
81+
if (m_Endpoint) {
82+
m_Endpoint->AddMessageReceived(jsonString.GetLength());
83+
}
84+
85+
auto start (ch::steady_clock::now());
86+
ch::steady_clock::duration cpuBoundDuration, totalDuration;
87+
88+
String rpcMethod("UNKNOWN");
89+
String diagnosticInfo; // Contains the diagnostic/debug information in case of an error.
7990

8091
try {
92+
Defer extractTotalDuration ([&start, &totalDuration]() {
93+
totalDuration = ch::steady_clock::now() - start;
94+
});
95+
8196
CpuBoundWork handleMessage (yc);
8297

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

85108
l_TaskStats.InsertValue(Utility::GetTime(), 1);
86109
} 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);
110+
diagnosticInfo = DiagnosticInformation(ex);
111+
}
90112

91-
break;
113+
auto severity = LogDebug;
114+
if (totalDuration >= ch::seconds(5) || (!m_ShuttingDown && !diagnosticInfo.IsEmpty())) {
115+
// Processing that RPC message seems to take an unexpectedly long time,
116+
// so promote the log entry from debug to warning.
117+
severity = LogWarning;
118+
}
119+
120+
Log statsLog(severity, "JsonRpcConnection");
121+
statsLog << (!diagnosticInfo.IsEmpty() ? "Error while processing" : "Processing") << " JSON-RPC '"
122+
<< rpcMethod << "' message for identity '" << m_Identity << "' ";
123+
124+
if (cpuBoundDuration >= ch::seconds(1)) {
125+
statsLog << "waited " << ch::duration_cast<ch::milliseconds>(cpuBoundDuration).count() << "ms on semaphore and";
92126
}
127+
128+
statsLog << "took total " << ch::duration_cast<ch::milliseconds>(totalDuration).count()
129+
<< "ms" << (diagnosticInfo.IsEmpty() ? "." : ": "+diagnosticInfo);
93130
}
94131

95132
Disconnect();
@@ -245,10 +282,8 @@ void JsonRpcConnection::Disconnect()
245282
});
246283
}
247284

248-
void JsonRpcConnection::MessageHandler(const String& jsonString)
285+
void JsonRpcConnection::MessageHandler(const Dictionary::Ptr& message)
249286
{
250-
Dictionary::Ptr message = JsonRpc::DecodeMessage(jsonString);
251-
252287
if (m_Endpoint && message->Contains("ts")) {
253288
double ts = message->Get("ts");
254289

@@ -267,8 +302,6 @@ void JsonRpcConnection::MessageHandler(const String& jsonString)
267302
origin->FromZone = m_Endpoint->GetZone();
268303
else
269304
origin->FromZone = Zone::GetByName(message->Get("originZone"));
270-
271-
m_Endpoint->AddMessageReceived(jsonString.GetLength());
272305
}
273306

274307
Value vmethod;

lib/remote/jsonrpcconnection.hpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,19 @@ 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+
/**
93+
* MessageHandler routes the provided message to its corresponding handler (if any).
94+
*
95+
* This will first verify the timestamp of that RPC message (if any) and subsequently, rejects any message whose
96+
* timestamp is less than the remote log position of the client Endpoint; otherwise, the endpoint's remote log
97+
* position is updated to that timestamp. It is not expected to happen, but any message lacking an RPC method or
98+
* referring to a non-existent one is also discarded. Afterwards, the RPC handler is then called for that message
99+
* and sends it's result back to the sender if the message contains an ID.
100+
*
101+
* @param message Dictionary::Ptr The RPC message you want to process.
102+
*/
103+
void MessageHandler(const Dictionary::Ptr& message);
92104

93105
void CertificateRequestResponseHandler(const Dictionary::Ptr& message);
94106

0 commit comments

Comments
 (0)