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