Ejemplo n.º 1
0
static int
metric_summary(datum_t *key, datum_t *val, void *arg)
{
   client_t *client = (client_t*) arg;
   char *name = (char*) key->data;
   char *type;
   char sum[256];
   Metric_t *metric = (Metric_t*) val->data;
   struct type_tag *tt;
   int rc,i;

   type = getfield(metric->strings, metric->type);

   tt = in_type_list(type, strlen(type));
   if (!tt) return 0;

   /* We sum everything in double to properly combine integer sources
      (3.0) with float sources (3.1).  This also avoids wraparound
      errors: for example memory KB exceeding 4TB. */
   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;
      }

   char buf[16 * 1024];
   char *b = buf;
   #define xml_print(client, ...) 0; b += snprintf(b, sizeof(buf) - (b - buf), __VA_ARGS__);

   rc = xml_print(client, "<METRICS NAME=\"%s\" SUM=\"%s\" NUM=\"%u\" "
      "TYPE=\"%s\" UNITS=\"%s\" SLOPE=\"%s\" SOURCE=\"%s\">\n",
      name, sum, metric->num,
      "double",         /* we always report double sums */
      getfield(metric->strings, metric->units),
      getfield(metric->strings, metric->slope),
      getfield(metric->strings, metric->source));

   rc = xml_print(client, "<EXTRA_DATA>\n");

   for (i=0; !rc && i<metric->ednameslen; i++) 
     {
       rc=xml_print(client, "<EXTRA_ELEMENT NAME=\"%s\" VAL=\"%s\"/>\n",
                    getfield(metric->strings, metric->ednames[i]),
                    getfield(metric->strings, metric->edvalues[i]));
     }

   rc = xml_print(client, "</EXTRA_DATA>\n");
   rc=xml_print(client, "</METRICS>\n");
   #undef xml_print
   rc = xml_print(client, "%s", buf);
   return rc;
}
Ejemplo n.º 2
0
/* 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;
}
Ejemplo n.º 3
0
/* Sums the metric summaries from all data sources. */
static int
sum_metrics(datum_t *key, datum_t *val, void *arg)
{
   datum_t *hash_datum, *rdatum;
   Metric_t *rootmetric, *metric;
   char *type;
   struct type_tag *tt;
   int do_sum = 1;

   metric = (Metric_t *) val->data;
   type = getfield(metric->strings, metric->type);

   hash_datum = hash_lookup(key, root.metric_summary);
   if (!hash_datum)
      {
         hash_datum = datum_new((char*) metric, val->size);
         do_sum = 0;
      }
   rootmetric = (Metric_t*) hash_datum->data;

   if (do_sum)
      {
         tt = in_type_list(type, strlen(type));
         if (!tt) {
            datum_free(hash_datum);
            return 0;
	 }

         /* We sum everything in double to properly combine integer sources
            (3.0) with float sources (3.1).  This also avoids wraparound
            errors: for example memory KB exceeding 4TB. */
         switch (tt->type)
            {
               case INT:
               case UINT:
               case FLOAT:
                  rootmetric->val.d += metric->val.d;
                  break;
               default:
                  break;
            }
         rootmetric->num += metric->num;
      }

   rdatum = hash_insert(key, hash_datum, root.metric_summary);

   datum_free(hash_datum);

   if (!rdatum)
      return 1;
   else
      return 0;
}
Ejemplo n.º 4
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;
   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;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
static int
startElement_METRICS(void *data, const char *el, const char **attr)
{
    xmldata_t *xmldata = (xmldata_t *)data;
    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 *metricnum = NULL;
    const char *type = NULL;
    int i;
    hash_t *summary;
    Metric_t *metric;

    /* In non-scalable mode, we do not process summary data. */
    if (!gmetad_config.scalable_mode) 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 TYPE_TAG:
            type = attr[i+1];
            break;
        case SUM_TAG:
            metricval = attr[i+1];
            break;
        case NUM_TAG:
            metricnum = attr[i+1];
        default:
            break;
        }
    }

    summary = xmldata->source.metric_summary;
    hash_datum = hash_lookup(&hashkey, summary);
    if (!hash_datum)
    {
        metric = &(xmldata->metric);
        memset((void*) metric, 0, sizeof(*metric));
        fillmetric(attr, metric, type);
    }
    else
    {
        memcpy(&xmldata->metric, hash_datum->data, hash_datum->size);
        datum_free(hash_datum);
        metric = &(xmldata->metric);

        tt = in_type_list(type, strlen(type));
        if (!tt) return 0;
        switch (tt->type)
        {
        case INT:
        case UINT:
        case FLOAT:
            metric->val.d += (double)
                             strtod(metricval, (char**) NULL);
            break;
        default:
            break;
        }
        metric->num += atoi(metricnum);
    }

    /* Update metric in summary table. */
    hashval.size = sizeof(*metric) - GMETAD_FRAMESIZE + metric->stringslen;
    hashval.data = (void*) metric;

    summary = xmldata->source.metric_summary;
    rdatum = hash_insert(&hashkey, &hashval, summary);
    if (!rdatum) {
        err_msg("Could not insert %s metric", name);
        return 1;
    }
    return 0;
}
Ejemplo n.º 7
0
/* Populates a Metric_t structure from a list of XML metric attribute strings.
 * We need the type string here because we cannot be sure it comes before
 * the metric value in the attribute list.
 */
static void
fillmetric(const char** attr, Metric_t *metric, const char* type)
{
    int i;
    /* INV: always points to the next free byte in metric.strings buffer. */
    int edge = 0;
    struct type_tag *tt;
    struct xml_tag *xt;
    char *metricval, *p;

    /* For old versions of gmond. */
    metric->slope = -1;

    for(i = 0; attr[i] ; i+=2)
    {
        /* Only process the XML tags that gmetad is interested in */
        xt = in_xml_list (attr[i], strlen(attr[i]));
        if (!xt)
            continue;

        switch( xt->tag )
        {
        case SUM_TAG:
        case VAL_TAG:
            metricval = (char*) attr[i+1];

            tt = in_type_list(type, strlen(type));
            if (!tt) return;

            switch (tt->type)
            {
            case INT:
            case TIMESTAMP:
            case UINT:
            case FLOAT:
                metric->val.d = (double)
                                strtod(metricval, (char**) NULL);
                p = strrchr(metricval, '.');
                if (p) metric->precision = (short int) strlen(p+1);
                break;
            case STRING:
                /* We store string values in the 'valstr' field. */
                break;
            }
            metric->valstr = addstring(metric->strings, &edge, metricval);
            break;
        case TYPE_TAG:
            metric->type = addstring(metric->strings, &edge, attr[i+1]);
            break;
        case UNITS_TAG:
            metric->units = addstring(metric->strings, &edge, attr[i+1]);
            break;
        case TN_TAG:
            metric->tn = atoi(attr[i+1]);
            break;
        case TMAX_TAG:
            metric->tmax = atoi(attr[i+1]);
            break;
        case DMAX_TAG:
            metric->dmax = atoi(attr[i+1]);
            break;
        case SLOPE_TAG:
            metric->slope = addstring(metric->strings, &edge, attr[i+1]);
            break;
        case SOURCE_TAG:
            metric->source = addstring(metric->strings, &edge, attr[i+1]);
            break;
        case NUM_TAG:
            metric->num = atoi(attr[i+1]);
            break;
        default:
            break;
        }
    }
    metric->stringslen = edge;

    /* We are ok with growing metric values b/c we write to a full-sized
     * buffer in xmldata. */
}
Ejemplo n.º 8
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;
}