コード例 #1
0
ファイル: process_xml.c プロジェクト: enswers/monitor-core
static int
endElement_GRID(void *data, const char *el)
{
   xmldata_t *xmldata = (xmldata_t *) data;

   /* In non-scalable mode, we ignore GRIDs. */
   if (!gmetad_config.scalable_mode)
      return 0;

   xmldata->grid_depth--;
   debug_msg("Found a </GRID>, depth is now %d", xmldata->grid_depth);

   datum_t hashkey, hashval;
   datum_t *rdatum;
   hash_t *summary;
   Source_t *source;

   /* Only keep info on sources we are an authority on. */
   if (authority_mode(xmldata))
      {
         source = &xmldata->source;

         /* Swap the metric_summary and metric_summary_pending over */
         pthread_mutex_lock(source->sum_finished);
         {
             summary = xmldata->source.metric_summary_pending;
             xmldata->source.metric_summary_pending = xmldata->source.metric_summary;
             xmldata->source.metric_summary = summary;
         }
         pthread_mutex_unlock(source->sum_finished);

         hashkey.data = (void*) xmldata->sourcename;
         hashkey.size = strlen(xmldata->sourcename) + 1;

         hashval.data = source;
         /* Trim structure to the correct length. */
         hashval.size = sizeof(*source) - GMETAD_FRAMESIZE + source->stringslen;

         /* We insert here to get an accurate hosts up/down value. */
         rdatum = hash_insert( &hashkey, &hashval, xmldata->root);
         if (!rdatum) {
               err_msg("Could not insert source %s", xmldata->sourcename);
               return 1;
         }
         /* Write the metric summaries to the RRD. */
         hash_foreach(summary, finish_processing_source, data);
      }
   return 0;
}
コード例 #2
0
ファイル: process_xml.c プロジェクト: reznor/monitor-core
static int
endElement_CLUSTER(void *data, const char *el)
{
    xmldata_t *xmldata = (xmldata_t *) data;
    datum_t hashkey, hashval;
    datum_t *rdatum;
    hash_t *summary;
    Source_t *source;

    /* Only keep info on sources we are an authority on. */
    if (authority_mode(xmldata))
    {
        source = &xmldata->source;
        summary = xmldata->source.metric_summary;

        /* Release the partial sum mutex */
        pthread_mutex_unlock(source->sum_finished);

        hashkey.data = (void*) xmldata->sourcename;
        hashkey.size = strlen(xmldata->sourcename) + 1;

        hashval.data = source;
        /* Trim structure to the correct length. */
        hashval.size = sizeof(*source) - GMETAD_FRAMESIZE + source->stringslen;

        /* We insert here to get an accurate hosts up/down value. */
        rdatum = hash_insert( &hashkey, &hashval, xmldata->root);
        if (!rdatum) {
            err_msg("Could not insert source %s", xmldata->sourcename);
            return 1;
        }
        /* Write the metric summaries to the RRD. */
        hash_foreach(summary, finish_processing_source, data);
    }
    return 0;
}
コード例 #3
0
ファイル: process_xml.c プロジェクト: reznor/monitor-core
/* XXX - There is an issue which will cause a failure if there are more than 16
  EXTRA_ELEMENTs.  This is a problem with the size of the data structure that
  is used to hold the metric information.
*/
static int
startElement_EXTRA_ELEMENT (void *data, const char *el, const char **attr)
{
    xmldata_t *xmldata = (xmldata_t *)data;
    int edge;
    struct xml_tag *xt;
    int i, name_off, value_off;
    Metric_t metric;
    char *name = getfield(xmldata->metric.strings, xmldata->metric.name);
    datum_t *rdatum;
    datum_t hashkey, hashval;
    datum_t *hash_datum = NULL;

    if (!xmldata->host_alive)
        return 0;

    /* Only keep extra element details if we are the authority on this cluster. */
    if (!authority_mode(xmldata))
        return 0;

    hashkey.data = (void*) name;
    hashkey.size =  strlen(name) + 1;

    hash_datum = hash_lookup (&hashkey, xmldata->host.metrics);
    if (!hash_datum)
        return 0;

    memcpy(&metric, hash_datum->data, hash_datum->size);
    datum_free(hash_datum);

    /* Check to make sure that we don't try to add more
        extra elements than the array can handle.
    */
    if (metric.ednameslen >= MAX_EXTRA_ELEMENTS)
    {
        debug_msg("Can not add more extra elements for [%s].  Capacity of %d reached[%s].",
                  name, MAX_EXTRA_ELEMENTS);
        return 0;
    }

    edge = metric.stringslen;

    name_off = value_off = -1;
    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_off = i;
            break;
        case VAL_TAG:
            value_off = i;
            break;
        default:
            break;
        }
    }

    if ((name_off >= 0) && (value_off >= 0))
    {
        const char *new_name = attr[name_off+1];
        const char *new_value = attr[value_off+1];

        metric.ednames[metric.ednameslen++] = addstring(metric.strings, &edge, new_name);
        metric.edvalues[metric.edvalueslen++] = addstring(metric.strings, &edge, new_value);

        metric.stringslen = edge;

        hashkey.data = (void*)name;
        hashkey.size =  strlen(name) + 1;

        /* 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);
        }
        else
        {
            hash_t *summary = xmldata->source.metric_summary;
            Metric_t sum_metric;

            /* do not add every SPOOF_HOST element to the summary table.
               if the same metric is SPOOF'd on more than ~MAX_EXTRA_ELEMENTS hosts
               then its summary table is destroyed.
             */
            if ( strlen(new_name) == 10 && !strcasecmp(new_name, SPOOF_HOST) )
                return 0;

            /* only update summary if metric is in hash */
            hash_datum = hash_lookup(&hashkey, summary);

            if (hash_datum) {
                int found = FALSE;

                memcpy(&sum_metric, hash_datum->data, hash_datum->size);
                datum_free(hash_datum);

                for (i = 0; i < sum_metric.ednameslen; i++) {
                    char *chk_name = getfield(sum_metric.strings, sum_metric.ednames[i]);
                    char *chk_value = getfield(sum_metric.strings, sum_metric.edvalues[i]);

                    /* If the name and value already exists, skip adding the strings. */
                    if (!strcasecmp(chk_name, new_name) && !strcasecmp(chk_value, new_value)) {
                        found = TRUE;
                        break;
                    }
                }
                if (!found) {
                    edge = sum_metric.stringslen;
                    sum_metric.ednames[sum_metric.ednameslen++] = addstring(sum_metric.strings, &edge, new_name);
                    sum_metric.edvalues[sum_metric.edvalueslen++] = addstring(sum_metric.strings, &edge, new_value);
                    sum_metric.stringslen = edge;
                }

                /* Trim graph display sum_metric at (352, 208) now or when in startElement_EXTRA_ELEMENT
                metric structure to the correct length. Tricky. */
                hashval.size = sizeof(sum_metric) - GMETAD_FRAMESIZE + sum_metric.stringslen;
                hashval.data = (void*) &sum_metric;

                /* Update metric in summary table. */
                rdatum = hash_insert(&hashkey, &hashval, summary);
                if (!rdatum)
                    err_msg("Could not insert summary %s metric", name);
            }
        }
    }

    return 0;
}
コード例 #4
0
ファイル: process_xml.c プロジェクト: reznor/monitor-core
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;
}
コード例 #5
0
ファイル: process_xml.c プロジェクト: reznor/monitor-core
static int
startElement_HOST(void *data, const char *el, const char **attr)
{
    xmldata_t *xmldata = (xmldata_t *)data;
    datum_t *hash_datum = NULL;
    datum_t *rdatum;
    datum_t hashkey, hashval;
    struct xml_tag *xt;
    uint32_t tn=0;
    uint32_t tmax=0;
    uint32_t reported=0;
    const char *name = NULL;
    int edge;
    int i;
    Host_t *host;
    hash_t *hosts;

    /* Check if the host is up. */
    for (i = 0; attr[i]; i+=2)
    {
        xt = in_xml_list (attr[i], strlen(attr[i]));
        if (!xt) continue;

        if (xt->tag == REPORTED_TAG)
            reported = strtoul(attr[i+1], (char **)NULL, 10);
        else if (xt->tag == TN_TAG)
            tn = atoi(attr[i+1]);
        else if (xt->tag == TMAX_TAG)
            tmax = atoi(attr[i+1]);
        else if (xt->tag == NAME_TAG)
            name = attr[i+1];
    }

    /* Is this host alive? For pre-2.5.0, we use the 60-second
     * method, otherwise we use the host's TN and TMAX attrs.
     */
    xmldata->host_alive = (xmldata->old || !tmax) ?
                          abs(xmldata->source.localtime - reported) < 60 :
                          tn < tmax * 4;

    if (xmldata->host_alive)
        xmldata->source.hosts_up++;
    else
        xmldata->source.hosts_down++;

    /* Only keep host details if we are the authority on this cluster. */
    if (!authority_mode(xmldata))
        return 0;

    host = &(xmldata->host);

    /* Use node Name for hash key (Query processing
     * requires a name key).
     */
    xmldata->hostname = realloc(xmldata->hostname, strlen(name)+1);
    strcpy(xmldata->hostname, name);

    /* Convert name to lower case - host names can't be
     * case sensitive
     */
    /*for(i = 0; name[i] != 0; i++)
        xmldata->hostname[i] = tolower(name[i]);
    xmldata->hostname[i] = 0; */

    hashkey.data = (void*) name;
    hashkey.size =  strlen(name) + 1;

    hosts = xmldata->source.authority;
    hash_datum = hash_lookup (&hashkey, hosts);
    if (!hash_datum)
    {
        memset((void*) host, 0, sizeof(*host));

        host->id = HOST_NODE;
        host->report_start = host_report_start;
        host->report_end = host_report_end;

        /* Only create one hash table for the host's metrics. Not user/builtin
         * like gmond. */
        host->metrics = hash_create(DEFAULT_METRICSIZE);
        if (!host->metrics)
        {
            err_msg("Could not create metric hash for host %s", name);
            return 1;
        }
    }
    else
    {
        /* Copy the stored host data into our Host buffer in xmldata. */
        memcpy(host, hash_datum->data, hash_datum->size);
        datum_free(hash_datum);
    }

    /* Edge has the same invariant as in fillmetric(). */
    edge = 0;

    host->location = -1;
    host->tags = -1;
    host->reported = reported;
    host->tn = tn;
    host->tmax = tmax;
    /* sacerdoti: Host TN tracks what gmond sees. TN=0 when gmond received last
     * heartbeat from node. Works because clocks move at same speed, and TN is
     * a relative timespan. */
    host->t0 = xmldata->now;
    host->t0.tv_sec -= host->tn;

    /* We will store this host in the cluster's authority table. */
    for(i = 0; attr[i]; i+=2)
    {
        xt = in_xml_list (attr[i], strlen(attr[i]));
        if (!xt) continue;

        switch( xt->tag )
        {
        case IP_TAG:
            host->ip = addstring(host->strings, &edge, attr[i+1]);
            break;
        case DMAX_TAG:
            host->dmax = strtoul(attr[i+1], (char **)NULL, 10);
            break;
        case LOCATION_TAG:
            host->location = addstring(host->strings, &edge, attr[i+1]);
            break;
        case TAGS_TAG:
            host->tags = addstring(host->strings, &edge, attr[i+1]);
            break;
        case STARTED_TAG:
            host->started = strtoul(attr[i+1], (char **)NULL, 10);
            break;
        default:
            break;
        }
    }
    host->stringslen = edge;

    /* Trim structure to the correct length. */
    hashval.size = sizeof(*host) - GMETAD_FRAMESIZE + host->stringslen;
    hashval.data = host;

    /* We dont care if this is an insert or an update. */
    rdatum = hash_insert(&hashkey, &hashval, hosts);
    if (!rdatum) {
        err_msg("Could not insert host %s", name);
        return 1;
    }
    return 0;
}
コード例 #6
0
ファイル: process_xml.c プロジェクト: reznor/monitor-core
static int
startElement_CLUSTER(void *data, const char *el, const char **attr)
{
    xmldata_t *xmldata = (xmldata_t *)data;
    struct xml_tag *xt;
    datum_t *hash_datum = NULL;
    datum_t hashkey;
    const char *name = NULL;
    int edge;
    int i;
    Source_t *source;

    /* Get name for hash key */
    for(i = 0; attr[i]; i+=2)
    {
        xt = in_xml_list (attr[i], strlen(attr[i]));
        if (!xt) continue;

        if (xt->tag == NAME_TAG)
            name = attr[i+1];
    }

    /* Only keep cluster details if we are the authority on this cluster. */
    if (!authority_mode(xmldata))
        return 0;

    source = &(xmldata->source);

    xmldata->sourcename = realloc(xmldata->sourcename, strlen(name)+1);
    strcpy(xmldata->sourcename, name);
    hashkey.data = (void*) name;
    hashkey.size =  strlen(name) + 1;

    hash_datum = hash_lookup(&hashkey, xmldata->root);
    if (!hash_datum)
    {
        memset((void*) source, 0, sizeof(*source));

        /* Set the identity of this host. */
        source->id = CLUSTER_NODE;
        source->report_start = source_report_start;
        source->report_end = source_report_end;

        source->authority = hash_create(DEFAULT_CLUSTERSIZE);
        if (!source->authority)
        {
            err_msg("Could not create hash table for cluster %s", name);
            return 1;
        }
        if(gmetad_config.case_sensitive_hostnames == 0)
            hash_set_flags(source->authority, HASH_FLAG_IGNORE_CASE);

        source->metric_summary = hash_create(DEFAULT_METRICSIZE);
        if (!source->metric_summary)
        {
            err_msg("Could not create summary hash for cluster %s", name);
            return 1;
        }
        source->ds = xmldata->ds;

        /* Initialize the partial sum lock */
        source->sum_finished = (pthread_mutex_t *)
                               malloc(sizeof(pthread_mutex_t));
        pthread_mutex_init(source->sum_finished, NULL);

        /* Grab the "partial sum" mutex until we are finished summarizing. */
        pthread_mutex_lock(source->sum_finished);
    }
    else
    {
        memcpy(source, hash_datum->data, hash_datum->size);
        datum_free(hash_datum);

        /* We need this lock before zeroing metric sums. */
        pthread_mutex_lock(source->sum_finished);

        source->hosts_up = 0;
        source->hosts_down = 0;

        hash_foreach(source->metric_summary, zero_out_summary, NULL);
    }

    /* Edge has the same invariant as in fillmetric(). */
    edge = 0;

    source->owner = -1;
    source->latlong = -1;
    source->url = -1;
    /* Fill in cluster attributes. */
    for(i = 0; attr[i]; i+=2)
    {
        xt = in_xml_list (attr[i], strlen(attr[i]));
        if (!xt)
            continue;

        switch( xt->tag )
        {
        case OWNER_TAG:
            source->owner = addstring(source->strings, &edge, attr[i+1]);
            break;
        case LATLONG_TAG:
            source->latlong = addstring(source->strings,
                                        &edge, attr[i+1]);
            break;
        case URL_TAG:
            source->url = addstring(source->strings, &edge, attr[i+1]);
            break;
        case LOCALTIME_TAG:
            source->localtime = strtoul(attr[i+1],
                                        (char **) NULL, 10);
            break;
        default:
            break;
        }
    }
    source->stringslen = edge;
    return 0;
}
コード例 #7
0
ファイル: process_xml.c プロジェクト: reznor/monitor-core
static int
startElement_GRID(void *data, const char *el, const char **attr)
{
    xmldata_t *xmldata = (xmldata_t *)data;
    struct xml_tag *xt;
    datum_t *hash_datum = NULL;
    datum_t hashkey;
    const char *name = NULL;
    int edge;
    int i;
    Source_t *source;

    /* In non-scalable mode, we ignore GRIDs. */
    if (!gmetad_config.scalable_mode)
        return 0;

    /* We do not keep info on nested grids. */
    if (authority_mode(xmldata))
    {
        /* Get name for hash key */
        for(i = 0; attr[i]; i+=2)
        {
            xt = in_xml_list (attr[i], strlen(attr[i]));
            if (!xt) continue;

            if (xt->tag == NAME_TAG)
            {
                name = attr[i+1];
                xmldata->sourcename =
                    realloc(xmldata->sourcename, strlen(name)+1);
                strcpy(xmldata->sourcename, name);
                hashkey.data = (void*) name;
                hashkey.size =  strlen(name) + 1;
            }
        }

        source = &(xmldata->source);

        /* Query the hash table for this cluster */
        hash_datum = hash_lookup(&hashkey, xmldata->root);
        if (!hash_datum)
        {   /* New Cluster */
            memset((void*) source, 0, sizeof(*source));

            source->id = GRID_NODE;
            source->report_start = source_report_start;
            source->report_end = source_report_end;

            source->metric_summary = hash_create(DEFAULT_METRICSIZE);
            if (!source->metric_summary)
            {
                err_msg("Could not create summary hash for cluster %s",
                        name);
                return 1;
            }
            source->ds = xmldata->ds;

            /* Initialize the partial sum lock */
            source->sum_finished = (pthread_mutex_t *)
                                   malloc(sizeof(pthread_mutex_t));
            pthread_mutex_init(source->sum_finished, NULL);

            /* Grab the "partial sum" mutex until we are finished
             * summarizing. */
            pthread_mutex_lock(source->sum_finished);
        }
        else
        {   /* Found Cluster. Put into our Source buffer in xmldata. */
            memcpy(source, hash_datum->data, hash_datum->size);
            datum_free(hash_datum);

            /* Grab the "partial sum" mutex until we are finished
             * summarizing. Needs to be done asap.*/
            pthread_mutex_lock(source->sum_finished);

            source->hosts_up = 0;
            source->hosts_down = 0;

            hash_foreach(source->metric_summary, zero_out_summary, NULL);
        }

        /* Edge has the same invariant as in fillmetric(). */
        edge = 0;

        /* Fill in grid attributes. */
        for(i = 0; attr[i]; i+=2)
        {
            xt = in_xml_list(attr[i], strlen(attr[i]));
            if (!xt)
                continue;

            switch( xt->tag )
            {
            case AUTHORITY_TAG:
                source->authority_ptr = addstring(source->strings,
                                                  &edge, attr[i+1]);
                break;
            case LOCALTIME_TAG:
                source->localtime = strtoul(attr[i+1],
                                            (char **) NULL, 10);
                break;
            default:
                break;
            }
        }
        source->stringslen = edge;
    }

    /* Must happen after all processing of this tag. */
    xmldata->grid_depth++;
    debug_msg("Found a <GRID>, depth is now %d", xmldata->grid_depth);

    return 0;
}