root/src/noit_check_log.c

Revision 870413eae711c48e44ae4e05a6183c3df3a63158, 11.0 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 3 years ago)

implementation of separating status and metrics logging, refs #356

  • 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  * CHECK:
48  *  'C' TIMESTAMP UUID TARGET MODULE NAME
49  *
50  * STATUS:
51  *  'S' TIMESTAMP UUID STATE AVAILABILITY DURATION STATUS_MESSAGE
52  *
53  * METRICS:
54  *  'M' TIMESTAMP UUID NAME TYPE VALUE
55  */
56
57 static noit_log_stream_t check_log = NULL;
58 static noit_log_stream_t status_log = NULL;
59 static noit_log_stream_t metrics_log = NULL;
60 #define SECPART(a) ((unsigned long)(a)->tv_sec)
61 #define MSECPART(a) ((unsigned long)((a)->tv_usec / 1000))
62 #define MAKE_CHECK_UUID_STR(uuid_str, len, ls, check) do { \
63   noit_boolean extended_id = noit_false; \
64   const char *v; \
65   v = noit_log_stream_get_property(ls, "extended_id"); \
66   if(v && !strcmp(v, "on")) extended_id = noit_true; \
67   uuid_str[0] = '\0'; \
68   if(extended_id) { \
69     strlcat(uuid_str, check->target, len-37); \
70     strlcat(uuid_str, "`", len-37); \
71     strlcat(uuid_str, check->module, len-37); \
72     strlcat(uuid_str, "`", len-37); \
73     strlcat(uuid_str, check->name, len-37); \
74     strlcat(uuid_str, "`", len-37); \
75   } \
76   uuid_unparse_lower(check->checkid, uuid_str + strlen(uuid_str)); \
77 } while(0)
78
79 static void
80 handle_extra_feeds(noit_check_t *check,
81                    int (*log_f)(noit_log_stream_t ls, noit_check_t *check)) {
82   noit_log_stream_t ls;
83   noit_skiplist_node *curr, *next;
84   const char *feed_name;
85
86   if(!check->feeds) return;
87   curr = next = noit_skiplist_getlist(check->feeds);
88   while(curr) {
89     /* We advance next here (before we try to use curr).
90      * We may need to remove the node we're looking at and that would
91      * disturb the iterator, so advance in advance. */
92     noit_skiplist_next(check->feeds, &next);
93     feed_name = (char *)curr->data;
94     ls = noit_log_stream_find(feed_name);
95     if(!ls || log_f(ls, check)) {
96       noit_check_transient_remove_feed(check, feed_name);
97       /* noit_skiplisti_remove(check->feeds, curr, free); */
98     }
99     curr = next;
100   }
101   /* We're done... we may have destroyed the last feed.
102    * that combined with transience means we should kill the check */
103   /* noit_check_transient_remove_feed(check, NULL); */
104 }
105
106 static int
107 _noit_check_log_check(noit_log_stream_t ls,
108                       noit_check_t *check) {
109   struct timeval __now;
110   char uuid_str[256*3+37];
111   SETUP_LOG(check, );
112   MAKE_CHECK_UUID_STR(uuid_str, sizeof(uuid_str), check_log, check);
113
114   gettimeofday(&__now, NULL);
115   return noit_log(ls, &__now, __FILE__, __LINE__,
116                   "C\t%lu.%03lu\t%s\t%s\t%s\t%s\n",
117                   SECPART(&__now), MSECPART(&__now),
118                   uuid_str, check->target, check->module, check->name);
119 }
120
121 void
122 noit_check_log_check(noit_check_t *check) {
123   if(!(check->flags & NP_TRANSIENT)) {
124     handle_extra_feeds(check, _noit_check_log_check);
125     SETUP_LOG(check, return);
126     _noit_check_log_check(check_log, check);
127   }
128 }
129
130 static int
131 _noit_check_log_status(noit_log_stream_t ls,
132                        noit_check_t *check) {
133   stats_t *c;
134   char uuid_str[256*3+37];
135   SETUP_LOG(status, );
136   MAKE_CHECK_UUID_STR(uuid_str, sizeof(uuid_str), status_log, check);
137
138   c = &check->stats.current;
139   return noit_log(ls, &c->whence, __FILE__, __LINE__,
140                   "S\t%lu.%03lu\t%s\t%c\t%c\t%d\t%s\n",
141                   SECPART(&c->whence), MSECPART(&c->whence), uuid_str,
142                   (char)c->state, (char)c->available, c->duration, c->status);
143 }
144 void
145 noit_check_log_status(noit_check_t *check) {
146   handle_extra_feeds(check, _noit_check_log_status);
147   if(!(check->flags & (NP_TRANSIENT | NP_SUPPRESS_STATUS))) {
148     SETUP_LOG(status, return);
149     _noit_check_log_status(status_log, check);
150   }
151 }
152 static int
153 _noit_check_log_metric(noit_log_stream_t ls, noit_check_t *check,
154                        const char *uuid_str,
155                        struct timeval *whence, metric_t *m) {
156   char our_uuid_str[256*3+37];
157   int srv = 0;
158   if(!noit_apply_filterset(check->filterset, check, m)) return 0;
159   if(!ls->enabled) return 0;
160
161   if(!uuid_str) {
162     MAKE_CHECK_UUID_STR(our_uuid_str, sizeof(our_uuid_str), metrics_log, check);
163     uuid_str = our_uuid_str;
164   }
165
166   if(!m->metric_value.s) { /* they are all null */
167     srv = noit_log(ls, whence, __FILE__, __LINE__,
168                    "M\t%lu.%03lu\t%s\t%s\t%c\t[[null]]\n",
169                    SECPART(whence), MSECPART(whence), uuid_str,
170                    m->metric_name, m->metric_type);
171   }
172   else {
173     switch(m->metric_type) {
174       case METRIC_INT32:
175         srv = noit_log(ls, whence, __FILE__, __LINE__,
176                        "M\t%lu.%03lu\t%s\t%s\t%c\t%d\n",
177                        SECPART(whence), MSECPART(whence), uuid_str,
178                        m->metric_name, m->metric_type, *(m->metric_value.i));
179         break;
180       case METRIC_UINT32:
181         srv = noit_log(ls, whence, __FILE__, __LINE__,
182                        "M\t%lu.%03lu\t%s\t%s\t%c\t%u\n",
183                        SECPART(whence), MSECPART(whence), uuid_str,
184                        m->metric_name, m->metric_type, *(m->metric_value.I));
185         break;
186       case METRIC_INT64:
187         srv = noit_log(ls, whence, __FILE__, __LINE__,
188                        "M\t%lu.%03lu\t%s\t%s\t%c\t%lld\n",
189                        SECPART(whence), MSECPART(whence), uuid_str,
190                        m->metric_name, m->metric_type,
191                        (long long int)*(m->metric_value.l));
192         break;
193       case METRIC_UINT64:
194         srv = noit_log(ls, whence, __FILE__, __LINE__,
195                        "M\t%lu.%03lu\t%s\t%s\t%c\t%llu\n",
196                        SECPART(whence), MSECPART(whence), uuid_str,
197                        m->metric_name, m->metric_type,
198                        (long long unsigned int)*(m->metric_value.L));
199         break;
200       case METRIC_DOUBLE:
201         srv = noit_log(ls, whence, __FILE__, __LINE__,
202                        "M\t%lu.%03lu\t%s\t%s\t%c\t%.12e\n",
203                        SECPART(whence), MSECPART(whence), uuid_str,
204                        m->metric_name, m->metric_type, *(m->metric_value.n));
205         break;
206       case METRIC_STRING:
207         srv = noit_log(ls, whence, __FILE__, __LINE__,
208                        "M\t%lu.%03lu\t%s\t%s\t%c\t%s\n",
209                        SECPART(whence), MSECPART(whence), uuid_str,
210                        m->metric_name, m->metric_type, m->metric_value.s);
211         break;
212       default:
213         noitL(noit_error, "Unknown metric type '%c' 0x%x\n",
214               m->metric_type, m->metric_type);
215     }
216   }
217   return srv;
218 }
219 static int
220 _noit_check_log_metrics(noit_log_stream_t ls, noit_check_t *check) {
221   int rv = 0;
222   int srv;
223   char uuid_str[256*3+37];
224   noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
225   const char *key;
226   int klen;
227   stats_t *c;
228   void *vm;
229   SETUP_LOG(metrics, );
230   MAKE_CHECK_UUID_STR(uuid_str, sizeof(uuid_str), metrics_log, check);
231
232   c = &check->stats.current;
233   while(noit_hash_next(&c->metrics, &iter, &key, &klen, &vm)) {
234     /* If we apply the filter set and it returns false, we don't log */
235     metric_t *m = (metric_t *)vm;
236     srv = _noit_check_log_metric(ls, check, uuid_str, &c->whence, m);
237     if(srv) rv = srv;
238   }
239   return rv;
240 }
241 void
242 noit_check_log_metrics(noit_check_t *check) {
243   handle_extra_feeds(check, _noit_check_log_metrics);
244   if(!(check->flags & (NP_TRANSIENT | NP_SUPPRESS_METRICS))) {
245     SETUP_LOG(metrics, return);
246     _noit_check_log_metrics(metrics_log, check);
247   }
248 }
249
250 void
251 noit_check_log_metric(noit_check_t *check, struct timeval *whence,
252                       metric_t *m) {
253   char uuid_str[256*3+37];
254   MAKE_CHECK_UUID_STR(uuid_str, sizeof(uuid_str), metrics_log, check);
255
256   /* handle feeds -- hust like handle_extra_feeds, but this
257    * is with different arguments.
258    */
259   if(check->feeds) {
260     noit_skiplist_node *curr, *next;
261     curr = next = noit_skiplist_getlist(check->feeds);
262     while(curr) {
263       const char *feed_name = (char *)curr->data;
264       noit_log_stream_t ls = noit_log_stream_find(feed_name);
265       noit_skiplist_next(check->feeds, &next);
266       if(!ls || _noit_check_log_metric(ls, check, uuid_str, whence, m))
267         noit_check_transient_remove_feed(check, feed_name);
268       curr = next;
269     }
270   }
271   if(!(check->flags & NP_TRANSIENT)) {
272     SETUP_LOG(metrics, return);
273     _noit_check_log_metric(metrics_log, check, uuid_str, whence, m);
274   }
275 }
276
277 int
278 noit_stats_snprint_metric_value(char *b, int l, metric_t *m) {
279   int rv;
280   if(!m->metric_value.s) { /* they are all null */
281     rv = snprintf(b, l, "[[null]]");
282   }
283   else {
284     switch(m->metric_type) {
285       case METRIC_INT32:
286         rv = snprintf(b, l, "%d", *(m->metric_value.i)); break;
287       case METRIC_UINT32:
288         rv = snprintf(b, l, "%u", *(m->metric_value.I)); break;
289       case METRIC_INT64:
290         rv = snprintf(b, l, "%lld", (long long int)*(m->metric_value.l)); break;
291       case METRIC_UINT64:
292         rv = snprintf(b, l, "%llu",
293                       (long long unsigned int)*(m->metric_value.L)); break;
294       case METRIC_DOUBLE:
295         rv = snprintf(b, l, "%.12e", *(m->metric_value.n)); break;
296       case METRIC_STRING:
297         rv = snprintf(b, l, "%s", m->metric_value.s); break;
298       default:
299         return -1;
300     }
301   }
302   return rv;
303 }
304 int
305 noit_stats_snprint_metric(char *b, int l, metric_t *m) {
306   int rv, nl;
307   nl = snprintf(b, l, "%s[%c] = ", m->metric_name, m->metric_type);
308   if(nl >= l || nl <= 0) return nl;
309   rv = noit_stats_snprint_metric_value(b+nl, l-nl, m);
310   if(rv == -1)
311     rv = snprintf(b+nl, l-nl, "[[unknown type]]");
312   return rv + nl;
313 }
Note: See TracBrowser for help on using the browser.