/* ** Copyright (C) 2001-2025 Zabbix SIA ** ** This program is free software: you can redistribute it and/or modify it under the terms of ** the GNU Affero General Public License as published by the Free Software Foundation, version 3. ** ** This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ** without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** See the GNU Affero General Public License for more details. ** ** You should have received a copy of the GNU Affero General Public License along with this program. ** If not, see <https://www.gnu.org/licenses/>. **/ #include "zbxsysinfo.h" #include "../sysinfo.h" #include "zbxstr.h" #include "zbxthreads.h" #include "zbxjson.h" #include "zbxalgo.h" #include "perfstat/perfstat.h" int user_perf_counter(AGENT_REQUEST *request, AGENT_RESULT *result) { int ret = SYSINFO_RET_FAIL; char *counter, *error = NULL; double value; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); if (1 != request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters.")); goto out; } if (NULL == (counter = get_rparam(request, 0)) || '\0' == *counter) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter.")); goto out; } if (SUCCEED != get_perf_counter_value_by_name(counter, &value, &error)) { SET_MSG_RESULT(result, error != NULL ? error : zbx_strdup(NULL, "Cannot obtain performance information from collector.")); goto out; } SET_DBL_RESULT(result, value); ret = SYSINFO_RET_OK; out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); return ret; } static int perf_counter_ex(const char *function, AGENT_REQUEST *request, AGENT_RESULT *result, zbx_perf_counter_lang_t lang) { char counterpath[PDH_MAX_COUNTER_PATH], *tmp, *error = NULL; int interval, ret = SYSINFO_RET_FAIL; double value; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", function); if (2 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); goto out; } tmp = get_rparam(request, 0); if (NULL == tmp || '\0' == *tmp) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter.")); goto out; } zbx_strscpy(counterpath, tmp); if (NULL == (tmp = get_rparam(request, 1)) || '\0' == *tmp) { interval = 1; } else if (FAIL == zbx_is_uint31(tmp, &interval)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter.")); goto out; } if (1 > interval || ZBX_MAX_COLLECTOR_PERIOD < interval) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Interval out of range.")); goto out; } if (FAIL == zbx_check_counter_path(counterpath, PERF_COUNTER_LANG_DEFAULT == lang)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid performance counter path.")); goto out; } if (SUCCEED != get_perf_counter_value_by_path(counterpath, interval, lang, &value, &error)) { SET_MSG_RESULT(result, error != NULL ? error : zbx_strdup(NULL, "Cannot obtain performance information from collector.")); goto out; } ret = SYSINFO_RET_OK; SET_DBL_RESULT(result, value); out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", function, zbx_result_string(ret)); return ret; } int perf_counter(AGENT_REQUEST *request, AGENT_RESULT *result) { return perf_counter_ex(__func__, request, result, PERF_COUNTER_LANG_DEFAULT); } int perf_counter_en(AGENT_REQUEST *request, AGENT_RESULT *result) { return perf_counter_ex(__func__, request, result, PERF_COUNTER_LANG_EN); } int perf_instance_discovery_ex(const char *function, AGENT_REQUEST *request, AGENT_RESULT *result, zbx_perf_counter_lang_t lang) { char *tmp; wchar_t *object_name = NULL; DWORD cnt_len = 0, inst_len = 0; struct zbx_json j; PDH_STATUS status; int ret = SYSINFO_RET_FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", function); if (1 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); goto err; } tmp = get_rparam(request, 0); if (NULL == tmp || '\0' == *tmp) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter.")); goto err; } if (PERF_COUNTER_LANG_EN == lang) { if (NULL == (object_name = get_object_name_local(tmp))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain object's localized name.")); goto err; } } else object_name = zbx_utf8_to_unicode(tmp); if (SUCCEED != refresh_object_cache()) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot refresh object cache.")); goto err; } if (PDH_CSTATUS_NO_OBJECT == (status = PdhEnumObjectItems(NULL, NULL, object_name, NULL, &cnt_len, NULL, &inst_len, PERF_DETAIL_WIZARD, 0))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot find object.")); goto err; } else if (PDH_MORE_DATA != status) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain required buffer size.")); goto err; } if (0 == inst_len) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Object does not support variable instances.")); goto err; } zbx_json_initarray(&j, ZBX_JSON_STAT_BUF_LEN); if (2 < inst_len) { wchar_t *cnt_list, *inst_list, *instance; zbx_vector_str_t instances, instances_uniq; cnt_list = zbx_malloc(NULL, sizeof(wchar_t) * cnt_len); inst_list = zbx_malloc(NULL, sizeof(wchar_t) * inst_len); if (ERROR_SUCCESS != PdhEnumObjectItems(NULL, NULL, object_name, cnt_list, &cnt_len, inst_list, &inst_len, PERF_DETAIL_WIZARD, 0)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot obtain object instances.")); zbx_json_free(&j); zbx_free(cnt_list); zbx_free(inst_list); goto err; } zbx_vector_str_create(&instances); for (instance = inst_list; L'\0' != *instance; instance += wcslen(instance) + 1) zbx_vector_str_append(&instances, zbx_unicode_to_utf8(instance)); zbx_vector_str_create(&instances_uniq); zbx_vector_str_append_array(&instances_uniq, instances.values, instances.values_num); zbx_vector_str_sort(&instances_uniq, ZBX_DEFAULT_STR_COMPARE_FUNC); zbx_vector_str_uniq(&instances_uniq, ZBX_DEFAULT_STR_COMPARE_FUNC); for (int i = 0; i < instances_uniq.values_num; i++) { zbx_json_addobject(&j, NULL); zbx_json_addstring(&j, "{#INSTANCE}", instances_uniq.values[i], ZBX_JSON_TYPE_STRING); zbx_json_close(&j); } zbx_vector_str_clear_ext(&instances, zbx_str_free); zbx_vector_str_destroy(&instances); zbx_vector_str_destroy(&instances_uniq); zbx_free(cnt_list); zbx_free(inst_list); } zbx_json_close(&j); SET_STR_RESULT(result, zbx_strdup(NULL, j.buffer)); zbx_json_free(&j); ret = SYSINFO_RET_OK; err: zbx_free(object_name); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", function); return ret; } int perf_instance_discovery(AGENT_REQUEST *request, AGENT_RESULT *result) { return perf_instance_discovery_ex(__func__, request, result, PERF_COUNTER_LANG_DEFAULT); } int perf_instance_discovery_en(AGENT_REQUEST *request, AGENT_RESULT *result) { return perf_instance_discovery_ex(__func__, request, result, PERF_COUNTER_LANG_EN); }