root/src/modules/selfcheck.c

Revision 1d796a9e4aa04f687faf086c5a1fe1155a9f19d8, 9.0 kB (checked in by Phil Maddox <philip.maddox@circonus.com>, 2 months ago)

Move Check Hash Inits To noit_check_make_attrs()

Rather than initializing a hash table for attrs, then passing it to
noit_check_make_attrs, just init inside noit_check_make_attrs itself.

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2009, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  * Copyright (c) 2015, Circonus, Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  *       copyright notice, this list of conditions and the following
14  *       disclaimer in the documentation and/or other materials provided
15  *       with the distribution.
16  *     * Neither the name OmniTI Computer Consulting, Inc. nor the names
17  *       of its contributors may be used to endorse or promote products
18  *       derived from this software without specific prior written
19  *       permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <mtev_defines.h>
35
36 #include <stdio.h>
37 #include <unistd.h>
38 #include <errno.h>
39 #include <math.h>
40
41 #include <mtev_hash.h>
42
43 #include "noit_mtev_bridge.h"
44 #include "noit_module.h"
45 #include "noit_jlog_listener.h"
46 #include "noit_check.h"
47 #include "noit_check_tools.h"
48 #include "noit_version.h"
49 #include <sys/utsname.h>
50
51 typedef struct {
52   noit_module_t *self;
53   noit_check_t *check;
54   mtev_hash_table attrs;
55   size_t logsize;
56   int timed_out;
57 } selfcheck_info_t;
58
59 struct threadq_crutch {
60   noit_check_t *check;
61 };
62
63 static mtev_log_stream_t nlerr = NULL;
64 static mtev_log_stream_t nldeb = NULL;
65
66 /*Function to return operating system information*/
67 static int selfcheck_os_version(char *buff, int len) {
68   struct utsname unameData;
69  
70   /*If error returned, print that operating system information is not available.*/
71   if (uname(&unameData)<0)
72   {
73     return snprintf(buff, len, "%s", "N/A");
74    
75   }
76  
77   /*Else, print operating system information.*/
78   else
79   {
80     return snprintf(buff, len, "%s %s %s", unameData.sysname,unameData.release,unameData.version);
81   }
82 }
83 static void selfcheck_cleanup(noit_module_t *self, noit_check_t *check) {
84   selfcheck_info_t *ci = check->closure;
85   if(ci) {
86     noit_check_release_attrs(&ci->attrs);
87     memset(ci, 0, sizeof(*ci));
88   }
89 }
90 static void jobq_thread_helper(eventer_jobq_t *jobq, void *closure) {
91   int s32;
92   char buffer[128];
93   struct threadq_crutch *crutch = (struct threadq_crutch *)closure;
94   s32 = jobq->concurrency;
95   if(s32 == 0) return; /* omit if no concurrency */
96   snprintf(buffer, sizeof(buffer), "%s_threads", jobq->queue_name);
97   noit_stats_set_metric(crutch->check, buffer, METRIC_INT32, &s32);
98 }
99 static int selfcheck_feed_details(jlog_feed_stats_t *s, void *closure) {
100   char buff[256];
101   uint64_t ms;
102   struct timeval now, diff;
103   struct threadq_crutch *crutch = (struct threadq_crutch *)closure;
104   gettimeofday(&now, NULL);
105
106   if(s->last_connection.tv_sec > 0) {
107     sub_timeval(now, s->last_connection, &diff);
108     ms = diff.tv_sec * 1000 + diff.tv_usec / 1000;
109     snprintf(buff, sizeof(buff), "feed`%s`last_connection_ms", s->feed_name);
110     noit_stats_set_metric(crutch->check, buff, METRIC_UINT64, &ms);
111   }
112
113   if(s->last_checkpoint.tv_sec > 0) {
114     sub_timeval(now, s->last_checkpoint, &diff);
115     ms = diff.tv_sec * 1000 + diff.tv_usec / 1000;
116     snprintf(buff, sizeof(buff), "feed`%s`last_checkpoint_ms", s->feed_name);
117     noit_stats_set_metric(crutch->check, buff, METRIC_UINT64, &ms);
118   }
119   return 1;
120 }
121 static void selfcheck_log_results(noit_module_t *self, noit_check_t *check) {
122   char buff[128];
123   u_int64_t u64;
124   int64_t s64;
125   int32_t s32;
126   struct threadq_crutch crutch;
127   struct timeval now, duration, epoch, diff;
128   selfcheck_info_t *ci = check->closure;
129
130   crutch.check = check;
131
132   gettimeofday(&now, NULL);
133   sub_timeval(now, check->last_fire_time, &duration);
134   noit_stats_set_whence(check, &now);
135   noit_stats_set_duration(check, duration.tv_sec * 1000 + duration.tv_usec / 1000);
136   noit_stats_set_available(check, NP_UNAVAILABLE);
137   noit_stats_set_state(check, NP_BAD);
138   if(ci->timed_out) noit_stats_set_status(check, "timeout");
139   else {
140     noit_stats_set_available(check, NP_AVAILABLE);
141     noit_stats_set_state(check, NP_GOOD);
142     noit_stats_set_status(check, "ok");
143   }
144   /* Set all the metrics here */
145   s64 = (int64_t)ci->logsize;
146   noit_stats_set_metric(check, "feed_bytes", METRIC_INT64, &s64);
147   s32 = noit_poller_check_count();
148   noit_stats_set_metric(check, "check_cnt", METRIC_INT32, &s32);
149   s32 = noit_poller_transient_check_count();
150   noit_stats_set_metric(check, "transient_cnt", METRIC_INT32, &s32);
151   if(eventer_get_epoch(&epoch)) s64 = 0;
152   else {
153     sub_timeval(now, epoch, &diff);
154     s64 = diff.tv_sec;
155   }
156   noit_stats_set_metric(check, "uptime", METRIC_INT64, &s64);
157   eventer_jobq_process_each(jobq_thread_helper, &crutch);
158   noit_build_version(buff, sizeof(buff));
159   noit_stats_set_metric(check, "version", METRIC_STRING, buff);
160  
161   /*Clear buffer, store operating system in it*/
162   memset(buff,'\0',sizeof(buff));
163   selfcheck_os_version(buff, sizeof(buff));
164   noit_stats_set_metric(check, "OS version", METRIC_STRING, buff);
165  
166   u64 = noit_check_completion_count();
167   noit_stats_set_metric(check, "checks_run", METRIC_UINT64, &u64);
168   u64 = noit_check_metric_count();
169   noit_stats_set_metric(check, "metrics_collected", METRIC_UINT64, &u64);
170   /* feed pull info */
171   noit_jlog_foreach_feed_stats(selfcheck_feed_details, &crutch);
172
173   noit_check_set_stats(check);
174 }
175
176 #define FETCH_CONFIG_OR(key, str) do { \
177   if(!mtev_hash_retr_str(check->config, #key, strlen(#key), &key)) \
178     key = str; \
179 } while(0)
180
181 static int selfcheck_log_size(eventer_t e, int mask, void *closure,
182                               struct timeval *now) {
183   selfcheck_info_t *ci = closure;
184   noit_check_t *check = ci->check;
185   const char *feedname;
186   char feedname_buff[128];
187   mtev_log_stream_t feed;
188
189   if(mask & (EVENTER_READ | EVENTER_WRITE)) {
190     /* this case is impossible from the eventer.  It is called as
191      * such on the synchronous completion of the event.
192      */
193     selfcheck_log_results(ci->self, ci->check);
194     selfcheck_cleanup(ci->self, ci->check);
195     check->flags &= ~NP_RUNNING;
196     return 0;
197   }
198   switch(mask) {
199     case EVENTER_ASYNCH_WORK:
200       /* Check the length of the log */
201       FETCH_CONFIG_OR(feedname, "feed");
202       noit_check_interpolate(feedname_buff, sizeof(feedname_buff), feedname,
203                              &ci->attrs, check->config);
204       feed = mtev_log_stream_find(feedname_buff);
205       if(!feed) ci->logsize = -1;
206       else ci->logsize = mtev_log_stream_size(feed);
207       ci->timed_out = 0;
208       return 0;
209       break;
210     case EVENTER_ASYNCH_CLEANUP:
211       /* This sets us up for a completion call. */
212       e->mask = EVENTER_READ | EVENTER_WRITE;
213       break;
214     default:
215       mtevFatal(mtev_error, "Unknown mask: 0x%04x\n", mask);
216   }
217   return 0;
218 }
219
220 static int selfcheck_initiate(noit_module_t *self, noit_check_t *check,
221                               noit_check_t *cause) {
222   selfcheck_info_t *ci = check->closure;
223   struct timeval __now;
224
225   /* We cannot be running */
226   BAIL_ON_RUNNING_CHECK(check);
227   check->flags |= NP_RUNNING;
228
229   ci->self = self;
230   ci->check = check;
231
232   ci->timed_out = 1;
233   noit_check_make_attrs(check, &ci->attrs);
234   gettimeofday(&__now, NULL);
235   memcpy(&check->last_fire_time, &__now, sizeof(__now));
236
237   /* Register a handler for the worker */
238   noit_check_run_full_asynch(check, selfcheck_log_size);
239   return 0;
240 }
241
242 static int selfcheck_initiate_check(noit_module_t *self, noit_check_t *check,
243                                    int once, noit_check_t *cause) {
244   if(!check->closure) {
245     selfcheck_info_t *check_info = calloc(1, sizeof(selfcheck_info_t));
246     check->closure = (void*)check_info;
247   }
248   INITIATE_CHECK(selfcheck_initiate, self, check, cause);
249   return 0;
250 }
251
252 static int selfcheck_onload(mtev_image_t *self) {
253   nlerr = mtev_log_stream_find("error/selfcheck");
254   nldeb = mtev_log_stream_find("debug/selfcheck");
255   if(!nlerr) nlerr = noit_stderr;
256   if(!nldeb) nldeb = noit_debug;
257
258   eventer_name_callback("selfcheck/selfcheck_log_size", selfcheck_log_size);
259   return 0;
260 }
261
262
263 #include "selfcheck.xmlh"
264 noit_module_t selfcheck = {
265   {
266     .magic = NOIT_MODULE_MAGIC,
267     .version = NOIT_MODULE_ABI_VERSION,
268     .name = "selfcheck",
269     .description = "noitd self-checker",
270     .xml_description = selfcheck_xml_description,
271     .onload = selfcheck_onload
272   },
273   NULL,
274   NULL,
275   selfcheck_initiate_check,
276   selfcheck_cleanup
277 };
278
Note: See TracBrowser for help on using the browser.