static void handle_extra_feeds(noit_check_t *check, int (*log_f)(noit_log_stream_t ls, noit_check_t *check)) { noit_log_stream_t ls; noit_skiplist_node *curr, *next; const char *feed_name; if(!check->feeds) return; curr = next = noit_skiplist_getlist(check->feeds); while(curr) { /* We advance next here (before we try to use curr). * We may need to remove the node we're looking at and that would * disturb the iterator, so advance in advance. */ noit_skiplist_next(check->feeds, &next); feed_name = (char *)curr->data; ls = noit_log_stream_find(feed_name); if(!ls || log_f(ls, check)) { noit_check_transient_remove_feed(check, feed_name); /* noit_skiplisti_remove(check->feeds, curr, free); */ } curr = next; } /* We're done... we may have destroyed the last feed. * that combined with transience means we should kill the check */ /* noit_check_transient_remove_feed(check, NULL); */ }
void noit_websocket_closure_free(void *jcl) { noit_websocket_closure_t *w = jcl; noit_check_transient_remove_feed(w->check, w->feed); free(w->feed); mtev_log_stream_close(w->log_stream); mtev_log_stream_free(w->log_stream); for (int i = 0; i < w->filter_count; i++) { free(w->filters[i]); } free(w->filters); free(w); }
static int noit_console_watch_check(noit_console_closure_t ncct, int argc, char **argv, noit_console_state_t *state, void *closure) { int i, cnt; int adding = (int)(vpsized_int)closure; int period = 0; char xpath[1024]; xmlXPathObjectPtr pobj = NULL; xmlXPathContextPtr xpath_ctxt = NULL; noit_conf_xml_xpath(NULL, &xpath_ctxt); if(argc < 1 || argc > 2) { nc_printf(ncct, "requires one or two arguments\n"); return -1; } /* An alternate period */ if(argc == 2) period = atoi(argv[1]); if(noit_console_mkcheck_xpath(xpath, sizeof(xpath), NULL, argc ? argv[0] : NULL)) { nc_printf(ncct, "ERROR: could not find check '%s'\n", argv[0]); return -1; } pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET || xmlXPathNodeSetIsEmpty(pobj->nodesetval)) { nc_printf(ncct, "no checks found\n"); goto out; } cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); for(i=0; i<cnt; i++) { uuid_t checkid; noit_check_t *check; xmlNodePtr node; char *uuid_conf; node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); uuid_conf = (char *)xmlGetProp(node, (xmlChar *)"uuid"); if(!uuid_conf || uuid_parse(uuid_conf, checkid)) { nc_printf(ncct, "%s has invalid or missing UUID!\n", (char *)xmlGetNodePath(node) + strlen("/noit")); continue; } if(period == 0) { check = noit_poller_lookup(checkid); if(!check) continue; if(adding) noit_check_transient_add_feed(check, ncct->feed_path); else noit_check_transient_remove_feed(check, ncct->feed_path); } else { if(adding) { check = noit_check_watch(checkid, period); /* This check must be watched from the console */ noit_check_transient_add_feed(check, ncct->feed_path); /* Note the check */ noit_check_log_check(check); /* kick it off, if it isn't running already */ if(!NOIT_CHECK_LIVE(check)) noit_check_activate(check); } else { check = noit_check_get_watch(checkid, period); if(check) noit_check_transient_remove_feed(check, ncct->feed_path); } } } out: if(pobj) xmlXPathFreeObject(pobj); return 0; }
int noit_livestream_handler(eventer_t e, int mask, void *closure, struct timeval *now) { eventer_t newe; pthread_t tid; int newmask = EVENTER_READ | EVENTER_EXCEPTION; acceptor_closure_t *ac = closure; noit_livestream_closure_t *jcl = ac->service_ctx; if(mask & EVENTER_EXCEPTION || (jcl && jcl->wants_shutdown)) { socket_error: /* Exceptions cause us to simply snip the connection */ eventer_remove_fd(e->fd); e->opset->close(e->fd, &newmask, e); if(jcl) noit_livestream_closure_free(jcl); if(ac) acceptor_closure_free(ac); return 0; } if(!ac->service_ctx || !jcl->feed) { int len; jcl = ac->service_ctx = noit_livestream_closure_alloc(); /* Setup logger to this channel */ if(!jcl->period) { u_int32_t nperiod; len = e->opset->read(e->fd, &nperiod, sizeof(nperiod), &mask, e); if(len == -1 && errno == EAGAIN) return mask | EVENTER_EXCEPTION; if(len != sizeof(nperiod)) goto socket_error; jcl->period = ntohl(nperiod); if(!jcl->period) { noitL(noit_error, "period of 0 specified in livestream. not allowed.\n"); goto socket_error; } } while(jcl->uuid_read < 36) { len = e->opset->read(e->fd, jcl->uuid_str + jcl->uuid_read, 36 - jcl->uuid_read, &mask, e); if(len == -1 && errno == EAGAIN) return mask | EVENTER_EXCEPTION; if(len == 0) goto socket_error; jcl->uuid_read += len; } jcl->uuid_str[36] = '\0'; if(uuid_parse(jcl->uuid_str, jcl->uuid)) { noitL(noit_error, "bad uuid received in livestream handler '%s'\n", jcl->uuid_str); goto socket_error; } jcl->feed = malloc(32); snprintf(jcl->feed, 32, "livestream/%d", noit_atomic_inc32(&ls_counter)); noit_log_stream_new(jcl->feed, "noit_livestream", jcl->feed, jcl, NULL); jcl->check = noit_check_watch(jcl->uuid, jcl->period); if(!jcl->check) { e->opset->close(e->fd, &newmask, e); return 0; } /* This check must be watched from the livestream */ noit_check_transient_add_feed(jcl->check, jcl->feed); /* Note the check */ noit_check_log_check(jcl->check); /* kick it off, if it isn't running already */ if(!NOIT_CHECK_LIVE(jcl->check)) noit_check_activate(jcl->check); } eventer_remove_fd(e->fd); newe = eventer_alloc(); memcpy(newe, e, sizeof(*e)); if(pthread_create(&tid, NULL, noit_livestream_thread_main, newe) == 0) { return 0; } noit_check_transient_remove_feed(jcl->check, jcl->feed); noit_livestream_closure_free(jcl); /* Undo our dup */ eventer_free(newe); /* Creating the thread failed, close it down and deschedule. */ e->opset->close(e->fd, &newmask, e); return 0; }
static void log_histo(struct histogram_config *conf, noit_check_t *check, u_int64_t whence_s, const char *metric_name, histogram_t *h, mtev_boolean live_feed) { mtev_boolean extended_id = mtev_false; char uuid_str[256*3+37]; const char *v; char *hist_serial = NULL; char *hist_encode = NULL; struct timeval whence; ssize_t est, enc_est; whence.tv_sec = whence_s; whence.tv_usec = 0; if(!conf->histogram) return; SETUP_LOG(metrics, ); if(metrics_log) { v = mtev_log_stream_get_property(metrics_log, "extended_id"); if(v && !strcmp(v, "on")) extended_id = mtev_true; } uuid_str[0] = '\0'; if(extended_id) { strlcat(uuid_str, check->target, sizeof(uuid_str)-37); strlcat(uuid_str, "`", sizeof(uuid_str)-37); strlcat(uuid_str, check->module, sizeof(uuid_str)-37); strlcat(uuid_str, "`", sizeof(uuid_str)-37); strlcat(uuid_str, check->name, sizeof(uuid_str)-37); strlcat(uuid_str, "`", sizeof(uuid_str)-37); } uuid_unparse_lower(check->checkid, uuid_str + strlen(uuid_str)); #define SECPART(a) ((unsigned long)(a)->tv_sec) #define MSECPART(a) ((unsigned long)((a)->tv_usec / 1000)) est = hist_serialize_estimate(h); hist_serial = malloc(est); if(!hist_serial) { mtevL(noit_error, "malloc(%d) failed\n", (int)est); goto cleanup; } enc_est = ((est + 2)/3)*4; hist_encode = malloc(enc_est); if(!hist_encode) { mtevL(noit_error, "malloc(%d) failed\n", (int)enc_est); goto cleanup; } if(hist_serialize(h, hist_serial, est) != est) { mtevL(noit_error, "histogram serialization failure\n"); goto cleanup; } enc_est = mtev_b64_encode((unsigned char *)hist_serial, est, hist_encode, enc_est); if(enc_est < 0) { mtevL(noit_error, "base64 histogram encoding failure\n"); goto cleanup; } if(live_feed && check->feeds) { mtev_skiplist_node *curr, *next; curr = next = mtev_skiplist_getlist(check->feeds); while(curr) { const char *feed_name = (char *)curr->data; mtev_log_stream_t ls = mtev_log_stream_find(feed_name); mtev_skiplist_next(check->feeds, &next); if(!ls || mtev_log(ls, &whence, __FILE__, __LINE__, "H1\t%lu.%03lu\t%s\t%s\t%.*s\n", SECPART(&whence), MSECPART(&whence), uuid_str, metric_name, (int)enc_est, hist_encode)) noit_check_transient_remove_feed(check, feed_name); curr = next; } } if(!live_feed) { SETUP_LOG(metrics, goto cleanup); mtev_log(metrics_log, &whence, __FILE__, __LINE__, "H1\t%lu.%03lu\t%s\t%s\t%.*s\n", SECPART(&whence), MSECPART(&whence), uuid_str, metric_name, (int)enc_est, hist_encode); }