root/src/noit_check_log_helpers.c

Revision 1af7f3ace60e510f2e2e9b6c1c4bc2d889c89f4f, 10.7 kB (checked in by Paul Querna <pquerna@apache.org>, 3 years ago)

Fix style of switch

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2011, 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 "noit_check.h"
35 #include "noit_check_log_helpers.h"
36 #include <stdio.h>
37 #include <zlib.h>
38 #include "utils/noit_b64.h"
39 #include "utils/noit_str.h"
40 #include "utils/noit_log.h"
41 #include "bundle.pb-c.h"
42
43 int
44 noit_check_log_bundle_compress_b64(noit_compression_type_t ctype,
45                                    const char *buf_in,
46                                    unsigned int len_in,
47                                    char ** buf_out,
48                                    unsigned int * len_out) {
49   uLong initial_dlen, dlen = 0;
50   char *compbuff = NULL, *b64buff;
51
52   // Compress saves 25% of space (ex 470 -> 330)
53   switch(ctype) {
54     case NOIT_COMPRESS_ZLIB:
55       /* Compress */
56       initial_dlen = dlen = compressBound((uLong)len_in);
57       compbuff = malloc(initial_dlen);
58       if(!compbuff) return -1;
59       if(Z_OK != compress2((Bytef *)compbuff, &dlen,
60                            (Bytef *)buf_in, len_in, 9)) {
61         noitL(noit_error, "Error compressing bundled metrics.\n");
62         free(compbuff);
63         return -1;
64       }
65       break;
66     case NOIT_COMPRESS_NONE:
67       // Or don't
68       dlen = (uLong)len_in;
69       compbuff = (char *)buf_in;
70       break;
71   }
72
73   /* Encode */
74   // Problems with the calculation?
75   initial_dlen = ((dlen + 2) / 3 * 4);
76   b64buff = malloc(initial_dlen);
77   if (!b64buff) {
78     if(ctype == NOIT_COMPRESS_ZLIB) free(compbuff);
79     return -1;
80   }
81   dlen = noit_b64_encode((unsigned char *)compbuff, dlen,
82                          (char *)b64buff, initial_dlen);
83   if(ctype == NOIT_COMPRESS_ZLIB) free(compbuff);
84   if(dlen == 0) {
85     noitL(noit_error, "Error base64'ing bundled metrics.\n");
86     free(b64buff);
87     return -1;
88   }
89   *buf_out = b64buff;
90   *len_out = (unsigned int)dlen;
91   return 0;
92 }
93
94 int
95 noit_check_log_bundle_decompress_b64(noit_compression_type_t ctype,
96                                      const char *buf_in,
97                                      unsigned int len_in,
98                                      char *buf_out,
99                                      unsigned int len_out) {
100   int rv;
101   uLong initial_dlen, dlen, rawlen;
102   char *compbuff, *rawbuff;
103
104   /* Decode */
105   initial_dlen = ((len_in / 4) * 3);
106   compbuff = malloc(initial_dlen);
107   if (!compbuff) return -1;
108   dlen = noit_b64_decode((char *)buf_in, len_in,
109                          (unsigned char *)compbuff, initial_dlen);
110   if(dlen == 0) {
111     noitL(noit_error, "Error base64'ing bundled metrics.\n");
112     free(compbuff);
113     return -1;
114   }
115
116   switch(ctype) {
117     case NOIT_COMPRESS_ZLIB:
118       /* Decompress */
119       rawlen = len_out;
120       if(Z_OK != (rv = uncompress((Bytef *)buf_out, &rawlen,
121                                   (Bytef *)compbuff, dlen)) ||
122          rawlen != len_out) {
123         noitL(noit_error, "Error decompressing bundle: %d (%u != %u).\n",
124               rv, (unsigned int)rawlen, (unsigned int)len_out);
125         free(compbuff);
126         return -1;
127       }
128       break;
129     case NOIT_COMPRESS_NONE:
130       // Or don't
131       rawlen = (uLong)dlen;
132       rawbuff = compbuff;
133       if(rawlen != len_out) {
134         if(compbuff) free(compbuff);
135         return -1;
136       }
137       memcpy(buf_out, rawbuff, rawlen);
138       break;
139   }
140
141   if(compbuff) free(compbuff);
142   return 0;
143 }
144
145 int
146 noit_stats_snprint_metric_value(char *b, int l, metric_t *m) {
147   int rv;
148   if(!m->metric_value.s) { /* they are all null */
149     rv = snprintf(b, l, "[[null]]");
150   }
151   else {
152     switch(m->metric_type) {
153       case METRIC_INT32:
154         rv = snprintf(b, l, "%d", *(m->metric_value.i)); break;
155       case METRIC_UINT32:
156         rv = snprintf(b, l, "%u", *(m->metric_value.I)); break;
157       case METRIC_INT64:
158         rv = snprintf(b, l, "%lld", (long long int)*(m->metric_value.l)); break;
159       case METRIC_UINT64:
160         rv = snprintf(b, l, "%llu",
161                       (long long unsigned int)*(m->metric_value.L)); break;
162       case METRIC_DOUBLE:
163         rv = snprintf(b, l, "%.12e", *(m->metric_value.n)); break;
164       case METRIC_STRING:
165         rv = snprintf(b, l, "%s", m->metric_value.s); break;
166       default:
167         return -1;
168     }
169   }
170   return rv;
171 }
172
173 int
174 noit_check_log_b_to_sm(const char *line, int len, char ***out) {
175   Bundle *bundle = NULL;
176   noit_compression_type_t ctype;
177   unsigned int ulen;
178   int i, size, cnt = 0, has_status = 0;
179   const char *cp1, *cp2, *rest, *error_str = NULL;
180   char *timestamp, *uuid_str, *target, *module, *name, *ulen_str;
181   unsigned char *raw_protobuf = NULL;
182
183   *out = NULL;
184   if(len < 3) return 0;
185   if(line[0] != 'B' || line[2] != '\t') return 0;
186   switch(line[1]) {
187     case '1': ctype = NOIT_COMPRESS_ZLIB; break;
188     case '2': ctype = NOIT_COMPRESS_NONE; break;
189     default: return 0;
190   }
191
192   /* All good, and we're off to the races */
193   line += 3; len -= 3;
194   cp1 = line;
195 #define SET_FIELD_FROM_BUNDLE(tgt) do { \
196   if(*cp1 == '\0') { error_str = "short line @ " #tgt; goto bad_line; } \
197   cp2 = strnstrn("\t", 1, cp1, len - (cp1 - line)); \
198   if(cp2 == NULL) { error_str = "no tab after " #tgt; goto bad_line; } \
199   tgt = (char *)alloca(cp2 - cp1 + 1); \
200   if(!tgt) { error_str = "alloca failed for " #tgt; goto bad_line; } \
201   memcpy(tgt, cp1, cp2 - cp1); \
202   tgt[cp2 - cp1] = '\0'; \
203   cp1 = cp2 + 1; \
204 } while(0)
205   SET_FIELD_FROM_BUNDLE(timestamp);
206   SET_FIELD_FROM_BUNDLE(uuid_str);
207   SET_FIELD_FROM_BUNDLE(target);
208   SET_FIELD_FROM_BUNDLE(module);
209   SET_FIELD_FROM_BUNDLE(name);
210   SET_FIELD_FROM_BUNDLE(ulen_str);
211   rest = cp1;
212
213   ulen = strtoul(ulen_str, NULL, 10);
214   raw_protobuf = malloc(ulen);
215   if(!raw_protobuf) {
216     noitL(noit_error, "bundle decode: memory exhausted\n");
217     goto bad_line;
218   }
219   if(noit_check_log_bundle_decompress_b64(ctype,
220                                           rest, len - (rest - line),
221                                           (char *)raw_protobuf,
222                                           ulen)) {
223     noitL(noit_error, "bundle decode: failed to decompress\n");
224     goto bad_line;
225   }
226   /* decode the protobuf */
227   bundle = bundle__unpack(&protobuf_c_system_allocator, ulen, raw_protobuf);
228   if(!bundle) {
229     noitL(noit_error, "bundle decode: protobuf invalid\n");
230     goto bad_line;
231   }
232   has_status = bundle->status ? 1 : 0;
233   cnt = bundle->n_metrics;
234   *out = calloc(sizeof(**out), cnt + has_status);
235   if(!*out) { error_str = "memory exhaustion"; goto bad_line; }
236   if(has_status) {
237     Status *status = bundle->status;
238     /* build out status line */
239     size = 2 /* S\t */ + strlen(timestamp) + 1 /* \t */ + strlen(uuid_str) +
240            5 /* \tG\tA\t */ + 11 /* max(strlen(duration)) */ +
241            1 /* \t */ +
242            (status->status ? strlen(status->status) : 8 /* [[null]] */) +
243            1 /* \0 */;
244     **out = malloc(size);
245     snprintf(**out, size, "S\t%s\t%s\t%c\t%c\t%d\t%s",
246              timestamp, uuid_str, status->state, status->available,
247              status->duration, status->status ? status->status : "[[null]]");
248   }
249   /* build our metric lines */
250   for(i=0; i<cnt; i++) {
251     Metric *metric = bundle->metrics[i];
252     metric_t m;
253     char scratch[64], *value_str;;
254     int value_size = 0;
255
256     m.metric_name = metric->name;
257     m.metric_type = metric->metrictype;
258     m.metric_value.vp = NULL;
259     scratch[0] = '\0';
260     value_str = scratch;
261     switch(m.metric_type) {
262       case METRIC_INT32:
263         m.metric_value.i = &metric->valuei32;
264         noit_stats_snprint_metric_value(scratch, 64, &m);
265         value_size = strlen(scratch);
266         break;
267       case METRIC_UINT32:
268         m.metric_value.I = &metric->valueui32;
269         noit_stats_snprint_metric_value(scratch, 64, &m);
270         value_size = strlen(scratch);
271         break;
272       case METRIC_INT64:
273         m.metric_value.l = &metric->valuei64;
274         noit_stats_snprint_metric_value(scratch, 64, &m);
275         value_size = strlen(scratch);
276         break;
277       case METRIC_UINT64:
278         m.metric_value.L = &metric->valueui64;
279         noit_stats_snprint_metric_value(scratch, 64, &m);
280         value_size = strlen(scratch);
281         break;
282       case METRIC_DOUBLE:
283         m.metric_value.n = &metric->valuedbl;
284         noit_stats_snprint_metric_value(scratch, 64, &m);
285         value_size = strlen(scratch);
286         break;
287       case METRIC_STRING:
288         m.metric_value.s = metric->valuestr ? metric->valuestr : "[[null]]";
289         value_str = metric->valuestr ? metric->valuestr : "[[null]]";
290         value_size = strlen(value_str);
291         break;
292       default:
293         break;
294     }
295     if(value_size == 0) continue; /* WTF, bad metric_type? */
296
297     size = 2 /* M\t */ + strlen(timestamp) + 1 /* \t */ +
298            strlen(uuid_str) + 1 /* \t */ + strlen(metric->name) +
299            3 /* \t<type>\t */ + value_size + 1 /* \0 */;
300     (*out)[i+has_status] = malloc(size);
301     snprintf((*out)[i+has_status], size, "M\t%s\t%s\t%s\t%c\t%s",
302              timestamp, uuid_str, metric->name, m.metric_type, value_str);
303   }
304   goto good_line;
305
306  bad_line:
307   if(*out) {
308     int i;
309     for(i=0; i<cnt + has_status; i++) if((*out)[i]) free((*out)[i]);
310     free(*out);
311     *out = NULL;
312   }
313   if(error_str) noitL(noit_error, "bundle: bad line due to %s\n", error_str);
314  good_line:
315   if(bundle) bundle__free_unpacked(bundle, &protobuf_c_system_allocator);
316   if(raw_protobuf) free(raw_protobuf);
317   return cnt + has_status;
318 }
Note: See TracBrowser for help on using the browser.