static int httptrap_yajl_cb_end_map(void *ctx) { struct value_list *p, *last_p = NULL; struct rest_json_payload *json = ctx; _YD("[%3d]%-.*s cb_end_map\n", json->depth, json->depth, ""); json->depth--; if(json->saw_complex_type == 0x3) { long double total = 0, cnt = 0; mtev_boolean use_avg = mtev_false; for(p=json->last_value;p;p=p->next) { noit_stats_set_metric_coerce(json->check, json->keys[json->depth], json->last_type, p->v); last_p = p; if(p->v != NULL && (json->last_type == 'L' || json->last_type == 'l' || json->last_type == 'I' || json->last_type == 'i' || json->last_type == 'n')) { total += strtold(p->v, NULL); cnt = cnt + 1; use_avg = mtev_true; } json->cnt++; } if(json->immediate && last_p != NULL) { if(use_avg) { double avg = total / cnt; noit_stats_log_immediate_metric(json->check, json->keys[json->depth], 'n', &avg); } else { noit_stats_log_immediate_metric(json->check, json->keys[json->depth], json->last_type, last_p->v); } } } json->saw_complex_type = 0; for(p=json->last_value;p;) { struct value_list *savenext; savenext = p->next; if(p->v) free(p->v); savenext = p->next; free(p); p = savenext; } json->last_value = NULL; return 1; }
/* Handling of results */ static void noit_snmp_log_results(noit_module_t *self, noit_check_t *check, struct snmp_pdu *pdu) { struct check_info *info = check->closure; struct variable_list *vars; struct timeval duration; char buff[128]; stats_t current; int nresults = 0; noit_check_stats_clear(check, ¤t); if(pdu) for(vars = pdu->variables; vars; vars = vars->next_variable) nresults++; gettimeofday(¤t.whence, NULL); sub_timeval(current.whence, check->last_fire_time, &duration); current.duration = duration.tv_sec * 1000 + duration.tv_usec / 1000; current.available = pdu ? NP_AVAILABLE : NP_UNAVAILABLE; current.state = (nresults == info->noids) ? NP_GOOD : NP_BAD; snprintf(buff, sizeof(buff), "%d/%d gets", nresults, info->noids); current.status = buff; /* We have no results over which to iterate. */ if(!pdu) { noit_check_set_stats(check, ¤t); return; } /* manipulate the information ourselves */ nresults = 0; for(vars = pdu->variables; vars; vars = vars->next_variable) { char *sp; int oid_idx; double float_conv; u_int64_t u64; int64_t i64; char *endptr; char varbuff[256]; /* find the oid to which this is the response */ oid_idx = nresults; /* our current idx is the most likely */ if(info->oids[oid_idx].oidlen != vars->name_length || memcmp(info->oids[oid_idx].oid, vars->name, vars->name_length * sizeof(oid))) { /* Not the most obvious guess */ for(oid_idx = info->noids - 1; oid_idx >= 0; oid_idx--) { if(info->oids[oid_idx].oidlen == vars->name_length && memcmp(info->oids[oid_idx].oid, vars->name, vars->name_length * sizeof(oid))) break; } } if(oid_idx < 0) { snprint_variable(varbuff, sizeof(varbuff), vars->name, vars->name_length, vars); noitL(nlerr, "Unexpected oid results to %s`%s`%s: %s\n", check->target, check->module, check->name, varbuff); nresults++; continue; } #define SETM(a,b) noit_stats_set_metric(check, ¤t, \ info->oids[oid_idx].confname, a, b) if(info->oids[oid_idx].type_should_override) { snprint_value(varbuff, sizeof(varbuff), vars->name, vars->name_length, vars); sp = strchr(varbuff, ' '); if(sp) sp++; noit_stats_set_metric_coerce(check, ¤t, info->oids[oid_idx].confname, info->oids[oid_idx].type_override, sp); } else { switch(vars->type) { case ASN_OCTET_STR: sp = malloc(1 + vars->val_len); memcpy(sp, vars->val.string, vars->val_len); sp[vars->val_len] = '\0'; SETM(METRIC_STRING, sp); free(sp); break; case ASN_INTEGER: case ASN_GAUGE: SETM(METRIC_INT32, vars->val.integer); break; case ASN_TIMETICKS: case ASN_COUNTER: SETM(METRIC_UINT32, vars->val.integer); break; case ASN_INTEGER64: printI64(varbuff, vars->val.counter64); i64 = strtoll(varbuff, &endptr, 10); SETM(METRIC_INT64, (varbuff == endptr) ? NULL : &i64); break; case ASN_COUNTER64: printU64(varbuff, vars->val.counter64); u64 = strtoull(varbuff, &endptr, 10); SETM(METRIC_UINT64, (varbuff == endptr) ? NULL : &u64); break; case ASN_FLOAT: if(vars->val.floatVal) float_conv = *(vars->val.floatVal); SETM(METRIC_DOUBLE, vars->val.floatVal ? &float_conv : NULL); break; case ASN_DOUBLE: SETM(METRIC_DOUBLE, vars->val.doubleVal); break; case SNMP_NOSUCHOBJECT: case SNMP_NOSUCHINSTANCE: SETM(METRIC_STRING, NULL); break; default: snprint_variable(varbuff, sizeof(varbuff), vars->name, vars->name_length, vars); /* Advance passed the first space and use that unless there * is no space or we have no more string left. */ sp = strchr(varbuff, ' '); if(sp) sp++; SETM(METRIC_STRING, (sp && *sp) ? sp : NULL); } } nresults++; } noit_check_set_stats(check, ¤t); }
static int populate_stats_from_resmon_formatted_json(noit_check_t *check, stats_t *s, struct json_object *o, const char *prefix) { int count = 0; char keybuff[256]; #define MKKEY(fmt, arg) do { \ if(prefix) snprintf(keybuff, sizeof(keybuff), "%s`" fmt, prefix, arg); \ else snprintf(keybuff, sizeof(keybuff), fmt, arg); \ } while(0) if(o == NULL) { if(prefix) { noit_stats_set_metric(check, s, prefix, METRIC_STRING, NULL); count++; } return count; } switch(json_object_get_type(o)) { /* sub callers */ case json_type_array: { int i, alen = json_object_array_length(o); for(i=0;i<alen;i++) { struct json_object *item = json_object_array_get_idx(o, i); MKKEY("%d", i); count += populate_stats_from_resmon_formatted_json(check, s, item, keybuff); } } break; case json_type_object: { struct lh_table *lh; struct lh_entry *el; struct json_object *has_type = NULL, *has_value = NULL; lh = json_object_get_object(o); lh_foreach(lh, el) { if(!strcmp(el->k, "_type")) has_type = (struct json_object *)el->v; else if(!strcmp(el->k, "_value")) has_value = (struct json_object *)el->v; else { struct json_object *item = (struct json_object *)el->v; MKKEY("%s", (const char *)el->k); count += populate_stats_from_resmon_formatted_json(check, s, item, keybuff); } } if(prefix && has_type && has_value && json_object_is_type(has_type, json_type_string) && json_object_is_type(has_value, json_type_string)) { const char *type_str = json_object_get_string(has_type); const char *value_str = json_object_get_string(has_value); switch(*type_str) { case METRIC_INT32: case METRIC_UINT32: case METRIC_INT64: case METRIC_UINT64: case METRIC_DOUBLE: case METRIC_STRING: noit_stats_set_metric_coerce(check, s, prefix, (metric_type_t)*type_str, value_str); count++; default: break; } } break; } /* directs */ case json_type_string: if(prefix) { noit_stats_set_metric(check, s, prefix, METRIC_GUESS, (char *)json_object_get_string(o)); count++; } break; case json_type_boolean: if(prefix) { int val = json_object_get_boolean(o) ? 1 : 0; noit_stats_set_metric(check, s, prefix, METRIC_INT32, &val); count++; } break; case json_type_null: if(prefix) { noit_stats_set_metric(check, s, prefix, METRIC_STRING, NULL); count++; } break; case json_type_double: if(prefix) { double val = json_object_get_double(o); noit_stats_set_metric(check, s, prefix, METRIC_DOUBLE, &val); count++; } break; case json_type_int: if(prefix) { int64_t i64; uint64_t u64; switch(json_object_get_int_overflow(o)) { case json_overflow_int: i64 = json_object_get_int(o); noit_stats_set_metric(check, s, prefix, METRIC_INT64, &i64); count++; break; case json_overflow_int64: i64 = json_object_get_int64(o); noit_stats_set_metric(check, s, prefix, METRIC_INT64, &i64); count++; break; case json_overflow_uint64: u64 = json_object_get_uint64(o); noit_stats_set_metric(check, s, prefix, METRIC_UINT64, &u64); count++; break; } } } return count; }