示例#1
0
/******************************************************************************
 *                                                                            *
 * Comments: Get the value of a counter. If it is a rate counter,             *
 *           sleep 1 second to get the second raw value.                      *
 *                                                                            *
 ******************************************************************************/
PDH_STATUS	calculate_counter_value(const char *function, const char *counterpath, double *value)
{
    PDH_HQUERY		query;
    PDH_HCOUNTER		handle = NULL;
    PDH_STATUS		pdh_status;
    PDH_RAW_COUNTER		rawData, rawData2;
    PDH_FMT_COUNTERVALUE	counterValue;

    if (ERROR_SUCCESS != (pdh_status = zbx_PdhOpenQuery(function, &query)))
        return pdh_status;

    if (ERROR_SUCCESS != (pdh_status = zbx_PdhAddCounter(function, NULL, query, counterpath, &handle)))
        goto close_query;

    if (ERROR_SUCCESS != (pdh_status = zbx_PdhCollectQueryData(function, counterpath, query)))
        goto remove_counter;

    if (ERROR_SUCCESS != (pdh_status = zbx_PdhGetRawCounterValue(function, counterpath, handle, &rawData)))
        goto remove_counter;

    if (PDH_CSTATUS_INVALID_DATA == (pdh_status = PdhCalculateCounterFromRawValue(handle, PDH_FMT_DOUBLE |
                                     PDH_FMT_NOCAP100, &rawData, NULL, &counterValue)))
    {
        /* some (e.g., rate) counters require two raw values, MSDN lacks documentation */
        /* about what happens but tests show that PDH_CSTATUS_INVALID_DATA is returned */

        zbx_sleep(1);

        if (ERROR_SUCCESS == (pdh_status = zbx_PdhCollectQueryData(function, counterpath, query)) &&
                ERROR_SUCCESS == (pdh_status = zbx_PdhGetRawCounterValue(function, counterpath,
                                               handle, &rawData2)))
        {
            pdh_status = PdhCalculateCounterFromRawValue(handle, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100,
                         &rawData2, &rawData, &counterValue);
        }
    }

    if (ERROR_SUCCESS != pdh_status || (PDH_CSTATUS_VALID_DATA != counterValue.CStatus &&
                                        PDH_CSTATUS_NEW_DATA != counterValue.CStatus))
    {
        if (ERROR_SUCCESS == pdh_status)
            pdh_status = counterValue.CStatus;

        zabbix_log(LOG_LEVEL_DEBUG, "%s(): cannot calculate counter value '%s': %s",
                   function, counterpath, strerror_from_module(pdh_status, L"PDH.DLL"));
    }
    else
    {
        *value = counterValue.doubleValue;
    }
remove_counter:
    PdhRemoveCounter(handle);
close_query:
    PdhCloseQuery(query);

    return pdh_status;
}
示例#2
0
void	collect_perfstat()
{
	const char		*__function_name = "collect_perfstat";
	PERF_COUNTER_DATA	*cptr;
	PDH_STATUS		pdh_status;
	time_t			now;
	PDH_FMT_COUNTERVALUE	value;

	if (SUCCEED != perf_collector_started())
		return;

	if (NULL == ppsd.pPerfCounterList)	/* no counters */
		return;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);

	now = time(NULL);

	/* refresh unsupported counters */
	if (ppsd.nextcheck <= now)
	{
		for (cptr = ppsd.pPerfCounterList; NULL != cptr; cptr = cptr->next)
 		{
			if (PERF_COUNTER_NOTSUPPORTED != cptr->status)
				continue;

			zbx_PdhAddCounter(__function_name, cptr, ppsd.pdh_query, cptr->counterpath, &cptr->handle);
		}

		ppsd.nextcheck = now + UNSUPPORTED_REFRESH_PERIOD;
	}

	/* query for new data */
	if (ERROR_SUCCESS != (pdh_status = PdhCollectQueryData(ppsd.pdh_query)))
	{
		for (cptr = ppsd.pPerfCounterList; NULL != cptr; cptr = cptr->next)
		{
			if (PERF_COUNTER_NOTSUPPORTED != cptr->status)
				deactivate_perf_counter(cptr);
		}

		zabbix_log(LOG_LEVEL_DEBUG, "%s() call to PdhCollectQueryData() failed: %s",
				__function_name, strerror_from_module(pdh_status, L"PDH.DLL"));

		goto out;
	}

	/* get the raw values */
	for (cptr = ppsd.pPerfCounterList; NULL != cptr; cptr = cptr->next)
	{
		if (PERF_COUNTER_NOTSUPPORTED == cptr->status)
			continue;

		if (ERROR_SUCCESS != zbx_PdhGetRawCounterValue(__function_name, cptr->counterpath,
				cptr->handle, &cptr->rawValues[cptr->olderRawValue]))
		{
			deactivate_perf_counter(cptr);
			continue;
		}

		if (PERF_COUNTER_INITIALIZED < cptr->status)
		{
			zabbix_log(LOG_LEVEL_DEBUG, "%s() counterpath:'%s' old first:%I64d second:%I64d",
					__function_name, cptr->counterpath,
					cptr->rawValues[(cptr->olderRawValue + 1) & 1].FirstValue,
					cptr->rawValues[(cptr->olderRawValue + 1) & 1].SecondValue);

			zabbix_log(LOG_LEVEL_DEBUG, "%s() counterpath:'%s' new first:%I64d second:%I64d",
					__function_name, cptr->counterpath,
					cptr->rawValues[cptr->olderRawValue].FirstValue,
					cptr->rawValues[cptr->olderRawValue].SecondValue);
		}

		cptr->olderRawValue = (cptr->olderRawValue + 1) & 1;

		pdh_status = PdhCalculateCounterFromRawValue(cptr->handle, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100,
				&cptr->rawValues[(cptr->olderRawValue + 1) & 1],
				(PERF_COUNTER_INITIALIZED < cptr->status ? &cptr->rawValues[cptr->olderRawValue] : NULL),
				&value);

		if (ERROR_SUCCESS == pdh_status && PDH_CSTATUS_VALID_DATA != value.CStatus &&
				PDH_CSTATUS_NEW_DATA != value.CStatus)
		{
			pdh_status = value.CStatus;
		}

		if (PDH_CSTATUS_INVALID_DATA == pdh_status)
		{
			/* some (e.g., rate) counters require two raw values, MSDN lacks documentation */
			/* about what happens but tests show that PDH_CSTATUS_INVALID_DATA is returned */

			cptr->status = PERF_COUNTER_GET_SECOND_VALUE;
			continue;
		}

		if (PDH_CALC_NEGATIVE_DENOMINATOR == pdh_status)
		{
			/* This counter type shows the average percentage of active time observed during the sample   */
			/* interval. This is an inverse counter. Inverse counters are calculated by monitoring the    */
			/* percentage of time that the service was inactive and then subtracting that value from 100  */
			/* percent. The formula used to calculate the counter value is:                               */
			/* (1 - (inactive time delta) / (total time delta)) x 100                                     */
			/* For some unknown reason sometimes the collected row values indicate that inactive delta is */
			/* greater than total time delta. There must be some kind of bug in how performance counters  */
			/* work. When this happens function PdhCalculateCounterFromRawValue() returns error           */
			/* PDH_CALC_NEGATIVE_DENOMINATOR. Basically this means that an item was inactive all the time */
			/* so we set the return value to 0.0 and change status to indicate success.                   */
			/* More info: technet.microsoft.com/en-us/library/cc757283(WS.10).aspx                        */

			zabbix_log(LOG_LEVEL_DEBUG, "%s() counterpath:'%s'"
					" negative denominator error is treated as 0.0",
					__function_name, cptr->counterpath);

			pdh_status = ERROR_SUCCESS;
			value.doubleValue = 0.0;	/* 100% inactive */
		}

		if (ERROR_SUCCESS == pdh_status)
		{
			zabbix_log(LOG_LEVEL_DEBUG, "%s() '%s' calculated value:" ZBX_FS_DBL, __function_name,
					cptr->counterpath, value.doubleValue);

			cptr->status = PERF_COUNTER_ACTIVE;
			cptr->value_current = (cptr->value_current + 1) % cptr->interval;
			if (cptr->value_count == cptr->interval)
				cptr->sum -= cptr->value_array[cptr->value_current];	/* remove the oldest value, value_count will not increase */
			cptr->value_array[cptr->value_current] = value.doubleValue;
			cptr->sum += cptr->value_array[cptr->value_current];
			if (cptr->value_count < cptr->interval)
				cptr->value_count++;
		}
		else
		{
			zabbix_log(LOG_LEVEL_WARNING, "cannot calculate performance counter value \"%s\": %s",
					cptr->counterpath, strerror_from_module(pdh_status, L"PDH.DLL"));

			deactivate_perf_counter(cptr);
		}
	}
out:
	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
}
示例#3
0
/******************************************************************************
 *                                                                            *
 * Comments: if the specified counter exists or a new is successfully         *
 *           added, a pointer to that counter is returned, NULL otherwise     *
 *                                                                            *
 ******************************************************************************/
PERF_COUNTER_DATA	*add_perf_counter(const char *name, const char *counterpath, int interval)
{
	const char		*__function_name = "add_perf_counter";
	PERF_COUNTER_DATA	*cptr;
	char			*alias_name;
	PDH_STATUS		pdh_status;
	int			result = FAIL;

	assert(counterpath);

	zabbix_log(LOG_LEVEL_DEBUG, "In %s() counter:'%s' interval:%d", __function_name, counterpath, interval);

	if (SUCCEED != perf_collector_started())
	{
		zabbix_log(LOG_LEVEL_WARNING, "PerfCounter '%s' FAILED: collector is not started!", counterpath);
		return NULL;
	}

	if (1 > interval || 900 < interval)
	{
		zabbix_log(LOG_LEVEL_WARNING, "PerfCounter '%s' FAILED: interval value out of range", counterpath);
		return NULL;
	}

	for (cptr = ppsd.pPerfCounterList; ; cptr = cptr->next)
	{
		/* add new parameters */
		if (NULL == cptr)
		{
			cptr = (PERF_COUNTER_DATA *)zbx_malloc(cptr, sizeof(PERF_COUNTER_DATA));

			/* initialize the counter */
			memset(cptr, 0, sizeof(PERF_COUNTER_DATA));
			if (NULL != name)
				cptr->name = strdup(name);
			cptr->counterpath = strdup(counterpath);
			cptr->interval = interval;
			cptr->value_current = -1;
			cptr->value_array = (double *)zbx_malloc(cptr->value_array, sizeof(double) * interval);

			/* add the counter to the query */
			pdh_status = zbx_PdhAddCounter(__function_name, cptr, ppsd.pdh_query, counterpath, &cptr->handle);

			zbx_mutex_lock(&perfstat_access);
			cptr->next = ppsd.pPerfCounterList;
			ppsd.pPerfCounterList = cptr;
			zbx_mutex_unlock(&perfstat_access);

			if (ERROR_SUCCESS != pdh_status && PDH_CSTATUS_NO_INSTANCE != pdh_status)
			{
				zabbix_log(LOG_LEVEL_WARNING, "cannot add performance counter \"%s\": invalid format",
						counterpath);
				cptr = NULL;	/* indicate a failure */
			}

			result = SUCCEED;
			break;
		}

		if (NULL != name && 0 == strcmp(cptr->name, name))
			break;

		if (NULL == name && 0 == strcmp(cptr->counterpath, counterpath) && cptr->interval == interval)
			break;
	}

	if (FAIL == result)
	{
		zabbix_log(LOG_LEVEL_DEBUG, "%s() counter '%s' already exists", __function_name, counterpath);
	}
	else if (NULL != name)
	{
		alias_name = zbx_dsprintf(NULL, "__UserPerfCounter[%s]", name);
		add_alias(name, alias_name);
		zbx_free(alias_name);
	}

	return cptr;
}
示例#4
0
/******************************************************************************
 *                                                                            *
 * Comments: if the specified counter exists or a new is successfully         *
 *           added, a pointer to that counter is returned, NULL otherwise     *
 *                                                                            *
 ******************************************************************************/
PERF_COUNTER_DATA	*add_perf_counter(const char *name, const char *counterpath, int interval, char **error)
{
	const char		*__function_name = "add_perf_counter";
	PERF_COUNTER_DATA	*cptr = NULL;
	PDH_STATUS		pdh_status;
	int			added = FAIL;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s() counter:'%s' interval:%d", __function_name, counterpath, interval);

	LOCK_PERFCOUNTERS;

	if (SUCCEED != perf_collector_started())
	{
		*error = zbx_strdup(*error, "Performance collector is not started.");
		goto out;
	}

	for (cptr = ppsd.pPerfCounterList; ; cptr = cptr->next)
	{
		/* add new parameters */
		if (NULL == cptr)
		{
			cptr = (PERF_COUNTER_DATA *)zbx_malloc(cptr, sizeof(PERF_COUNTER_DATA));

			/* initialize the counter */
			memset(cptr, 0, sizeof(PERF_COUNTER_DATA));
			if (NULL != name)
				cptr->name = zbx_strdup(NULL, name);
			cptr->counterpath = zbx_strdup(NULL, counterpath);
			cptr->interval = interval;
			cptr->value_current = -1;
			cptr->value_array = (double *)zbx_malloc(cptr->value_array, sizeof(double) * interval);

			/* add the counter to the query */
			pdh_status = zbx_PdhAddCounter(__function_name, cptr, ppsd.pdh_query, counterpath,
					&cptr->handle);

			cptr->next = ppsd.pPerfCounterList;
			ppsd.pPerfCounterList = cptr;

			if (ERROR_SUCCESS != pdh_status && PDH_CSTATUS_NO_INSTANCE != pdh_status)
			{
				*error = zbx_dsprintf(*error, "Invalid performance counter format.");
				cptr = NULL;	/* indicate a failure */
			}

			added = SUCCEED;
			break;
		}

		if (NULL != name && 0 == strcmp(cptr->name, name))
			break;

		if (NULL == name && 0 == strcmp(cptr->counterpath, counterpath) && cptr->interval == interval)
			break;
	}

	if (FAIL == added)
	{
		zabbix_log(LOG_LEVEL_DEBUG, "%s() counter '%s' already exists", __function_name, counterpath);
	}
	else if (NULL != name)
	{
		char	*alias_name;

		alias_name = zbx_dsprintf(NULL, "__UserPerfCounter[%s]", name);
		add_alias(name, alias_name);
		zbx_free(alias_name);
	}
out:
	UNLOCK_PERFCOUNTERS;

	zabbix_log(LOG_LEVEL_DEBUG, "End of %s(): %s", __function_name, NULL == cptr ? "FAIL" : "SUCCEED");

	return cptr;
}