2 * collectd - src/target_notification.c
3 * Copyright (C) 2008 Florian Forster
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; only version 2 of the License is applicable.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Florian Forster <octo at verplant.org>
24 #include "filter_chain.h"
25 #include "utils_cache.h"
26 #include "utils_subst.h"
33 typedef struct tn_data_s tn_data_t;
35 static int tn_config_add_severity (tn_data_t *data, /* {{{ */
36 const oconfig_item_t *ci)
38 if ((ci->values_num != 1)
39 || (ci->values[0].type != OCONFIG_TYPE_STRING))
41 ERROR ("Target `notification': The `%s' option requires exactly one string "
42 "argument.", ci->key);
46 if ((strcasecmp ("FAILURE", ci->values[0].value.string) == 0)
47 || (strcasecmp ("CRITICAL", ci->values[0].value.string) == 0))
48 data->severity = NOTIF_FAILURE;
49 else if ((strcasecmp ("WARNING", ci->values[0].value.string) == 0)
50 || (strcasecmp ("WARN", ci->values[0].value.string) == 0))
51 data->severity = NOTIF_WARNING;
52 else if (strcasecmp ("OKAY", ci->values[0].value.string) == 0)
53 data->severity = NOTIF_OKAY;
56 WARNING ("Target `notification': Unknown severity `%s'. "
57 "Will use `FAILURE' instead.",
58 ci->values[0].value.string);
59 data->severity = NOTIF_FAILURE;
63 } /* }}} int tn_config_add_severity */
65 static int tn_config_add_string (char **dest, /* {{{ */
66 const oconfig_item_t *ci)
73 if ((ci->values_num != 1)
74 || (ci->values[0].type != OCONFIG_TYPE_STRING))
76 ERROR ("Target `notification': The `%s' option requires exactly one string "
77 "argument.", ci->key);
81 if (ci->values[0].value.string[0] == 0)
83 ERROR ("Target `notification': The `%s' option does not accept empty strings.",
88 temp = sstrdup (ci->values[0].value.string);
91 ERROR ("tn_config_add_string: sstrdup failed.");
99 } /* }}} int tn_config_add_string */
101 static int tn_destroy (void **user_data) /* {{{ */
105 if (user_data == NULL)
112 sfree (data->message);
116 } /* }}} int tn_destroy */
118 static int tn_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
124 data = (tn_data_t *) malloc (sizeof (*data));
127 ERROR ("tn_create: malloc failed.");
130 memset (data, 0, sizeof (*data));
132 data->message = NULL;
136 for (i = 0; i < ci->children_num; i++)
138 oconfig_item_t *child = ci->children + i;
140 if (strcasecmp ("Message", child->key) == 0)
141 status = tn_config_add_string (&data->message, child);
142 else if (strcasecmp ("Severity", child->key) == 0)
143 status = tn_config_add_severity (data, child);
146 ERROR ("Target `notification': The `%s' configuration option is not understood "
147 "and will be ignored.", child->key);
155 /* Additional sanity-checking */
158 if ((data->severity != NOTIF_FAILURE)
159 && (data->severity != NOTIF_WARNING)
160 && (data->severity != NOTIF_OKAY))
162 DEBUG ("Target `notification': Setting "
163 "the default severity `WARNING'.");
164 data->severity = NOTIF_WARNING;
167 if (data->message == NULL)
169 ERROR ("Target `notification': No `Message' option has been specified. "
170 "Without it, the `Notification' target is useless.");
179 tn_destroy ((void *) data);
185 } /* }}} int tn_create */
187 static int tn_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
188 notification_meta_t __attribute__((unused)) **meta, void **user_data)
192 char temp[NOTIF_MAX_MSG_LEN];
199 if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
205 ERROR ("Target `notification': Invoke: `data' is NULL.");
209 /* Initialize the structure. */
210 memset (&n, 0, sizeof (n));
211 n.severity = data->severity;
213 sstrncpy (n.message, data->message, sizeof (n.message));
214 sstrncpy (n.host, vl->host, sizeof (n.host));
215 sstrncpy (n.plugin, vl->plugin, sizeof (n.plugin));
216 sstrncpy (n.plugin_instance, vl->plugin_instance,
217 sizeof (n.plugin_instance));
218 sstrncpy (n.type, vl->type, sizeof (n.type));
219 sstrncpy (n.type_instance, vl->type_instance,
220 sizeof (n.type_instance));
223 #define REPLACE_FIELD(t,v) \
224 if (subst_string (temp, sizeof (temp), n.message, t, v) != NULL) \
225 sstrncpy (n.message, temp, sizeof (n.message));
226 REPLACE_FIELD ("%{host}", n.host);
227 REPLACE_FIELD ("%{plugin}", n.plugin);
228 REPLACE_FIELD ("%{plugin_instance}", n.plugin_instance);
229 REPLACE_FIELD ("%{type}", n.type);
230 REPLACE_FIELD ("%{type_instance}", n.type_instance);
234 for (i = 0; i < ds->ds_num; i++)
236 char template[DATA_MAX_NAME_LEN];
237 char value_str[DATA_MAX_NAME_LEN];
239 ssnprintf (template, sizeof (template), "%%{ds:%s}", ds->ds[i].name);
241 if (ds->ds[i].type != DS_TYPE_GAUGE)
243 if ((rates == NULL) && (rates_failed == 0))
245 rates = uc_get_rate (ds, vl);
251 /* If this is a gauge value, use the current value. */
252 if (ds->ds[i].type == DS_TYPE_GAUGE)
253 ssnprintf (value_str, sizeof (value_str),
254 "%g", (double) vl->values[i].gauge);
255 /* If it's a counter, try to use the current rate. This may fail, if the
256 * value has been renamed. */
257 else if (rates != NULL)
258 ssnprintf (value_str, sizeof (value_str),
259 "%g", (double) rates[i]);
260 /* Since we don't know any better, use the string `unknown'. */
262 sstrncpy (value_str, "unknown", sizeof (value_str));
264 REPLACE_FIELD (template, value_str);
268 plugin_dispatch_notification (&n);
270 return (FC_TARGET_CONTINUE);
271 } /* }}} int tn_invoke */
273 void module_register (void)
277 memset (&tproc, 0, sizeof (tproc));
278 tproc.create = tn_create;
279 tproc.destroy = tn_destroy;
280 tproc.invoke = tn_invoke;
281 fc_register_target ("notification", tproc);
282 } /* module_register */
284 /* vim: set sw=2 sts=2 tw=78 et fdm=marker : */