1 /******************************************************************************
3 * Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License *
7 * as published by the Free Software Foundation; either version 2 *
8 * of the License, or (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software Foundation *
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ******************************************************************************/
20 #include "db_ido/dbevents.hpp"
21 #include "db_ido/dbtype.hpp"
22 #include "db_ido/dbvalue.hpp"
23 #include "base/convert.hpp"
24 #include "base/objectlock.hpp"
25 #include "base/initialize.hpp"
26 #include "base/configtype.hpp"
27 #include "base/utility.hpp"
28 #include "base/logger.hpp"
29 #include "remote/endpoint.hpp"
30 #include "icinga/notification.hpp"
31 #include "icinga/checkcommand.hpp"
32 #include "icinga/eventcommand.hpp"
33 #include "icinga/externalcommandprocessor.hpp"
34 #include "icinga/compatutility.hpp"
35 #include "icinga/icingaapplication.hpp"
36 #include <boost/algorithm/string/join.hpp>
38 using namespace icinga;
40 INITIALIZE_ONCE(&DbEvents::StaticInitialize);
42 void DbEvents::StaticInitialize(void)
45 Comment::OnCommentAdded.connect(boost::bind(&DbEvents::AddComment, _1));
46 Comment::OnCommentRemoved.connect(boost::bind(&DbEvents::RemoveComment, _1));
47 Downtime::OnDowntimeAdded.connect(boost::bind(&DbEvents::AddDowntime, _1));
48 Downtime::OnDowntimeRemoved.connect(boost::bind(&DbEvents::RemoveDowntime, _1));
49 Downtime::OnDowntimeTriggered.connect(boost::bind(&DbEvents::TriggerDowntime, _1));
50 Checkable::OnAcknowledgementSet.connect(boost::bind(&DbEvents::AddAcknowledgement, _1, _4));
51 Checkable::OnAcknowledgementCleared.connect(boost::bind(&DbEvents::RemoveAcknowledgement, _1));
53 Checkable::OnNextCheckUpdated.connect(boost::bind(&DbEvents::NextCheckUpdatedHandler, _1));
54 Checkable::OnFlappingChanged.connect(boost::bind(&DbEvents::FlappingChangedHandler, _1));
55 Checkable::OnNotificationSentToAllUsers.connect(boost::bind(&DbEvents::LastNotificationChangedHandler, _1, _2));
57 Checkable::OnEnableActiveChecksChanged.connect(boost::bind(&DbEvents::EnableActiveChecksChangedHandler, _1));
58 Checkable::OnEnablePassiveChecksChanged.connect(boost::bind(&DbEvents::EnablePassiveChecksChangedHandler, _1));
59 Checkable::OnEnableNotificationsChanged.connect(boost::bind(&DbEvents::EnableNotificationsChangedHandler, _1));
60 Checkable::OnEnablePerfdataChanged.connect(boost::bind(&DbEvents::EnablePerfdataChangedHandler, _1));
61 Checkable::OnEnableFlappingChanged.connect(boost::bind(&DbEvents::EnableFlappingChangedHandler, _1));
63 Checkable::OnReachabilityChanged.connect(boost::bind(&DbEvents::ReachabilityChangedHandler, _1, _2, _3));
66 Comment::OnCommentAdded.connect(boost::bind(&DbEvents::AddCommentHistory, _1));
67 Downtime::OnDowntimeAdded.connect(boost::bind(&DbEvents::AddDowntimeHistory, _1));
68 Checkable::OnAcknowledgementSet.connect(boost::bind(&DbEvents::AddAcknowledgementHistory, _1, _2, _3, _4, _5, _6));
70 Checkable::OnNotificationSentToAllUsers.connect(boost::bind(&DbEvents::AddNotificationHistory, _1, _2, _3, _4, _5, _6, _7));
72 Checkable::OnStateChange.connect(boost::bind(&DbEvents::AddStateChangeHistory, _1, _2, _3));
74 Checkable::OnNewCheckResult.connect(boost::bind(&DbEvents::AddCheckResultLogHistory, _1, _2));
75 Checkable::OnNotificationSentToUser.connect(boost::bind(&DbEvents::AddNotificationSentLogHistory, _1, _2, _3, _4, _5, _6, _7));
76 Checkable::OnFlappingChanged.connect(boost::bind(&DbEvents::AddFlappingChangedLogHistory, _1));
77 Checkable::OnEnableFlappingChanged.connect(boost::bind(&DbEvents::AddEnableFlappingChangedLogHistory, _1));
78 Downtime::OnDowntimeTriggered.connect(boost::bind(&DbEvents::AddTriggerDowntimeLogHistory, _1));
79 Downtime::OnDowntimeRemoved.connect(boost::bind(&DbEvents::AddRemoveDowntimeLogHistory, _1));
81 Checkable::OnFlappingChanged.connect(boost::bind(&DbEvents::AddFlappingChangedHistory, _1));
82 Checkable::OnEnableFlappingChanged.connect(boost::bind(&DbEvents::AddEnableFlappingChangedHistory, _1));
83 Checkable::OnNewCheckResult.connect(boost::bind(&DbEvents::AddCheckableCheckHistory, _1, _2));
85 Checkable::OnEventCommandExecuted.connect(boost::bind(&DbEvents::AddEventHandlerHistory, _1));
87 ExternalCommandProcessor::OnNewExternalCommand.connect(boost::bind(&DbEvents::AddExternalCommandHistory, _1, _2, _3));
91 void DbEvents::NextCheckUpdatedHandler(const Checkable::Ptr& checkable)
95 tie(host, service) = GetHostService(checkable);
99 query1.Table = "servicestatus";
101 query1.Table = "hoststatus";
103 query1.Type = DbQueryUpdate;
104 query1.Category = DbCatState;
105 query1.StatusUpdate = true;
106 query1.Object = DbObject::GetOrCreateByObject(checkable);
108 Dictionary::Ptr fields1 = new Dictionary();
109 fields1->Set("next_check", DbValue::FromTimestamp(checkable->GetNextCheck()));
111 query1.Fields = fields1;
113 query1.WhereCriteria = new Dictionary();
115 query1.WhereCriteria->Set("service_object_id", service);
117 query1.WhereCriteria->Set("host_object_id", host);
119 DbObject::OnQuery(query1);
122 void DbEvents::FlappingChangedHandler(const Checkable::Ptr& checkable)
125 Service::Ptr service;
126 tie(host, service) = GetHostService(checkable);
130 query1.Table = "servicestatus";
132 query1.Table = "hoststatus";
134 query1.Type = DbQueryUpdate;
135 query1.Category = DbCatState;
136 query1.StatusUpdate = true;
137 query1.Object = DbObject::GetOrCreateByObject(checkable);
139 Dictionary::Ptr fields1 = new Dictionary();
140 fields1->Set("is_flapping", CompatUtility::GetCheckableIsFlapping(checkable));
141 fields1->Set("percent_state_change", CompatUtility::GetCheckablePercentStateChange(checkable));
143 query1.Fields = fields1;
145 query1.WhereCriteria = new Dictionary();
147 query1.WhereCriteria->Set("service_object_id", service);
149 query1.WhereCriteria->Set("host_object_id", host);
151 query1.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */
153 DbObject::OnQuery(query1);
156 void DbEvents::LastNotificationChangedHandler(const Notification::Ptr& notification, const Checkable::Ptr& checkable)
158 double now = Utility::GetTime();
159 std::pair<unsigned long, unsigned long> now_bag = CompatUtility::ConvertTimestamp(now);
160 std::pair<unsigned long, unsigned long> time_bag = CompatUtility::ConvertTimestamp(notification->GetNextNotification());
163 Service::Ptr service;
164 tie(host, service) = GetHostService(checkable);
168 query1.Table = "servicestatus";
170 query1.Table = "hoststatus";
172 query1.Type = DbQueryUpdate;
173 query1.Category = DbCatState;
174 query1.StatusUpdate = true;
175 query1.Object = DbObject::GetOrCreateByObject(checkable);
177 Dictionary::Ptr fields1 = new Dictionary();
178 fields1->Set("last_notification", DbValue::FromTimestamp(now_bag.first));
179 fields1->Set("next_notification", DbValue::FromTimestamp(time_bag.first));
180 fields1->Set("current_notification_number", notification->GetNotificationNumber());
182 query1.Fields = fields1;
184 query1.WhereCriteria = new Dictionary();
186 query1.WhereCriteria->Set("service_object_id", service);
188 query1.WhereCriteria->Set("host_object_id", host);
190 query1.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */
192 DbObject::OnQuery(query1);
195 void DbEvents::ReachabilityChangedHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, std::set<Checkable::Ptr> children)
197 int is_reachable = 0;
199 if (cr->GetState() == ServiceOK)
202 Log(LogDebug, "DbEvents")
203 << "Updating reachability for checkable '" << checkable->GetName() << "': " << (is_reachable ? "" : "not" ) << " reachable for " << children.size() << " children.";
205 for (const Checkable::Ptr& child : children) {
206 Log(LogDebug, "DbEvents")
207 << "Updating reachability for checkable '" << child->GetName() << "': " << (is_reachable ? "" : "not" ) << " reachable.";
210 Service::Ptr service;
211 tie(host, service) = GetHostService(child);
215 query1.Table = "servicestatus";
217 query1.Table = "hoststatus";
219 query1.Type = DbQueryUpdate;
220 query1.Category = DbCatState;
221 query1.StatusUpdate = true;
222 query1.Object = DbObject::GetOrCreateByObject(child);
224 Dictionary::Ptr fields1 = new Dictionary();
225 fields1->Set("is_reachable", is_reachable);
227 query1.Fields = fields1;
229 query1.WhereCriteria = new Dictionary();
231 query1.WhereCriteria->Set("service_object_id", service);
233 query1.WhereCriteria->Set("host_object_id", host);
235 query1.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */
237 DbObject::OnQuery(query1);
241 /* enable changed events */
242 void DbEvents::EnableActiveChecksChangedHandler(const Checkable::Ptr& checkable)
244 EnableChangedHandlerInternal(checkable, "active_checks_enabled", checkable->GetEnableActiveChecks());
247 void DbEvents::EnablePassiveChecksChangedHandler(const Checkable::Ptr& checkable)
249 EnableChangedHandlerInternal(checkable, "passive_checks_enabled", checkable->GetEnablePassiveChecks());
252 void DbEvents::EnableNotificationsChangedHandler(const Checkable::Ptr& checkable)
254 EnableChangedHandlerInternal(checkable, "notifications_enabled", checkable->GetEnableNotifications());
257 void DbEvents::EnablePerfdataChangedHandler(const Checkable::Ptr& checkable)
259 EnableChangedHandlerInternal(checkable, "process_performance_data", checkable->GetEnablePerfdata());
262 void DbEvents::EnableFlappingChangedHandler(const Checkable::Ptr& checkable)
264 EnableChangedHandlerInternal(checkable, "flap_detection_enabled", checkable->GetEnableFlapping());
267 void DbEvents::EnableChangedHandlerInternal(const Checkable::Ptr& checkable, const String& fieldName, bool enabled)
270 Service::Ptr service;
271 tie(host, service) = GetHostService(checkable);
275 query1.Table = "servicestatus";
277 query1.Table = "hoststatus";
279 query1.Type = DbQueryUpdate;
280 query1.Category = DbCatState;
281 query1.StatusUpdate = true;
282 query1.Object = DbObject::GetOrCreateByObject(checkable);
284 Dictionary::Ptr fields1 = new Dictionary();
285 fields1->Set(fieldName, enabled);
286 query1.Fields = fields1;
288 query1.WhereCriteria = new Dictionary();
290 query1.WhereCriteria->Set("service_object_id", service);
292 query1.WhereCriteria->Set("host_object_id", host);
294 query1.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */
296 DbObject::OnQuery(query1);
301 void DbEvents::AddComments(const Checkable::Ptr& checkable)
303 std::set<Comment::Ptr> comments = checkable->GetComments();
305 std::vector<DbQuery> queries;
307 for (const Comment::Ptr& comment : comments) {
308 AddCommentInternal(queries, comment, false);
311 DbObject::OnMultipleQueries(queries);
314 void DbEvents::AddComment(const Comment::Ptr& comment)
316 std::vector<DbQuery> queries;
317 AddCommentInternal(queries, comment, false);
318 DbObject::OnMultipleQueries(queries);
321 void DbEvents::AddCommentHistory(const Comment::Ptr& comment)
323 std::vector<DbQuery> queries;
324 AddCommentInternal(queries, comment, true);
325 DbObject::OnMultipleQueries(queries);
328 void DbEvents::AddCommentInternal(std::vector<DbQuery>& queries, const Comment::Ptr& comment, bool historical)
330 Checkable::Ptr checkable = comment->GetCheckable();
332 unsigned long entry_time = static_cast<long>(comment->GetEntryTime());
333 unsigned long entry_time_usec = (comment->GetEntryTime() - entry_time) * 1000 * 1000;
335 Dictionary::Ptr fields1 = new Dictionary();
336 fields1->Set("entry_time", DbValue::FromTimestamp(entry_time));
337 fields1->Set("entry_time_usec", entry_time_usec);
338 fields1->Set("entry_type", comment->GetEntryType());
339 fields1->Set("object_id", checkable);
341 if (checkable->GetReflectionType() == Host::TypeInstance) {
342 fields1->Set("comment_type", 2);
343 /* requires idoutils 1.10 schema fix */
344 fields1->Set("internal_comment_id", comment->GetLegacyId());
345 } else if (checkable->GetReflectionType() == Service::TypeInstance) {
346 fields1->Set("comment_type", 1);
347 fields1->Set("internal_comment_id", comment->GetLegacyId());
349 Log(LogDebug, "DbEvents", "unknown object type for adding comment.");
353 fields1->Set("name", comment->GetName());
354 fields1->Set("comment_time", DbValue::FromTimestamp(entry_time)); /* same as entry_time */
355 fields1->Set("author_name", comment->GetAuthor());
356 fields1->Set("comment_data", comment->GetText());
357 fields1->Set("is_persistent", comment->GetPersistent() ? 1 : 0);
358 fields1->Set("comment_source", 1); /* external */
359 fields1->Set("expires", (comment->GetExpireTime() > 0) ? 1 : 0);
360 fields1->Set("expiration_time", DbValue::FromTimestamp(comment->GetExpireTime()));
361 fields1->Set("instance_id", 0); /* DbConnection class fills in real ID */
363 String node = IcingaApplication::GetInstance()->GetNodeName();
365 Endpoint::Ptr endpoint = Endpoint::GetByName(node);
367 fields1->Set("endpoint_object_id", endpoint);
371 query1.Table = "comments";
372 query1.Type = DbQueryInsert | DbQueryUpdate;
374 fields1->Set("session_token", 0); /* DbConnection class fills in real ID */
376 query1.WhereCriteria = new Dictionary();
377 query1.WhereCriteria->Set("object_id", checkable);
378 query1.WhereCriteria->Set("comment_time", DbValue::FromTimestamp(entry_time));
379 query1.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */
380 /* Match the unique constraint. */
381 query1.WhereCriteria->Set("internal_comment_id", comment->GetLegacyId());
383 query1.Table = "commenthistory";
384 query1.Type = DbQueryInsert;
386 query1.Category = DbCatComment;
387 query1.Fields = fields1;
389 queries.push_back(query1);
392 void DbEvents::RemoveComment(const Comment::Ptr& comment)
394 std::vector<DbQuery> queries;
395 RemoveCommentInternal(queries, comment);
396 DbObject::OnMultipleQueries(queries);
399 void DbEvents::RemoveCommentInternal(std::vector<DbQuery>& queries, const Comment::Ptr& comment)
401 Checkable::Ptr checkable = comment->GetCheckable();
403 unsigned long entry_time = static_cast<long>(comment->GetEntryTime());
407 query1.Table = "comments";
408 query1.Type = DbQueryDelete;
409 query1.Category = DbCatComment;
410 query1.WhereCriteria = new Dictionary();
411 query1.WhereCriteria->Set("object_id", checkable);
412 query1.WhereCriteria->Set("entry_time", DbValue::FromTimestamp(entry_time));
413 query1.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */
414 query1.WhereCriteria->Set("name", comment->GetName());
415 queries.push_back(query1);
417 /* History - update deletion time for service/host */
418 double now = Utility::GetTime();
419 std::pair<unsigned long, unsigned long> time_bag = CompatUtility::ConvertTimestamp(now);
422 query2.Table = "commenthistory";
423 query2.Type = DbQueryUpdate;
424 query2.Category = DbCatComment;
426 Dictionary::Ptr fields2 = new Dictionary();
427 fields2->Set("deletion_time", DbValue::FromTimestamp(time_bag.first));
428 fields2->Set("deletion_time_usec", time_bag.second);
429 query2.Fields = fields2;
431 query2.WhereCriteria = new Dictionary();
432 query2.WhereCriteria->Set("object_id", checkable);
433 query2.WhereCriteria->Set("entry_time", DbValue::FromTimestamp(entry_time));
434 query2.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */
435 query2.WhereCriteria->Set("name", comment->GetName());
436 queries.push_back(query2);
440 void DbEvents::AddDowntimes(const Checkable::Ptr& checkable)
442 std::set<Downtime::Ptr> downtimes = checkable->GetDowntimes();
444 std::vector<DbQuery> queries;
446 for (const Downtime::Ptr& downtime : downtimes) {
447 AddDowntimeInternal(queries, downtime, false);
450 DbObject::OnMultipleQueries(queries);
453 void DbEvents::AddDowntime(const Downtime::Ptr& downtime)
455 std::vector<DbQuery> queries;
456 AddDowntimeInternal(queries, downtime, false);
457 DbObject::OnMultipleQueries(queries);
460 void DbEvents::AddDowntimeHistory(const Downtime::Ptr& downtime)
462 std::vector<DbQuery> queries;
463 AddDowntimeInternal(queries, downtime, true);
464 DbObject::OnMultipleQueries(queries);
467 void DbEvents::AddDowntimeInternal(std::vector<DbQuery>& queries, const Downtime::Ptr& downtime, bool historical)
469 Checkable::Ptr checkable = downtime->GetCheckable();
471 Dictionary::Ptr fields1 = new Dictionary();
472 fields1->Set("entry_time", DbValue::FromTimestamp(downtime->GetEntryTime()));
473 fields1->Set("object_id", checkable);
475 if (checkable->GetReflectionType() == Host::TypeInstance) {
476 fields1->Set("downtime_type", 2);
477 /* requires idoutils 1.10 schema fix */
478 fields1->Set("internal_downtime_id", downtime->GetLegacyId());
479 } else if (checkable->GetReflectionType() == Service::TypeInstance) {
480 fields1->Set("downtime_type", 1);
481 fields1->Set("internal_downtime_id", downtime->GetLegacyId());
483 Log(LogDebug, "DbEvents", "unknown object type for adding downtime.");
487 fields1->Set("author_name", downtime->GetAuthor());
488 fields1->Set("comment_data", downtime->GetComment());
489 fields1->Set("triggered_by_id", Downtime::GetByName(downtime->GetTriggeredBy()));
490 fields1->Set("is_fixed", downtime->GetFixed() ? 1 : 0);
491 fields1->Set("duration", downtime->GetDuration());
492 fields1->Set("scheduled_start_time", DbValue::FromTimestamp(downtime->GetStartTime()));
493 fields1->Set("scheduled_end_time", DbValue::FromTimestamp(downtime->GetEndTime()));
494 fields1->Set("name", downtime->GetName());
496 /* flexible downtimes are started at trigger time */
497 if (downtime->GetFixed()) {
498 std::pair<unsigned long, unsigned long> time_bag = CompatUtility::ConvertTimestamp(downtime->GetStartTime());
499 fields1->Set("actual_start_time", DbValue::FromTimestamp(time_bag.first));
500 fields1->Set("actual_start_time_usec", time_bag.second);
501 fields1->Set("was_started", ((downtime->GetStartTime() <= Utility::GetTime()) ? 1 : 0));
504 fields1->Set("is_in_effect", (downtime->IsInEffect() ? 1 : 0));
505 fields1->Set("trigger_time", DbValue::FromTimestamp(downtime->GetTriggerTime()));
506 fields1->Set("instance_id", 0); /* DbConnection class fills in real ID */
508 String node = IcingaApplication::GetInstance()->GetNodeName();
510 Endpoint::Ptr endpoint = Endpoint::GetByName(node);
512 fields1->Set("endpoint_object_id", endpoint);
517 query1.Table = "scheduleddowntime";
518 query1.Type = DbQueryInsert | DbQueryUpdate;
520 fields1->Set("session_token", 0); /* DbConnection class fills in real ID */
522 query1.WhereCriteria = new Dictionary();
523 query1.WhereCriteria->Set("object_id", checkable);
524 query1.WhereCriteria->Set("entry_time", DbValue::FromTimestamp(downtime->GetEntryTime()));
525 query1.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */
526 /* Match the unique constraint. */
527 query1.WhereCriteria->Set("internal_downtime_id", downtime->GetLegacyId());
529 query1.Table = "downtimehistory";
530 query1.Type = DbQueryInsert;
533 query1.Category = DbCatDowntime;
534 query1.Fields = fields1;
536 queries.push_back(query1);
538 /* host/service status */
541 Service::Ptr service;
542 tie(host, service) = GetHostService(checkable);
546 query2.Table = "servicestatus";
548 query2.Table = "hoststatus";
550 query2.Type = DbQueryUpdate;
551 query2.Category = DbCatState;
552 query2.StatusUpdate = true;
553 query2.Object = DbObject::GetOrCreateByObject(checkable);
555 Dictionary::Ptr fields2 = new Dictionary();
556 fields2->Set("scheduled_downtime_depth", checkable->GetDowntimeDepth());
558 query2.Fields = fields2;
560 query2.WhereCriteria = new Dictionary();
562 query2.WhereCriteria->Set("service_object_id", service);
564 query2.WhereCriteria->Set("host_object_id", host);
566 query2.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */
568 queries.push_back(query2);
572 void DbEvents::RemoveDowntime(const Downtime::Ptr& downtime)
574 std::vector<DbQuery> queries;
575 RemoveDowntimeInternal(queries, downtime);
576 DbObject::OnMultipleQueries(queries);
579 void DbEvents::RemoveDowntimeInternal(std::vector<DbQuery>& queries, const Downtime::Ptr& downtime)
581 Checkable::Ptr checkable = downtime->GetCheckable();
585 query1.Table = "scheduleddowntime";
586 query1.Type = DbQueryDelete;
587 query1.Category = DbCatDowntime;
588 query1.WhereCriteria = new Dictionary();
590 query1.WhereCriteria->Set("object_id", checkable);
591 query1.WhereCriteria->Set("entry_time", DbValue::FromTimestamp(downtime->GetEntryTime()));
592 query1.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */
593 query1.WhereCriteria->Set("scheduled_start_time", DbValue::FromTimestamp(downtime->GetStartTime()));
594 query1.WhereCriteria->Set("scheduled_end_time", DbValue::FromTimestamp(downtime->GetEndTime()));
595 query1.WhereCriteria->Set("name", downtime->GetName());
596 queries.push_back(query1);
598 /* History - update actual_end_time, was_cancelled for service (and host in case) */
599 double now = Utility::GetTime();
600 std::pair<unsigned long, unsigned long> time_bag = CompatUtility::ConvertTimestamp(now);
603 query3.Table = "downtimehistory";
604 query3.Type = DbQueryUpdate;
605 query3.Category = DbCatDowntime;
607 Dictionary::Ptr fields3 = new Dictionary();
608 fields3->Set("was_cancelled", downtime->GetWasCancelled() ? 1 : 0);
610 if (downtime->GetFixed() || (!downtime->GetFixed() && downtime->GetTriggerTime() > 0)) {
611 fields3->Set("actual_end_time", DbValue::FromTimestamp(time_bag.first));
612 fields3->Set("actual_end_time_usec", time_bag.second);
615 fields3->Set("is_in_effect", 0);
616 query3.Fields = fields3;
618 query3.WhereCriteria = new Dictionary();
619 query3.WhereCriteria->Set("object_id", checkable);
620 query3.WhereCriteria->Set("entry_time", DbValue::FromTimestamp(downtime->GetEntryTime()));
621 query3.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */
622 query3.WhereCriteria->Set("scheduled_start_time", DbValue::FromTimestamp(downtime->GetStartTime()));
623 query3.WhereCriteria->Set("scheduled_end_time", DbValue::FromTimestamp(downtime->GetEndTime()));
624 query3.WhereCriteria->Set("name", downtime->GetName());
626 queries.push_back(query3);
628 /* host/service status */
630 Service::Ptr service;
631 tie(host, service) = GetHostService(checkable);
635 query4.Table = "servicestatus";
637 query4.Table = "hoststatus";
639 query4.Type = DbQueryUpdate;
640 query4.Category = DbCatState;
641 query4.StatusUpdate = true;
642 query4.Object = DbObject::GetOrCreateByObject(checkable);
644 Dictionary::Ptr fields4 = new Dictionary();
645 fields4->Set("scheduled_downtime_depth", checkable->GetDowntimeDepth());
647 query4.Fields = fields4;
649 query4.WhereCriteria = new Dictionary();
651 query4.WhereCriteria->Set("service_object_id", service);
653 query4.WhereCriteria->Set("host_object_id", host);
655 query4.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */
657 queries.push_back(query4);
660 void DbEvents::TriggerDowntime(const Downtime::Ptr& downtime)
662 Checkable::Ptr checkable = downtime->GetCheckable();
664 double now = Utility::GetTime();
665 std::pair<unsigned long, unsigned long> time_bag = CompatUtility::ConvertTimestamp(now);
669 query1.Table = "scheduleddowntime";
670 query1.Type = DbQueryUpdate;
671 query1.Category = DbCatDowntime;
673 Dictionary::Ptr fields1 = new Dictionary();
674 fields1->Set("was_started", 1);
675 fields1->Set("actual_start_time", DbValue::FromTimestamp(time_bag.first));
676 fields1->Set("actual_start_time_usec", time_bag.second);
677 fields1->Set("is_in_effect", (downtime->IsInEffect() ? 1 : 0));
678 fields1->Set("trigger_time", DbValue::FromTimestamp(downtime->GetTriggerTime()));
679 fields1->Set("instance_id", 0); /* DbConnection class fills in real ID */
681 query1.WhereCriteria = new Dictionary();
682 query1.WhereCriteria->Set("object_id", checkable);
683 query1.WhereCriteria->Set("entry_time", DbValue::FromTimestamp(downtime->GetEntryTime()));
684 query1.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */
685 query1.WhereCriteria->Set("scheduled_start_time", DbValue::FromTimestamp(downtime->GetStartTime()));
686 query1.WhereCriteria->Set("scheduled_end_time", DbValue::FromTimestamp(downtime->GetEndTime()));
687 query1.WhereCriteria->Set("name", downtime->GetName());
689 query1.Fields = fields1;
690 DbObject::OnQuery(query1);
692 /* History - downtime was started for service (and host in case) */
694 query3.Table = "downtimehistory";
695 query3.Type = DbQueryUpdate;
696 query3.Category = DbCatDowntime;
698 Dictionary::Ptr fields3 = new Dictionary();
699 fields3->Set("was_started", 1);
700 fields3->Set("is_in_effect", 1);
701 fields3->Set("actual_start_time", DbValue::FromTimestamp(time_bag.first));
702 fields3->Set("actual_start_time_usec", time_bag.second);
703 fields3->Set("trigger_time", DbValue::FromTimestamp(downtime->GetTriggerTime()));
704 query3.Fields = fields3;
706 query3.WhereCriteria = query1.WhereCriteria;
708 DbObject::OnQuery(query3);
710 /* host/service status */
712 Service::Ptr service;
713 tie(host, service) = GetHostService(checkable);
717 query4.Table = "servicestatus";
719 query4.Table = "hoststatus";
721 query4.Type = DbQueryUpdate;
722 query4.Category = DbCatState;
723 query4.StatusUpdate = true;
724 query4.Object = DbObject::GetOrCreateByObject(checkable);
726 Dictionary::Ptr fields4 = new Dictionary();
727 fields4->Set("scheduled_downtime_depth", checkable->GetDowntimeDepth());
729 query4.Fields = fields4;
731 query4.WhereCriteria = new Dictionary();
733 query4.WhereCriteria->Set("service_object_id", service);
735 query4.WhereCriteria->Set("host_object_id", host);
737 query4.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */
739 DbObject::OnQuery(query4);
742 /* acknowledgements */
743 void DbEvents::AddAcknowledgementHistory(const Checkable::Ptr& checkable, const String& author, const String& comment,
744 AcknowledgementType type, bool notify, double expiry)
746 Log(LogDebug, "DbEvents")
747 << "add acknowledgement history for '" << checkable->GetName() << "'";
749 double now = Utility::GetTime();
750 std::pair<unsigned long, unsigned long> time_bag = CompatUtility::ConvertTimestamp(now);
752 unsigned long end_time = static_cast<long>(expiry);
755 query1.Table = "acknowledgements";
756 query1.Type = DbQueryInsert;
757 query1.Category = DbCatAcknowledgement;
760 Service::Ptr service;
761 tie(host, service) = GetHostService(checkable);
763 Dictionary::Ptr fields1 = new Dictionary();
764 fields1->Set("entry_time", DbValue::FromTimestamp(time_bag.first));
765 fields1->Set("entry_time_usec", time_bag.second);
766 fields1->Set("acknowledgement_type", type);
767 fields1->Set("object_id", checkable);
768 fields1->Set("author_name", author);
769 fields1->Set("comment_data", comment);
770 fields1->Set("persistent_comment", 1); //always persistent
771 fields1->Set("notify_contacts", notify ? 1 : 0);
772 fields1->Set("is_sticky", type == AcknowledgementSticky ? 1 : 0);
773 fields1->Set("end_time", DbValue::FromTimestamp(end_time));
774 fields1->Set("instance_id", 0); /* DbConnection class fills in real ID */
777 fields1->Set("state", service->GetState());
779 fields1->Set("state", CompatUtility::GetHostCurrentState(host));
782 String node = IcingaApplication::GetInstance()->GetNodeName();
784 Endpoint::Ptr endpoint = Endpoint::GetByName(node);
786 fields1->Set("endpoint_object_id", endpoint);
788 query1.Fields = fields1;
789 DbObject::OnQuery(query1);
792 void DbEvents::AddAcknowledgement(const Checkable::Ptr& checkable, AcknowledgementType type)
794 Log(LogDebug, "DbEvents")
795 << "add acknowledgement for '" << checkable->GetName() << "'";
797 AddAcknowledgementInternal(checkable, type, true);
800 void DbEvents::RemoveAcknowledgement(const Checkable::Ptr& checkable)
802 Log(LogDebug, "DbEvents")
803 << "remove acknowledgement for '" << checkable->GetName() << "'";
805 AddAcknowledgementInternal(checkable, AcknowledgementNone, false);
808 void DbEvents::AddAcknowledgementInternal(const Checkable::Ptr& checkable, AcknowledgementType type, bool add)
811 Service::Ptr service;
812 tie(host, service) = GetHostService(checkable);
816 query1.Table = "servicestatus";
818 query1.Table = "hoststatus";
820 query1.Type = DbQueryUpdate;
821 query1.Category = DbCatState;
822 query1.StatusUpdate = true;
823 query1.Object = DbObject::GetOrCreateByObject(checkable);
825 Dictionary::Ptr fields1 = new Dictionary();
826 fields1->Set("acknowledgement_type", type);
827 fields1->Set("problem_has_been_acknowledged", add ? 1 : 0);
828 query1.Fields = fields1;
830 query1.WhereCriteria = new Dictionary();
832 query1.WhereCriteria->Set("service_object_id", service);
834 query1.WhereCriteria->Set("host_object_id", host);
836 query1.WhereCriteria->Set("instance_id", 0); /* DbConnection class fills in real ID */
838 DbObject::OnQuery(query1);
842 void DbEvents::AddNotificationHistory(const Notification::Ptr& notification, const Checkable::Ptr& checkable, const std::set<User::Ptr>& users, NotificationType type,
843 const CheckResult::Ptr& cr, const String& author, const String& text)
845 Log(LogDebug, "DbEvents")
846 << "add notification history for '" << checkable->GetName() << "'";
848 /* start and end happen at the same time */
849 double now = Utility::GetTime();
850 std::pair<unsigned long, unsigned long> time_bag = CompatUtility::ConvertTimestamp(now);
853 query1.Table = "notifications";
854 query1.Type = DbQueryInsert;
855 query1.Category = DbCatNotification;
856 query1.NotificationInsertID = new DbValue(DbValueObjectInsertID, -1);
859 Service::Ptr service;
860 tie(host, service) = GetHostService(checkable);
862 Dictionary::Ptr fields1 = new Dictionary();
863 fields1->Set("notification_type", 1); /* service */
864 fields1->Set("notification_reason", CompatUtility::MapNotificationReasonType(type));
865 fields1->Set("object_id", checkable);
866 fields1->Set("start_time", DbValue::FromTimestamp(time_bag.first));
867 fields1->Set("start_time_usec", time_bag.second);
868 fields1->Set("end_time", DbValue::FromTimestamp(time_bag.first));
869 fields1->Set("end_time_usec", time_bag.second);
872 fields1->Set("state", service->GetState());
874 fields1->Set("state", CompatUtility::GetHostCurrentState(host));
878 fields1->Set("output", CompatUtility::GetCheckResultOutput(cr));
879 fields1->Set("long_output", CompatUtility::GetCheckResultLongOutput(cr));
882 fields1->Set("escalated", 0);
883 fields1->Set("contacts_notified", static_cast<long>(users.size()));
884 fields1->Set("instance_id", 0); /* DbConnection class fills in real ID */
886 String node = IcingaApplication::GetInstance()->GetNodeName();
888 Endpoint::Ptr endpoint = Endpoint::GetByName(node);
890 fields1->Set("endpoint_object_id", endpoint);
892 query1.Fields = fields1;
893 DbObject::OnQuery(query1);
895 std::vector<DbQuery> queries;
897 for (const User::Ptr& user : users) {
898 Log(LogDebug, "DbEvents")
899 << "add contact notification history for service '" << checkable->GetName() << "' and user '" << user->GetName() << "'.";
902 query2.Table = "contactnotifications";
903 query2.Type = DbQueryInsert;
904 query2.Category = DbCatNotification;
906 Dictionary::Ptr fields2 = new Dictionary();
907 fields2->Set("contact_object_id", user);
908 fields2->Set("start_time", DbValue::FromTimestamp(time_bag.first));
909 fields2->Set("start_time_usec", time_bag.second);
910 fields2->Set("end_time", DbValue::FromTimestamp(time_bag.first));
911 fields2->Set("end_time_usec", time_bag.second);
913 fields2->Set("notification_id", query1.NotificationInsertID);
914 fields2->Set("instance_id", 0); /* DbConnection class fills in real ID */
916 query2.Fields = fields2;
917 queries.push_back(query2);
920 DbObject::OnMultipleQueries(queries);
924 void DbEvents::AddStateChangeHistory(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, StateType type)
926 Log(LogDebug, "DbEvents")
927 << "add state change history for '" << checkable->GetName() << "'";
929 double ts = cr->GetExecutionEnd();
930 std::pair<unsigned long, unsigned long> state_time_bag = CompatUtility::ConvertTimestamp(ts);
933 query1.Table = "statehistory";
934 query1.Type = DbQueryInsert;
935 query1.Category = DbCatStateHistory;
938 Service::Ptr service;
939 tie(host, service) = GetHostService(checkable);
941 Dictionary::Ptr fields1 = new Dictionary();
942 fields1->Set("state_time", DbValue::FromTimestamp(state_time_bag.first));
943 fields1->Set("state_time_usec", state_time_bag.second);
944 fields1->Set("object_id", checkable);
945 fields1->Set("state_change", 1); /* service */
946 fields1->Set("state_type", checkable->GetStateType());
947 fields1->Set("current_check_attempt", checkable->GetCheckAttempt());
948 fields1->Set("max_check_attempts", checkable->GetMaxCheckAttempts());
951 fields1->Set("state", service->GetState());
952 fields1->Set("last_state", service->GetLastState());
953 fields1->Set("last_hard_state", service->GetLastHardState());
955 fields1->Set("state", CompatUtility::GetHostCurrentState(host));
956 fields1->Set("last_state", host->GetLastState());
957 fields1->Set("last_hard_state", host->GetLastHardState());
961 fields1->Set("output", CompatUtility::GetCheckResultOutput(cr));
962 fields1->Set("long_output", CompatUtility::GetCheckResultLongOutput(cr));
963 fields1->Set("check_source", cr->GetCheckSource());
966 fields1->Set("instance_id", 0); /* DbConnection class fills in real ID */
968 String node = IcingaApplication::GetInstance()->GetNodeName();
970 Endpoint::Ptr endpoint = Endpoint::GetByName(node);
972 fields1->Set("endpoint_object_id", endpoint);
974 query1.Fields = fields1;
975 DbObject::OnQuery(query1);
979 void DbEvents::AddCheckResultLogHistory(const Checkable::Ptr& checkable, const CheckResult::Ptr &cr)
981 Dictionary::Ptr vars_after = cr->GetVarsAfter();
983 long state_after = vars_after->Get("state");
984 long stateType_after = vars_after->Get("state_type");
985 long attempt_after = vars_after->Get("attempt");
986 bool reachable_after = vars_after->Get("reachable");
988 Dictionary::Ptr vars_before = cr->GetVarsBefore();
991 long state_before = vars_before->Get("state");
992 long stateType_before = vars_before->Get("state_type");
993 long attempt_before = vars_before->Get("attempt");
994 bool reachable_before = vars_before->Get("reachable");
996 if (state_before == state_after && stateType_before == stateType_after &&
997 attempt_before == attempt_after && reachable_before == reachable_after)
998 return; /* Nothing changed, ignore this checkresult. */
1005 output = CompatUtility::GetCheckResultOutput(cr);
1008 Service::Ptr service;
1009 tie(host, service) = GetHostService(checkable);
1011 std::ostringstream msgbuf;
1014 msgbuf << "SERVICE ALERT: "
1015 << host->GetName() << ";"
1016 << service->GetShortName() << ";"
1017 << Service::StateToString(service->GetState()) << ";"
1018 << Service::StateTypeToString(service->GetStateType()) << ";"
1019 << attempt_after << ";"
1023 switch (service->GetState()) {
1025 type = LogEntryTypeServiceOk;
1027 case ServiceUnknown:
1028 type = LogEntryTypeServiceUnknown;
1030 case ServiceWarning:
1031 type = LogEntryTypeServiceWarning;
1033 case ServiceCritical:
1034 type = LogEntryTypeServiceCritical;
1037 Log(LogCritical, "DbEvents")
1038 << "Unknown service state: " << state_after;
1042 msgbuf << "HOST ALERT: "
1043 << host->GetName() << ";"
1044 << CompatUtility::GetHostStateString(host) << ";"
1045 << Host::StateTypeToString(host->GetStateType()) << ";"
1046 << attempt_after << ";"
1050 switch (host->GetState()) {
1052 type = LogEntryTypeHostUp;
1055 type = LogEntryTypeHostDown;
1058 Log(LogCritical, "DbEvents")
1059 << "Unknown host state: " << state_after;
1063 if (!reachable_after)
1064 type = LogEntryTypeHostUnreachable;
1067 AddLogHistory(checkable, msgbuf.str(), type);
1070 void DbEvents::AddTriggerDowntimeLogHistory(const Downtime::Ptr& downtime)
1072 Checkable::Ptr checkable = downtime->GetCheckable();
1075 Service::Ptr service;
1076 tie(host, service) = GetHostService(checkable);
1078 std::ostringstream msgbuf;
1081 msgbuf << "SERVICE DOWNTIME ALERT: "
1082 << host->GetName() << ";"
1083 << service->GetShortName() << ";"
1084 << "STARTED" << "; "
1085 << "Service has entered a period of scheduled downtime."
1088 msgbuf << "HOST DOWNTIME ALERT: "
1089 << host->GetName() << ";"
1090 << "STARTED" << "; "
1091 << "Service has entered a period of scheduled downtime."
1095 AddLogHistory(checkable, msgbuf.str(), LogEntryTypeInfoMessage);
1098 void DbEvents::AddRemoveDowntimeLogHistory(const Downtime::Ptr& downtime)
1100 Checkable::Ptr checkable = downtime->GetCheckable();
1102 String downtime_output;
1103 String downtime_state_str;
1105 if (downtime->GetWasCancelled()) {
1106 downtime_output = "Scheduled downtime for service has been cancelled.";
1107 downtime_state_str = "CANCELLED";
1109 downtime_output = "Service has exited from a period of scheduled downtime.";
1110 downtime_state_str = "STOPPED";
1114 Service::Ptr service;
1115 tie(host, service) = GetHostService(checkable);
1117 std::ostringstream msgbuf;
1120 msgbuf << "SERVICE DOWNTIME ALERT: "
1121 << host->GetName() << ";"
1122 << service->GetShortName() << ";"
1123 << downtime_state_str << "; "
1127 msgbuf << "HOST DOWNTIME ALERT: "
1128 << host->GetName() << ";"
1129 << downtime_state_str << "; "
1134 AddLogHistory(checkable, msgbuf.str(), LogEntryTypeInfoMessage);
1137 void DbEvents::AddNotificationSentLogHistory(const Notification::Ptr& notification, const Checkable::Ptr& checkable, const User::Ptr& user,
1138 NotificationType notification_type, const CheckResult::Ptr& cr,
1139 const String& author, const String& comment_text)
1141 CheckCommand::Ptr commandObj = checkable->GetCheckCommand();
1143 String check_command = "";
1145 check_command = commandObj->GetName();
1147 String notification_type_str = Notification::NotificationTypeToString(notification_type);
1149 String author_comment = "";
1150 if (notification_type == NotificationCustom || notification_type == NotificationAcknowledgement) {
1151 author_comment = ";" + author + ";" + comment_text;
1160 output = CompatUtility::GetCheckResultOutput(cr);
1163 Service::Ptr service;
1164 tie(host, service) = GetHostService(checkable);
1166 std::ostringstream msgbuf;
1169 msgbuf << "SERVICE NOTIFICATION: "
1170 << user->GetName() << ";"
1171 << host->GetName() << ";"
1172 << service->GetShortName() << ";"
1173 << notification_type_str << " "
1174 << "(" << Service::StateToString(service->GetState()) << ");"
1175 << check_command << ";"
1176 << output << author_comment
1179 msgbuf << "HOST NOTIFICATION: "
1180 << user->GetName() << ";"
1181 << host->GetName() << ";"
1182 << notification_type_str << " "
1183 << "(" << Host::StateToString(host->GetState()) << ");"
1184 << check_command << ";"
1185 << output << author_comment
1189 AddLogHistory(checkable, msgbuf.str(), LogEntryTypeHostNotification);
1192 void DbEvents::AddFlappingChangedLogHistory(const Checkable::Ptr& checkable)
1194 String flapping_state_str;
1195 String flapping_output;
1197 if (checkable->IsFlapping()) {
1198 flapping_output = "Service appears to have started flapping (" + Convert::ToString(checkable->GetFlappingCurrent()) + "% change >= " + Convert::ToString(checkable->GetFlappingThresholdHigh()) + "% threshold)";
1199 flapping_state_str = "STARTED";
1201 flapping_output = "Service appears to have stopped flapping (" + Convert::ToString(checkable->GetFlappingCurrent()) + "% change < " + Convert::ToString(checkable->GetFlappingThresholdLow()) + "% threshold)";
1202 flapping_state_str = "STOPPED";
1206 Service::Ptr service;
1207 tie(host, service) = GetHostService(checkable);
1209 std::ostringstream msgbuf;
1212 msgbuf << "SERVICE FLAPPING ALERT: "
1213 << host->GetName() << ";"
1214 << service->GetShortName() << ";"
1215 << flapping_state_str << "; "
1219 msgbuf << "HOST FLAPPING ALERT: "
1220 << host->GetName() << ";"
1221 << flapping_state_str << "; "
1226 AddLogHistory(checkable, msgbuf.str(), LogEntryTypeInfoMessage);
1229 void DbEvents::AddEnableFlappingChangedLogHistory(const Checkable::Ptr& checkable)
1231 if (!checkable->GetEnableFlapping())
1234 String flapping_output = "Flap detection has been disabled";
1235 String flapping_state_str = "DISABLED";
1238 Service::Ptr service;
1239 tie(host, service) = GetHostService(checkable);
1241 std::ostringstream msgbuf;
1244 msgbuf << "SERVICE FLAPPING ALERT: "
1245 << host->GetName() << ";"
1246 << service->GetShortName() << ";"
1247 << flapping_state_str << "; "
1251 msgbuf << "HOST FLAPPING ALERT: "
1252 << host->GetName() << ";"
1253 << flapping_state_str << "; "
1258 AddLogHistory(checkable, msgbuf.str(), LogEntryTypeInfoMessage);
1261 void DbEvents::AddLogHistory(const Checkable::Ptr& checkable, String buffer, LogEntryType type)
1263 Log(LogDebug, "DbEvents")
1264 << "add log entry history for '" << checkable->GetName() << "'";
1266 double now = Utility::GetTime();
1267 std::pair<unsigned long, unsigned long> time_bag = CompatUtility::ConvertTimestamp(now);
1270 query1.Table = "logentries";
1271 query1.Type = DbQueryInsert;
1272 query1.Category = DbCatLog;
1274 Dictionary::Ptr fields1 = new Dictionary();
1275 fields1->Set("logentry_time", DbValue::FromTimestamp(time_bag.first));
1276 fields1->Set("entry_time", DbValue::FromTimestamp(time_bag.first));
1277 fields1->Set("entry_time_usec", time_bag.second);
1278 fields1->Set("object_id", checkable); // added in 1.10 see #4754
1279 fields1->Set("logentry_type", type);
1280 fields1->Set("logentry_data", buffer);
1282 fields1->Set("instance_id", 0); /* DbConnection class fills in real ID */
1284 String node = IcingaApplication::GetInstance()->GetNodeName();
1286 Endpoint::Ptr endpoint = Endpoint::GetByName(node);
1288 fields1->Set("endpoint_object_id", endpoint);
1290 query1.Fields = fields1;
1291 DbObject::OnQuery(query1);
1294 /* flappinghistory */
1295 void DbEvents::AddFlappingChangedHistory(const Checkable::Ptr& checkable)
1297 Log(LogDebug, "DbEvents")
1298 << "add flapping history for '" << checkable->GetName() << "'";
1300 double now = Utility::GetTime();
1301 std::pair<unsigned long, unsigned long> time_bag = CompatUtility::ConvertTimestamp(now);
1304 query1.Table = "flappinghistory";
1305 query1.Type = DbQueryInsert;
1306 query1.Category = DbCatFlapping;
1308 Dictionary::Ptr fields1 = new Dictionary();
1310 fields1->Set("event_time", DbValue::FromTimestamp(time_bag.first));
1311 fields1->Set("event_time_usec", time_bag.second);
1313 if (checkable->IsFlapping())
1314 fields1->Set("event_type", 1000);
1316 fields1->Set("event_type", 1001);
1317 fields1->Set("reason_type", 1);
1321 Service::Ptr service;
1322 tie(host, service) = GetHostService(checkable);
1324 fields1->Set("flapping_type", service ? 1 : 0);
1325 fields1->Set("object_id", checkable);
1326 fields1->Set("percent_state_change", checkable->GetFlappingCurrent());
1327 fields1->Set("low_threshold", checkable->GetFlappingThresholdLow());
1328 fields1->Set("high_threshold", checkable->GetFlappingThresholdHigh());
1330 fields1->Set("instance_id", 0); /* DbConnection class fills in real ID */
1332 String node = IcingaApplication::GetInstance()->GetNodeName();
1334 Endpoint::Ptr endpoint = Endpoint::GetByName(node);
1336 fields1->Set("endpoint_object_id", endpoint);
1338 query1.Fields = fields1;
1339 DbObject::OnQuery(query1);
1342 void DbEvents::AddEnableFlappingChangedHistory(const Checkable::Ptr& checkable)
1344 Log(LogDebug, "DbEvents")
1345 << "add flapping history for '" << checkable->GetName() << "'";
1347 double now = Utility::GetTime();
1348 std::pair<unsigned long, unsigned long> time_bag = CompatUtility::ConvertTimestamp(now);
1351 query1.Table = "flappinghistory";
1352 query1.Type = DbQueryInsert;
1353 query1.Category = DbCatFlapping;
1355 Dictionary::Ptr fields1 = new Dictionary();
1357 fields1->Set("event_time", DbValue::FromTimestamp(time_bag.first));
1358 fields1->Set("event_time_usec", time_bag.second);
1360 if (!checkable->GetEnableFlapping())
1363 fields1->Set("event_type", 1001);
1364 fields1->Set("reason_type", 2);
1367 Service::Ptr service;
1368 tie(host, service) = GetHostService(checkable);
1370 fields1->Set("flapping_type", service ? 1 : 0);
1371 fields1->Set("object_id", checkable);
1372 fields1->Set("percent_state_change", checkable->GetFlappingCurrent());
1373 fields1->Set("low_threshold", checkable->GetFlappingThresholdLow());
1374 fields1->Set("high_threshold", checkable->GetFlappingThresholdHigh());
1376 fields1->Set("instance_id", 0); /* DbConnection class fills in real ID */
1378 String node = IcingaApplication::GetInstance()->GetNodeName();
1380 Endpoint::Ptr endpoint = Endpoint::GetByName(node);
1382 fields1->Set("endpoint_object_id", endpoint);
1384 query1.Fields = fields1;
1385 DbObject::OnQuery(query1);
1389 void DbEvents::AddCheckableCheckHistory(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr)
1394 Log(LogDebug, "DbEvents")
1395 << "add checkable check history for '" << checkable->GetName() << "'";
1398 Service::Ptr service;
1399 tie(host, service) = GetHostService(checkable);
1401 std::ostringstream msgbuf;
1404 query1.Table = service ? "servicechecks" : "hostchecks";
1405 query1.Type = DbQueryInsert;
1406 query1.Category = DbCatCheck;
1408 Dictionary::Ptr fields1 = new Dictionary();
1409 fields1->Set("check_type", CompatUtility::GetCheckableCheckType(checkable));
1410 fields1->Set("current_check_attempt", checkable->GetCheckAttempt());
1411 fields1->Set("max_check_attempts", checkable->GetMaxCheckAttempts());
1412 fields1->Set("state_type", checkable->GetStateType());
1414 double start = cr->GetExecutionStart();
1415 std::pair<unsigned long, unsigned long> time_bag_start = CompatUtility::ConvertTimestamp(start);
1417 double end = cr->GetExecutionEnd();
1418 std::pair<unsigned long, unsigned long> time_bag_end = CompatUtility::ConvertTimestamp(end);
1420 double execution_time = cr->CalculateExecutionTime();
1422 fields1->Set("start_time", DbValue::FromTimestamp(time_bag_start.first));
1423 fields1->Set("start_time_usec", time_bag_start.second);
1424 fields1->Set("end_time", DbValue::FromTimestamp(time_bag_end.first));
1425 fields1->Set("end_time_usec", time_bag_end.second);
1426 fields1->Set("command_object_id", checkable->GetCheckCommand());
1427 fields1->Set("command_args", Empty);
1428 fields1->Set("command_line", CompatUtility::GetCommandLine(checkable->GetCheckCommand()));
1429 fields1->Set("execution_time", Convert::ToString(execution_time));
1430 fields1->Set("latency", Convert::ToString(cr->CalculateLatency()));
1431 fields1->Set("return_code", cr->GetExitStatus());
1432 fields1->Set("output", CompatUtility::GetCheckResultOutput(cr));
1433 fields1->Set("long_output", CompatUtility::GetCheckResultLongOutput(cr));
1434 fields1->Set("perfdata", CompatUtility::GetCheckResultPerfdata(cr));
1436 fields1->Set("instance_id", 0); /* DbConnection class fills in real ID */
1439 fields1->Set("service_object_id", service);
1440 fields1->Set("state", service->GetState());
1442 fields1->Set("host_object_id", host);
1443 fields1->Set("state", CompatUtility::GetHostCurrentState(host));
1446 String node = IcingaApplication::GetInstance()->GetNodeName();
1448 Endpoint::Ptr endpoint = Endpoint::GetByName(node);
1450 fields1->Set("endpoint_object_id", endpoint);
1452 query1.Fields = fields1;
1453 DbObject::OnQuery(query1);
1457 void DbEvents::AddEventHandlerHistory(const Checkable::Ptr& checkable)
1459 Log(LogDebug, "DbEvents")
1460 << "add eventhandler history for '" << checkable->GetName() << "'";
1462 double now = Utility::GetTime();
1463 std::pair<unsigned long, unsigned long> time_bag = CompatUtility::ConvertTimestamp(now);
1466 query1.Table = "eventhandlers";
1467 query1.Type = DbQueryInsert;
1468 query1.Category = DbCatEventHandler;
1470 Dictionary::Ptr fields1 = new Dictionary();
1473 Service::Ptr service;
1474 tie(host, service) = GetHostService(checkable);
1476 fields1->Set("object_id", checkable);
1479 fields1->Set("state", service->GetState());
1480 fields1->Set("eventhandler_type", 1);
1482 fields1->Set("state", CompatUtility::GetHostCurrentState(host));
1483 fields1->Set("eventhandler_type", 0);
1486 fields1->Set("state_type", checkable->GetStateType());
1488 fields1->Set("start_time", DbValue::FromTimestamp(time_bag.first));
1489 fields1->Set("start_time_usec", time_bag.second);
1490 fields1->Set("end_time", DbValue::FromTimestamp(time_bag.first));
1491 fields1->Set("end_time_usec", time_bag.second);
1492 fields1->Set("command_object_id", checkable->GetEventCommand());
1494 fields1->Set("instance_id", 0); /* DbConnection class fills in real ID */
1496 String node = IcingaApplication::GetInstance()->GetNodeName();
1498 Endpoint::Ptr endpoint = Endpoint::GetByName(node);
1500 fields1->Set("endpoint_object_id", endpoint);
1502 query1.Fields = fields1;
1503 DbObject::OnQuery(query1);
1506 /* externalcommands */
1507 void DbEvents::AddExternalCommandHistory(double time, const String& command, const std::vector<String>& arguments)
1509 Log(LogDebug, "DbEvents", "add external command history");
1512 query1.Table = "externalcommands";
1513 query1.Type = DbQueryInsert;
1514 query1.Category = DbCatExternalCommand;
1516 Dictionary::Ptr fields1 = new Dictionary();
1518 fields1->Set("entry_time", DbValue::FromTimestamp(static_cast<long>(time)));
1519 fields1->Set("command_type", CompatUtility::MapExternalCommandType(command));
1520 fields1->Set("command_name", command);
1521 fields1->Set("command_args", boost::algorithm::join(arguments, ";"));
1523 fields1->Set("instance_id", 0); /* DbConnection class fills in real ID */
1525 String node = IcingaApplication::GetInstance()->GetNodeName();
1527 Endpoint::Ptr endpoint = Endpoint::GetByName(node);
1529 fields1->Set("endpoint_object_id", endpoint);
1531 query1.Fields = fields1;
1532 DbObject::OnQuery(query1);