Ejemplo n.º 1
0
xmlNodePtr
noit_check_state_as_xml(noit_check_t *check) {
    xmlNodePtr state, tmp, metrics;
    noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
    const char *k;
    int klen;
    void *data;
    stats_t *c = &check->stats.current;

    state = xmlNewNode(NULL, (xmlChar *)"state");
    NODE_CONTENT(state, "running", NOIT_CHECK_RUNNING(check)?"true":"false");
    NODE_CONTENT(state, "killed", NOIT_CHECK_KILLED(check)?"true":"false");
    NODE_CONTENT(state, "configured",
                 NOIT_CHECK_CONFIGURED(check)?"true":"false");
    NODE_CONTENT(state, "disabled", NOIT_CHECK_DISABLED(check)?"true":"false");
    NODE_CONTENT(state, "target_ip", check->target_ip);
    xmlAddChild(state, (tmp = xmlNewNode(NULL, (xmlChar *)"last_run")));
    if(check->stats.current.whence.tv_sec) {
        struct timeval f = check->stats.current.whence;
        struct timeval n;
        char timestr[20];
        gettimeofday(&n, NULL);
        snprintf(timestr, sizeof(timestr), "%0.3f",
                 n.tv_sec + (n.tv_usec / 1000000.0));
        xmlSetProp(tmp, (xmlChar *)"now", (xmlChar *)timestr);
        snprintf(timestr, sizeof(timestr), "%0.3f",
                 f.tv_sec + (f.tv_usec / 1000000.0));
        xmlNodeAddContent(tmp, (xmlChar *)timestr);
    }
    if(c->available) { /* truth here means the check has been run */
        char buff[20], *compiler_warning;
        snprintf(buff, sizeof(buff), "%0.3f", (float)c->duration/1000.0);
        compiler_warning = buff;
        NODE_CONTENT(state, "runtime", compiler_warning);
    }
    NODE_CONTENT(state, "availability",
                 noit_check_available_string(c->available));
    NODE_CONTENT(state, "state", noit_check_state_string(c->state));
    NODE_CONTENT(state, "status", c->status ? c->status : "");
    memset(&iter, 0, sizeof(iter));
    xmlAddChild(state, (metrics = xmlNewNode(NULL, (xmlChar *)"metrics")));
    while(noit_hash_next(&c->metrics, &iter, &k, &klen, &data)) {
        char buff[256];
        metric_t *m = (metric_t *)data;
        xmlAddChild(metrics, (tmp = xmlNewNode(NULL, (xmlChar *)"metric")));
        xmlSetProp(tmp, (xmlChar *)"name", (xmlChar *)m->metric_name);
        buff[0] = m->metric_type;
        buff[1] = '\0';
        xmlSetProp(tmp, (xmlChar *)"type", (xmlChar *)buff);
        if(m->metric_value.s) {
            int rv;
            rv = noit_stats_snprint_metric_value(buff, sizeof(buff), m);
            if(rv < 0)
                xmlSetProp(tmp, (xmlChar *)"error", (xmlChar *)"unknown type");
            else
                xmlNodeAddContent(tmp, (xmlChar *)buff);
        }
    }
    return state;
}
Ejemplo n.º 2
0
static struct json_object *
stats_to_json(stats_t *c) {
  struct json_object *doc;
  doc = json_object_new_object();
  mtev_hash_table *metrics;
  mtev_hash_iter iter = MTEV_HASH_ITER_ZERO;
  const char *k;
  int klen;
  void *data;

  metrics = noit_check_stats_metrics(c);
  while(mtev_hash_next(metrics, &iter, &k, &klen, &data)) {
    char buff[256];
    metric_t *m = (metric_t *)data;
    struct json_object *metric = json_object_new_object();
    buff[0] = m->metric_type; buff[1] = '\0';
    json_object_object_add(metric, "_type", json_object_new_string(buff));
    if(m->metric_value.s) {
      int rv;
      rv = noit_stats_snprint_metric_value(buff, sizeof(buff), m);
      if(rv >= 0)
        json_object_object_add(metric, "_value", json_object_new_string(buff));
    }
    json_object_object_add(doc, m->metric_name, metric);
  }
  return doc;
}
Ejemplo n.º 3
0
static void
add_metrics_to_node(stats_t *c, xmlNodePtr metrics, const char *type,
                    int include_time) {
  mtev_hash_table *mets;
  mtev_hash_iter iter = MTEV_HASH_ITER_ZERO;
  const char *k;
  int klen;
  void *data;
  xmlNodePtr tmp;

  mets = noit_check_stats_metrics(c);
  while(mtev_hash_next(mets, &iter, &k, &klen, &data)) {
    char buff[256];
    metric_t *m = (metric_t *)data;
    xmlAddChild(metrics, (tmp = xmlNewNode(NULL, (xmlChar *)"metric")));
    xmlSetProp(tmp, (xmlChar *)"name", (xmlChar *)m->metric_name);
    buff[0] = m->metric_type; buff[1] = '\0';
    xmlSetProp(tmp, (xmlChar *)"type", (xmlChar *)buff);
    if(m->metric_value.s) {
      int rv;
      rv = noit_stats_snprint_metric_value(buff, sizeof(buff), m);
      if(rv < 0)
        xmlSetProp(tmp, (xmlChar *)"error", (xmlChar *)"unknown type");
      else
        xmlNodeAddContent(tmp, (xmlChar *)buff);
    }
  }
  xmlSetProp(metrics, (xmlChar *)"type", (const xmlChar *) type);
  if(include_time) {
    struct timeval *f = noit_check_stats_whence(c, NULL);
    char timestr[20];
    snprintf(timestr, sizeof(timestr), "%0.3f",
             f->tv_sec + (f->tv_usec / 1000000.0));
    xmlSetProp(metrics, (xmlChar *)"timestamp", (xmlChar *)timestr);
  }
}
Ejemplo n.º 4
0
static int
rest_httptrap_handler(mtev_http_rest_closure_t *restc,
                      int npats, char **pats) {
  int mask, complete = 0, cnt;
  struct rest_json_payload *rxc = NULL;
  const char *error = "internal error", *secret = NULL;
  mtev_http_session_ctx *ctx = restc->http_ctx;
  const unsigned int DEBUGDATA_OUT_SIZE=4096;
  const unsigned int JSON_OUT_SIZE=DEBUGDATA_OUT_SIZE+128;
  char json_out[JSON_OUT_SIZE];
  char debugdata_out[DEBUGDATA_OUT_SIZE];
  int debugflag=0;
  const char *debugchkflag;
  noit_check_t *check;
  uuid_t check_id;
  mtev_http_request *req;
  mtev_hash_table *hdrs;

  if(npats != 2) {
    error = "bad uri";
    goto error;
  }
  if(uuid_parse(pats[0], check_id)) {
    error = "uuid parse error";
    goto error;
  }

  if(restc->call_closure == NULL) {
    mtev_boolean allowed = mtev_false;
    httptrap_closure_t *ccl = NULL;
    const char *delimiter = NULL;
    rxc = restc->call_closure = calloc(1, sizeof(*rxc));
    rxc->delimiter = DEFAULT_HTTPTRAP_DELIMITER;
    check = noit_poller_lookup(check_id);
    if(!check) {
      error = "no such check";
      goto error;
    }
    if(!httptrap_surrogate && strcmp(check->module, "httptrap")) {
      error = "no such httptrap check";
      goto error;
    }
 
    /* check "secret" then "httptrap_secret" as a fallback */
    (void)mtev_hash_retr_str(check->config, "secret", strlen("secret"), &secret);
    if(!secret) (void)mtev_hash_retr_str(check->config, "httptrap_secret", strlen("httptrap_secret"), &secret);
    if(secret && !strcmp(pats[1], secret)) allowed = mtev_true;
    if(!allowed && cross_module_reverse_allowed(check, pats[1])) allowed = mtev_true;

    if(!allowed) {
      error = "secret mismatch";
      goto error;
    }

    /* check "delimiter" then "httptrap_delimiter" as a fallback */
    (void)mtev_hash_retr_str(check->config, "delimiter", strlen("delimiter"), &delimiter);
    if(!delimiter) (void)mtev_hash_retr_str(check->config, "httptrap_delimiter", strlen("httptrap_delimiter"), &delimiter);
    if(delimiter && *delimiter) rxc->delimiter = *delimiter;
    rxc->check = check;
    uuid_copy(rxc->check_id, check_id);
    rxc->parser = yajl_alloc(&httptrap_yajl_callbacks, NULL, rxc);
    rxc->depth = -1;
    yajl_config(rxc->parser, yajl_allow_comments, 1);
    yajl_config(rxc->parser, yajl_dont_validate_strings, 1);
    yajl_config(rxc->parser, yajl_allow_trailing_garbage, 1);
    yajl_config(rxc->parser, yajl_allow_partial_values, 1);
    restc->call_closure_free = rest_json_payload_free;
  }
  else rxc = restc->call_closure;

  /* flip threads */
  {
    mtev_http_connection *conn = mtev_http_session_connection(ctx);
    eventer_t e = mtev_http_connection_event(conn);
    if(e) {
      pthread_t tgt = CHOOSE_EVENTER_THREAD_FOR_CHECK(rxc->check);
      if(!pthread_equal(e->thr_owner, tgt)) {
        e->thr_owner = tgt;
        return EVENTER_READ | EVENTER_WRITE | EVENTER_EXCEPTION;
      }
    }
  }

  rxc = rest_get_json_upload(restc, &mask, &complete);
  if(rxc == NULL && !complete) return mask;

  if(!rxc) goto error;
  if(rxc->error) goto error;

  cnt = rxc->cnt;

  mtev_http_response_status_set(ctx, 200, "OK"); 
  mtev_http_response_header_set(ctx, "Content-Type", "application/json");
  mtev_http_response_option_set(ctx, MTEV_HTTP_CLOSE); 
  
  /*Examine headers for x-circonus-httptrap-debug flag*/
  req = mtev_http_session_request(ctx);
  hdrs = mtev_http_request_headers_table(req); 
    
  /*Check if debug header passed in. If present and set to true, set debugflag value to one.*/
  if(mtev_hash_retr_str(hdrs, "x-circonus-httptrap-debug", strlen("x-circonus-httptrap-debug"), &debugchkflag))
  {
    if (strcmp(debugchkflag,"true")==0)
    {
      debugflag=1;
    }
  }
   
  /*If debugflag remains zero, simply output the number of metrics.*/
  if (debugflag==0)
  {
    snprintf(json_out, sizeof(json_out),
           "{ \"stats\": %d }", cnt);    
  }
  
  /*Otherwise, if set to one, output current metrics in addition to number of current metrics.*/
  else if (debugflag==1)
  {        
      stats_t *c;
      mtev_hash_table *metrics;
        
      /*Retrieve check information.*/        
      check = noit_poller_lookup(check_id);
      c = noit_check_get_stats_current(check);
      metrics = noit_check_stats_metrics(c);
      mtev_hash_iter iter = MTEV_HASH_ITER_ZERO;
      const char *k;
      int klen;
      void *data;
      int written=0;
      int offset=0;
      memset(debugdata_out,'\0',sizeof(debugdata_out));
      
      /*Extract metrics*/
      while(mtev_hash_next(metrics, &iter, &k, &klen, &data))
      {
        char buff[256];
        int toWrite = DEBUGDATA_OUT_SIZE-offset;
        metric_t *tmp=(metric_t *)data;
        char *metric_name=tmp->metric_name;
        metric_type_t metric_type=tmp->metric_type;
        noit_stats_snprint_metric_value(buff, sizeof(buff), tmp);
        written = snprintf(debugdata_out + offset, toWrite, "\"%s\": {\"_type\":\"%c\",\"_value\":\"%s\"},", metric_name,metric_type,buff);
        if(toWrite < written) 
        {
            break;
        }
        offset += written;
      }
        
      /*Set last character to empty-don't want extra comma in output*/
      if (offset>1)
      {
        snprintf(debugdata_out + (offset-1), 1, "%s"," ");
      }
      
      /*Output stats and metrics.*/
      snprintf(json_out, sizeof(json_out)+strlen(debugdata_out),
             "{ \"stats\": %d, \"metrics\": {%s } }", cnt, debugdata_out);
  }

  mtev_http_response_append(ctx, json_out, strlen(json_out));
  mtev_http_response_end(ctx);
  return 0;

 error:
  mtev_http_response_server_error(ctx, "application/json");
  mtev_http_response_append(ctx, "{ \"error\": \"", 12);
  if(rxc && rxc->error) error = rxc->error;
  mtev_http_response_append(ctx, error, strlen(error));
  mtev_http_response_append(ctx, "\" }", 3);
  mtev_http_response_end(ctx);
  return 0;
}