root/src/noit_check_log.c

Revision c2fc05493b26a8adf1c753d6e1784b2e52ce5fe9, 11.8 kB (checked in by Dan Di Spaltro <dan@cloudkick.com>, 3 years ago)

Add name to the delete metric

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  *       copyright notice, this list of conditions and the following
13  *       disclaimer in the documentation and/or other materials provided
14  *       with the distribution.
15  *     * Neither the name OmniTI Computer Consulting, Inc. nor the names
16  *       of its contributors may be used to endorse or promote products
17  *       derived from this software without specific prior written
18  *       permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "noit_defines.h"
34
35 #include <uuid/uuid.h>
36 #include <netinet/in.h>
37
38 #include "noit_check.h"
39 #include "noit_filters.h"
40 #include "utils/noit_log.h"
41 #include "jlog/jlog.h"
42
43 /* Log format is tab delimited:
44  * NOIT CONFIG (implemented in noit_conf.c):
45  *  'n' TIMESTAMP strlen(xmlconfig) base64(gzip(xmlconfig))
46  *
47  * DELETE:
48  *  'D' TIMESTAMP UUID NAME
49  *
50  * CHECK:
51  *  'C' TIMESTAMP UUID TARGET MODULE NAME
52  *
53  * STATUS:
54  *  'S' TIMESTAMP UUID STATE AVAILABILITY DURATION STATUS_MESSAGE
55  *
56  * METRICS:
57  *  'M' TIMESTAMP UUID NAME TYPE VALUE
58  */
59
60 static noit_log_stream_t check_log = NULL;
61 static noit_log_stream_t status_log = NULL;
62 static noit_log_stream_t metrics_log = NULL;
63 static noit_log_stream_t delete_log = NULL;
64 #define SECPART(a) ((unsigned long)(a)->tv_sec)
65 #define MSECPART(a) ((unsigned long)((a)->tv_usec / 1000))
66 #define MAKE_CHECK_UUID_STR(uuid_str, len, ls, check) do { \
67   noit_boolean extended_id = noit_false; \
68   const char *v; \
69   v = noit_log_stream_get_property(ls, "extended_id"); \
70   if(v && !strcmp(v, "on")) extended_id = noit_true; \
71   uuid_str[0] = '\0'; \
72   if(extended_id) { \
73     strlcat(uuid_str, check->target, len-37); \
74     strlcat(uuid_str, "`", len-37); \
75     strlcat(uuid_str, check->module, len-37); \
76     strlcat(uuid_str, "`", len-37); \
77     strlcat(uuid_str, check->name, len-37); \
78     strlcat(uuid_str, "`", len-37); \
79   } \
80   uuid_unparse_lower(check->checkid, uuid_str + strlen(uuid_str)); \
81 } while(0)
82
83 static void
84 handle_extra_feeds(noit_check_t *check,
85                    int (*log_f)(noit_log_stream_t ls, noit_check_t *check)) {
86   noit_log_stream_t ls;
87   noit_skiplist_node *curr, *next;
88   const char *feed_name;
89
90   if(!check->feeds) return;
91   curr = next = noit_skiplist_getlist(check->feeds);
92   while(curr) {
93     /* We advance next here (before we try to use curr).
94      * We may need to remove the node we're looking at and that would
95      * disturb the iterator, so advance in advance. */
96     noit_skiplist_next(check->feeds, &next);
97     feed_name = (char *)curr->data;
98     ls = noit_log_stream_find(feed_name);
99     if(!ls || log_f(ls, check)) {
100       noit_check_transient_remove_feed(check, feed_name);
101       /* noit_skiplisti_remove(check->feeds, curr, free); */
102     }
103     curr = next;
104   }
105   /* We're done... we may have destroyed the last feed.
106    * that combined with transience means we should kill the check */
107   /* noit_check_transient_remove_feed(check, NULL); */
108 }
109
110 static int
111 _noit_check_log_delete(noit_log_stream_t ls,
112                        noit_check_t *check) {
113   stats_t *c;
114   char uuid_str[256*3+37];
115   SETUP_LOG(delete, );
116   MAKE_CHECK_UUID_STR(uuid_str, sizeof(uuid_str), status_log, check);
117
118   c = &check->stats.current;
119   return noit_log(ls, &c->whence, __FILE__, __LINE__,
120                   "D\t%lu.%03lu\t%s\t%s\n",
121                   SECPART(&c->whence), MSECPART(&c->whence), uuid_str, check->name);
122 }
123 void
124 noit_check_log_delete(noit_check_t *check) {
125   if(!(check->flags & NP_TRANSIENT)) {
126     handle_extra_feeds(check, _noit_check_log_delete);
127     SETUP_LOG(delete, return);
128     _noit_check_log_delete(delete_log, check);
129   }
130 }
131
132 static int
133 _noit_check_log_check(noit_log_stream_t ls,
134                       noit_check_t *check) {
135   struct timeval __now;
136   char uuid_str[256*3+37];
137   SETUP_LOG(check, );
138   MAKE_CHECK_UUID_STR(uuid_str, sizeof(uuid_str), check_log, check);
139
140   gettimeofday(&__now, NULL);
141   return noit_log(ls, &__now, __FILE__, __LINE__,
142                   "C\t%lu.%03lu\t%s\t%s\t%s\t%s\n",
143                   SECPART(&__now), MSECPART(&__now),
144                   uuid_str, check->target, check->module, check->name);
145 }
146
147 void
148 noit_check_log_check(noit_check_t *check) {
149   if(!(check->flags & NP_TRANSIENT)) {
150     handle_extra_feeds(check, _noit_check_log_check);
151     SETUP_LOG(check, return);
152     _noit_check_log_check(check_log, check);
153   }
154 }
155
156 static int
157 _noit_check_log_status(noit_log_stream_t ls,
158                        noit_check_t *check) {
159   stats_t *c;
160   char uuid_str[256*3+37];
161   SETUP_LOG(status, );
162   MAKE_CHECK_UUID_STR(uuid_str, sizeof(uuid_str), status_log, check);
163
164   c = &check->stats.current;
165   return noit_log(ls, &c->whence, __FILE__, __LINE__,
166                   "S\t%lu.%03lu\t%s\t%c\t%c\t%d\t%s\n",
167                   SECPART(&c->whence), MSECPART(&c->whence), uuid_str,
168                   (char)c->state, (char)c->available, c->duration, c->status);
169 }
170 void
171 noit_check_log_status(noit_check_t *check) {
172   handle_extra_feeds(check, _noit_check_log_status);
173   if(!(check->flags & (NP_TRANSIENT | NP_SUPPRESS_STATUS))) {
174     SETUP_LOG(status, return);
175     _noit_check_log_status(status_log, check);
176   }
177 }
178 static int
179 _noit_check_log_metric(noit_log_stream_t ls, noit_check_t *check,
180                        const char *uuid_str,
181                        struct timeval *whence, metric_t *m) {
182   char our_uuid_str[256*3+37];
183   int srv = 0;
184   if(!noit_apply_filterset(check->filterset, check, m)) return 0;
185   if(!ls->enabled) return 0;
186
187   if(!uuid_str) {
188     MAKE_CHECK_UUID_STR(our_uuid_str, sizeof(our_uuid_str), metrics_log, check);
189     uuid_str = our_uuid_str;
190   }
191
192   if(!m->metric_value.s) { /* they are all null */
193     srv = noit_log(ls, whence, __FILE__, __LINE__,
194                    "M\t%lu.%03lu\t%s\t%s\t%c\t[[null]]\n",
195                    SECPART(whence), MSECPART(whence), uuid_str,
196                    m->metric_name, m->metric_type);
197   }
198   else {
199     switch(m->metric_type) {
200       case METRIC_INT32:
201         srv = noit_log(ls, whence, __FILE__, __LINE__,
202                        "M\t%lu.%03lu\t%s\t%s\t%c\t%d\n",
203                        SECPART(whence), MSECPART(whence), uuid_str,
204                        m->metric_name, m->metric_type, *(m->metric_value.i));
205         break;
206       case METRIC_UINT32:
207         srv = noit_log(ls, whence, __FILE__, __LINE__,
208                        "M\t%lu.%03lu\t%s\t%s\t%c\t%u\n",
209                        SECPART(whence), MSECPART(whence), uuid_str,
210                        m->metric_name, m->metric_type, *(m->metric_value.I));
211         break;
212       case METRIC_INT64:
213         srv = noit_log(ls, whence, __FILE__, __LINE__,
214                        "M\t%lu.%03lu\t%s\t%s\t%c\t%lld\n",
215                        SECPART(whence), MSECPART(whence), uuid_str,
216                        m->metric_name, m->metric_type,
217                        (long long int)*(m->metric_value.l));
218         break;
219       case METRIC_UINT64:
220         srv = noit_log(ls, whence, __FILE__, __LINE__,
221                        "M\t%lu.%03lu\t%s\t%s\t%c\t%llu\n",
222                        SECPART(whence), MSECPART(whence), uuid_str,
223                        m->metric_name, m->metric_type,
224                        (long long unsigned int)*(m->metric_value.L));
225         break;
226       case METRIC_DOUBLE:
227         srv = noit_log(ls, whence, __FILE__, __LINE__,
228                        "M\t%lu.%03lu\t%s\t%s\t%c\t%.12e\n",
229                        SECPART(whence), MSECPART(whence), uuid_str,
230                        m->metric_name, m->metric_type, *(m->metric_value.n));
231         break;
232       case METRIC_STRING:
233         srv = noit_log(ls, whence, __FILE__, __LINE__,
234                        "M\t%lu.%03lu\t%s\t%s\t%c\t%s\n",
235                        SECPART(whence), MSECPART(whence), uuid_str,
236                        m->metric_name, m->metric_type, m->metric_value.s);
237         break;
238       default:
239         noitL(noit_error, "Unknown metric type '%c' 0x%x\n",
240               m->metric_type, m->metric_type);
241     }
242   }
243   return srv;
244 }
245 static int
246 _noit_check_log_metrics(noit_log_stream_t ls, noit_check_t *check) {
247   int rv = 0;
248   int srv;
249   char uuid_str[256*3+37];
250   noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
251   const char *key;
252   int klen;
253   stats_t *c;
254   void *vm;
255   SETUP_LOG(metrics, );
256   MAKE_CHECK_UUID_STR(uuid_str, sizeof(uuid_str), metrics_log, check);
257
258   c = &check->stats.current;
259   while(noit_hash_next(&c->metrics, &iter, &key, &klen, &vm)) {
260     /* If we apply the filter set and it returns false, we don't log */
261     metric_t *m = (metric_t *)vm;
262     srv = _noit_check_log_metric(ls, check, uuid_str, &c->whence, m);
263     if(srv) rv = srv;
264   }
265   return rv;
266 }
267 void
268 noit_check_log_metrics(noit_check_t *check) {
269   handle_extra_feeds(check, _noit_check_log_metrics);
270   if(!(check->flags & (NP_TRANSIENT | NP_SUPPRESS_METRICS))) {
271     SETUP_LOG(metrics, return);
272     _noit_check_log_metrics(metrics_log, check);
273   }
274 }
275
276 void
277 noit_check_log_metric(noit_check_t *check, struct timeval *whence,
278                       metric_t *m) {
279   char uuid_str[256*3+37];
280   MAKE_CHECK_UUID_STR(uuid_str, sizeof(uuid_str), metrics_log, check);
281
282   /* handle feeds -- hust like handle_extra_feeds, but this
283    * is with different arguments.
284    */
285   if(check->feeds) {
286     noit_skiplist_node *curr, *next;
287     curr = next = noit_skiplist_getlist(check->feeds);
288     while(curr) {
289       const char *feed_name = (char *)curr->data;
290       noit_log_stream_t ls = noit_log_stream_find(feed_name);
291       noit_skiplist_next(check->feeds, &next);
292       if(!ls || _noit_check_log_metric(ls, check, uuid_str, whence, m))
293         noit_check_transient_remove_feed(check, feed_name);
294       curr = next;
295     }
296   }
297   if(!(check->flags & NP_TRANSIENT)) {
298     SETUP_LOG(metrics, return);
299     _noit_check_log_metric(metrics_log, check, uuid_str, whence, m);
300   }
301 }
302
303 int
304 noit_stats_snprint_metric_value(char *b, int l, metric_t *m) {
305   int rv;
306   if(!m->metric_value.s) { /* they are all null */
307     rv = snprintf(b, l, "[[null]]");
308   }
309   else {
310     switch(m->metric_type) {
311       case METRIC_INT32:
312         rv = snprintf(b, l, "%d", *(m->metric_value.i)); break;
313       case METRIC_UINT32:
314         rv = snprintf(b, l, "%u", *(m->metric_value.I)); break;
315       case METRIC_INT64:
316         rv = snprintf(b, l, "%lld", (long long int)*(m->metric_value.l)); break;
317       case METRIC_UINT64:
318         rv = snprintf(b, l, "%llu",
319                       (long long unsigned int)*(m->metric_value.L)); break;
320       case METRIC_DOUBLE:
321         rv = snprintf(b, l, "%.12e", *(m->metric_value.n)); break;
322       case METRIC_STRING:
323         rv = snprintf(b, l, "%s", m->metric_value.s); break;
324       default:
325         return -1;
326     }
327   }
328   return rv;
329 }
330 int
331 noit_stats_snprint_metric(char *b, int l, metric_t *m) {
332   int rv, nl;
333   nl = snprintf(b, l, "%s[%c] = ", m->metric_name, m->metric_type);
334   if(nl >= l || nl <= 0) return nl;
335   rv = noit_stats_snprint_metric_value(b+nl, l-nl, m);
336   if(rv == -1)
337     rv = snprintf(b+nl, l-nl, "[[unknown type]]");
338   return rv + nl;
339 }
Note: See TracBrowser for help on using the browser.