root/src/noit_check_log.c

Revision d8ec2a3842ef728eff873aba1e90e632c10d88a4, 15.5 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 2 years ago)

Add period and timeout to the bundle.

Update both generated code, c and java.
Add a Makefile command to generate.

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007-2012, 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 #include "dtrace_probes.h"
35
36 #include <uuid/uuid.h>
37 #include <netinet/in.h>
38
39 #include "noit_check.h"
40 #include "noit_filters.h"
41 #include "utils/noit_log.h"
42 #include "jlog/jlog.h"
43
44 #include "bundle.pb-c.h"
45 #include "noit_check_log_helpers.h"
46
47 /* Log format is tab delimited:
48  * NOIT CONFIG (implemented in noit_conf.c):
49  *  'n' TIMESTAMP strlen(xmlconfig) base64(gzip(xmlconfig))
50  *
51  * DELETE:
52  *  'D' TIMESTAMP UUID NAME
53  *
54  * CHECK:
55  *  'C' TIMESTAMP UUID TARGET MODULE NAME
56  *
57  * STATUS:
58  *  'S' TIMESTAMP UUID STATE AVAILABILITY DURATION STATUS_MESSAGE
59  *
60  * METRICS:
61  *  'M' TIMESTAMP UUID NAME TYPE VALUE
62  *
63  * BUNDLE
64  *  'B#' TIMESTAMP UUID TARGET MODULE NAME strlen(base64(gzipped(payload))) base64(gzipped(payload))
65  * 
66  */
67
68 static noit_log_stream_t check_log = NULL;
69 static noit_log_stream_t status_log = NULL;
70 static noit_log_stream_t metrics_log = NULL;
71 static noit_log_stream_t delete_log = NULL;
72 static noit_log_stream_t bundle_log = NULL;
73
74 #define SECPART(a) ((unsigned long)(a)->tv_sec)
75 #define MSECPART(a) ((unsigned long)((a)->tv_usec / 1000))
76 #define MAKE_CHECK_UUID_STR(uuid_str, len, ls, check) do { \
77   noit_boolean extended_id = noit_false; \
78   const char *v; \
79   v = noit_log_stream_get_property(ls, "extended_id"); \
80   if(v && !strcmp(v, "on")) extended_id = noit_true; \
81   uuid_str[0] = '\0'; \
82   if(extended_id) { \
83     strlcat(uuid_str, check->target, len-37); \
84     strlcat(uuid_str, "`", len-37); \
85     strlcat(uuid_str, check->module, len-37); \
86     strlcat(uuid_str, "`", len-37); \
87     strlcat(uuid_str, check->name, len-37); \
88     strlcat(uuid_str, "`", len-37); \
89   } \
90   uuid_unparse_lower(check->checkid, uuid_str + strlen(uuid_str)); \
91 } while(0)
92
93 static void
94 handle_extra_feeds(noit_check_t *check,
95                    int (*log_f)(noit_log_stream_t ls, noit_check_t *check)) {
96   noit_log_stream_t ls;
97   noit_skiplist_node *curr, *next;
98   const char *feed_name;
99
100   if(!check->feeds) return;
101   curr = next = noit_skiplist_getlist(check->feeds);
102   while(curr) {
103     /* We advance next here (before we try to use curr).
104      * We may need to remove the node we're looking at and that would
105      * disturb the iterator, so advance in advance. */
106     noit_skiplist_next(check->feeds, &next);
107     feed_name = (char *)curr->data;
108     ls = noit_log_stream_find(feed_name);
109     if(!ls || log_f(ls, check)) {
110       noit_check_transient_remove_feed(check, feed_name);
111       /* noit_skiplisti_remove(check->feeds, curr, free); */
112     }
113     curr = next;
114   }
115   /* We're done... we may have destroyed the last feed.
116    * that combined with transience means we should kill the check */
117   /* noit_check_transient_remove_feed(check, NULL); */
118 }
119
120 static int
121 _noit_check_log_delete(noit_log_stream_t ls,
122                        noit_check_t *check) {
123   stats_t *c;
124   char uuid_str[256*3+37];
125   SETUP_LOG(delete, );
126   MAKE_CHECK_UUID_STR(uuid_str, sizeof(uuid_str), status_log, check);
127
128   c = &check->stats.current;
129   return noit_log(ls, &c->whence, __FILE__, __LINE__,
130                   "D\t%lu.%03lu\t%s\t%s\n",
131                   SECPART(&c->whence), MSECPART(&c->whence), uuid_str, check->name);
132 }
133 void
134 noit_check_log_delete(noit_check_t *check) {
135   if(!(check->flags & NP_TRANSIENT)) {
136     handle_extra_feeds(check, _noit_check_log_delete);
137     SETUP_LOG(delete, return);
138     _noit_check_log_delete(delete_log, check);
139   }
140 }
141
142 static int
143 _noit_check_log_check(noit_log_stream_t ls,
144                       noit_check_t *check) {
145   struct timeval __now;
146   char uuid_str[256*3+37];
147   SETUP_LOG(check, );
148   MAKE_CHECK_UUID_STR(uuid_str, sizeof(uuid_str), check_log, check);
149
150   gettimeofday(&__now, NULL);
151   return noit_log(ls, &__now, __FILE__, __LINE__,
152                   "C\t%lu.%03lu\t%s\t%s\t%s\t%s\n",
153                   SECPART(&__now), MSECPART(&__now),
154                   uuid_str, check->target, check->module, check->name);
155 }
156
157 void
158 noit_check_log_check(noit_check_t *check) {
159   if(!(check->flags & NP_TRANSIENT)) {
160     handle_extra_feeds(check, _noit_check_log_check);
161     SETUP_LOG(check, return);
162     _noit_check_log_check(check_log, check);
163   }
164 }
165
166 static int
167 _noit_check_log_status(noit_log_stream_t ls,
168                        noit_check_t *check) {
169   stats_t *c;
170   char uuid_str[256*3+37];
171   SETUP_LOG(status, );
172   MAKE_CHECK_UUID_STR(uuid_str, sizeof(uuid_str), status_log, check);
173
174   c = &check->stats.current;
175   return noit_log(ls, &c->whence, __FILE__, __LINE__,
176                   "S\t%lu.%03lu\t%s\t%c\t%c\t%d\t%s\n",
177                   SECPART(&c->whence), MSECPART(&c->whence), uuid_str,
178                   (char)c->state, (char)c->available, c->duration, c->status);
179 }
180 void
181 noit_check_log_status(noit_check_t *check) {
182   handle_extra_feeds(check, _noit_check_log_status);
183   if(!(check->flags & (NP_TRANSIENT | NP_SUPPRESS_STATUS))) {
184     SETUP_LOG(status, return);
185     _noit_check_log_status(status_log, check);
186   }
187 }
188 static int
189 _noit_check_log_metric(noit_log_stream_t ls, noit_check_t *check,
190                        const char *uuid_str,
191                        struct timeval *whence, metric_t *m) {
192   char our_uuid_str[256*3+37];
193   int srv = 0;
194   if(!noit_apply_filterset(check->filterset, check, m)) return 0;
195   if(!ls->enabled) return 0;
196
197   if(!uuid_str) {
198     MAKE_CHECK_UUID_STR(our_uuid_str, sizeof(our_uuid_str), metrics_log, check);
199     uuid_str = our_uuid_str;
200   }
201
202   if(!m->metric_value.s) { /* they are all null */
203     srv = noit_log(ls, whence, __FILE__, __LINE__,
204                    "M\t%lu.%03lu\t%s\t%s\t%c\t[[null]]\n",
205                    SECPART(whence), MSECPART(whence), uuid_str,
206                    m->metric_name, m->metric_type);
207   }
208   else {
209     switch(m->metric_type) {
210       case METRIC_INT32:
211         srv = noit_log(ls, whence, __FILE__, __LINE__,
212                        "M\t%lu.%03lu\t%s\t%s\t%c\t%d\n",
213                        SECPART(whence), MSECPART(whence), uuid_str,
214                        m->metric_name, m->metric_type, *(m->metric_value.i));
215         break;
216       case METRIC_UINT32:
217         srv = noit_log(ls, whence, __FILE__, __LINE__,
218                        "M\t%lu.%03lu\t%s\t%s\t%c\t%u\n",
219                        SECPART(whence), MSECPART(whence), uuid_str,
220                        m->metric_name, m->metric_type, *(m->metric_value.I));
221         break;
222       case METRIC_INT64:
223         srv = noit_log(ls, whence, __FILE__, __LINE__,
224                        "M\t%lu.%03lu\t%s\t%s\t%c\t%lld\n",
225                        SECPART(whence), MSECPART(whence), uuid_str,
226                        m->metric_name, m->metric_type,
227                        (long long int)*(m->metric_value.l));
228         break;
229       case METRIC_UINT64:
230         srv = noit_log(ls, whence, __FILE__, __LINE__,
231                        "M\t%lu.%03lu\t%s\t%s\t%c\t%llu\n",
232                        SECPART(whence), MSECPART(whence), uuid_str,
233                        m->metric_name, m->metric_type,
234                        (long long unsigned int)*(m->metric_value.L));
235         break;
236       case METRIC_DOUBLE:
237         srv = noit_log(ls, whence, __FILE__, __LINE__,
238                        "M\t%lu.%03lu\t%s\t%s\t%c\t%.12e\n",
239                        SECPART(whence), MSECPART(whence), uuid_str,
240                        m->metric_name, m->metric_type, *(m->metric_value.n));
241         break;
242       case METRIC_STRING:
243         srv = noit_log(ls, whence, __FILE__, __LINE__,
244                        "M\t%lu.%03lu\t%s\t%s\t%c\t%s\n",
245                        SECPART(whence), MSECPART(whence), uuid_str,
246                        m->metric_name, m->metric_type, m->metric_value.s);
247         break;
248       default:
249         noitL(noit_error, "Unknown metric type '%c' 0x%x\n",
250               m->metric_type, m->metric_type);
251     }
252   }
253   return srv;
254 }
255 static int
256 _noit_check_log_metrics(noit_log_stream_t ls, noit_check_t *check) {
257   int rv = 0;
258   int srv;
259   char uuid_str[256*3+37];
260   noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
261   const char *key;
262   int klen;
263   stats_t *c;
264   void *vm;
265   SETUP_LOG(metrics, );
266   MAKE_CHECK_UUID_STR(uuid_str, sizeof(uuid_str), metrics_log, check);
267
268   c = &check->stats.current;
269   while(noit_hash_next(&c->metrics, &iter, &key, &klen, &vm)) {
270     /* If we apply the filter set and it returns false, we don't log */
271     metric_t *m = (metric_t *)vm;
272     srv = _noit_check_log_metric(ls, check, uuid_str, &c->whence, m);
273     if(srv) rv = srv;
274   }
275   return rv;
276 }
277 void
278 noit_check_log_metrics(noit_check_t *check) {
279   handle_extra_feeds(check, _noit_check_log_metrics);
280   if(!(check->flags & (NP_TRANSIENT | NP_SUPPRESS_METRICS))) {
281     SETUP_LOG(metrics, return);
282     _noit_check_log_metrics(metrics_log, check);
283   }
284 }
285
286
287 static int
288 _noit_check_log_bundle_metric(noit_log_stream_t ls, Metric *metric, metric_t *m) {
289   metric->metrictype = (int)m->metric_type;
290
291   metric->name = m->metric_name;
292   if(m->metric_value.vp != NULL) {
293     switch (m->metric_type) {
294       case METRIC_INT32:
295         metric->has_valuei32 = noit_true;
296         metric->valuei32 = *(m->metric_value.i); break;
297       case METRIC_UINT32:
298         metric->has_valueui32 = noit_true;
299         metric->valueui32 = *(m->metric_value.I); break;
300       case METRIC_INT64:
301         metric->has_valuei64 = noit_true;
302         metric->valuei64 = *(m->metric_value.l); break;
303       case METRIC_UINT64:
304         metric->has_valueui64 = noit_true;
305         metric->valueui64 = *(m->metric_value.L); break;
306       case METRIC_DOUBLE:
307         metric->has_valuedbl = noit_true;
308         metric->valuedbl = *(m->metric_value.n); break;
309       case METRIC_STRING:
310         metric->valuestr = m->metric_value.s; break;
311       default:
312         return -1;
313     }
314   }
315   return 0;
316 }
317
318 static int
319 noit_check_log_bundle_serialize(noit_log_stream_t ls, noit_check_t *check) {
320   int rv = 0;
321   char uuid_str[256*3+37];
322   noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
323   noit_hash_iter iter2 = NOIT_HASH_ITER_ZERO;
324   const char *key;
325   int klen, i=0, size, j;
326   unsigned int out_size;
327   stats_t *c;
328   void *vm;
329   char *buf, *out_buf;
330   noit_compression_type_t comp;
331   Bundle bundle = BUNDLE__INIT;
332   SETUP_LOG(bundle, );
333   MAKE_CHECK_UUID_STR(uuid_str, sizeof(uuid_str), bundle_log, check);
334   noit_boolean use_compression = noit_true;
335   const char *v_comp;
336   v_comp = noit_log_stream_get_property(ls, "compression");
337   if(v_comp && !strcmp(v_comp, "off")) use_compression = noit_false;
338
339   // Get a bundle
340   c = &check->stats.current;
341
342   // Set attributes
343   bundle.status = malloc(sizeof(Status));
344   status__init(bundle.status);
345   bundle.status->available = c->available;
346   bundle.status->state = c->state;
347   bundle.status->duration = c->duration;
348   bundle.status->status = c->status;
349   bundle.has_period = noit_true;
350   bundle.period = check->period;
351   bundle.has_timeout = noit_true;
352   bundle.timeout = check->timeout;
353
354
355   // Just count
356   while(noit_hash_next(&c->metrics, &iter, &key, &klen, &vm)) {
357     bundle.n_metrics++;
358   }
359
360   if(bundle.n_metrics > 0) {
361     bundle.metrics = malloc(bundle.n_metrics * sizeof(Metric*));
362
363     // Now convert
364     while(noit_hash_next(&c->metrics, &iter2, &key, &klen, &vm)) {
365       /* If we apply the filter set and it returns false, we don't log */
366       metric_t *m = (metric_t *)vm;
367       if(!noit_apply_filterset(check->filterset, check, m)) continue;
368       bundle.metrics[i] = malloc(sizeof(Metric));
369       metric__init(bundle.metrics[i]);
370       _noit_check_log_bundle_metric(ls, bundle.metrics[i], m);
371       if(NOIT_CHECK_METRIC_ENABLED()) {
372         char buff[256];
373         noit_stats_snprint_metric(buff, sizeof(buff), m);
374         NOIT_CHECK_METRIC(uuid_str, check->module, check->name, check->target,
375                           m->metric_name, m->metric_type, buff);
376       }
377       i++;
378     }
379     bundle.n_metrics = i;
380   }
381
382   size = bundle__get_packed_size(&bundle);
383   buf = malloc(size);
384   bundle__pack(&bundle, (uint8_t*)buf);
385
386   // Compress + B64
387   comp = use_compression ? NOIT_COMPRESS_ZLIB : NOIT_COMPRESS_NONE;
388   noit_check_log_bundle_compress_b64(comp, buf, size, &out_buf, &out_size);
389   rv = noit_log(ls, &(c->whence), __FILE__, __LINE__,
390                 "B%c\t%lu.%03lu\t%s\t%s\t%s\t%s\t%d\t%.*s\n",
391                 use_compression ? '1' : '2',
392                 SECPART(&(c->whence)), MSECPART(&(c->whence)),
393                 uuid_str, check->target, check->module, check->name, size,
394                 (unsigned int)out_size, out_buf);
395
396   free(buf);
397   free(out_buf);
398   // Free all the resources
399   for (j=0; j<i; j++) {
400     free(bundle.metrics[j]);
401   }
402   free(bundle.metrics);
403   free(bundle.status);
404   return rv;
405 }
406
407 void
408 noit_check_log_bundle(noit_check_t *check) {
409   handle_extra_feeds(check, noit_check_log_bundle_serialize);
410   if(!(check->flags & (NP_TRANSIENT | NP_SUPPRESS_STATUS | NP_SUPPRESS_METRICS))) {
411     SETUP_LOG(bundle, return);
412     noit_check_log_bundle_serialize(bundle_log, check);
413   }
414 }
415
416 void
417 noit_check_log_metric(noit_check_t *check, struct timeval *whence,
418                       metric_t *m) {
419   char uuid_str[256*3+37];
420   MAKE_CHECK_UUID_STR(uuid_str, sizeof(uuid_str), metrics_log, check);
421
422   /* handle feeds -- hust like handle_extra_feeds, but this
423    * is with different arguments.
424    */
425   if(check->feeds) {
426     noit_skiplist_node *curr, *next;
427     curr = next = noit_skiplist_getlist(check->feeds);
428     while(curr) {
429       const char *feed_name = (char *)curr->data;
430       noit_log_stream_t ls = noit_log_stream_find(feed_name);
431       noit_skiplist_next(check->feeds, &next);
432       if(!ls || _noit_check_log_metric(ls, check, uuid_str, whence, m))
433         noit_check_transient_remove_feed(check, feed_name);
434       curr = next;
435     }
436   }
437   if(!(check->flags & NP_TRANSIENT)) {
438     SETUP_LOG(metrics, return);
439     _noit_check_log_metric(metrics_log, check, uuid_str, whence, m);
440     if(NOIT_CHECK_METRIC_ENABLED()) {
441       char buff[256];
442       noit_stats_snprint_metric(buff, sizeof(buff), m);
443       NOIT_CHECK_METRIC(uuid_str, check->module, check->name, check->target,
444                         m->metric_name, m->metric_type, buff);
445     }
446   }
447 }
448
449 int
450 noit_stats_snprint_metric(char *b, int l, metric_t *m) {
451   int rv, nl;
452   nl = snprintf(b, l, "%s[%c] = ", m->metric_name, m->metric_type);
453   if(nl >= l || nl <= 0) return nl;
454   rv = noit_stats_snprint_metric_value(b+nl, l-nl, m);
455   if(rv == -1)
456     rv = snprintf(b+nl, l-nl, "[[unknown type]]");
457   return rv + nl;
458 }
459
Note: See TracBrowser for help on using the browser.