int check_counter_path(char *counterPath) { const char *__function_name = "check_counter_path"; PDH_COUNTER_PATH_ELEMENTS *cpe = NULL; PDH_STATUS status; int is_numeric, ret = FAIL; DWORD dwSize = 0; wchar_t *wcounterPath; wcounterPath = zbx_utf8_to_unicode(counterPath); status = PdhParseCounterPath(wcounterPath, NULL, &dwSize, 0); if (PDH_MORE_DATA == status || ERROR_SUCCESS == status) { cpe = (PDH_COUNTER_PATH_ELEMENTS *)zbx_malloc(cpe, dwSize); } else { zabbix_log(LOG_LEVEL_ERR, "cannot get required buffer size for counter path '%s': %s", counterPath, strerror_from_module(status, L"PDH.DLL")); goto clean; } if (ERROR_SUCCESS != (status = PdhParseCounterPath(wcounterPath, cpe, &dwSize, 0))) { zabbix_log(LOG_LEVEL_ERR, "cannot parse counter path '%s': %s", counterPath, strerror_from_module(status, L"PDH.DLL")); goto clean; } is_numeric = (SUCCEED == _wis_uint(cpe->szObjectName) ? 0x01 : 0); is_numeric |= (SUCCEED == _wis_uint(cpe->szCounterName) ? 0x02 : 0); if (0 != is_numeric) { if (0x01 & is_numeric) cpe->szObjectName = get_counter_name(_wtoi(cpe->szObjectName)); if (0x02 & is_numeric) cpe->szCounterName = get_counter_name(_wtoi(cpe->szCounterName)); if (ERROR_SUCCESS != zbx_PdhMakeCounterPath(__function_name, cpe, counterPath)) goto clean; zabbix_log(LOG_LEVEL_DEBUG, "counter path converted to '%s'", counterPath); } ret = SUCCEED; clean: zbx_free(cpe); zbx_free(wcounterPath); return ret; }
/// Default discoverer function for performance counters; to be registered /// with the counter types. It is suitable to be used for all counters /// following the naming scheme: /// /// /<objectname>{locality#<locality_id>/thread#<threadnum>}/<instancename> /// bool locality_thread_counter_discoverer(counter_info const& info, HPX_STD_FUNCTION<discover_counter_func> const& f, error_code& ec) { performance_counters::counter_info i = info; // compose the counter name templates performance_counters::counter_path_elements p; performance_counters::counter_status status = get_counter_path_elements(info.fullname_, p, ec); if (!status_is_valid(status)) return false; p.parentinstancename_ = "locality#<*>"; p.parentinstanceindex_ = -1; p.instancename_ = "total"; p.instanceindex_ = -1; status = get_counter_name(p, i.fullname_, ec); if (!status_is_valid(status) || !f(i, ec) || ec) return false; p.instancename_ = "worker-thread#<*>"; p.instanceindex_ = -1; status = get_counter_name(p, i.fullname_, ec); if (!status_is_valid(status) || !f(i, ec) || ec) return false; // boost::uint32_t last_locality = get_num_localities(); // std::size_t num_threads = get_os_thread_count(); // for (boost::uint32_t l = 0; l <= last_locality; ++l) // { // p.parentinstanceindex_ = static_cast<boost::int32_t>(l); // p.instancename_ = "total"; // p.instanceindex_ = -1; // status = get_counter_name(p, i.fullname_, ec); // if (!status_is_valid(status) || !f(i, ec) || ec) // return false; // // for (std::size_t t = 0; t < num_threads; ++t) // { // p.instancename_ = "worker-thread"; // p.instanceindex_ = static_cast<boost::int32_t>(t); // status = get_counter_name(p, i.fullname_, ec); // if (!status_is_valid(status) || !f(i, ec) || ec) // return false; // } // } if (&ec != &throws) ec = make_success_code(); return true; }
/// Default discoverer function for performance counters; to be registered /// with the counter types. It is suitable to be used for all counters /// following the naming scheme: /// /// /<objectname>(<objectinstance>/total)/<instancename> /// bool agas_counter_discoverer(counter_info const& info, HPX_STD_FUNCTION<discover_counter_func> const& f, error_code& ec) { performance_counters::counter_info i_ = info; // compose the counter names performance_counters::counter_path_elements p; performance_counters::counter_status status = get_counter_path_elements(info.fullname_, p, ec); if (!status_is_valid(status)) return false; p.parentinstancename_ = "agas"; p.parentinstanceindex_ = -1; p.instanceindex_ = -1; // list all counter related to agas for (std::size_t i = 0; i < sizeof(agas::detail::counter_services)/sizeof(agas::detail::counter_services[0]); ++i) { p.instancename_ = agas::detail::counter_services[i].name_; status = get_counter_name(p, i_.fullname_, ec); if (!status_is_valid(status) || !f(i_, ec) || ec) return false; } return true; }
bool expand_counter_info_localities( counter_info& i, counter_path_elements& p, discover_counter_func const& f, error_code& ec) { bool expand_threads = false; if (is_thread_kind(p.instancename_)) { p.instancename_ = get_thread_kind(p.instancename_) + "-thread"; expand_threads = true; } boost::uint32_t last_locality = get_num_localities_sync(); for (boost::uint32_t l = 0; l != last_locality; ++l) { p.parentinstanceindex_ = static_cast<boost::int32_t>(l); if (expand_threads) { if (!detail::expand_counter_info_threads(i, p, f, ec)) return false; } else { counter_status status = get_counter_name(p, i.fullname_, ec); if (!status_is_valid(status) || !f(i, ec) || ec) return false; } } return true; }
/// Default discoverer function for performance counters; to be registered /// with the counter types. It is suitable to be used for all counters /// following the naming scheme: /// /// /<objectname>{locality#<locality_id>/thread#<threadnum>}/<instancename> /// bool locality_thread_counter_discoverer(counter_info const& info, HPX_STD_FUNCTION<discover_counter_func> const& f, discover_counters_mode mode, error_code& ec) { performance_counters::counter_info i = info; // compose the counter name templates performance_counters::counter_path_elements p; performance_counters::counter_status status = get_counter_path_elements(info.fullname_, p, ec); if (!status_is_valid(status)) return false; if (mode == discover_counters_minimal || p.parentinstancename_.empty() || p.instancename_.empty()) { if (p.parentinstancename_.empty()) { p.parentinstancename_ = "locality#*"; p.parentinstanceindex_ = -1; } if (p.instancename_.empty()) { p.instancename_ = "total"; p.instanceindex_ = -1; } status = get_counter_name(p, i.fullname_, ec); if (!status_is_valid(status) || !f(i, ec) || ec) return false; p.instancename_ = "worker-thread#*"; p.instanceindex_ = -1; status = get_counter_name(p, i.fullname_, ec); if (!status_is_valid(status) || !f(i, ec) || ec) return false; } else if (!f(i, ec) || ec) { return false; } if (&ec != &throws) ec = make_success_code(); return true; }
/// Creation function for aggregating performance counters to be registered /// with the counter types. naming::gid_type statistics_counter_creator(counter_info const& info, error_code& ec) { switch (info.type_) { case counter_aggregating: { counter_path_elements paths; get_counter_path_elements(info.fullname_, paths, ec); if (ec) return naming::invalid_gid; if (!paths.parentinstance_is_basename_) { HPX_THROWS_IF(ec, bad_parameter, "statistics_counter_creator", "invalid aggregate counter " "name (instance name must be valid base counter name)"); return naming::invalid_gid; } std::string base_name; get_counter_name(paths.parentinstancename_, base_name, ec); if (ec) return naming::invalid_gid; std::vector<boost::int64_t> parameters; if (!paths.parameters_.empty()) { // try to interpret the additional parameter as interval // time (ms) namespace qi = boost::spirit::qi; if (!qi::parse(paths.parameters_.begin(), paths.parameters_.end(), qi::int_ % ',', parameters)) { HPX_THROWS_IF(ec, bad_parameter, "statistics_counter_creator", "invalid parameter specification for counter: " + paths.parameters_); return naming::invalid_gid; } } else { parameters.push_back(1000); // sample interval parameters.push_back(10); // rolling window } return create_statistics_counter(info, base_name, parameters, ec); } break; default: HPX_THROWS_IF(ec, bad_parameter, "statistics_counter_creator", "invalid counter type requested"); return naming::invalid_gid; } }
/////////////////////////////////////////////////////////////////////// // expand main counter name bool expand_counter_info_threads( counter_info& i, counter_path_elements& p, discover_counter_func const& f, error_code& ec) { std::size_t num_threads = get_os_thread_count(); for (std::size_t l = 0; l != num_threads; ++l) { p.instanceindex_ = static_cast<boost::int64_t>(l); counter_status status = get_counter_name(p, i.fullname_, ec); if (!status_is_valid(status) || !f(i, ec) || ec) return false; } return true; }
/////////////////////////////////////////////////////////////////////// /// Expand all wild-cards in a counter base name (for aggregate counters) bool expand_basecounter( counter_info const& info, counter_path_elements& p, discover_counter_func const& f, error_code& ec) { // discover all base names std::vector<counter_info> counter_infos; counter_status status = discover_counter_type(p.parentinstancename_, counter_infos, discover_counters_full, ec); if (!status_is_valid(status) || ec) return false; counter_info i = info; for (counter_info& basei : counter_infos) { p.parentinstancename_ = basei.fullname_; counter_status status = get_counter_name(p, i.fullname_, ec); if (!status_is_valid(status) || !f(i, ec) || ec) return false; } return true; }
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; }
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; }