/****************************************************************************** * * * Function: get_perf_counter_value_by_path * * * * Purpose: gets average performance counter value * * * * Parameters: counterpath - [IN] the performance counter path * * interval - [IN] the data collection interval in seconds * * value - [OUT] the calculated value * * error - [OUT] the error message * * * * Returns: SUCCEED - the value was retrieved successfully * * FAIL - otherwise * * * * Comments: The value is retrieved from collector (if it has been requested * * before) or directly from Windows performance counters if * * possible. * * * ******************************************************************************/ int get_perf_counter_value_by_path(const char *counterpath, int interval, double *value, char **error) { const char *__function_name = "get_perf_counter_value_by_path"; int ret = FAIL; PERF_COUNTER_DATA *perfs = NULL; zabbix_log(LOG_LEVEL_DEBUG, "In %s() path:%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 (perfs = ppsd.pPerfCounterList; NULL != perfs; perfs = perfs->next) { if (0 == strcmp(perfs->counterpath, counterpath)) { if (perfs->interval < interval) extend_perf_counter_interval(perfs, interval); if (PERF_COUNTER_ACTIVE != perfs->status) break; /* the counter data is already being collected, return it */ *value = compute_average_value(perfs, interval); ret = SUCCEED; goto out; } } /* if the requested counter is not already being monitored - start monitoring */ if (NULL == perfs) perfs = add_perf_counter(NULL, counterpath, interval, error); out: UNLOCK_PERFCOUNTERS; if (SUCCEED != ret && NULL != perfs) { /* request counter value directly from Windows performance counters */ if (ERROR_SUCCESS == calculate_counter_value(__function_name, counterpath, value)) ret = SUCCEED; } zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
/****************************************************************************** * * * Function: load_perf_counters * * * * Purpose: load performance counters from configuration * * * * Parameters: lines - array of PerfCounter configuration entries * * * * Return value: * * * * Author: Vladimir Levijev * * * * Comments: * * * ******************************************************************************/ void load_perf_counters(const char **lines) { char name[MAX_STRING_LEN], counterpath[PDH_MAX_COUNTER_PATH], interval[8]; const char **pline, *msg; LPTSTR wcounterPath; #define ZBX_PC_FAIL(_msg) {msg = _msg; goto pc_fail;} for (pline = lines; NULL != *pline; pline++) { if (3 < num_param(*pline)) ZBX_PC_FAIL("required parameter missing"); if (0 != get_param(*pline, 1, name, sizeof(name))) ZBX_PC_FAIL("cannot parse key"); if (0 != get_param(*pline, 2, counterpath, sizeof(counterpath))) ZBX_PC_FAIL("cannot parse counter path"); if (0 != get_param(*pline, 3, interval, sizeof(interval))) ZBX_PC_FAIL("cannot parse interval"); wcounterPath = zbx_acp_to_unicode(counterpath); zbx_unicode_to_utf8_static(wcounterPath, counterpath, PDH_MAX_COUNTER_PATH); zbx_free(wcounterPath); if (FAIL == check_counter_path(counterpath)) ZBX_PC_FAIL("invalid counter path"); if (NULL == add_perf_counter(name, counterpath, atoi(interval))) ZBX_PC_FAIL("cannot add counter"); continue; pc_fail: zabbix_log(LOG_LEVEL_CRIT, "PerfCounter '%s' FAILED: %s", *pline, msg); exit(FAIL); } #undef ZBX_PC_FAIL }
int PERF_COUNTER(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result) { const char *__function_name = "PERF_COUNTER"; char counterpath[PDH_MAX_COUNTER_PATH], tmp[MAX_STRING_LEN]; int ret = SYSINFO_RET_FAIL, interval; double value; PERF_COUNTER_DATA *perfs = NULL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (2 < num_param(param)) goto clean; if (0 != get_param(param, 1, counterpath, sizeof(counterpath)) || '\0' == *counterpath) goto clean; if (0 != get_param(param, 2, tmp, sizeof(tmp)) || '\0' == *tmp) interval = 1; else if (FAIL == is_uint(tmp)) goto clean; else interval = atoi(tmp); if (FAIL == check_counter_path(counterpath)) goto clean; if (1 < interval) { if (!PERF_COLLECTOR_STARTED(collector)) { zabbix_log(LOG_LEVEL_DEBUG, "Collector is not started!"); goto clean; } for (perfs = collector->perfs.pPerfCounterList; NULL != perfs; perfs = perfs->next) { if (0 == strcmp(perfs->counterpath, counterpath) && perfs->interval == interval) { if (PERF_COUNTER_ACTIVE != perfs->status) break; SET_DBL_RESULT(result, compute_average_value(__function_name, perfs, USE_DEFAULT_INTERVAL)); ret = SYSINFO_RET_OK; goto clean; } } if (NULL == perfs && NULL == (perfs = add_perf_counter(NULL, counterpath, interval))) goto clean; } if (ERROR_SUCCESS == calculate_counter_value(__function_name, counterpath, &value)) { if (NULL != perfs) perfs->status = PERF_COUNTER_INITIALIZED; SET_DBL_RESULT(result, value); ret = SYSINFO_RET_OK; } clean: zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); return ret; }
int init_cpu_collector(ZBX_CPUS_STAT_DATA *pcpus) { const char *__function_name = "init_cpu_collector"; int cpu_num, ret = FAIL; #ifdef _WINDOWS TCHAR cpu[8]; char counterPath[PDH_MAX_COUNTER_PATH]; PDH_COUNTER_PATH_ELEMENTS cpe; #else #ifdef HAVE_KSTAT_H kstat_ctl_t *kc; kstat_t *k, *kd; #endif #endif zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); #ifdef _WINDOWS cpe.szMachineName = NULL; cpe.szObjectName = get_counter_name(PCI_PROCESSOR); cpe.szInstanceName = cpu; cpe.szParentInstance = NULL; cpe.dwInstanceIndex = -1; cpe.szCounterName = get_counter_name(PCI_PROCESSOR_TIME); for (cpu_num = 0; cpu_num <= pcpus->count; cpu_num++) { if (0 == cpu_num) zbx_wsnprintf(cpu, sizeof(cpu) / sizeof(TCHAR), TEXT("_Total")); else _itow_s(cpu_num - 1, cpu, sizeof(cpu) / sizeof(TCHAR), 10); if (ERROR_SUCCESS != zbx_PdhMakeCounterPath(__function_name, &cpe, counterPath)) goto clean; if (NULL == (pcpus->cpu_counter[cpu_num] = add_perf_counter(NULL, counterPath, MAX_CPU_HISTORY))) goto clean; } cpe.szObjectName = get_counter_name(PCI_SYSTEM); cpe.szInstanceName = NULL; cpe.szCounterName = get_counter_name(PCI_PROCESSOR_QUEUE_LENGTH); if (ERROR_SUCCESS != zbx_PdhMakeCounterPath(__function_name, &cpe, counterPath)) goto clean; if (NULL == (pcpus->queue_counter = add_perf_counter(NULL, counterPath, MAX_CPU_HISTORY))) goto clean; ret = SUCCEED; clean: #else /* not _WINDOWS */ if (ZBX_MUTEX_ERROR == zbx_mutex_create_force(&cpustats_lock, ZBX_MUTEX_CPUSTATS)) { zbx_error("unable to create mutex for cpu collector"); exit(FAIL); } for (cpu_num = 0; cpu_num <= pcpus->count; cpu_num++) pcpus->cpu[cpu_num].cpu_num = cpu_num; #ifdef HAVE_KSTAT_H /* Solaris */ if (NULL != (kc = kstat_open())) { if (NULL != (k = kstat_lookup(kc, "unix", 0, "kstat_headers")) && -1 != kstat_read(kc, k, NULL)) { int i; for (i = 0, cpu_num = 1; i < k->ks_ndata; i++) { kd = (kstat_t *)k->ks_data; if (0 == strcmp(kd[i].ks_module, "cpu_info")) pcpus->cpu[cpu_num++].cpu_num = kd[i].ks_instance + 1; } } kstat_close(kc); } #endif /* HAVE_KSTAT_H */ ret = SUCCEED; #endif /* _WINDOWS */ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
/****************************************************************************** * * * Function: load_perf_counters * * * * Purpose: load performance counters from configuration * * * * Parameters: lines - array of PerfCounter configuration entries * * * * Return value: * * * * Author: Vladimir Levijev * * * * Comments: * * * ******************************************************************************/ void load_perf_counters(const char **lines) { char name[MAX_STRING_LEN], counterpath[PDH_MAX_COUNTER_PATH], interval[8]; const char **pline; char *error = NULL; LPTSTR wcounterPath; int period; for (pline = lines; NULL != *pline; pline++) { if (3 < num_param(*pline)) { error = zbx_strdup(error, "Required parameter missing."); goto pc_fail; } if (0 != get_param(*pline, 1, name, sizeof(name))) { error = zbx_strdup(error, "Cannot parse key."); goto pc_fail; } if (0 != get_param(*pline, 2, counterpath, sizeof(counterpath))) { error = zbx_strdup(error, "Cannot parse counter path."); goto pc_fail; } if (0 != get_param(*pline, 3, interval, sizeof(interval))) { error = zbx_strdup(error, "Cannot parse interval."); goto pc_fail; } wcounterPath = zbx_acp_to_unicode(counterpath); zbx_unicode_to_utf8_static(wcounterPath, counterpath, PDH_MAX_COUNTER_PATH); zbx_free(wcounterPath); if (FAIL == check_counter_path(counterpath)) { error = zbx_strdup(error, "Invalid counter path."); goto pc_fail; } period = atoi(interval); if (1 > period || MAX_COLLECTOR_PERIOD < period) { error = zbx_strdup(NULL, "Interval out of range."); goto pc_fail; } if (NULL == add_perf_counter(name, counterpath, period, &error)) { if (NULL == error) error = zbx_strdup(error, "Failed to add new performance counter."); goto pc_fail; } continue; pc_fail: zabbix_log(LOG_LEVEL_CRIT, "cannot add performance counter \"%s\": %s", *pline, error); zbx_free(error); exit(EXIT_FAILURE); } }
int init_cpu_collector(ZBX_CPUS_STAT_DATA *pcpus) { const char *__function_name = "init_cpu_collector"; int cpu_num, ret = FAIL; #ifdef _WINDOWS TCHAR cpu[8]; char counterPath[PDH_MAX_COUNTER_PATH]; PDH_COUNTER_PATH_ELEMENTS cpe; #endif zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); #ifdef _WINDOWS cpe.szMachineName = NULL; cpe.szObjectName = get_counter_name(PCI_PROCESSOR); cpe.szInstanceName = cpu; cpe.szParentInstance = NULL; cpe.dwInstanceIndex = -1; cpe.szCounterName = get_counter_name(PCI_PROCESSOR_TIME); for (cpu_num = 0; cpu_num <= pcpus->count; cpu_num++) { if (0 == cpu_num) zbx_wsnprintf(cpu, sizeof(cpu) / sizeof(TCHAR), TEXT("_Total")); else _itow_s(cpu_num - 1, cpu, sizeof(cpu) / sizeof(TCHAR), 10); if (ERROR_SUCCESS != zbx_PdhMakeCounterPath(__function_name, &cpe, counterPath)) goto clean; if (NULL == (pcpus->cpu_counter[cpu_num] = add_perf_counter(NULL, counterPath, MAX_CPU_HISTORY))) goto clean; } cpe.szObjectName = get_counter_name(PCI_SYSTEM); cpe.szInstanceName = NULL; cpe.szCounterName = get_counter_name(PCI_PROCESSOR_QUEUE_LENGTH); if (ERROR_SUCCESS != zbx_PdhMakeCounterPath(__function_name, &cpe, counterPath)) goto clean; if (NULL == (pcpus->queue_counter = add_perf_counter(NULL, counterPath, MAX_CPU_HISTORY))) goto clean; ret = SUCCEED; clean: #else /* not _WINDOWS */ if (ZBX_MUTEX_ERROR == zbx_mutex_create_force(&cpustats_lock, ZBX_MUTEX_CPUSTATS)) { zbx_error("unable to create mutex for cpu collector"); exit(EXIT_FAILURE); } #ifndef HAVE_KSTAT_H for (cpu_num = 0; cpu_num <= pcpus->count; cpu_num++) pcpus->cpu[cpu_num].cpu_num = cpu_num; #else /* Solaris */ /* CPU instance numbers on Solaris can be non-contiguous, we don't know them yet */ pcpus->cpu[0].cpu_num = 0; for (cpu_num = 1; cpu_num <= pcpus->count; cpu_num++) pcpus->cpu[cpu_num].cpu_num = -1; if (NULL == (kc = kstat_open())) { zbx_error("kstat_open() failed"); exit(EXIT_FAILURE); } kc_id = kc->kc_chain_id; if (NULL == ksp) ksp = zbx_malloc(ksp, sizeof(kstat_t *) * pcpus->count); if (SUCCEED != refresh_kstat(pcpus)) { zbx_error("kstat_chain_update() failed"); exit(EXIT_FAILURE); } #endif /* HAVE_KSTAT_H */ ret = SUCCEED; #endif /* _WINDOWS */ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }