import: Add support for passive host and service checks
[nagios-reports-module.git] / hooks.c
blob85776adf47f209fc90eb04459bb79a1c10e96eee
1 /*
2 * Copyright(C) 2005,2007 op5 AB
3 * All rights reserved.
5 * See LICENSE.GPL for license details
7 * This code is taken from the mrm project and modified to suit
8 * the ndbneb database logger
9 */
11 #include "module.h"
12 #include "sql.h"
13 #include "hooks.h"
14 #include "utils.h"
15 #include "hash.h"
16 #include <nagios/broker.h>
18 * sql_query() arguments are usually both numerous and extremely long,
19 * and the idiom is common enough that we want to shorten the syntax
20 * as much as possible, so do that with this macro
22 #define RQ return sql_query
23 #define esc(s) sql_escape(s)
25 #define HOST_STATES_HASH_BUCKETS 4096
26 #define SERVICE_STATES_HASH_BUCKETS (HOST_STATES_HASH_BUCKETS * 4)
29 * The hooks are called from broker.c in Nagios.
31 static hash_table *host_states;
32 static hash_table *svc_states;
34 int hook_init(void)
36 host_states = hash_init(HOST_STATES_HASH_BUCKETS);
37 if (!host_states)
38 return -1;
40 svc_states = hash_init(SERVICE_STATES_HASH_BUCKETS);
41 if (!svc_states) {
42 free(host_states);
43 host_states = NULL;
44 return -1;
47 return prime_initial_states(host_states, svc_states);
50 static inline int has_state_change(int *old, int state, int type)
53 * A state change is considered to consist of a change
54 * to either state_type or state, so we OR the two
55 * together to form a complete state. This will make
56 * the module log as follows:
57 * service foo;poo is HARD OK initially
58 * service foo;poo goes to SOFT WARN, attempt 1 (logged)
59 * service foo;poo goes to SOFT WARN, attempt 2 (not logged)
60 * service foo;poo goes to HARD WARN (logged)
62 state = CAT_STATE(state, type);
64 if (*old == state)
65 return 0;
67 *old = state;
68 return 1;
71 static inline int host_has_new_state(nebstruct_host_check_data *ds)
73 int *old_state;
75 old_state = hash_find(host_states, ds->host_name);
76 if (!old_state) {
77 int *state;
79 state = malloc(sizeof(*state));
80 *state = CAT_STATE(ds->state, ds->state_type);
81 hash_add(host_states, ds->host_name, state);
82 return 1;
85 return has_state_change(old_state, ds->state, ds->state_type);
88 static inline int service_has_new_state(nebstruct_service_check_data *ds)
90 int *old_state;
92 old_state = hash_find2(svc_states, ds->host_name, ds->service_description);
93 if (!old_state) {
94 int *state;
96 state = malloc(sizeof(*state));
97 *state = CAT_STATE(ds->state, ds->state_type);
98 hash_add2(svc_states, ds->host_name, ds->service_description, state);
99 return 1;
102 return has_state_change(old_state, ds->state, ds->state_type);
105 int hook_host_result(int cb, void *data)
107 nebstruct_host_check_data *ds = (nebstruct_host_check_data *)data;
109 /* ignore unprocessed and passive checks */
110 if (ds->type != NEBTYPE_HOSTCHECK_PROCESSED ||
111 cb != NEBCALLBACK_HOST_CHECK_DATA)
113 return 0;
116 linfo("Check result processed for host '%s'", ds->host_name);
118 if (!host_has_new_state(ds)) {
119 linfo("state not changed for host '%s'", ds->host_name);
120 return 0;
123 RQ("INSERT INTO %s ("
124 "timestamp, event_type, host_name, state, "
125 "hard, retry, output"
126 ") VALUES(%lu, %d, '%s', %d, %d, %d, '%s')",
127 sql_table_name(),
128 ds->timestamp.tv_sec, ds->type, esc(ds->host_name), ds->state,
129 ds->state_type == HARD_STATE, ds->current_attempt,
130 esc(ds->output));
133 int hook_service_result(int cb, void *data)
135 nebstruct_service_check_data *ds = (nebstruct_service_check_data *)data;
137 /* ignore unprocessed and passive checks */
138 if (ds->type != NEBTYPE_SERVICECHECK_PROCESSED
139 || cb != NEBCALLBACK_SERVICE_CHECK_DATA)
141 return 0;
144 linfo("Check result processed for service '%s' on host '%s'",
145 ds->service_description, ds->host_name);
147 if (!service_has_new_state(ds)) {
148 linfo("state not changed for service '%s' on host '%s'",
149 ds->service_description, ds->host_name);
150 return 0;
153 RQ("INSERT INTO %s ("
154 "timestamp, event_type, host_name, service_description, state, "
155 "hard, retry, output) "
156 "VALUES(%lu, %d, '%s', '%s', '%d', '%d', '%d', '%s')",
157 sql_table_name(),
158 ds->timestamp.tv_sec, ds->type, esc(ds->host_name),
159 esc(ds->service_description), ds->state,
160 ds->state_type == HARD_STATE, ds->current_attempt,
161 esc(ds->output));
164 int hook_downtime(int cb, void *data)
166 nebstruct_downtime_data *ds = (nebstruct_downtime_data *)data;
167 int depth;
169 switch (ds->type) {
170 case NEBTYPE_DOWNTIME_START:
171 case NEBTYPE_DOWNTIME_STOP:
172 break;
173 default:
174 return 0;
177 if (ds->service_description) {
178 depth = dt_depth_svc(ds->type, ds->host_name, ds->service_description);
180 linfo("Inserting service downtime entry");
181 RQ("INSERT INTO %s"
182 "(timestamp, event_type, host_name,"
183 "service_description, downtime_depth) "
184 "VALUES(%lu, %d, '%s', '%s', %d)",
185 sql_table_name(),
186 ds->timestamp.tv_sec, ds->type, esc(ds->host_name),
187 esc(ds->service_description), depth);
190 depth = dt_depth_host(ds->type, ds->host_name);
191 linfo("Inserting host downtime_data");
192 RQ("INSERT INTO %s"
193 "(timestamp, event_type, host_name, downtime_depth)"
194 "VALUES(%lu, %d, '%s', %d)",
195 sql_table_name(),
196 ds->timestamp.tv_sec, ds->type, esc(ds->host_name), depth);
199 int hook_process_data(int cb, void *data)
201 nebstruct_process_data *ds = (nebstruct_process_data *)data;
203 switch(ds->type) {
204 case NEBTYPE_PROCESS_START:
205 case NEBTYPE_PROCESS_SHUTDOWN:
206 break;
207 case NEBTYPE_PROCESS_RESTART:
208 ds->type = NEBTYPE_PROCESS_SHUTDOWN;
209 break;
210 default:
211 return 0;
214 linfo("Logging Monitor process %s event",
215 ds->type == NEBTYPE_PROCESS_START ? "START" : "STOP");
217 RQ("INSERT INTO %s(timestamp, event_type) "
218 "VALUES(%lu, %d)",
219 sql_table_name(), ds->timestamp.tv_sec, ds->type);