Code

5dfd10ac056a792705a305895cfceb7a0c9d785e
[collectd.git] / src / daemon / utils_tail_match.c
1 /*
2  * collectd - src/utils_tail_match.c
3  * Copyright (C) 2007-2008  C-Ware, Inc.
4  * Copyright (C) 2008       Florian Forster
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  * Author:
25  *   Luke Heberling <lukeh at c-ware.com>
26  *   Florian Forster <octo at collectd.org>
27  *
28  * Description:
29  *   Encapsulates useful code to plugins which must parse a log file.
30  */
32 #include "collectd.h"
34 #include "common.h"
35 #include "plugin.h"
36 #include "utils_match.h"
37 #include "utils_tail.h"
38 #include "utils_tail_match.h"
39 #include "utils_latency_config.h"
41 struct cu_tail_match_simple_s
42 {
43   char plugin[DATA_MAX_NAME_LEN];
44   char plugin_instance[DATA_MAX_NAME_LEN];
45   char type[DATA_MAX_NAME_LEN];
46   char type_instance[DATA_MAX_NAME_LEN];
47   cdtime_t interval;
48   latency_config_t latency_config;
49 };
50 typedef struct cu_tail_match_simple_s cu_tail_match_simple_t;
52 struct cu_tail_match_match_s
53 {
54   cu_match_t *match;
55   void *user_data;
56   int (*submit) (cu_match_t *match, void *user_data);
57   void (*free) (void *user_data);
58 };
59 typedef struct cu_tail_match_match_s cu_tail_match_match_t;
61 struct cu_tail_match_s
62 {
63   int flags;
64   cu_tail_t *tail;
66   cdtime_t interval;
67   cu_tail_match_match_t *matches;
68   size_t matches_num;
69 };
71 /*
72  * Private functions
73  */
74 static int simple_submit_match (cu_match_t *match, void *user_data)
75 {
76   cu_tail_match_simple_t *data = (cu_tail_match_simple_t *) user_data;
77   cu_match_value_t *match_value;
78   value_list_t vl = VALUE_LIST_INIT;
79   value_t values[1];
81   match_value = (cu_match_value_t *) match_get_user_data (match);
82   if (match_value == NULL)
83     return (-1);
85   if ((match_value->ds_type & UTILS_MATCH_DS_TYPE_GAUGE)
86       && (match_value->values_num == 0))
87     values[0].gauge = NAN;
88   else
89     values[0] = match_value->value;
91   vl.values = values;
92   vl.values_len = 1;
93   sstrncpy (vl.plugin, data->plugin, sizeof (vl.plugin));
94   sstrncpy (vl.plugin_instance, data->plugin_instance,
95       sizeof (vl.plugin_instance));
96   sstrncpy (vl.type, data->type, sizeof (vl.type));
97   sstrncpy (vl.type_instance, data->type_instance,
98       sizeof (vl.type_instance));
100   vl.interval = data->interval;
101   plugin_dispatch_values (&vl);
103   match_value_reset (match_value);
104   return (0);
105 } /* int simple_submit_match */
107 static int simple_submit_latency (cu_match_t *match, void *user_data)
109   cu_tail_match_simple_t *data = (cu_tail_match_simple_t *) user_data;
110   cu_match_value_t *match_value;
111   value_list_t vl = VALUE_LIST_INIT;
113   match_value = (cu_match_value_t *) match_get_user_data (match);
114   if (match_value == NULL)
115     return (-1);
117   vl.values = &(value_t) { .gauge = NAN };
118   vl.values_len = 1;
119   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
120   sstrncpy (vl.plugin, data->plugin, sizeof (vl.plugin));
121   sstrncpy (vl.plugin_instance, data->plugin_instance,
122       sizeof (vl.plugin_instance));
123   sstrncpy (vl.type, data->type, sizeof (vl.type));
124   vl.interval = data->interval;
125   vl.time = cdtime ();
127   if (data->latency_config.lower) {
128     ssnprintf (vl.type_instance, sizeof (vl.type_instance),
129         "lower");
130     vl.values[0].gauge = (match_value->values_num != 0)
131       ? CDTIME_T_TO_DOUBLE (latency_counter_get_min (match_value->latency))
132       : NAN;
133     plugin_dispatch_values (&vl);
134   }
136   if (data->latency_config.avg) {
137     ssnprintf (vl.type_instance, sizeof (vl.type_instance),
138         "average");
139     vl.values[0].gauge = (match_value->values_num != 0)
140       ? CDTIME_T_TO_DOUBLE (latency_counter_get_average (match_value->latency))
141       : NAN;
142     plugin_dispatch_values (&vl);
143   }
145   if (data->latency_config.upper) {
146     ssnprintf (vl.type_instance, sizeof (vl.type_instance),
147         "upper");
148     vl.values[0].gauge = (match_value->values_num != 0)
149       ? CDTIME_T_TO_DOUBLE (latency_counter_get_max (match_value->latency))
150       : NAN;
151     plugin_dispatch_values (&vl);
152   }
154   /* Submit percentiles */
155   if (data->latency_config.percentile_type != NULL)
156     sstrncpy (vl.type, data->latency_config.percentile_type, sizeof (vl.type));
157   for (size_t i = 0; i < data->latency_config.percentile_num; i++)
158   {
159     ssnprintf (vl.type_instance, sizeof (vl.type_instance),
160         "percentile-%.0f",  data->latency_config.percentile[i]);
161     vl.values[0].gauge = (match_value->values_num != 0)
162       ? CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (match_value->latency,
163                                             data->latency_config.percentile[i]))
164       : NAN;
165     plugin_dispatch_values (&vl);
166   }
168   /* Submit rates */
169   sstrncpy (vl.type, data->type, sizeof (vl.type));
170   if (data->latency_config.rates_type != NULL)
171     sstrncpy (vl.type, data->latency_config.rates_type, sizeof (vl.type));
172   for (size_t i = 0; i < data->latency_config.rates_num; i++)
173   {
174     ssnprintf (vl.type_instance, sizeof (vl.type_instance),
175         "rate-%.3f-%.3f",
176         CDTIME_T_TO_DOUBLE(data->latency_config.rates[i * 2]),
177         CDTIME_T_TO_DOUBLE(data->latency_config.rates[i * 2 + 1]));
178     vl.values[0].gauge = (match_value->values_num != 0) 
179       ? latency_counter_get_rate (match_value->latency,
180                                   data->latency_config.rates[i * 2],
181                                   data->latency_config.rates[i * 2 + 1],
182                                   vl.time)
183       : NAN;
184     plugin_dispatch_values (&vl);
185   }
186   latency_counter_reset (match_value->latency);
188   match_value->value.gauge = NAN;
189   match_value->values_num = 0;
191   return (0);
192 } /* int simple_submit_latency */
194 static int tail_callback (void *data, char *buf,
195     int __attribute__((unused)) buflen)
197   cu_tail_match_t *obj = (cu_tail_match_t *) data;
199   for (size_t i = 0; i < obj->matches_num; i++)
200     match_apply (obj->matches[i].match, buf);
202   return (0);
203 } /* int tail_callback */
205 static void tail_match_simple_free (void *data)
207   cu_tail_match_simple_t *user_data = (cu_tail_match_simple_t *) data;
208   latency_config_free(user_data->latency_config);
209   sfree (user_data);
210 } /* void tail_match_simple_free */
212 /*
213  * Public functions
214  */
215 cu_tail_match_t *tail_match_create (const char *filename)
217   cu_tail_match_t *obj;
219   obj = calloc (1, sizeof (*obj));
220   if (obj == NULL)
221     return (NULL);
223   obj->tail = cu_tail_create (filename);
224   if (obj->tail == NULL)
225   {
226     sfree (obj);
227     return (NULL);
228   }
230   return (obj);
231 } /* cu_tail_match_t *tail_match_create */
233 void tail_match_destroy (cu_tail_match_t *obj)
235   if (obj == NULL)
236     return;
238   if (obj->tail != NULL)
239   {
240     cu_tail_destroy (obj->tail);
241     obj->tail = NULL;
242   }
244   for (size_t i = 0; i < obj->matches_num; i++)
245   {
246     cu_tail_match_match_t *match = obj->matches + i;
247     if (match->match != NULL)
248     {
249       match_destroy (match->match);
250       match->match = NULL;
251     }
253     if ((match->user_data != NULL)
254         && (match->free != NULL))
255       (*match->free) (match->user_data);
256     match->user_data = NULL;
257   }
259   sfree (obj->matches);
260   sfree (obj);
261 } /* void tail_match_destroy */
263 int tail_match_add_match (cu_tail_match_t *obj, cu_match_t *match,
264     int (*submit_match) (cu_match_t *match, void *user_data),
265     void *user_data,
266     void (*free_user_data) (void *user_data))
268   cu_tail_match_match_t *temp;
270   temp = realloc (obj->matches,
271       sizeof (cu_tail_match_match_t) * (obj->matches_num + 1));
272   if (temp == NULL)
273     return (-1);
275   obj->matches = temp;
276   obj->matches_num++;
278   DEBUG ("tail_match_add_match interval %lf", CDTIME_T_TO_DOUBLE(((cu_tail_match_simple_t *)user_data)->interval));
279   temp = obj->matches + (obj->matches_num - 1);
281   temp->match = match;
282   temp->user_data = user_data;
283   temp->submit = submit_match;
284   temp->free = free_user_data;
286   return (0);
287 } /* int tail_match_add_match */
289 int tail_match_add_match_simple (cu_tail_match_t *obj,
290     const char *regex, const char *excluderegex, int ds_type,
291     const char *plugin, const char *plugin_instance,
292     const char *type, const char *type_instance,
293     const latency_config_t latency_cfg,
294     const cdtime_t interval)
296   cu_match_t *match;
297   cu_tail_match_simple_t *user_data;
298   int status;
300   match = match_create_simple (regex, excluderegex, ds_type);
301   if (match == NULL)
302     return (-1);
304   user_data = calloc (1, sizeof (*user_data));
305   if (user_data == NULL)
306   {
307     match_destroy (match);
308     return (-1);
309   }
311   sstrncpy (user_data->plugin, plugin, sizeof (user_data->plugin));
312   if (plugin_instance != NULL)
313     sstrncpy (user_data->plugin_instance, plugin_instance,
314         sizeof (user_data->plugin_instance));
316   sstrncpy (user_data->type, type, sizeof (user_data->type));
317   if (type_instance != NULL)
318     sstrncpy (user_data->type_instance, type_instance,
319         sizeof (user_data->type_instance));
321   user_data->interval = interval;
323   if ((ds_type & UTILS_MATCH_DS_TYPE_GAUGE)
324       && (ds_type & UTILS_MATCH_CF_GAUGE_LATENCY))
325   {
326     status = latency_config_copy(&user_data->latency_config, latency_cfg);
327     if (status != 0)
328     {
329       ERROR ("tail_match_add_match_simple: latency_config_copy() failed.");
330       status = -1;
331       goto out;
332     }
334     status = tail_match_add_match (obj, match, simple_submit_latency,
335       user_data, tail_match_simple_free);
336   } else {
337     status = tail_match_add_match (obj, match, simple_submit_match,
338       user_data, free);
339   }
341 out:
342   if (status != 0)
343   {
344     tail_match_simple_free(user_data);
345     match_destroy (match);
346   }
348   return (status);
349 } /* int tail_match_add_match_simple */
351 int tail_match_read (cu_tail_match_t *obj)
353   char buffer[4096];
354   int status;
356   status = cu_tail_read (obj->tail, buffer, sizeof (buffer), tail_callback,
357       (void *) obj);
358   if (status != 0)
359   {
360     ERROR ("tail_match: cu_tail_read failed.");
361     return (status);
362   }
364   for (size_t i = 0; i < obj->matches_num; i++)
365   {
366     cu_tail_match_match_t *lt_match = obj->matches + i;
368     if (lt_match->submit == NULL)
369       continue;
371     (*lt_match->submit) (lt_match->match, lt_match->user_data);
372   }
374   return (0);
375 } /* int tail_match_read */
377 /* vim: set sw=2 sts=2 ts=8 : */