1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
3 #include "icinga/cib.hpp"
4 #include "icinga/host.hpp"
5 #include "icinga/service.hpp"
6 #include "icinga/clusterevents.hpp"
7 #include "base/application.hpp"
8 #include "base/objectlock.hpp"
9 #include "base/utility.hpp"
10 #include "base/perfdatavalue.hpp"
11 #include "base/configtype.hpp"
12 #include "base/statsfunction.hpp"
14 using namespace icinga;
16 RingBuffer CIB::m_ActiveHostChecksStatistics(15 * 60);
17 RingBuffer CIB::m_ActiveServiceChecksStatistics(15 * 60);
18 RingBuffer CIB::m_PassiveHostChecksStatistics(15 * 60);
19 RingBuffer CIB::m_PassiveServiceChecksStatistics(15 * 60);
21 void CIB::UpdateActiveHostChecksStatistics(long tv, int num)
23 m_ActiveHostChecksStatistics.InsertValue(tv, num);
26 void CIB::UpdateActiveServiceChecksStatistics(long tv, int num)
28 m_ActiveServiceChecksStatistics.InsertValue(tv, num);
31 int CIB::GetActiveHostChecksStatistics(long timespan)
33 return m_ActiveHostChecksStatistics.UpdateAndGetValues(Utility::GetTime(), timespan);
36 int CIB::GetActiveServiceChecksStatistics(long timespan)
38 return m_ActiveServiceChecksStatistics.UpdateAndGetValues(Utility::GetTime(), timespan);
41 void CIB::UpdatePassiveHostChecksStatistics(long tv, int num)
43 m_PassiveServiceChecksStatistics.InsertValue(tv, num);
46 void CIB::UpdatePassiveServiceChecksStatistics(long tv, int num)
48 m_PassiveServiceChecksStatistics.InsertValue(tv, num);
51 int CIB::GetPassiveHostChecksStatistics(long timespan)
53 return m_PassiveHostChecksStatistics.UpdateAndGetValues(Utility::GetTime(), timespan);
56 int CIB::GetPassiveServiceChecksStatistics(long timespan)
58 return m_PassiveServiceChecksStatistics.UpdateAndGetValues(Utility::GetTime(), timespan);
61 CheckableCheckStatistics CIB::CalculateHostCheckStats()
63 double min_latency = -1, max_latency = 0, sum_latency = 0;
64 int count_latency = 0;
65 double min_execution_time = -1, max_execution_time = 0, sum_execution_time = 0;
66 int count_execution_time = 0;
67 bool checkresult = false;
69 for (const Host::Ptr& host : ConfigType::GetObjectsByType<Host>()) {
70 ObjectLock olock(host);
72 CheckResult::Ptr cr = host->GetLastCheckResult();
77 /* set to true, we have a checkresult */
81 double latency = cr->CalculateLatency();
83 if (min_latency == -1 || latency < min_latency)
84 min_latency = latency;
86 if (latency > max_latency)
87 max_latency = latency;
89 sum_latency += latency;
93 double execution_time = cr->CalculateExecutionTime();
95 if (min_execution_time == -1 || execution_time < min_execution_time)
96 min_execution_time = execution_time;
98 if (execution_time > max_execution_time)
99 max_execution_time = execution_time;
101 sum_execution_time += execution_time;
102 count_execution_time++;
107 min_execution_time = 0;
110 CheckableCheckStatistics ccs;
112 ccs.min_latency = min_latency;
113 ccs.max_latency = max_latency;
114 ccs.avg_latency = sum_latency / count_latency;
115 ccs.min_execution_time = min_execution_time;
116 ccs.max_execution_time = max_execution_time;
117 ccs.avg_execution_time = sum_execution_time / count_execution_time;
122 CheckableCheckStatistics CIB::CalculateServiceCheckStats()
124 double min_latency = -1, max_latency = 0, sum_latency = 0;
125 int count_latency = 0;
126 double min_execution_time = -1, max_execution_time = 0, sum_execution_time = 0;
127 int count_execution_time = 0;
128 bool checkresult = false;
130 for (const Service::Ptr& service : ConfigType::GetObjectsByType<Service>()) {
131 ObjectLock olock(service);
133 CheckResult::Ptr cr = service->GetLastCheckResult();
138 /* set to true, we have a checkresult */
142 double latency = cr->CalculateLatency();
144 if (min_latency == -1 || latency < min_latency)
145 min_latency = latency;
147 if (latency > max_latency)
148 max_latency = latency;
150 sum_latency += latency;
154 double execution_time = cr->CalculateExecutionTime();
156 if (min_execution_time == -1 || execution_time < min_execution_time)
157 min_execution_time = execution_time;
159 if (execution_time > max_execution_time)
160 max_execution_time = execution_time;
162 sum_execution_time += execution_time;
163 count_execution_time++;
168 min_execution_time = 0;
171 CheckableCheckStatistics ccs;
173 ccs.min_latency = min_latency;
174 ccs.max_latency = max_latency;
175 ccs.avg_latency = sum_latency / count_latency;
176 ccs.min_execution_time = min_execution_time;
177 ccs.max_execution_time = max_execution_time;
178 ccs.avg_execution_time = sum_execution_time / count_execution_time;
183 ServiceStatistics CIB::CalculateServiceStats()
185 ServiceStatistics ss = {};
187 for (const Service::Ptr& service : ConfigType::GetObjectsByType<Service>()) {
188 ObjectLock olock(service);
190 if (service->GetState() == ServiceOK)
192 if (service->GetState() == ServiceWarning)
193 ss.services_warning++;
194 if (service->GetState() == ServiceCritical)
195 ss.services_critical++;
196 if (service->GetState() == ServiceUnknown)
197 ss.services_unknown++;
199 CheckResult::Ptr cr = service->GetLastCheckResult();
202 ss.services_pending++;
204 if (!service->IsReachable())
205 ss.services_unreachable++;
207 if (service->IsFlapping())
208 ss.services_flapping++;
209 if (service->IsInDowntime())
210 ss.services_in_downtime++;
211 if (service->IsAcknowledged())
212 ss.services_acknowledged++;
214 if (service->GetHandled())
215 ss.services_handled++;
216 if (service->GetProblem())
217 ss.services_problem++;
223 HostStatistics CIB::CalculateHostStats()
225 HostStatistics hs = {};
227 for (const Host::Ptr& host : ConfigType::GetObjectsByType<Host>()) {
228 ObjectLock olock(host);
230 if (host->IsReachable()) {
231 if (host->GetState() == HostUp)
233 if (host->GetState() == HostDown)
236 hs.hosts_unreachable++;
238 if (!host->GetLastCheckResult())
241 if (host->IsFlapping())
243 if (host->IsInDowntime())
244 hs.hosts_in_downtime++;
245 if (host->IsAcknowledged())
246 hs.hosts_acknowledged++;
248 if (host->GetHandled())
250 if (host->GetProblem())
258 * 'perfdata' must be a flat dictionary with double values
259 * 'status' dictionary can contain multiple levels of dictionaries
261 std::pair<Dictionary::Ptr, Array::Ptr> CIB::GetFeatureStats()
263 Dictionary::Ptr status = new Dictionary();
264 Array::Ptr perfdata = new Array();
266 Namespace::Ptr statsFunctions = ScriptGlobal::Get("StatsFunctions", &Empty);
268 if (statsFunctions) {
269 ObjectLock olock(statsFunctions);
271 for (const Namespace::Pair& kv : statsFunctions)
272 static_cast<Function::Ptr>(kv.second->Get())->Invoke({ status, perfdata });
275 return std::make_pair(status, perfdata);
278 REGISTER_STATSFUNCTION(CIB, &CIB::StatsFunc);
280 void CIB::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata) {
281 double interval = Utility::GetTime() - Application::GetStartTime();
286 status->Set("active_host_checks", GetActiveHostChecksStatistics(interval) / interval);
287 status->Set("passive_host_checks", GetPassiveHostChecksStatistics(interval) / interval);
288 status->Set("active_host_checks_1min", GetActiveHostChecksStatistics(60));
289 status->Set("passive_host_checks_1min", GetPassiveHostChecksStatistics(60));
290 status->Set("active_host_checks_5min", GetActiveHostChecksStatistics(60 * 5));
291 status->Set("passive_host_checks_5min", GetPassiveHostChecksStatistics(60 * 5));
292 status->Set("active_host_checks_15min", GetActiveHostChecksStatistics(60 * 15));
293 status->Set("passive_host_checks_15min", GetPassiveHostChecksStatistics(60 * 15));
295 status->Set("active_service_checks", GetActiveServiceChecksStatistics(interval) / interval);
296 status->Set("passive_service_checks", GetPassiveServiceChecksStatistics(interval) / interval);
297 status->Set("active_service_checks_1min", GetActiveServiceChecksStatistics(60));
298 status->Set("passive_service_checks_1min", GetPassiveServiceChecksStatistics(60));
299 status->Set("active_service_checks_5min", GetActiveServiceChecksStatistics(60 * 5));
300 status->Set("passive_service_checks_5min", GetPassiveServiceChecksStatistics(60 * 5));
301 status->Set("active_service_checks_15min", GetActiveServiceChecksStatistics(60 * 15));
302 status->Set("passive_service_checks_15min", GetPassiveServiceChecksStatistics(60 * 15));
304 // Checker related stats
305 status->Set("remote_check_queue", ClusterEvents::GetCheckRequestQueueSize());
306 status->Set("current_pending_callbacks", Application::GetTP().GetPending());
307 status->Set("current_concurrent_checks", Checkable::CurrentConcurrentChecks.load());
309 CheckableCheckStatistics scs = CalculateServiceCheckStats();
311 status->Set("min_latency", scs.min_latency);
312 status->Set("max_latency", scs.max_latency);
313 status->Set("avg_latency", scs.avg_latency);
314 status->Set("min_execution_time", scs.min_execution_time);
315 status->Set("max_execution_time", scs.max_execution_time);
316 status->Set("avg_execution_time", scs.avg_execution_time);
318 ServiceStatistics ss = CalculateServiceStats();
320 status->Set("num_services_ok", ss.services_ok);
321 status->Set("num_services_warning", ss.services_warning);
322 status->Set("num_services_critical", ss.services_critical);
323 status->Set("num_services_unknown", ss.services_unknown);
324 status->Set("num_services_pending", ss.services_pending);
325 status->Set("num_services_unreachable", ss.services_unreachable);
326 status->Set("num_services_flapping", ss.services_flapping);
327 status->Set("num_services_in_downtime", ss.services_in_downtime);
328 status->Set("num_services_acknowledged", ss.services_acknowledged);
329 status->Set("num_services_handled", ss.services_handled);
330 status->Set("num_services_problem", ss.services_problem);
332 double uptime = Utility::GetTime() - Application::GetStartTime();
333 status->Set("uptime", uptime);
335 HostStatistics hs = CalculateHostStats();
337 status->Set("num_hosts_up", hs.hosts_up);
338 status->Set("num_hosts_down", hs.hosts_down);
339 status->Set("num_hosts_pending", hs.hosts_pending);
340 status->Set("num_hosts_unreachable", hs.hosts_unreachable);
341 status->Set("num_hosts_flapping", hs.hosts_flapping);
342 status->Set("num_hosts_in_downtime", hs.hosts_in_downtime);
343 status->Set("num_hosts_acknowledged", hs.hosts_acknowledged);
344 status->Set("num_hosts_handled", hs.hosts_handled);
345 status->Set("num_hosts_problem", hs.hosts_problem);