root/src/modules/selfcheck.c

Revision 95623e8a5216c115a97b91e085c15cd6bbf3f8c9, 6.9 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 4 years ago)

closes #243

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2009, 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 <stdio.h>
36 #include <unistd.h>
37 #include <errno.h>
38 #include <assert.h>
39 #include <math.h>
40
41 #include "noit_module.h"
42 #include "noit_check.h"
43 #include "noit_check_tools.h"
44 #include "utils/noit_log.h"
45 #include "utils/noit_hash.h"
46
47 typedef struct {
48   noit_module_t *self;
49   noit_check_t *check;
50   noit_hash_table attrs;
51   size_t logsize;
52   int timed_out;
53 } selfcheck_info_t;
54
55 static noit_log_stream_t nlerr = NULL;
56 static noit_log_stream_t nldeb = NULL;
57
58 static void selfcheck_cleanup(noit_module_t *self, noit_check_t *check) {
59   selfcheck_info_t *ci = check->closure;
60   if(ci) {
61     noit_check_release_attrs(&ci->attrs);
62     memset(ci, 0, sizeof(*ci));
63   }
64 }
65 static void jobq_thread_helper(eventer_jobq_t *jobq, void *closure) {
66   int s32;
67   char buffer[128];
68   stats_t *current = (stats_t *)closure;
69   s32 = jobq->concurrency;
70   if(s32 == 0) return; /* omit if no concurrency */
71   snprintf(buffer, sizeof(buffer), "%s_threads", jobq->queue_name);
72   noit_stats_set_metric(current, buffer, METRIC_INT32, &s32);
73 }
74 static void selfcheck_log_results(noit_module_t *self, noit_check_t *check) {
75   char buff[128];
76   u_int64_t u64;
77   int64_t s64;
78   int32_t s32;
79   stats_t current;
80   struct timeval duration, epoch, diff;
81   selfcheck_info_t *ci = check->closure;
82
83   noit_check_stats_clear(&current);
84
85   gettimeofday(&current.whence, NULL);
86   sub_timeval(current.whence, check->last_fire_time, &duration);
87   current.duration = duration.tv_sec * 1000 + duration.tv_usec / 1000;
88   current.available = NP_UNAVAILABLE;
89   current.state = NP_BAD;
90   if(ci->timed_out) current.status = "timeout";
91   else {
92     current.available = NP_AVAILABLE;
93     current.state = NP_GOOD;
94     current.status = "ok";
95   }
96   /* Set all the metrics here */
97   s64 = (int64_t)ci->logsize;
98   noit_stats_set_metric(&current, "feed_bytes", METRIC_INT64, &s64);
99   s32 = noit_poller_check_count();
100   noit_stats_set_metric(&current, "check_cnt", METRIC_INT32, &s32);
101   s32 = noit_poller_transient_check_count();
102   noit_stats_set_metric(&current, "transient_cnt", METRIC_INT32, &s32);
103   if(eventer_get_epoch(&epoch)) s64 = 0;
104   else {
105     sub_timeval(current.whence, epoch, &diff);
106     s64 = diff.tv_sec;
107   }
108   noit_stats_set_metric(&current, "uptime", METRIC_INT64, &s64);
109   eventer_jobq_process_each(jobq_thread_helper, &current);
110   noit_build_version(buff, sizeof(buff));
111   noit_stats_set_metric(&current, "version", METRIC_STRING, buff);
112   u64 = noit_check_completion_count();
113   noit_stats_set_metric(&current, "checks_run", METRIC_UINT64, &u64);
114
115   noit_check_set_stats(self, check, &current);
116 }
117
118 #define FETCH_CONFIG_OR(key, str) do { \
119   if(!noit_hash_retr_str(check->config, #key, strlen(#key), &key)) \
120     key = str; \
121 } while(0)
122
123 static int selfcheck_log_size(eventer_t e, int mask, void *closure,
124                               struct timeval *now) {
125   selfcheck_info_t *ci = closure;
126   noit_check_t *check = ci->check;
127   const char *feedname;
128   char feedname_buff[128];
129   noit_log_stream_t feed;
130
131   if(mask & (EVENTER_READ | EVENTER_WRITE)) {
132     /* this case is impossible from the eventer.  It is called as
133      * such on the synchronous completion of the event.
134      */
135     selfcheck_log_results(ci->self, ci->check);
136     selfcheck_cleanup(ci->self, ci->check);
137     check->flags &= ~NP_RUNNING;
138     return 0;
139   }
140   switch(mask) {
141     case EVENTER_ASYNCH_WORK:
142       /* Check the length of the log */
143       FETCH_CONFIG_OR(feedname, "feed");
144       noit_check_interpolate(feedname_buff, sizeof(feedname_buff), feedname,
145                              &ci->attrs, check->config);
146       feed = noit_log_stream_find(feedname_buff);
147       if(!feed) ci->logsize = -1;
148       else ci->logsize = noit_log_stream_size(feed);
149       ci->timed_out = 0;
150       return 0;
151       break;
152     case EVENTER_ASYNCH_CLEANUP:
153       /* This sets us up for a completion call. */
154       e->mask = EVENTER_READ | EVENTER_WRITE;
155       break;
156     default:
157       abort();
158   }
159   return 0;
160 }
161
162 static int selfcheck_initiate(noit_module_t *self, noit_check_t *check) {
163   selfcheck_info_t *ci = check->closure;
164   struct timeval __now;
165
166   /* We cannot be running */
167   assert(!(check->flags & NP_RUNNING));
168   check->flags |= NP_RUNNING;
169
170   ci->self = self;
171   ci->check = check;
172
173   ci->timed_out = 1;
174   noit_check_make_attrs(check, &ci->attrs);
175   gettimeofday(&__now, NULL);
176   memcpy(&check->last_fire_time, &__now, sizeof(__now));
177
178   /* Register a handler for the worker */
179   noit_check_run_full_asynch(check, selfcheck_log_size);
180   return 0;
181 }
182
183 static int selfcheck_initiate_check(noit_module_t *self, noit_check_t *check,
184                                    int once, noit_check_t *parent) {
185   if(!check->closure) check->closure = calloc(1, sizeof(selfcheck_info_t));
186   INITIATE_CHECK(selfcheck_initiate, self, check);
187   return 0;
188 }
189
190 static int selfcheck_onload(noit_image_t *self) {
191   nlerr = noit_log_stream_find("error/selfcheck");
192   nldeb = noit_log_stream_find("debug/selfcheck");
193   if(!nlerr) nlerr = noit_stderr;
194   if(!nldeb) nldeb = noit_debug;
195
196   eventer_name_callback("selfcheck/selfcheck_log_size", selfcheck_log_size);
197   return 0;
198 }
199
200 #include "selfcheck.xmlh"
201 noit_module_t selfcheck = {
202   {
203     NOIT_MODULE_MAGIC,
204     NOIT_MODULE_ABI_VERSION,
205     "selfcheck",
206     "noitd self-checker",
207     selfcheck_xml_description,
208     selfcheck_onload
209   },
210   NULL,
211   NULL,
212   selfcheck_initiate_check,
213   selfcheck_cleanup
214 };
215
Note: See TracBrowser for help on using the browser.