/* Write a metric summary value to the RRD database. */ static int finish_processing_source(datum_t *key, datum_t *val, void *arg) { xmldata_t *xmldata = (xmldata_t *) arg; char *name, *type; char sum[512]; char num[256]; Metric_t *metric; struct type_tag *tt; llist_entry *le; name = (char*) key->data; metric = (Metric_t*) val->data; type = getfield(metric->strings, metric->type); /* Don't save to RRD if the datasource is dead or write_rrds is off */ if( xmldata->ds->dead || gmetad_config.write_rrds != 1) return 1; tt = in_type_list(type, strlen(type)); if (!tt) return 0; /* Don't save to RRD if this is a metric not to be summarized */ if (llist_search(&(gmetad_config.unsummarized_metrics), (void *)name, llist_strncmp, &le) == 0) return 0; switch (tt->type) { case INT: case UINT: sprintf(sum, "%.f", metric->val.d); break; case FLOAT: sprintf(sum, "%.*f", (int) metric->precision, metric->val.d); break; default: break; } sprintf(num, "%u", metric->num); /* Save the data to a round robin database if this data source is * alive. */ if (!xmldata->ds->dead && !xmldata->rval) { debug_msg("Writing Summary data for source %s, metric %s", xmldata->sourcename, name); xmldata->rval = write_data_to_rrd(xmldata->sourcename, NULL, name, sum, num, xmldata->ds->step, xmldata->source.localtime, cstr_to_slope(getfield(metric->strings, metric->slope))); } return xmldata->rval; }
static int write_root_summary(datum_t *key, datum_t *val, void *arg) { char *name, *type; char sum[256]; char num[256]; Metric_t *metric; int rc; struct type_tag *tt; llist_entry *le; char *p; name = (char*) key->data; metric = (Metric_t*) val->data; type = getfield(metric->strings, metric->type); /* Summarize all numeric metrics */ tt = in_type_list(type, strlen(type)); /* Don't write a summary for an unknown or STRING type */ if (!tt || (tt->type == STRING)) return 0; /* Don't write a summary for metrics not to be summarized */ if (llist_search(&(gmetad_config.unsummarized_metrics), (void *)key->data, llist_strncmp, &le) == 0) return 0; /* Don't write a summary for metris that appears to be sFlow VM metrics */ if (gmetad_config.unsummarized_sflow_vm_metrics && (p = strchr(name, '.')) != NULL && *(p+1) == 'v') return 0; ganglia_scoreboard_inc(METS_SUMRZ_ROOT); /* We log all our sums in double which does not suffer from wraparound errors: for example memory KB exceeding 4TB. -twitham */ sprintf(sum, "%.5f", metric->val.d); sprintf(num, "%u", metric->num); /* err_msg("Writing Overall Summary for metric %s (%s)", name, sum); */ /* Save the data to a rrd file unless write_rrds == off */ if (gmetad_config.write_rrds == 0) return 0; debug_msg("Writing Root Summary data for metric %s", name); rc = write_data_to_rrd( NULL, NULL, name, sum, num, 15, 0, cstr_to_slope(getfield(metric->strings, metric->slope))); if (rc) { err_msg("Unable to write meta data for metric %s to RRD", name); } return 0; }
static int write_root_summary(datum_t *key, datum_t *val, void *arg) { char *name, *type; char sum[256]; char num[256]; Metric_t *metric; int rc; struct type_tag *tt; name = (char*) key->data; metric = (Metric_t*) val->data; type = getfield(metric->strings, metric->type); /* Summarize all numeric metrics */ tt = in_type_list(type, strlen(type)); /* Don't write a summary for an unknown or STRING type. */ if (!tt || (tt->type == STRING)) return 0; /* We log all our sums in double which does not suffer from wraparound errors: for example memory KB exceeding 4TB. -twitham */ sprintf(sum, "%.5f", metric->val.d); sprintf(num, "%u", metric->num); /* err_msg("Writing Overall Summary for metric %s (%s)", name, sum); */ /* Save the data to a rrd file unless write_rrds == off */ if (gmetad_config.write_rrds == 0) return 0; rc = write_data_to_rrd( NULL, NULL, name, sum, num, 15, 0, metric->slope); if (rc) { err_msg("Unable to write meta data for metric %s to RRD", name); } return 0; }
static int startElement_METRIC(void *data, const char *el, const char **attr) { xmldata_t *xmldata = (xmldata_t *)data; ganglia_slope_t slope = GANGLIA_SLOPE_UNSPECIFIED; struct xml_tag *xt; struct type_tag *tt; datum_t *hash_datum = NULL; datum_t *rdatum; datum_t hashkey, hashval; const char *name = NULL; const char *metricval = NULL; const char *type = NULL; int do_summary; int i, edge, carbon_ret; hash_t *summary; Metric_t *metric; if (!xmldata->host_alive ) return 0; /* Get name for hash key, and val/type for summaries. */ for(i = 0; attr[i]; i+=2) { xt = in_xml_list(attr[i], strlen(attr[i])); if (!xt) continue; switch (xt->tag) { case NAME_TAG: name = attr[i+1]; hashkey.data = (void*) name; hashkey.size = strlen(name) + 1; break; case VAL_TAG: metricval = attr[i+1]; break; case TYPE_TAG: type = attr[i+1]; break; case SLOPE_TAG: slope = cstr_to_slope(attr[i+1]); default: break; } } metric = &(xmldata->metric); memset((void*) metric, 0, sizeof(*metric)); /* Summarize all numeric metrics */ do_summary = 0; tt = in_type_list(type, strlen(type)); if (!tt) return 0; if (tt->type==INT || tt->type==UINT || tt->type==FLOAT) do_summary = 1; /* Only keep metric details if we are the authority on this cluster. */ if (authority_mode(xmldata)) { /* Save the data to a round robin database if the data source is alive */ fillmetric(attr, metric, type); if (metric->dmax && metric->tn > metric->dmax) return 0; if (do_summary && !xmldata->ds->dead && !xmldata->rval) { debug_msg("Updating host %s, metric %s", xmldata->hostname, name); if ( gmetad_config.write_rrds == 1 ) xmldata->rval = write_data_to_rrd(xmldata->sourcename, xmldata->hostname, name, metricval, NULL, xmldata->ds->step, xmldata->source.localtime, slope); if (gmetad_config.carbon_server) // if the user has specified a carbon server, send the metric to carbon as well carbon_ret=write_data_to_carbon(xmldata->sourcename, xmldata->hostname, name, metricval,xmldata->source.localtime); } metric->id = METRIC_NODE; metric->report_start = metric_report_start; metric->report_end = metric_report_end; edge = metric->stringslen; metric->name = addstring(metric->strings, &edge, name); metric->stringslen = edge; /* Set local idea of T0. */ metric->t0 = xmldata->now; metric->t0.tv_sec -= metric->tn; /* Trim metric structure to the correct length. */ hashval.size = sizeof(*metric) - GMETAD_FRAMESIZE + metric->stringslen; hashval.data = (void*) metric; /* Update full metric in cluster host table. */ rdatum = hash_insert(&hashkey, &hashval, xmldata->host.metrics); if (!rdatum) { err_msg("Could not insert %s metric", name); } } /* Always update summary for numeric metrics. */ if (do_summary) { summary = xmldata->source.metric_summary; hash_datum = hash_lookup(&hashkey, summary); if (!hash_datum) { if (!authority_mode(xmldata)) { metric = &(xmldata->metric); memset((void*) metric, 0, sizeof(*metric)); fillmetric(attr, metric, type); } /* else we have already filled in the metric above. */ } else { memcpy(&xmldata->metric, hash_datum->data, hash_datum->size); datum_free(hash_datum); metric = &(xmldata->metric); switch (tt->type) { case INT: case UINT: case FLOAT: metric->val.d += (double) strtod(metricval, (char**) NULL); break; default: break; } } metric->num++; metric->t0 = xmldata->now; /* tell cleanup thread we are using this */ /* Trim metric structure to the correct length. Tricky. */ hashval.size = sizeof(*metric) - GMETAD_FRAMESIZE + metric->stringslen; hashval.data = (void*) metric; /* Update metric in summary table. */ rdatum = hash_insert(&hashkey, &hashval, summary); if (!rdatum) err_msg("Could not insert %s metric", name); } return 0; }