1 /* $Id: pubseq_gateway_stat.cpp 629837 2021-04-22 12:47:49Z ivanov $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Authors: Sergey Satskiy
27 *
28 * File Description:
29 *
30 */
31
32 #include <ncbi_pch.hpp>
33
34 #include "pubseq_gateway_stat.hpp"
35 #include "pubseq_gateway_logging.hpp"
36
37 USING_NCBI_SCOPE;
38
39 static const string kValue("value");
40 static const string kName("name");
41 static const string kDescription("description");
42
43
CPSGSCounters()44 CPSGSCounters::CPSGSCounters()
45 {
46 m_Counters[ePSGS_BadUrlPath] =
47 new SCounterInfo(
48 "BadUrlPathCount", "Unknown URL counter",
49 "Number of times clients requested a path "
50 "which is not served by the server",
51 true, true, false);
52 m_Counters[ePSGS_InsufficientArgs] =
53 new SCounterInfo(
54 "InsufficientArgumentsCount", "Insufficient arguments counter",
55 "Number of times clients did not supply all the requiried arguments",
56 true, true, false);
57 m_Counters[ePSGS_MalformedArgs] =
58 new SCounterInfo(
59 "MalformedArgumentsCount", "Malformed arguments counter",
60 "Number of times clients supplied malformed arguments",
61 true, true, false);
62 m_Counters[ePSGS_GetBlobNotFound] =
63 new SCounterInfo(
64 "GetBlobNotFoundCount", "Blob not found counter",
65 "Number of times clients requested a blob which was not found",
66 true, true, false);
67 m_Counters[ePSGS_UnknownError] =
68 new SCounterInfo(
69 "UnknownErrorCount", "Unknown error counter",
70 "Number of times an unknown error has been detected",
71 true, true, false);
72 m_Counters[ePSGS_ClientSatToSatNameError] =
73 new SCounterInfo(
74 "ClientSatToSatNameErrorCount",
75 "Client provided sat to sat name mapping error counter",
76 "Number of times a client provided sat could not be mapped to a sat name",
77 true, true, false);
78 m_Counters[ePSGS_ServerSatToSatNameError] =
79 new SCounterInfo(
80 "ServerSatToSatNameErrorCount",
81 "Server data sat to sat name mapping error counter",
82 "Number of times a server data sat could not be mapped to a sat name",
83 true, true, false);
84 m_Counters[ePSGS_BlobPropsNotFoundError] =
85 new SCounterInfo(
86 "BlobPropsNotFoundErrorCount", "Blob properties not found counter",
87 "Number of times blob properties were not found",
88 true, true, false);
89 m_Counters[ePSGS_LMDBError] =
90 new SCounterInfo(
91 "LMDBErrorCount", "LMDB cache error count",
92 "Number of times an error was detected while searching in the LMDB cache",
93 true, true, false);
94 m_Counters[ePSGS_CassQueryTimeoutError] =
95 new SCounterInfo(
96 "CassQueryTimeoutErrorCount", "Cassandra query timeout error counter",
97 "Number of times a timeout error was detected while executing a Cassandra query",
98 true, true, false);
99 m_Counters[ePSGS_InvalidId2InfoError] =
100 new SCounterInfo(
101 "InvalidId2InfoErrorCount", "Invalid bioseq info ID2 field error counter",
102 "Number of times a malformed bioseq info ID2 field was detected",
103 true, true, false);
104 m_Counters[ePSGS_SplitHistoryNotFoundError] =
105 new SCounterInfo(
106 "SplitHistoryNotFoundErrorCount", "Split history not found error count",
107 "Number of times a split history was not found",
108 true, true, false);
109 m_Counters[ePSGS_MaxHopsExceededError] =
110 new SCounterInfo(
111 "MaxHopsExceededErrorCount", "Max hops exceeded error count",
112 "Number of times the max number of hops was exceeded",
113 true, true, false);
114 m_Counters[ePSGS_InputSeqIdNotResolved] =
115 new SCounterInfo(
116 "InputSeqIdNotResolved", "Seq id not resolved counter",
117 "Number of times a client provided seq id could not be resolved",
118 true, false, false);
119 m_Counters[ePSGS_TSEChunkSplitVersionCacheMatched] =
120 new SCounterInfo(
121 "TSEChunkSplitVersionCacheMatched",
122 "Requested TSE chunk split version matched the cached one counter",
123 "Number of times a client requested TSE chunk split version "
124 "matched the cached version",
125 true, false, false);
126 m_Counters[ePSGS_TSEChunkSplitVersionCacheNotMatched] =
127 new SCounterInfo(
128 "TSEChunkSplitVersionCacheNotMatched",
129 "Requested TSE chunk split version did not match the cached one counter",
130 "Number of times a client requested TSE chunk split version "
131 "did not match the cached version",
132 true, false, false);
133 m_Counters[ePSGS_AdminRequest] =
134 new SCounterInfo(
135 "AdminRequestCount", "Administrative requests counter",
136 "Number of time a client requested administrative functionality",
137 true, false, true);
138 m_Counters[ePSGS_ResolveRequest] =
139 new SCounterInfo(
140 "ResolveRequestCount", "Resolve requests counter",
141 "Number of times a client requested resolve functionality",
142 true, false, true);
143 m_Counters[ePSGS_GetBlobBySeqIdRequest] =
144 new SCounterInfo(
145 "GetBlobBySeqIdRequestCount", "Blob requests (by seq id) counter",
146 "Number of times a client requested a blob by seq id",
147 true, false, true);
148 m_Counters[ePSGS_GetBlobBySatSatKeyRequest] =
149 new SCounterInfo(
150 "GetBlobBySatSatKeyRequestCount", "Blob requests (by sat and sat key) counter",
151 "Number of times a client requested a blob by sat and sat key",
152 true, false, true);
153 m_Counters[ePSGS_GetNamedAnnotations] =
154 new SCounterInfo(
155 "GetNamedAnnotationsCount", "Named annotations requests counter",
156 "Number of times a client requested named annotations",
157 true, false, true);
158 m_Counters[ePSGS_TestIORequest] =
159 new SCounterInfo(
160 "TestIORequestCount", "Test input/output requests counter",
161 "Number of times a client requested an input/output test",
162 true, false, true);
163 m_Counters[ePSGS_GetTSEChunk] =
164 new SCounterInfo(
165 "GetTSEChunkCount", "TSE chunk requests counter",
166 "Number of times a client requested a TSE chunk",
167 true, false, true);
168 m_Counters[ePSGS_HealthRequest] =
169 new SCounterInfo(
170 "HealthRequestCount", "Health requests counter",
171 "Number of times a client requested health or deep-health status",
172 true, false, true);
173 m_Counters[ePSGS_Si2csiCacheHit] =
174 new SCounterInfo(
175 "Si2csiCacheHit", "si2csi cache hit counter",
176 "Number of times a si2csi LMDB cache lookup found a record",
177 true, false, false);
178 m_Counters[ePSGS_Si2csiCacheMiss] =
179 new SCounterInfo(
180 "Si2csiCacheMiss", "si2csi cache miss counter",
181 "Number of times a si2csi LMDB cache lookup did not find a record",
182 true, false, false);
183 m_Counters[ePSGS_BioseqInfoCacheHit] =
184 new SCounterInfo(
185 "BioseqInfoCacheHit", "bioseq info cache hit counter",
186 "Number of times a bioseq info LMDB cache lookup found a record",
187 true, false, false);
188 m_Counters[ePSGS_BioseqInfoCacheMiss] =
189 new SCounterInfo(
190 "BioseqInfoCacheMiss", "bioseq info cache miss counter",
191 "Number of times a bioseq info LMDB cache lookup did not find a record",
192 true, false, false);
193 m_Counters[ePSGS_BlobPropCacheHit] =
194 new SCounterInfo(
195 "BlobPropCacheHit", "Blob properties cache hit counter",
196 "Number of times a blob properties LMDB cache lookup found a record",
197 true, false, false);
198 m_Counters[ePSGS_BlobPropCacheMiss] =
199 new SCounterInfo(
200 "BlobPropCacheMiss", "Blob properties cache miss counter",
201 "Number of times a blob properties LMDB cache lookup did not find a record",
202 true, false, false);
203 m_Counters[ePSGS_Si2csiNotFound] =
204 new SCounterInfo(
205 "Si2csiNotFound", "si2csi not found in Cassandra counter",
206 "Number of times a Cassandra si2csi query resulted in no records",
207 true, false, false);
208 m_Counters[ePSGS_Si2csiFoundOne] =
209 new SCounterInfo(
210 "Si2csiFoundOne", "si2csi found one record in Cassandra counter",
211 "Number of times a Cassandra si2csi query resulted in exactly one record",
212 true, false, false);
213 m_Counters[ePSGS_Si2csiFoundMany] =
214 new SCounterInfo(
215 "Si2csiFoundMany", "si2csi found more than one record in Cassandra counter",
216 "Number of times a Cassandra si2csi query resulted in more than one record",
217 true, false, false);
218 m_Counters[ePSGS_BioseqInfoNotFound] =
219 new SCounterInfo(
220 "BioseqInfoNotFound", "bioseq info not found in Cassandra counter",
221 "Number of times a Cassandra bioseq info query resulted in no records",
222 true, false, false);
223 m_Counters[ePSGS_BioseqInfoFoundOne] =
224 new SCounterInfo(
225 "BioseqInfoFoundOne", "bioseq info found one record in Cassandra counter",
226 "Number of times a Cassandra bioseq info query resulted in exactly one record",
227 true, false, false);
228 m_Counters[ePSGS_BioseqInfoFoundMany] =
229 new SCounterInfo(
230 "BioseqInfoFoundMany", "bioseq info found more than one record in Cassandra counter",
231 "Number of times a Cassandra bioseq info query resulted in more than one record",
232 true, false, false);
233 m_Counters[ePSGS_Si2csiError] =
234 new SCounterInfo(
235 "Si2csiError", "si2csi Cassandra query execution error counter",
236 "Number of time a Cassandra si2csi query resulted in an error",
237 true, true, false);
238 m_Counters[ePSGS_BioseqInfoError] =
239 new SCounterInfo(
240 "BioseqInfoError", "bioseq info Cassandra query execution error counter",
241 "Number of times a Cassandra bioseq info query resulted in an error",
242 true, true, false);
243
244 // The counters below are for the sake of an identifier, name and
245 // description. The name and description can be overwritten by the
246 // configuration values
247
248 m_Counters[ePSGS_TotalRequest] =
249 new SCounterInfo(
250 "TotalRequestCount", "Total number of requests",
251 "Total number of requests",
252 false, false, false);
253 m_Counters[ePSGS_TotalError] =
254 new SCounterInfo(
255 "TotalErrorCount", "Total number of errors",
256 "Total number of errors",
257 false, false, false);
258 m_Counters[ePSGS_CassandraActiveStatements] =
259 new SCounterInfo(
260 "CassandraActiveStatementsCount", "Cassandra active statements counter",
261 "Number of the currently active Cassandra queries",
262 false, false, false);
263 m_Counters[ePSGS_NumberOfConnections] =
264 new SCounterInfo(
265 "NumberOfConnections", "Cassandra connections counter",
266 "Number of the connections to Cassandra",
267 false, false, false);
268 m_Counters[ePSGS_ActiveRequest] =
269 new SCounterInfo(
270 "ActiveRequestCount", "Active requests counter",
271 "Number of the currently active client requests",
272 false, false, false);
273 m_Counters[ePSGS_ShutdownRequested] =
274 new SCounterInfo(
275 "ShutdownRequested", "Shutdown requested flag",
276 "Shutdown requested flag",
277 false, false, false);
278 m_Counters[ePSGS_GracefulShutdownExpiredInSec] =
279 new SCounterInfo(
280 "GracefulShutdownExpiredInSec", "Graceful shutdown expiration",
281 "Graceful shutdown expiration in seconds from now",
282 false, false, false);
283 }
284
285
~CPSGSCounters()286 CPSGSCounters::~CPSGSCounters()
287 {
288 for (auto & item: m_Counters) {
289 delete item.second;
290 }
291 }
292
293
Increment(EPSGS_CounterType counter)294 void CPSGSCounters::Increment(EPSGS_CounterType counter)
295 {
296 auto it = m_Counters.find(counter);
297 if (it == m_Counters.end()) {
298 PSG_ERROR("There is no information about the counter with id " +
299 to_string(counter) + ". Nothing was incremented.");
300 return;
301 }
302
303 ++(it->second->m_Value);
304 }
305
306
UpdateConfiguredNameDescription(const map<string,tuple<string,string>> & conf)307 void CPSGSCounters::UpdateConfiguredNameDescription(
308 const map<string, tuple<string, string>> & conf)
309 {
310 for (auto const & conf_item : conf) {
311 for (auto & counter: m_Counters) {
312 if (counter.second->m_Identifier == conf_item.first) {
313 counter.second->m_Name = get<0>(conf_item.second);
314 counter.second->m_Description = get<1>(conf_item.second);
315 break;
316 }
317 }
318 }
319 }
320
321
PopulateDictionary(CJsonNode & dict)322 void CPSGSCounters::PopulateDictionary(CJsonNode & dict)
323 {
324 uint64_t err_sum(0);
325 uint64_t req_sum(0);
326 uint64_t value(0);
327
328 for (auto const & item: m_Counters) {
329 if (!item.second->m_IsMonotonicCounter)
330 continue;
331
332 value = item.second->m_Value;
333 if (item.second->m_IsErrorCounter) {
334 err_sum += value;
335 } else {
336 if (item.second->m_IsRequestCounter) {
337 req_sum += value;
338 }
339 }
340 AppendValueNode(dict, item.second->m_Identifier,
341 item.second->m_Name, item.second->m_Description,
342 value);
343 }
344
345 AppendValueNode(dict,
346 m_Counters[ePSGS_TotalRequest]->m_Identifier,
347 m_Counters[ePSGS_TotalRequest]->m_Name,
348 m_Counters[ePSGS_TotalRequest]->m_Description,
349 req_sum);
350 AppendValueNode(dict,
351 m_Counters[ePSGS_TotalError]->m_Identifier,
352 m_Counters[ePSGS_TotalError]->m_Name,
353 m_Counters[ePSGS_TotalError]->m_Description,
354 err_sum);
355 }
356
357
AppendValueNode(CJsonNode & dict,const string & id,const string & name,const string & description,uint64_t value)358 void CPSGSCounters::AppendValueNode(CJsonNode & dict, const string & id,
359 const string & name, const string & description,
360 uint64_t value)
361 {
362 CJsonNode value_dict(CJsonNode::NewObjectNode());
363
364 value_dict.SetInteger(kValue, value);
365 value_dict.SetString(kName, name);
366 value_dict.SetString(kDescription, description);
367 dict.SetByKey(id, value_dict);
368 }
369
370
AppendValueNode(CJsonNode & dict,const string & id,const string & name,const string & description,bool value)371 void CPSGSCounters::AppendValueNode(CJsonNode & dict, const string & id,
372 const string & name, const string & description,
373 bool value)
374 {
375 CJsonNode value_dict(CJsonNode::NewObjectNode());
376
377 value_dict.SetBoolean(kValue, value);
378 value_dict.SetString(kName, name);
379 value_dict.SetString(kDescription, description);
380 dict.SetByKey(id, value_dict);
381
382 }
383
384
AppendValueNode(CJsonNode & dict,const string & id,const string & name,const string & description,const string & value)385 void CPSGSCounters::AppendValueNode(CJsonNode & dict, const string & id,
386 const string & name, const string & description,
387 const string & value)
388 {
389 CJsonNode value_dict(CJsonNode::NewObjectNode());
390
391 value_dict.SetString(kValue, value);
392 value_dict.SetString(kName, name);
393 value_dict.SetString(kDescription, description);
394 dict.SetByKey(id, value_dict);
395
396 }
397
398
AppendValueNode(CJsonNode & dict,EPSGS_CounterType counter_type,uint64_t value)399 void CPSGSCounters::AppendValueNode(CJsonNode & dict,
400 EPSGS_CounterType counter_type,
401 uint64_t value)
402 {
403 AppendValueNode(dict,
404 m_Counters[counter_type]->m_Identifier,
405 m_Counters[counter_type]->m_Name,
406 m_Counters[counter_type]->m_Description,
407 value);
408 }
409
410
AppendValueNode(CJsonNode & dict,EPSGS_CounterType counter_type,bool value)411 void CPSGSCounters::AppendValueNode(CJsonNode & dict,
412 EPSGS_CounterType counter_type,
413 bool value)
414 {
415 AppendValueNode(dict,
416 m_Counters[counter_type]->m_Identifier,
417 m_Counters[counter_type]->m_Name,
418 m_Counters[counter_type]->m_Description,
419 value);
420 }
421
422
AppendValueNode(CJsonNode & dict,EPSGS_CounterType counter_type,const string & value)423 void CPSGSCounters::AppendValueNode(CJsonNode & dict,
424 EPSGS_CounterType counter_type,
425 const string & value)
426 {
427 AppendValueNode(dict,
428 m_Counters[counter_type]->m_Identifier,
429 m_Counters[counter_type]->m_Name,
430 m_Counters[counter_type]->m_Description,
431 value);
432 }
433
434