/* ** Zabbix ** Copyright (C) 2001-2023 Zabbix SIA ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** 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 General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. **/ #include "pp_execute.h" #include "pp_cache.h" #include "pp_error.h" #include "log.h" #include "item_preproc.h" #include "zbxprometheus.h" #include "zbxxml.h" #include "preproc_snmp.h" #ifdef HAVE_LIBXML2 # ifndef LIBXML_THREAD_ENABLED # error Zabbix requires libxml2 library built with thread support. # endif #endif /****************************************************************************** * * * Purpose: execute 'multiply by' step * * * * Parameters: value_type - [IN] the item value type * * value - [IN/OUT] the input/output value * * params - [IN] the preprocessing parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_execute_multiply(unsigned char value_type, zbx_variant_t *value, const char *params) { char buffer[MAX_STRING_LEN], *error = NULL, *errmsg = NULL; zbx_strlcpy(buffer, params, sizeof(buffer)); zbx_trim_float(buffer); if (FAIL == zbx_is_double(buffer, NULL)) { error = zbx_dsprintf(NULL, "a numerical value is expected or the value is out of range"); } else if (SUCCEED == item_preproc_multiplier_variant(value_type, value, buffer, &errmsg)) { return SUCCEED; } else { error = zbx_dsprintf(NULL, "cannot apply multiplier \"%s\" to value of type \"%s\": %s", params, zbx_variant_type_desc(value), errmsg); zbx_free(errmsg); } zbx_variant_clear(value); zbx_variant_set_error(value, error); return FAIL; } /****************************************************************************** * * * Purpose: return preprocessing 'trim' step descriptions for error messages * * * ******************************************************************************/ static const char *pp_trim_desc(int type) { switch (type) { case ZBX_PREPROC_RTRIM: return "right "; case ZBX_PREPROC_LTRIM: return "left "; default: return ""; } } /****************************************************************************** * * * Purpose: execute 'trim ?' step * * * * Parameters: type - [IN] the preprocessing step type - (left|right)trim * * value - [IN/OUT] the input/output value * * params - [IN] the preprocessing parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_execute_trim(int type, zbx_variant_t *value, const char *params) { char *errmsg = NULL, *characters; if (SUCCEED == item_preproc_trim(value, type, params, &errmsg)) return SUCCEED; characters = zbx_str_printable_dyn(params); zbx_variant_clear(value); zbx_variant_set_error(value, zbx_dsprintf(NULL, "cannot perform %strim of \"%s\" for value of type" " \"%s\": %s", pp_trim_desc(type), characters, zbx_variant_type_desc(value), errmsg)); zbx_free(characters); zbx_free(errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute 'check for unsupported' step * * * * Parameters: value - [IN] the input * * * * Result value: SUCCEED - the input value does not have an error * * FAIL - otherwise. * * * ******************************************************************************/ static int pp_check_not_error(const zbx_variant_t *value) { if (ZBX_VARIANT_ERR == value->type) return FAIL; return SUCCEED; } /****************************************************************************** * * * Purpose: return preprocessing 'delta' step descriptions for error messages * * * ******************************************************************************/ static const char *pp_delta_desc(int type) { switch (type) { case ZBX_PREPROC_DELTA_VALUE: return "simple change"; case ZBX_PREPROC_DELTA_SPEED: return "speed per second"; default: return ""; } } /****************************************************************************** * * * Purpose: execute 'delta ?' step * * * * Parameters: type - [IN] the preprocessing step type - * * (change|speed) * * value_type - [IN] the item value type * * value - [IN/OUT] the input/output value * * ts - [IN] the value timestamp * * history_value - [IN/OUT] the last value * * history_ts - [IN/OUT] the last value timestamp * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_execute_delta(int type, unsigned char value_type, zbx_variant_t *value, zbx_timespec_t ts, zbx_variant_t *history_value, zbx_timespec_t *history_ts) { char *errmsg = NULL; if (SUCCEED == item_preproc_delta(value_type, value, &ts, type, history_value, history_ts, &errmsg)) return SUCCEED; zbx_variant_clear(value); zbx_variant_set_error(value, zbx_dsprintf(NULL, "cannot calculate delta (%s) for value of type" " \"%s\": %s", pp_delta_desc(type), zbx_variant_type_desc(value), errmsg)); zbx_free(errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute 'regsub' step * * * * Parameters: value - [IN/OUT] the input/output value * * params - [IN] the preprocessing parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_execute_regsub(zbx_variant_t *value, const char *params) { char *errmsg = NULL, *ptr; int len; if (SUCCEED == item_preproc_regsub_op(value, params, &errmsg)) return SUCCEED; if (NULL == (ptr = strchr(params, '\n'))) len = (int)strlen(params); else len = (int)(ptr - params); zbx_variant_clear(value); zbx_variant_set_error(value, zbx_dsprintf(NULL, "cannot perform regular expression \"%.*s\"" " match for value of type \"%s\": %s", len, params, zbx_variant_type_desc(value), errmsg)); zbx_free(errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute jsonpath query * * * * Parameters: cache - [IN] the preprocessing cache * * value - [IN/OUT] the value to process * * params - [IN] the step parameters * * errmsg - [OUT] error message * * * * Result value: SUCCEED - the query was executed successfully. * * FAIL - otherwise. * * * ******************************************************************************/ static int pp_excute_jsonpath_query(zbx_pp_cache_t *cache, zbx_variant_t *value, const char *params, char **errmsg) { char *data = NULL; if (NULL == cache || ZBX_PREPROC_JSONPATH != cache->type) { zbx_jsonobj_t obj; if (FAIL == item_preproc_convert_value(value, ZBX_VARIANT_STR, errmsg)) return FAIL; if (FAIL == zbx_jsonobj_open(value->data.str, &obj)) { *errmsg = zbx_strdup(*errmsg, zbx_json_strerror()); return FAIL; } if (FAIL == zbx_jsonobj_query(&obj, params, &data)) { zbx_jsonobj_clear(&obj); *errmsg = zbx_strdup(*errmsg, zbx_json_strerror()); return FAIL; } zbx_jsonobj_clear(&obj); } else { zbx_jsonobj_t *obj; if (NULL == (obj = (zbx_jsonobj_t *)cache->data)) { if (FAIL == item_preproc_convert_value(value, ZBX_VARIANT_STR, errmsg)) return FAIL; obj = (zbx_jsonobj_t *)zbx_malloc(NULL, sizeof(zbx_jsonobj_t)); if (SUCCEED != zbx_jsonobj_open(value->data.str, obj)) { *errmsg = zbx_strdup(*errmsg, zbx_json_strerror()); zbx_free(obj); cache->type = ZBX_PREPROC_NONE; return FAIL; } cache->data = (void *)obj; } if (FAIL == zbx_jsonobj_query(obj, params, &data)) { *errmsg = zbx_strdup(*errmsg, zbx_json_strerror()); return FAIL; } zbx_jsonobj_disable_indexing(obj); } if (NULL == data) { *errmsg = zbx_strdup(*errmsg, "no data matches the specified path"); return FAIL; } zbx_variant_clear(value); zbx_variant_set_str(value, data); return SUCCEED; } /****************************************************************************** * * * Purpose: execute 'jsonpath' step * * * * Parameters: cache - [IN] the preprocessing cache * * value - [IN/OUT] the value to process * * params - [IN] the step parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_execute_jsonpath(zbx_pp_cache_t *cache, zbx_variant_t *value, const char *params) { char *errmsg = NULL; if (SUCCEED == pp_excute_jsonpath_query(cache, value, params, &errmsg)) return SUCCEED; zbx_variant_clear(value); zbx_variant_set_error(value, zbx_dsprintf(NULL, "cannot extract value from json by path \"%s\": %s", params, errmsg)); zbx_free(errmsg); return FAIL; } /****************************************************************************** * * * Purpose: return 'to dec' step descriptions for error messages * * * ******************************************************************************/ static const char *pp_2dec_desc(int type) { switch (type) { case ZBX_PREPROC_BOOL2DEC: return "boolean"; case ZBX_PREPROC_OCT2DEC: return "octal"; case ZBX_PREPROC_HEX2DEC: return "hexadecimal"; default: return ""; } } /****************************************************************************** * * * Purpose: execute '?2dec' step * * * * Parameters: type - [IN] the preprocessing step type - * * (boolean|octal|hexadecimal)2dec * * value - [IN/OUT] the input/output value * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_execute_2dec(int type, zbx_variant_t *value) { char *errmsg = NULL, *value_desc; if (SUCCEED == item_preproc_2dec(value, type, &errmsg)) return SUCCEED; value_desc = zbx_strdup(NULL, zbx_variant_value_desc(value)); zbx_variant_clear(value); zbx_variant_set_error(value, zbx_dsprintf(NULL, "cannot convert value \"%s\" from %s to decimal format: %s", value_desc, pp_2dec_desc(type), errmsg)); zbx_free(value_desc); zbx_free(errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute xpath query * * * * Parameters: value - [IN/OUT] the value to process * * params - [IN] the step parameters * * error - [OUT] the error message * * * * Result value: SUCCEED - the query was executed successfully. * * FAIL - otherwise. * * * ******************************************************************************/ static int pp_execute_xpath_query(zbx_variant_t *value, const char *params, char **error) { char *errmsg = NULL; if (FAIL == item_preproc_convert_value(value, ZBX_VARIANT_STR, error)) return FAIL; if (SUCCEED == zbx_query_xpath(value, params, &errmsg)) return SUCCEED; *error = zbx_dsprintf(NULL, "cannot extract XML value with xpath \"%s\": %s", params, errmsg); zbx_free(errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute 'xpath' step * * * * Parameters: value - [IN/OUT] the value to process * * params - [IN] the step parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_execute_xpath(zbx_variant_t *value, const char *params) { char *errmsg = NULL; if (SUCCEED == pp_execute_xpath_query(value, params, &errmsg)) return SUCCEED; zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute 'validate range' step * * * * Parameters: value_type - [IN] the item value type * * value - [IN/OUT] the value to process * * params - [IN] the step parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_validate_range(unsigned char value_type, zbx_variant_t *value, const char *params) { char *errmsg = NULL; if (SUCCEED == item_preproc_validate_range(value_type, value, params, &errmsg)) return SUCCEED; zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute 'validate regex' step * * * * Parameters: value - [IN/OUT] the value to process * * params - [IN] the step parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_validate_regex(zbx_variant_t *value, const char *params) { char *errmsg = NULL; if (SUCCEED == item_preproc_validate_regex(value, params, &errmsg)) return SUCCEED; zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute 'validate not regex' step * * * * Parameters: value - [IN/OUT] the value to process * * params - [IN] the step parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_validate_not_regex(zbx_variant_t *value, const char *params) { char *errmsg = NULL; if (SUCCEED == item_preproc_validate_not_regex(value, params, &errmsg)) return SUCCEED; zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute 'error from json' step * * * * Parameters: value - [IN/OUT] the value to process * * params - [IN] the step parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_error_from_json(zbx_variant_t *value, const char *params) { char *errmsg = NULL; int ret; ret = item_preproc_get_error_from_json(value, params, &errmsg); if (NULL != errmsg) { zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); ret = FAIL; } return ret; } /****************************************************************************** * * * Purpose: execute 'error from xml' step * * * * Parameters: value - [IN/OUT] the value to process * * params - [IN] the step parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_error_from_xml(zbx_variant_t *value, const char *params) { char *errmsg = NULL; int ret; ret = item_preproc_get_error_from_xml(value, params, &errmsg); if (NULL != errmsg) { zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); ret = FAIL; } return ret; } /****************************************************************************** * * * Purpose: execute 'error from regex' step * * * * Parameters: value - [IN/OUT] the value to process * * params - [IN] the step parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_error_from_regex(zbx_variant_t *value, const char *params) { char *errmsg = NULL; int ret; ret = item_preproc_get_error_from_regex(value, params, &errmsg); if (NULL != errmsg) { zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); ret = FAIL; } return ret; } /****************************************************************************** * * * Purpose: execute 'throttle timed value' step * * * * Parameters: value - [IN/OUT] the input/output value * * ts - [IN] the value timestamp * * params - [IN] the step parameters * * history_value - [IN/OUT] the last value * * history_ts - [IN/OUT] the last value timestamp * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_throttle_timed_value(zbx_variant_t *value, zbx_timespec_t ts, const char *params, zbx_variant_t *history_value, zbx_timespec_t *history_ts) { char *errmsg = NULL; if (SUCCEED == item_preproc_throttle_timed_value(value, &ts, params, history_value, history_ts, &errmsg)) return SUCCEED; zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute 'script' step * * * * Parameters: value - [IN/OUT] the input/output value * * params - [IN] the step parameters * * history_value - [IN/OUT] the script bytecode * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_execute_script(zbx_pp_context_t *ctx, zbx_variant_t *value, const char *params, zbx_variant_t *history_value) { char *errmsg = NULL; if (SUCCEED == item_preproc_script(pp_context_es_engine(ctx), value, params, history_value, &errmsg)) return SUCCEED; zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute prometheus pattern query * * * * Parameters: cache - [IN] the preprocessing cache * * value - [IN/OUT] the value to process * * params - [IN] the step parameters * * errmsg - [OUT] error message * * * * Return value: SUCCEED - the query was performed successfully * * FAIL - otherwise * * * ******************************************************************************/ static int pp_execute_prometheus_query(zbx_pp_cache_t *cache, zbx_variant_t *value, const char *params, char **errmsg) { char *pattern, *request, *output, *value_out = NULL, *err = NULL; int ret = FAIL; pattern = zbx_strdup(NULL, params); if (NULL == (request = strchr(pattern, '\n'))) { *errmsg = zbx_strdup(*errmsg, "cannot find second parameter"); goto out; } *request++ = '\0'; if (NULL == (output = strchr(request, '\n'))) { *errmsg = zbx_strdup(*errmsg, "cannot find third parameter"); goto out; } *output++ = '\0'; if (NULL == cache || ZBX_PREPROC_PROMETHEUS_PATTERN != cache->type) { if (FAIL == item_preproc_convert_value(value, ZBX_VARIANT_STR, errmsg)) goto out; ret = zbx_prometheus_pattern(value->data.str, pattern, request, output, &value_out, &err); } else { zbx_prometheus_t *prom_cache; if (NULL == (prom_cache = (zbx_prometheus_t *)cache->data)) { if (FAIL == item_preproc_convert_value(value, ZBX_VARIANT_STR, errmsg)) goto out; prom_cache = (zbx_prometheus_t *)zbx_malloc(NULL, sizeof(zbx_prometheus_t)); if (SUCCEED != zbx_prometheus_init(prom_cache, value->data.str, &err)) { zbx_free(prom_cache); cache->type = ZBX_PREPROC_NONE; goto out; } cache->data = (void *)prom_cache; } ret = zbx_prometheus_pattern_ex(prom_cache, pattern, request, output, &value_out, &err); } out: zbx_free(pattern); if (FAIL == ret) { if (NULL == *errmsg) *errmsg = zbx_dsprintf(*errmsg, "cannot apply Prometheus pattern: %s", err); zbx_free(err); return FAIL; } zbx_variant_clear(value); zbx_variant_set_str(value, value_out); return SUCCEED; } /****************************************************************************** * * * Purpose: execute 'prometheus pattern' step * * * * Parameters: cache - [IN] the preprocessing cache * * value - [IN/OUT] the value to process * * params - [IN] the step parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_execute_prometheus_pattern(zbx_pp_cache_t *cache, zbx_variant_t *value, const char *params) { char *errmsg = NULL; if (SUCCEED == pp_execute_prometheus_query(cache, value, params, &errmsg)) return SUCCEED; zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute 'prometheus to json' step * * * * Parameters: value - [IN/OUT] the value to process * * params - [IN] the step parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_execute_prometheus_to_json(zbx_variant_t *value, const char *params) { char *errmsg = NULL; if (SUCCEED == item_preproc_prometheus_to_json(value, params, &errmsg)) return SUCCEED; zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute 'csv to json' step * * * * Parameters: value - [IN/OUT] the value to process * * params - [IN] the step parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_execute_csv_to_json(zbx_variant_t *value, const char *params) { char *errmsg = NULL; if (SUCCEED == item_preproc_csv_to_json(value, params, &errmsg)) return SUCCEED; zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute 'xml to json' step * * * * Parameters: value - [IN/OUT] the value to process * * params - [IN] the step parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_execute_xml_to_json(zbx_variant_t *value) { char *errmsg = NULL; if (SUCCEED == item_preproc_xml_to_json(value, &errmsg)) return SUCCEED; zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute 'str replace' step * * * * Parameters: value - [IN/OUT] the value to process * * params - [IN] the step parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_execute_str_replace(zbx_variant_t *value, const char *params) { char *errmsg = NULL; if (SUCCEED == item_preproc_str_replace(value, params, &errmsg)) return SUCCEED; zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute 'snmp to value' step * * * * Parameters: cache - [IN/OUT] the preprocessing cache * * value - [IN/OUT] the value to process * * params - [IN] the step parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_execute_snmp_to_value(zbx_pp_cache_t *cache, zbx_variant_t *value, const char *params) { char *errmsg = NULL; if (SUCCEED == item_preproc_snmp_walk_to_value(cache, value, params, &errmsg)) return SUCCEED; zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute 'snmp to json' step * * * * Parameters: value - [IN/OUT] the value to process * * params - [IN] the step parameters * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ static int pp_execute_snmp_to_json(zbx_variant_t *value, const char *params) { char *errmsg = NULL; if (SUCCEED == item_preproc_snmp_walk_to_json(value, params, &errmsg)) return SUCCEED; zbx_variant_clear(value); zbx_variant_set_error(value, errmsg); return FAIL; } /****************************************************************************** * * * Purpose: execute preprocessing step * * * * Parameters: ctx - [IN] the worker specific execution context * * cache - [IN] the preprocessing cache * * value_type - [IN] the item value type * * value - [IN/OUT] the input/output value * * ts - [IN] the value timestamp * * step - [IN] the step to execute * * history_value - [IN/OUT] the last value * * history_ts - [IN/OUT] the last value timestamp * * * * Result value: SUCCEED - the preprocessing step was executed successfully. * * FAIL - otherwise. The error message is stored in value. * * * ******************************************************************************/ int pp_execute_step(zbx_pp_context_t *ctx, zbx_pp_cache_t *cache, unsigned char value_type, zbx_variant_t *value, zbx_timespec_t ts, zbx_pp_step_t *step, zbx_variant_t *history_value, zbx_timespec_t *history_ts) { int ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s() step:%d params:'%s' value:'%s' cache:%p", __func__, step->type, ZBX_NULL2EMPTY_STR(step->params), zbx_variant_value_desc(value), (void *)cache); switch (step->type) { case ZBX_PREPROC_MULTIPLIER: ret = pp_execute_multiply(value_type, value, step->params); goto out; case ZBX_PREPROC_RTRIM: case ZBX_PREPROC_LTRIM: case ZBX_PREPROC_TRIM: ret = pp_execute_trim(step->type, value, step->params); goto out; case ZBX_PREPROC_REGSUB: ret = pp_execute_regsub(value, step->params); goto out; case ZBX_PREPROC_BOOL2DEC: case ZBX_PREPROC_OCT2DEC: case ZBX_PREPROC_HEX2DEC: ret = pp_execute_2dec(step->type, value); goto out; case ZBX_PREPROC_DELTA_VALUE: case ZBX_PREPROC_DELTA_SPEED: ret = pp_execute_delta(step->type, value_type, value, ts, history_value, history_ts); goto out; case ZBX_PREPROC_XPATH: ret = pp_execute_xpath(value, step->params); goto out; case ZBX_PREPROC_JSONPATH: ret = pp_execute_jsonpath(cache, value, step->params); goto out; case ZBX_PREPROC_VALIDATE_RANGE: ret = pp_validate_range(value_type, value, step->params); goto out; case ZBX_PREPROC_VALIDATE_REGEX: ret = pp_validate_regex(value, step->params); goto out; case ZBX_PREPROC_VALIDATE_NOT_REGEX: ret = pp_validate_not_regex(value, step->params); goto out; case ZBX_PREPROC_VALIDATE_NOT_SUPPORTED: ret = pp_check_not_error(value); goto out; case ZBX_PREPROC_ERROR_FIELD_JSON: ret = pp_error_from_json(value, step->params); goto out; case ZBX_PREPROC_ERROR_FIELD_XML: ret = pp_error_from_xml(value, step->params); goto out; case ZBX_PREPROC_ERROR_FIELD_REGEX: ret = pp_error_from_regex(value, step->params); goto out; case ZBX_PREPROC_THROTTLE_VALUE: ret = item_preproc_throttle_value(value, &ts, history_value, history_ts); goto out; case ZBX_PREPROC_THROTTLE_TIMED_VALUE: ret = pp_throttle_timed_value(value, ts, step->params, history_value, history_ts); goto out; case ZBX_PREPROC_SCRIPT: ret = pp_execute_script(ctx, value, step->params, history_value); goto out; case ZBX_PREPROC_PROMETHEUS_PATTERN: ret = pp_execute_prometheus_pattern(cache, value, step->params); goto out; case ZBX_PREPROC_PROMETHEUS_TO_JSON: ret = pp_execute_prometheus_to_json(value, step->params); goto out; case ZBX_PREPROC_CSV_TO_JSON: ret = pp_execute_csv_to_json(value, step->params); goto out; case ZBX_PREPROC_XML_TO_JSON: ret = pp_execute_xml_to_json(value); goto out; case ZBX_PREPROC_STR_REPLACE: ret = pp_execute_str_replace(value, step->params); goto out; case ZBX_PREPROC_SNMP_WALK_TO_VALUE: ret = pp_execute_snmp_to_value(cache, value, step->params); goto out; case ZBX_PREPROC_SNMP_WALK_TO_JSON: ret = pp_execute_snmp_to_json(value, step->params); goto out; default: zbx_variant_clear(value); zbx_variant_set_error(value, zbx_dsprintf(NULL, "unknown preprocessing step")); ret = FAIL; } out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s() ret:%s value:%s", __func__, zbx_result_string(ret), zbx_variant_value_desc(value)); return ret; } /****************************************************************************** * * * Purpose: execute preprocessing steps * * * * Parameters: ctx - [IN] the worker specific execution context * * preproc - [IN] the item preprocessing data * * cache - [IN] the preprocessing cache * * value_in - [IN] the input value * * ts - [IN] the value timestamp * * value_out - [OUT] the output value * * results_out - [OUT] the results for each step (optional) * * results_num_out - [OUT] the number of results (optional) * * * ******************************************************************************/ void pp_execute(zbx_pp_context_t *ctx, zbx_pp_item_preproc_t *preproc, zbx_pp_cache_t *cache, zbx_variant_t *value_in, zbx_timespec_t ts, zbx_variant_t *value_out, zbx_pp_result_t **results_out, int *results_num_out) { zbx_pp_result_t *results; zbx_pp_history_t *history; int quote_error, results_num, action; zbx_variant_t value_raw; zabbix_log(LOG_LEVEL_DEBUG, "In %s(): value:%s type:%s", __func__, zbx_variant_value_desc(NULL == cache ? value_in : &cache->value), zbx_variant_type_desc(NULL == cache ? value_in : &cache->value)); if (NULL == preproc || 0 == preproc->steps_num) { zbx_variant_copy(value_out, NULL != cache ? &cache->value : value_in); goto out; } if (NULL == cache) { zbx_variant_copy(value_out, value_in); } else { /* preprocessing cache is enabled only for the first step, */ /* so prepare output value based on first step type */ pp_cache_prepare_output_value(cache, preproc->steps[0].type, value_out); /* set input value for error reporting */ value_in = &cache->value; } results = (zbx_pp_result_t *)zbx_malloc(NULL, sizeof(zbx_pp_result_t) * (size_t)preproc->steps_num); history = (0 != preproc->history_num ? zbx_pp_history_create(preproc->history_num) : NULL); results_num = 0; zbx_variant_set_none(&value_raw); for (int i = 0; i < preproc->steps_num; i++) { zbx_variant_t history_value; zbx_timespec_t history_ts; if (ZBX_VARIANT_ERR == value_out->type && ZBX_PREPROC_VALIDATE_NOT_SUPPORTED != preproc->steps[i].type) break; action = ZBX_PREPROC_FAIL_DEFAULT; quote_error = 0; pp_history_pop(preproc->history, i, &history_value, &history_ts); if (SUCCEED != pp_execute_step(ctx, cache, preproc->value_type, value_out, ts, preproc->steps + i, &history_value, &history_ts)) { zbx_variant_copy(&value_raw, value_out); if (ZBX_PREPROC_FAIL_DEFAULT == (action = pp_error_on_fail(value_out, preproc->steps + i))) zbx_variant_clear(&value_raw); } else { if (ZBX_VARIANT_ERR == value_out->type) quote_error = 1; } pp_result_set(results + results_num++, value_out, action, &value_raw); if (NULL != history && ZBX_VARIANT_NONE != history_value.type && ZBX_VARIANT_ERR != value_out->type) { if (SUCCEED == zbx_pp_preproc_has_history(preproc->steps[i].type)) zbx_pp_history_add(history, i, &history_value, history_ts); } zbx_variant_clear(&history_value); cache = NULL; if (ZBX_VARIANT_NONE == value_out->type) break; } if (ZBX_VARIANT_ERR == value_out->type) { /* reset preprocessing history in the case of error */ if (NULL != history) { pp_history_free(history); history = NULL; } if (0 != results_num && ZBX_PREPROC_FAIL_SET_ERROR != action && 0 == quote_error) { char *error = NULL; pp_format_error(value_in, results, results_num, &error); zbx_variant_clear(value_out); zbx_variant_set_error(value_out, error); } } /* replace preprocessing history */ if (NULL != preproc->history) pp_history_free(preproc->history); preproc->history = history; if (NULL != results_out) { *results_out = results; *results_num_out = results_num; } else pp_free_results(results, results_num); out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s(): value:'%s' type:%s", __func__, zbx_variant_value_desc(value_out), zbx_variant_type_desc(value_out)); } void pp_context_init(zbx_pp_context_t *ctx) { memset(ctx, 0, sizeof(zbx_pp_context_t)); } void pp_context_destroy(zbx_pp_context_t *ctx) { if (0 != ctx->es_initialized) zbx_es_destroy(&ctx->es_engine); } zbx_es_t *pp_context_es_engine(zbx_pp_context_t *ctx) { if (0 == ctx->es_initialized) { zbx_es_init(&ctx->es_engine); ctx->es_initialized = 1; } return &ctx->es_engine; }