diff options
-rw-r--r-- | include/common.h | 2 | ||||
-rw-r--r-- | include/zbxserver.h | 1 | ||||
-rw-r--r-- | src/libs/zbxcommon/str.c | 64 | ||||
-rw-r--r-- | src/libs/zbxserver/expression.c | 74 | ||||
-rw-r--r-- | src/zabbix_server/events.c | 2 |
5 files changed, 138 insertions, 5 deletions
diff --git a/include/common.h b/include/common.h index e71955870e7..458e9ecba8d 100644 --- a/include/common.h +++ b/include/common.h @@ -1409,6 +1409,7 @@ int zbx_strcmp_natural(const char *s1, const char *s2); #define ZBX_TOKEN_SIMPLE_MACRO 0x00020 #define ZBX_TOKEN_REFERENCE 0x00040 #define ZBX_TOKEN_LLD_FUNC_MACRO 0x00080 +#define ZBX_TOKEN_EXPRESSION_MACRO 0x00100 /* additional token flags */ #define ZBX_TOKEN_TRIGGER 0x004000 @@ -1489,6 +1490,7 @@ typedef union zbx_token_macro_t objectid; zbx_token_macro_t macro; zbx_token_macro_t lld_macro; + zbx_token_macro_t expression_macro; zbx_token_user_macro_t user_macro; zbx_token_func_macro_t func_macro; zbx_token_func_macro_t lld_func_macro; diff --git a/include/zbxserver.h b/include/zbxserver.h index d6de7772675..b144f357c33 100644 --- a/include/zbxserver.h +++ b/include/zbxserver.h @@ -48,6 +48,7 @@ #define MACRO_TYPE_HTTP_XML 0x00400000 #define MACRO_TYPE_ALLOWED_HOSTS 0x00800000 #define MACRO_TYPE_ITEM_TAG 0x01000000 +#define MACRO_TYPE_EVENT_NAME 0x02000000 /* event name in trigger configuration */ #define MACRO_EXPAND_NO 0 #define MACRO_EXPAND_YES 1 diff --git a/src/libs/zbxcommon/str.c b/src/libs/zbxcommon/str.c index 17d50705d76..3514db13d17 100644 --- a/src/libs/zbxcommon/str.c +++ b/src/libs/zbxcommon/str.c @@ -3627,6 +3627,66 @@ static int zbx_token_parse_lld_macro(const char *expression, const char *macro, /****************************************************************************** * * + * Function: zbx_token_parse_expression_macro * + * * + * Purpose: parses expression macro token * + * * + * Parameters: expression - [IN] the expression * + * macro - [IN] the beginning of the token * + * token - [OUT] the token data * + * * + * Return value: SUCCEED - the expression macro was parsed successfully * + * FAIL - macro does not point at valid expression macro * + * * + * Comments: If the macro points at valid expression macro in the expression * + * then the generic token fields are set and the * + * token->data.expression_macro structure is filled with expression * + * macro specific data. * + * Contents of macro are not validated because expression macro may * + * contain user macro contexts and item keys with string arguments. * + * * + ******************************************************************************/ +static int zbx_token_parse_expression_macro(const char *expression, const char *macro, zbx_token_t *token) +{ + const char *ptr; + size_t level; + size_t offset; + zbx_token_macro_t *data; + + /* find the end of expression macro */ + for (ptr = macro + 2, level = 1; '}' != *ptr || 1 != level; ptr++) + { + if ('\0' == *ptr) + return FAIL; + + if ('{' == *ptr) + level++; + + if ('}' == *ptr) + level--; + } + + /* empty macro */ + if (ptr == macro + 2) + return FAIL; + + offset = macro - expression; + + /* initialize token */ + token->type = ZBX_TOKEN_EXPRESSION_MACRO; + token->loc.l = offset; + token->loc.r = offset + (ptr - macro); + + /* initialize token data */ + data = &token->data.expression_macro; + data->name.l = offset + 2; + data->name.r = token->loc.r - 1; + + return SUCCEED; +} + +/****************************************************************************** + * * * Function: zbx_token_parse_objectid * * * * Purpose: parses object id token * @@ -4223,7 +4283,9 @@ int zbx_token_find(const char *expression, int pos, zbx_token_t *token, zbx_toke case '#': ret = zbx_token_parse_lld_macro(expression, ptr, token); break; - + case '?': + ret = zbx_token_parse_expression_macro(expression, ptr, token); + break; case '{': ret = zbx_token_parse_nested_macro(expression, ptr, token); break; diff --git a/src/libs/zbxserver/expression.c b/src/libs/zbxserver/expression.c index 0f295bb5ee5..57fce5fbf9f 100644 --- a/src/libs/zbxserver/expression.c +++ b/src/libs/zbxserver/expression.c @@ -2525,6 +2525,61 @@ static void get_event_value(const char *macro, const DB_EVENT *event, char **rep /****************************************************************************** * * + * Function: get_expression_macro_result * + * * + * Purpose: calculate result of expression macro * + * * + * Return value: upon successful completion return SUCCEED * + * otherwise FAIL * + * * + ******************************************************************************/ +static int get_expression_macro_result(const DB_EVENT *event, const DB_EVENT *r_event, DB_ALERT *alert, + const DB_ACKNOWLEDGE *ack, char **expression, char **replace_to, char *error, int maxerrlen) +{ + int ret; + double expression_result; + int unknown_idx; + zbx_vector_ptr_t unknown_msgs; /* pointers to messages about origins of 'unknown' values */ + char eval_errors[1024] = { 0 }; + + zabbix_log(LOG_LEVEL_DEBUG, "In %s() expression:'%s'", __func__, *expression); + + substitute_simple_macros_impl(NULL, event, r_event, NULL, NULL, NULL, NULL, alert, ack, NULL, expression, + MACRO_TYPE_MESSAGE_NORMAL, error, maxerrlen); + + zbx_vector_ptr_create(&unknown_msgs); + + if (SUCCEED != evaluate(&expression_result, *expression, eval_errors, sizeof(eval_errors), &unknown_msgs)) + { + zabbix_log(LOG_LEVEL_DEBUG, "%s() %s", __func__, eval_errors); + + for (unknown_idx = 0; unknown_idx < unknown_msgs.values_num; unknown_idx++) + { + zabbix_log(LOG_LEVEL_DEBUG, "%s() %s", __func__, (char *)(unknown_msgs.values[unknown_idx])); + } + + ret = FAIL; + } + else + { + size_t alloc_len; + size_t offset; + + zbx_snprintf_alloc(replace_to, &alloc_len, &offset, "%f", expression_result); + + ret = SUCCEED; + } + + zbx_vector_ptr_clear_ext(&unknown_msgs, zbx_ptr_free); + zbx_vector_ptr_destroy(&unknown_msgs); + + zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret)); + + return ret; +} + +/****************************************************************************** + * * * Function: get_history_log_value * * * * Purpose: retrieve a particular attribute of a log value * @@ -2937,7 +2992,7 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT zabbix_log(LOG_LEVEL_DEBUG, "In %s() data:'%s'", __func__, *data); - if (0 != (macro_type & MACRO_TYPE_TRIGGER_DESCRIPTION)) + if (0 != (macro_type & (MACRO_TYPE_TRIGGER_DESCRIPTION | MACRO_TYPE_EVENT_NAME))) token_search = ZBX_TOKEN_SEARCH_REFERENCES; else token_search = ZBX_TOKEN_SEARCH_BASIC; @@ -2963,7 +3018,7 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT case ZBX_TOKEN_OBJECTID: case ZBX_TOKEN_LLD_MACRO: case ZBX_TOKEN_LLD_FUNC_MACRO: - /* neither lld or {123123} macros are processed by this function, skip them */ + /* neither lld nor {123123} macros are processed by this function, skip them */ pos = token.loc.r + 1; continue; case ZBX_TOKEN_MACRO: @@ -3011,6 +3066,7 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT m = NULL; break; case ZBX_TOKEN_REFERENCE: + case ZBX_TOKEN_EXPRESSION_MACRO: /* These macros (and probably all other in the future) must be resolved using only */ /* information stored in token.data union. For now, force crash if they rely on m. */ m = NULL; @@ -4059,7 +4115,8 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT } } } - else if (0 != (macro_type & (MACRO_TYPE_TRIGGER_DESCRIPTION | MACRO_TYPE_TRIGGER_COMMENTS))) + else if (0 != (macro_type & (MACRO_TYPE_TRIGGER_DESCRIPTION | MACRO_TYPE_TRIGGER_COMMENTS | + MACRO_TYPE_EVENT_NAME))) { if (EVENT_OBJECT_TRIGGER == event->object) { @@ -4083,6 +4140,17 @@ static int substitute_simple_macros_impl(zbx_uint64_t *actionid, const DB_EVENT get_trigger_expression_constant(expression, &token.data.reference, &replace_to); } + else if (ZBX_TOKEN_EXPRESSION_MACRO == token.type && + 0 != (macro_type & MACRO_TYPE_EVENT_NAME)) + { + c = (*data)[token.loc.r]; + (*data)[token.loc.r] = '\0'; + + expression = zbx_strdup(expression, *data + token.loc.l + 2); + + ret = get_expression_macro_result(event, r_event, alert, ack, &expression, + &replace_to, error, maxerrlen); + } else if (0 == strcmp(m, MVAR_HOST_HOST) || 0 == strcmp(m, MVAR_HOSTNAME)) { ret = DBget_trigger_value(event->trigger.expression, &replace_to, N_functionid, diff --git a/src/zabbix_server/events.c b/src/zabbix_server/events.c index 2566209b150..a52653b2ca8 100644 --- a/src/zabbix_server/events.c +++ b/src/zabbix_server/events.c @@ -241,7 +241,7 @@ DB_EVENT *zbx_add_event(unsigned char source, unsigned char object, zbx_uint64_t &event->trigger.correlation_tag, MACRO_TYPE_TRIGGER_TAG, NULL, 0); substitute_simple_macros(NULL, event, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - &event->name, MACRO_TYPE_TRIGGER_DESCRIPTION, NULL, 0); + &event->name, MACRO_TYPE_EVENT_NAME, NULL, 0); zbx_vector_ptr_create(&event->tags); |