1 /*  $Id: alerts.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: PSG server alerts
29  *
30  */
31 #include <ncbi_pch.hpp>
32 #include <corelib/ncbistd.hpp>
33 
34 #include "alerts.hpp"
35 #include "pubseq_gateway_convert_utils.hpp"
36 
37 
38 struct SAlertToId
39 {
40     EPSGS_AlertType     type;
41     string              id;
42 };
43 
44 
45 const SAlertToId     kAlertToIdMap[] = {
46     { ePSGS_ConfigAuthDecrypt,                "ConfigAuthDecrypt" },
47     { ePSGS_ConfigHttpWorkers,                "ConfigHttpWorkers" },
48     { ePSGS_ConfigListenerBacklog,            "ConfigListenerBacklog" },
49     { ePSGS_ConfigMaxConnections,             "ConfigMaxConnections" },
50     { ePSGS_ConfigTimeout,                    "ConfigTimeout" },
51     { ePSGS_ConfigRetries,                    "ConfigRetries" },
52     { ePSGS_ConfigExcludeCacheSize,           "ConfigExcludeCacheSize" },
53     { ePSGS_ConfigExcludeCachePurgeSize,      "ConfigExcludeCachePurgeSize" },
54     { ePSGS_ConfigExcludeCacheInactivity,     "ConfigExcludeCacheInactivity" },
55     { ePSGS_ConfigStatScaleType,              "ConfigStatScaleType" },
56     { ePSGS_ConfigStatMinMaxVal,              "ConfigStatMinMaxVal" },
57     { ePSGS_ConfigStatNBins,                  "ConfigStatNBins" },
58     { ePSGS_OpenCassandra,                    "OpenCassandra" },
59     { ePSGS_NoValidCassandraMapping,          "NoValidCassandraMapping" },
60     { ePSGS_InvalidCassandraMapping,          "InvalidCassandraMapping" },
61     { ePSGS_NewCassandraMappingAccepted,      "NewCassandraMappingAccepted"},
62     { ePSGS_NewCassandraSatNamesMapping,      "NewCassandraSatNamesMapping" },
63     { ePSGS_OpenCache,                        "OpenCache" },
64     { ePSGS_NoCassandraPublicCommentsMapping, "NoCassandraPublicCommentsMapping" },
65 };
66 const size_t        kAlertToIdMapSize = sizeof(kAlertToIdMap) / sizeof(SAlertToId);
67 
68 
69 
Serialize(void) const70 CJsonNode SPSGAlertAttributes::Serialize(void) const
71 {
72     CJsonNode       result = CJsonNode::NewObjectNode();
73 
74     if (m_AcknowledgedTimestamp.time_since_epoch().count() == 0)
75         result.SetString("AcknowledgedTime", "n/a");
76     else
77         result.SetString("AcknowledgedTime",
78                          FormatPreciseTime(m_AcknowledgedTimestamp));
79 
80     result.SetString("LastDetectedTime",
81                      FormatPreciseTime(m_LastDetectedTimestamp));
82     result.SetBoolean("On", m_On);
83     result.SetInteger("Count", m_Count);
84     result.SetInteger("CountSinceAcknowledge", m_CountSinceAck);
85     result.SetString("User", m_User);
86     result.SetString("Message", m_Message);
87     return result;
88 }
89 
90 
Register(enum EPSGS_AlertType alert_type,const string & message)91 void CPSGAlerts::Register(enum EPSGS_AlertType  alert_type,
92                           const string &   message)
93 {
94     map<EPSGS_AlertType,
95         SPSGAlertAttributes>::iterator      found;
96     lock_guard<mutex>                       guard(m_Lock);
97 
98     found = m_Alerts.find(alert_type);
99     if (found != m_Alerts.end()) {
100         // Alert has already been there
101         found->second.m_LastDetectedTimestamp = chrono::system_clock::now();
102         found->second.m_On = true;
103         ++found->second.m_Count;
104         ++found->second.m_CountSinceAck;
105         found->second.m_Message = message;
106         return;
107     }
108 
109     // Brand new alert
110     SPSGAlertAttributes     attrs;
111     attrs.m_Message = message;
112     m_Alerts[alert_type] = attrs;
113 }
114 
115 
Acknowledge(const string & alert_id,const string & user)116 EPSGS_AlertAckResult CPSGAlerts::Acknowledge(const string &  alert_id,
117                                              const string &  user)
118 {
119     EPSGS_AlertType     type = x_IdToType(alert_id);
120     if (type == EPSGS_AlertType::ePSGS_Unknown)
121         return ePSGS_AlertNotFound;
122 
123     return Acknowledge(type, user);
124 }
125 
126 
Acknowledge(EPSGS_AlertType alert_type,const string & user)127 EPSGS_AlertAckResult CPSGAlerts::Acknowledge(EPSGS_AlertType alert_type,
128                                              const string &  user)
129 {
130     map<EPSGS_AlertType,
131         SPSGAlertAttributes>::iterator      found;
132     lock_guard<mutex>                       guard(m_Lock);
133 
134     found = m_Alerts.find(alert_type);
135     if (found == m_Alerts.end())
136         return ePSGS_AlertNotFound;
137 
138     if (!found->second.m_On)
139         return ePSGS_AlertAlreadyAcknowledged;
140 
141     found->second.m_AcknowledgedTimestamp = chrono::system_clock::now();
142     found->second.m_On = false;
143     found->second.m_User = user;
144     found->second.m_CountSinceAck = 0;
145     return ePSGS_AlertAcknowledged;
146 }
147 
148 
x_IdToType(const string & alert_id) const149 EPSGS_AlertType CPSGAlerts::x_IdToType(const string &  alert_id) const
150 {
151     for (size_t  k = 0; k < kAlertToIdMapSize; ++k) {
152         if (NStr::CompareNocase(alert_id, kAlertToIdMap[k].id) == 0)
153             return kAlertToIdMap[k].type;
154     }
155     return EPSGS_AlertType::ePSGS_Unknown;
156 }
157 
158 
x_TypeToId(EPSGS_AlertType type) const159 string CPSGAlerts::x_TypeToId(EPSGS_AlertType  type) const
160 {
161     for (size_t  k = 0; k < kAlertToIdMapSize; ++k) {
162         if (kAlertToIdMap[k].type == type)
163             return kAlertToIdMap[k].id;
164     }
165     return "unknown";
166 }
167 
168 
169 // Provides the alerts
Serialize(void) const170 CJsonNode CPSGAlerts::Serialize(void) const
171 {
172     CJsonNode                                   result = CJsonNode::NewObjectNode();
173     map<EPSGS_AlertType,
174         SPSGAlertAttributes>::const_iterator    k;
175     lock_guard<mutex>                           guard(m_Lock);
176 
177     for (k = m_Alerts.begin(); k != m_Alerts.end(); ++k) {
178         result.SetByKey(x_TypeToId(k->first), k->second.Serialize());
179     }
180     return result;
181 }
182 
183 
184 // Provides only the active alerts
SerializeActive(void) const185 CJsonNode CPSGAlerts::SerializeActive(void) const
186 {
187     CJsonNode                                   result = CJsonNode::NewObjectNode();
188     map<EPSGS_AlertType,
189         SPSGAlertAttributes>::const_iterator    k;
190     lock_guard<mutex>                           guard(m_Lock);
191 
192     for (k = m_Alerts.begin(); k != m_Alerts.end(); ++k) {
193         if (k->second.m_On) {
194             result.SetByKey(x_TypeToId(k->first), k->second.Serialize());
195         }
196     }
197     return result;
198 }
199 
200