Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndris Zeila <andris.zeila@zabbix.com>2018-10-19 14:03:43 +0300
committerAndris Zeila <andris.zeila@zabbix.com>2018-10-19 14:03:43 +0300
commit755091f798cc252aa5ea437b6d8ad7c444ffba89 (patch)
treef1c9326a1e0059a0f39df41a1edbbb6dbf4b6f45
parent4a41d695e07d9364d1730c8442b7cf0a753ebc0e (diff)
........S. [ZBXNEXT-4724] added error extraction preprocessing options
-rw-r--r--src/zabbix_server/preprocessor/item_preproc.c233
-rw-r--r--src/zabbix_server/preprocessor/preproc_manager.c4
-rw-r--r--tests/zabbix_server/preprocessor/zbx_item_preproc.yaml148
3 files changed, 375 insertions, 10 deletions
diff --git a/src/zabbix_server/preprocessor/item_preproc.c b/src/zabbix_server/preprocessor/item_preproc.c
index e7ebac2f38e..b7a8c7f217f 100644
--- a/src/zabbix_server/preprocessor/item_preproc.c
+++ b/src/zabbix_server/preprocessor/item_preproc.c
@@ -918,7 +918,6 @@ static int item_preproc_xpath_op(zbx_variant_t *value, const char *params, char
for (i = 0; i < nodeset->nodeNr; i++)
xmlNodeDump(xmlBufferLocal, doc, nodeset->nodeTab[i], 0, 0);
}
-
zbx_variant_clear(value);
zbx_variant_set_str(value, zbx_strdup(NULL, (const char *)xmlBufferLocal->content));
@@ -950,10 +949,10 @@ static int item_preproc_xpath_op(zbx_variant_t *value, const char *params, char
ret = SUCCEED;
}
else
- *errmsg = zbx_dsprintf(*errmsg, "Invalid numeric value");
+ *errmsg = zbx_strdup(*errmsg, "Invalid numeric value");
break;
default:
- *errmsg = zbx_dsprintf(*errmsg, "Unknown result");
+ *errmsg = zbx_strdup(*errmsg, "Unknown result");
break;
}
out:
@@ -1107,6 +1106,8 @@ static int item_preproc_validate_regex(zbx_variant_t *value, const char *params,
zbx_regexp_free(regex);
out:
+ zbx_variant_clear(&value_str);
+
return ret;
}
@@ -1152,7 +1153,212 @@ static int item_preproc_validate_not_regex(zbx_variant_t *value, const char *par
zbx_regexp_free(regex);
out:
- return ret;}
+ zbx_variant_clear(&value_str);
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: item_preproc_get_error_from_json *
+ * *
+ * Purpose: checks for presence of error field in json data *
+ * *
+ * Parameters: value - [IN/OUT] the value to process *
+ * params - [IN] the operation parameters *
+ * errmsg - [OUT] error message part *
+ * error - [OUT] direct error message *
+ * *
+ * Return value: FAIL - the specified error field exists *
+ * SUCCEED - otherwise *
+ * *
+ * Comments: This preprocessing step is used to check if the returned data *
+ * contains explicit (API related) error message and sets it as *
+ * error. *
+ * *
+ ******************************************************************************/
+static int item_preproc_get_error_from_json(zbx_variant_t *value, const char *params, char **errmsg, char **error)
+{
+ zbx_variant_t value_str;
+ char err[MAX_STRING_LEN];
+ int ret = SUCCEED;
+ struct zbx_json_parse jp, jp_out;
+ size_t data_alloc = 0;
+
+ if (FAIL == zbx_json_path_check(params, err, sizeof(err)))
+ {
+ *errmsg = zbx_strdup(*errmsg, err);
+ return FAIL;
+ }
+
+ zbx_variant_set_variant(&value_str, value);
+
+ if (FAIL == item_preproc_convert_value(&value_str, ZBX_VARIANT_STR, errmsg))
+ goto out;
+
+ if (FAIL == zbx_json_open(value->data.str, &jp) || FAIL == zbx_json_path_open(&jp, params, &jp_out))
+ goto out;
+
+ zbx_free(*error);
+ zbx_json_value_dyn(&jp_out, error, &data_alloc);
+ ret = FAIL;
+out:
+ zbx_variant_clear(&value_str);
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: item_preproc_get_error_from_xml *
+ * *
+ * Purpose: checks for presence of error field in XML data *
+ * *
+ * Parameters: value - [IN/OUT] the value to process *
+ * params - [IN] the operation parameters *
+ * errmsg - [OUT] error message *
+ * *
+ * Return value: FAIL - the specified error field exists *
+ * SUCCEED - otherwise *
+ * *
+ * Comments: This preprocessing step is used to check if the returned data *
+ * contains explicit (API related) error message and sets it as *
+ * error. *
+ * *
+ ******************************************************************************/
+static int item_preproc_get_error_from_xml(zbx_variant_t *value, const char *params, char **errmsg, char **error)
+{
+#ifndef HAVE_LIBXML2
+ ZBX_UNUSED(value);
+ ZBX_UNUSED(params);
+ *error = zbx_dsprintf(*error, "Zabbix was compiled without libxml2 support");
+ return FAIL;
+#else
+ zbx_variant_t value_str;
+ int ret = SUCCEED, i;
+ xmlDoc *doc = NULL;
+ xmlXPathContext *xpathCtx = NULL;
+ xmlXPathObject *xpathObj = NULL;
+ xmlErrorPtr pErr;
+ xmlBufferPtr xmlBufferLocal;
+
+ zbx_variant_set_variant(&value_str, value);
+
+ if (FAIL == item_preproc_convert_value(&value_str, ZBX_VARIANT_STR, errmsg))
+ goto out;
+
+ if (NULL == (doc = xmlReadMemory(value_str.data.str, strlen(value_str.data.str), "noname.xml", NULL, 0)))
+ goto out;
+
+ xpathCtx = xmlXPathNewContext(doc);
+
+ if (NULL == (xpathObj = xmlXPathEvalExpression((xmlChar *)params, xpathCtx)))
+ {
+ pErr = xmlGetLastError();
+ *errmsg = zbx_dsprintf(*errmsg, "cannot parse xpath: %s", pErr->message);
+ ret = FAIL;
+ goto out;
+ }
+
+ switch (xpathObj->type)
+ {
+ case XPATH_NODESET:
+ if (0 != xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
+ goto out;
+
+ xmlBufferLocal = xmlBufferCreate();
+
+ for (i = 0; i < xpathObj->nodesetval->nodeNr; i++)
+ xmlNodeDump(xmlBufferLocal, doc, xpathObj->nodesetval->nodeTab[i], 0, 0);
+
+ *error = zbx_strdup(*error, (const char *)xmlBufferLocal->content);
+ xmlBufferFree(xmlBufferLocal);
+ break;
+ case XPATH_STRING:
+ *error = zbx_strdup(*error, (const char *)xpathObj->stringval);
+ break;
+ case XPATH_BOOLEAN:
+ *error = zbx_dsprintf(*error, "%d", xpathObj->boolval);
+ break;
+ case XPATH_NUMBER:
+ *error = zbx_dsprintf(*error, ZBX_FS_DBL, xpathObj->floatval);
+ break;
+ default:
+ *error = zbx_strdup(*error, "Unknown error");
+ break;
+ }
+
+ ret = FAIL;
+out:
+ zbx_variant_clear(&value_str);
+
+ if (NULL != xpathObj)
+ xmlXPathFreeObject(xpathObj);
+
+ if (NULL != xpathCtx)
+ xmlXPathFreeContext(xpathCtx);
+
+ if (NULL != doc)
+ xmlFreeDoc(doc);
+
+ return ret;
+#endif
+}
+
+/******************************************************************************
+ * *
+ * Function: item_preproc_get_error_from_regex *
+ * *
+ * Purpose: checks for presence of error pattern matching regular expression *
+ * *
+ * Parameters: value - [IN/OUT] the value to process *
+ * params - [IN] the operation parameters *
+ * errmsg - [OUT] error message part *
+ * error - [OUT] direct error message *
+ * *
+ * Return value: FAIL - the specified error field exists *
+ * SUCCEED - otherwise *
+ * *
+ * Comments: This preprocessing step is used to check if the returned data *
+ * contains explicit (API related) error message and sets it as *
+ * error. *
+ * *
+ ******************************************************************************/
+static int item_preproc_get_error_from_regex(zbx_variant_t *value, const char *params, char **errmsg, char **error)
+{
+ zbx_variant_t value_str;
+ int ret = SUCCEED;
+ char pattern[ITEM_PREPROC_PARAMS_LEN * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1], *output;
+
+ zbx_variant_set_variant(&value_str, value);
+
+ if (FAIL == item_preproc_convert_value(&value_str, ZBX_VARIANT_STR, errmsg))
+ goto out;
+
+ zbx_strlcpy(pattern, params, sizeof(pattern));
+ if (NULL == (output = strchr(pattern, '\n')))
+ {
+ *errmsg = zbx_strdup(*errmsg, "cannot find second parameter");
+ ret = FAIL;
+ goto out;
+ }
+
+ *output++ = '\0';
+
+ if (FAIL == zbx_mregexp_sub(value_str.data.str, pattern, output, error))
+ {
+ *errmsg = zbx_dsprintf(*errmsg, "invalid regular expression \"%s\"", pattern);
+ ret = FAIL;
+ goto out;
+ }
+
+ if (NULL != *error)
+ ret = FAIL;
+out:
+ zbx_variant_clear(&value_str);
+
+ return ret;
+}
/******************************************************************************
* *
@@ -1176,7 +1382,7 @@ out:
int zbx_item_preproc(int index, unsigned char value_type, zbx_variant_t *value, const zbx_timespec_t *ts,
const zbx_preproc_op_t *op, zbx_item_history_value_t *history_value, char **error)
{
- int ret;
+ int ret, error_handler = op->error_handler;
char *errmsg = NULL;
switch (op->type)
@@ -1226,6 +1432,15 @@ int zbx_item_preproc(int index, unsigned char value_type, zbx_variant_t *value,
case ZBX_PREPROC_VALIDATE_NOT_REGEX:
ret = item_preproc_validate_not_regex(value, op->params, &errmsg);
break;
+ case ZBX_PREPROC_ERROR_FIELD_JSON:
+ ret = item_preproc_get_error_from_json(value, op->params, &errmsg, error);
+ break;
+ case ZBX_PREPROC_ERROR_FIELD_XML:
+ ret = item_preproc_get_error_from_xml(value, op->params, &errmsg, error);
+ break;
+ case ZBX_PREPROC_ERROR_FIELD_REGEX:
+ ret = item_preproc_get_error_from_regex(value, op->params, &errmsg, error);
+ break;
default:
errmsg = zbx_dsprintf(NULL, "unknown preprocessing operation");
ret = FAIL;
@@ -1234,10 +1449,12 @@ int zbx_item_preproc(int index, unsigned char value_type, zbx_variant_t *value,
if (SUCCEED == ret)
return SUCCEED;
- switch (op->error_handler)
+ switch (error_handler)
{
case ZBX_PREPROC_FAIL_DEFAULT:
- *error = zbx_dsprintf(*error, "Item preprocessing step #%d failed: %s", index, errmsg);
+ /* if errmsg is NULL then error was set directly by preprocessing step */
+ if (NULL != errmsg)
+ *error = zbx_dsprintf(*error, "Item preprocessing step #%d failed: %s", index, errmsg);
break;
case ZBX_PREPROC_FAIL_DISCARD_VALUE:
zbx_variant_clear(value);
@@ -1249,7 +1466,7 @@ int zbx_item_preproc(int index, unsigned char value_type, zbx_variant_t *value,
ret = SUCCEED;
break;
case ZBX_PREPROC_FAIL_SET_ERROR:
- *error = zbx_strdup(NULL, op->error_handler_params);
+ *error = zbx_strdup(*error, op->error_handler_params);
break;
}
diff --git a/src/zabbix_server/preprocessor/preproc_manager.c b/src/zabbix_server/preprocessor/preproc_manager.c
index 0cf1b189d00..0ab0727ac29 100644
--- a/src/zabbix_server/preprocessor/preproc_manager.c
+++ b/src/zabbix_server/preprocessor/preproc_manager.c
@@ -562,7 +562,7 @@ static void preprocessor_enqueue(zbx_preprocessing_manager_t *manager, zbx_prepr
zbx_preprocessing_states_t state;
unsigned char priority = ZBX_PREPROC_PRIORITY_NONE;
- zabbix_log(LOG_LEVEL_DEBUG, "In %s() itemid: %" ZBX_FS_UI64, __function_name, value->itemid);
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s() itemid: " ZBX_FS_UI64, __function_name, value->itemid);
item_local.itemid = value->itemid;
item = (zbx_preproc_item_t *)zbx_hashset_search(&manager->item_config, &item_local);
@@ -672,7 +672,7 @@ static void preprocessor_enqueue_dependent(zbx_preprocessing_manager_t *manager,
zbx_preproc_item_t *item, item_local;
zbx_preproc_item_value_t value;
- zabbix_log(LOG_LEVEL_DEBUG, "In %s() itemid: %" PRIu64, __function_name, source_value->itemid);
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s() itemid: " ZBX_FS_UI64, __function_name, source_value->itemid);
if (NULL != source_value->result && ISSET_VALUE(source_value->result))
{
diff --git a/tests/zabbix_server/preprocessor/zbx_item_preproc.yaml b/tests/zabbix_server/preprocessor/zbx_item_preproc.yaml
index 8ed7a0f0680..d1c5f09ca4f 100644
--- a/tests/zabbix_server/preprocessor/zbx_item_preproc.yaml
+++ b/tests/zabbix_server/preprocessor/zbx_item_preproc.yaml
@@ -1127,6 +1127,154 @@ in:
out:
return: FAIL
error: custom error
+---
+test case: jsonerror(x, $.error)
+in:
+ value:
+ value_type: ITEM_VALUE_TYPE_STR
+ time: 2017-10-29 03:15:00 +03:00
+ data: x
+ step:
+ type: ZBX_PREPROC_ERROR_FIELD_JSON
+ params: $.error
+out:
+ return: SUCCEED
+ value: x
+---
+test case: jsonerror({"error":"error message"}, $error)
+in:
+ value:
+ value_type: ITEM_VALUE_TYPE_STR
+ time: 2017-10-29 03:15:00 +03:00
+ data: |-
+ {"error":"error message"}
+ step:
+ type: ZBX_PREPROC_ERROR_FIELD_JSON
+ params: $error
+out:
+ return: FAIL
+---
+test case: jsonerror({"data":"123"}, $.error)
+in:
+ value:
+ value_type: ITEM_VALUE_TYPE_STR
+ time: 2017-10-29 03:15:00 +03:00
+ data: |-
+ {"data":"123"}
+ step:
+ type: ZBX_PREPROC_ERROR_FIELD_JSON
+ params: $.error
+out:
+ return: SUCCEED
+ value: |-
+ {"data":"123"}
+---
+test case: jsonerror({"error":"error message"}, $.error)
+in:
+ value:
+ value_type: ITEM_VALUE_TYPE_STR
+ time: 2017-10-29 03:15:00 +03:00
+ data: |-
+ {"error":"error message"}
+ step:
+ type: ZBX_PREPROC_ERROR_FIELD_JSON
+ params: $.error
+out:
+ return: FAIL
+ error: error message
+---
+test case: xmlerror(x, //error)
+in:
+ value:
+ value_type: ITEM_VALUE_TYPE_STR
+ time: 2017-10-29 03:15:00 +03:00
+ data: x
+ step:
+ type: ZBX_PREPROC_ERROR_FIELD_XML
+ params: //error
+out:
+ return: SUCCEED
+ value: x
+---
+test case: xmlerror(<a><error>custom error</error></a>, "//text(")
+in:
+ value:
+ value_type: ITEM_VALUE_TYPE_STR
+ time: 2017-10-29 03:15:00 +03:00
+ data: <a><error>custom error</error></a>
+ step:
+ type: ZBX_PREPROC_ERROR_FIELD_XML
+ params: //text(
+out:
+ return: FAIL
+---
+test case: xmlerror(<a><error>custom error</error></a>, "//error/text()")
+in:
+ value:
+ value_type: ITEM_VALUE_TYPE_STR
+ time: 2017-10-29 03:15:00 +03:00
+ data: <a><error>custom error</error></a>
+ step:
+ type: ZBX_PREPROC_ERROR_FIELD_XML
+ params: //error/text()
+out:
+ return: FAIL
+ error: custom error
+---
+test case: xmlerror(<a><value>1</value></a>, "//error/text()")
+in:
+ value:
+ value_type: ITEM_VALUE_TYPE_STR
+ time: 2017-10-29 03:15:00 +03:00
+ data: <a><value>1</value></a>
+ step:
+ type: ZBX_PREPROC_ERROR_FIELD_XML
+ params: //error/text()
+out:
+ return: SUCCEED
+ value: <a><value>1</value></a>
+---
+test case: regexerror("error:123, "error:([0-9+)")
+in:
+ value:
+ value_type: ITEM_VALUE_TYPE_STR
+ time: 2017-10-29 03:15:00 +03:00
+ data: error:123
+ step:
+ type: ZBX_PREPROC_ERROR_FIELD_REGEX
+ params: ([0-9+)
+out:
+ return: FAIL
+---
+test case: regexerror("error:123, "error:([0-9]+)")
+in:
+ value:
+ value_type: ITEM_VALUE_TYPE_STR
+ time: 2017-10-29 03:15:00 +03:00
+ data: error:123
+ step:
+ type: ZBX_PREPROC_ERROR_FIELD_REGEX
+ params: |-
+ error:([0-9]+)
+ \1
+out:
+ return: FAIL
+ error: 123
+---
+test case: regexerror("value:123, "error:([0-9]+)")
+in:
+ value:
+ value_type: ITEM_VALUE_TYPE_STR
+ time: 2017-10-29 03:15:00 +03:00
+ data: value:123
+ step:
+ type: ZBX_PREPROC_ERROR_FIELD_REGEX
+ params: |-
+ error:([0-9]+)
+ \1
+out:
+ return: SUCCEED
+ value: value:123
...