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:
-rw-r--r--include/common.h2
-rw-r--r--include/zbxserver.h3
-rw-r--r--include/zbxtrends.h4
-rw-r--r--src/libs/zbxcommon/time.c14
-rw-r--r--src/libs/zbxdbcache/dbconfig.c8
-rw-r--r--src/libs/zbxdbhigh/trigger.c32
-rw-r--r--src/libs/zbxeval/eval.h27
-rw-r--r--src/libs/zbxserver/Makefile.am3
-rw-r--r--src/libs/zbxserver/evalfunc.c163
-rw-r--r--src/libs/zbxserver/evalfunc2.c2293
-rw-r--r--src/libs/zbxserver/expression.c2
-rw-r--r--src/libs/zbxtrends/trends.c167
-rw-r--r--tests/libs/zbxcommon/zbx_tm_add.yaml48
-rw-r--r--tests/libs/zbxcommon/zbx_tm_round_down.yaml16
-rw-r--r--tests/libs/zbxcommon/zbx_tm_round_up.yaml16
-rw-r--r--tests/libs/zbxcommon/zbx_tm_sub.yaml32
-rw-r--r--tests/libs/zbxserver/evaluate_function.c4
-rw-r--r--tests/libs/zbxserver/evaluate_function.yaml795
-rw-r--r--tests/libs/zbxtrends/zbx_trends_parse_range.c7
-rw-r--r--tests/libs/zbxtrends/zbx_trends_parse_range.yaml134
-rw-r--r--ui/include/defines.inc.php2
21 files changed, 2939 insertions, 833 deletions
diff --git a/include/common.h b/include/common.h
index 13beaf1acd8..3e21d92d70b 100644
--- a/include/common.h
+++ b/include/common.h
@@ -1646,6 +1646,8 @@ int zbx_str_extract(const char *text, size_t len, char **value);
typedef enum
{
ZBX_TIME_UNIT_UNKNOWN,
+ ZBX_TIME_UNIT_SECOND,
+ ZBX_TIME_UNIT_MINUTE,
ZBX_TIME_UNIT_HOUR,
ZBX_TIME_UNIT_DAY,
ZBX_TIME_UNIT_WEEK,
diff --git a/include/zbxserver.h b/include/zbxserver.h
index da0778313cf..8076dddfa67 100644
--- a/include/zbxserver.h
+++ b/include/zbxserver.h
@@ -62,6 +62,9 @@ void get_functionids(zbx_vector_uint64_t *functionids, const char *expression);
int evaluate_function(char **value, DC_ITEM *item, const char *function, const char *parameter,
const zbx_timespec_t *ts, char **error);
+int evaluate_function2(char **value, DC_ITEM *item, const char *function, const char *parameter,
+ const zbx_timespec_t *ts, char **error);
+
int substitute_simple_macros(zbx_uint64_t *actionid, const DB_EVENT *event, const DB_EVENT *r_event,
zbx_uint64_t *userid, const zbx_uint64_t *hostid, const DC_HOST *dc_host, const DC_ITEM *dc_item,
diff --git a/include/zbxtrends.h b/include/zbxtrends.h
index a99b587af94..33ed4387d14 100644
--- a/include/zbxtrends.h
+++ b/include/zbxtrends.h
@@ -25,9 +25,9 @@
#include "dbcache.h"
int zbx_trends_parse_base(const char *params, zbx_time_unit_t *base, char **error);
+int zbx_parse_timeshift(time_t from, const char *timeshift, struct tm *tm, char **error);
-int zbx_trends_parse_range(time_t from, const char *period, const char *period_shift, int *start, int *end,
- char **error);
+int zbx_trends_parse_range(time_t from, const char *param, int *start, int *end, char **error);
int zbx_trends_parse_nextcheck(time_t from, const char *period_shift, time_t *nextcheck, char **error);
int zbx_trends_eval_avg(const char *table, zbx_uint64_t itemid, int start, int end, double *value, char **error);
diff --git a/src/libs/zbxcommon/time.c b/src/libs/zbxcommon/time.c
index b5864e2837b..170d7c26f90 100644
--- a/src/libs/zbxcommon/time.c
+++ b/src/libs/zbxcommon/time.c
@@ -22,12 +22,17 @@
static void tm_add(struct tm *tm, int multiplier, zbx_time_unit_t base);
static void tm_sub(struct tm *tm, int multiplier, zbx_time_unit_t base);
-static int time_unit_seconds[ZBX_TIME_UNIT_COUNT] = {0, SEC_PER_HOUR, SEC_PER_DAY, SEC_PER_WEEK, 0, 0};
+static int time_unit_seconds[ZBX_TIME_UNIT_COUNT] = {0, 1, SEC_PER_MIN, SEC_PER_HOUR, SEC_PER_DAY, SEC_PER_WEEK, 0,
+ 0};
zbx_time_unit_t zbx_tm_str_to_unit(const char *text)
{
switch (*text)
{
+ case 's':
+ return ZBX_TIME_UNIT_SECOND;
+ case 'm':
+ return ZBX_TIME_UNIT_MINUTE;
case 'h':
return ZBX_TIME_UNIT_HOUR;
case 'd':
@@ -315,9 +320,12 @@ void zbx_tm_round_up(struct tm *tm, zbx_time_unit_t base)
if (0 != tm->tm_sec)
{
tm->tm_sec = 0;
- tm->tm_min++;
+ zbx_tm_add(tm, 1, ZBX_TIME_UNIT_MINUTE);
}
+ if (ZBX_TIME_UNIT_MINUTE == base)
+ return;
+
if (0 != tm->tm_min)
{
tm->tm_min = 0;
@@ -400,6 +408,8 @@ void zbx_tm_round_down(struct tm *tm, zbx_time_unit_t base)
ZBX_FALLTHROUGH;
case ZBX_TIME_UNIT_HOUR:
tm->tm_min = 0;
+ ZBX_FALLTHROUGH;
+ case ZBX_TIME_UNIT_MINUTE:
tm->tm_sec = 0;
break;
default:
diff --git a/src/libs/zbxdbcache/dbconfig.c b/src/libs/zbxdbcache/dbconfig.c
index 64b074dae0e..062e7b05788 100644
--- a/src/libs/zbxdbcache/dbconfig.c
+++ b/src/libs/zbxdbcache/dbconfig.c
@@ -3925,11 +3925,11 @@ static int dc_function_calculate_nextcheck(const zbx_trigger_timer_t *timer, tim
{
struct tm tm;
time_t nextcheck;
- int offsets[ZBX_TIME_UNIT_COUNT] = {0, SEC_PER_MIN * 10, SEC_PER_HOUR + SEC_PER_MIN * 10,
+ int offsets[ZBX_TIME_UNIT_COUNT] = {0, 0, 0, SEC_PER_MIN * 10,
SEC_PER_HOUR + SEC_PER_MIN * 10, SEC_PER_HOUR + SEC_PER_MIN * 10,
- SEC_PER_HOUR + SEC_PER_MIN * 10};
- int periods[ZBX_TIME_UNIT_COUNT] = {0, SEC_PER_MIN * 10, SEC_PER_HOUR, SEC_PER_HOUR * 11,
- SEC_PER_DAY - SEC_PER_HOUR, SEC_PER_DAY - SEC_PER_HOUR};
+ SEC_PER_HOUR + SEC_PER_MIN * 10, SEC_PER_HOUR + SEC_PER_MIN * 10};
+ int periods[ZBX_TIME_UNIT_COUNT] = {0, 0, 0, SEC_PER_MIN * 10, SEC_PER_HOUR,
+ SEC_PER_HOUR * 11, SEC_PER_DAY - SEC_PER_HOUR, SEC_PER_DAY - SEC_PER_HOUR};
if (ZBX_TIME_UNIT_HOUR == timer->trend_base)
{
diff --git a/src/libs/zbxdbhigh/trigger.c b/src/libs/zbxdbhigh/trigger.c
index 82078904c9d..56cd6c45dd0 100644
--- a/src/libs/zbxdbhigh/trigger.c
+++ b/src/libs/zbxdbhigh/trigger.c
@@ -32,15 +32,6 @@
#define ZBX_FLAGS_TRIGGER_CREATE_EVENT \
(ZBX_FLAGS_TRIGGER_CREATE_TRIGGER_EVENT | ZBX_FLAGS_TRIGGER_CREATE_INTERNAL_EVENT)
-/* DB_TRIGGER cached objects */
-typedef enum
-{
- ZBX_DB_TRIGGER_CACHE_EVAL_CTX,
- ZBX_DB_TRIGGER_CACHE_EVAL_CTX_R,
- ZBX_DB_TRIGGER_CACHE_EVAL_CTX_MACROS,
-}
-zbx_db_trigger_cache_t;
-
/******************************************************************************
* *
* Function: zbx_process_trigger *
@@ -316,7 +307,8 @@ void zbx_append_trigger_diff(zbx_vector_ptr_t *trigger_diff, zbx_uint64_t trigge
/* temporary cache of trigger related data */
typedef struct
{
- zbx_uint64_t flags;
+ zbx_uint32_t init;
+ zbx_uint32_t done;
zbx_eval_context_t eval_ctx;
zbx_eval_context_t eval_ctx_r;
zbx_vector_uint64_t hostids;
@@ -347,22 +339,22 @@ static zbx_trigger_cache_t *db_trigger_get_cache(const DB_TRIGGER *trigger, zbx_
{
zbx_trigger_cache_t *cache;
char *error = NULL;
- zbx_uint64_t flag = __UINT64_C(1) << state;
+ zbx_uint32_t flag = 1 << state;
zbx_vector_uint64_t functionids;
if (NULL == trigger->cache)
{
cache = (zbx_trigger_cache_t *)zbx_malloc(NULL, sizeof(zbx_trigger_cache_t));
- cache->flags = 0;
+ cache->init = cache->done = 0;
((DB_TRIGGER *)trigger)->cache = cache;
}
else
cache = (zbx_trigger_cache_t *)trigger->cache;
- if (0 != (cache->flags & flag))
- return 0 != (cache->flags & (flag << 32)) ? cache : NULL;
+ if (0 != (cache->init & flag))
+ return 0 != (cache->done & flag) ? cache : NULL;
- cache->flags |= flag;
+ cache->init |= flag;
switch (state)
{
@@ -388,7 +380,7 @@ static zbx_trigger_cache_t *db_trigger_get_cache(const DB_TRIGGER *trigger, zbx_
return NULL;
}
break;
- case ZBX_DB_TRIGGER_CACHE_EVAL_CTX_MACROS:
+ case ZBX_TRIGGER_CACHE_EVAL_CTX_MACROS:
if (NULL == db_trigger_get_cache(trigger, ZBX_TRIGGER_CACHE_EVAL_CTX))
return NULL;
zbx_dc_eval_expand_user_macros(&cache->eval_ctx);
@@ -404,7 +396,7 @@ static zbx_trigger_cache_t *db_trigger_get_cache(const DB_TRIGGER *trigger, zbx_
return NULL;
}
- cache->flags |= (flag << 32);
+ cache->done |= flag;
return cache;
}
@@ -420,13 +412,13 @@ static zbx_trigger_cache_t *db_trigger_get_cache(const DB_TRIGGER *trigger, zbx_
******************************************************************************/
static void trigger_cache_free(zbx_trigger_cache_t *cache)
{
- if (0 != (cache->flags & (__UINT64_C(1) << ZBX_TRIGGER_CACHE_EVAL_CTX << 32)))
+ if (0 != (cache->done & (1 << ZBX_TRIGGER_CACHE_EVAL_CTX)))
zbx_eval_clear(&cache->eval_ctx);
- if (0 != (cache->flags & (__UINT64_C(1) << ZBX_TRIGGER_CACHE_EVAL_CTX_R << 32)))
+ if (0 != (cache->done & (1 << ZBX_TRIGGER_CACHE_EVAL_CTX_R)))
zbx_eval_clear(&cache->eval_ctx_r);
- if (0 != (cache->flags & (__UINT64_C(1) << ZBX_TRIGGER_CACHE_HOSTIDS << 32)))
+ if (0 != (cache->done & (1 << ZBX_TRIGGER_CACHE_HOSTIDS)))
zbx_vector_uint64_destroy(&cache->hostids);
zbx_free(cache);
diff --git a/src/libs/zbxeval/eval.h b/src/libs/zbxeval/eval.h
new file mode 100644
index 00000000000..0439d7db87b
--- /dev/null
+++ b/src/libs/zbxeval/eval.h
@@ -0,0 +1,27 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2021 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.
+**/
+
+#ifndef ZABBIX_EVAL_H
+#define ZABBIX_EVAL_H
+
+#include "common.h"
+
+int eval_compare_token(const zbx_eval_context_t *ctx, const zbx_strloc_t *loc, const char *text,
+ size_t len);
+#endif
diff --git a/src/libs/zbxserver/Makefile.am b/src/libs/zbxserver/Makefile.am
index c6c5253be7c..3a651e9b08a 100644
--- a/src/libs/zbxserver/Makefile.am
+++ b/src/libs/zbxserver/Makefile.am
@@ -9,7 +9,8 @@ libzbxserver_a_SOURCES = \
macrofunc.c \
macrofunc.h \
zabbix_stats.c \
- zabbix_stats.h
+ zabbix_stats.h \
+ evalfunc2.c
libzbxserver_server_a_SOURCES = \
zabbix_stats.h \
diff --git a/src/libs/zbxserver/evalfunc.c b/src/libs/zbxserver/evalfunc.c
index 812aa9e3a99..df63045a3f6 100644
--- a/src/libs/zbxserver/evalfunc.c
+++ b/src/libs/zbxserver/evalfunc.c
@@ -2697,6 +2697,167 @@ out:
/******************************************************************************
* *
+ * Function: trends_parse_range *
+ * *
+ * Purpose: parse trend function period arguments into time range using old *
+ * parameter format *
+ * *
+ * Parameters: from - [IN] the time the period shift is calculated *
+ * from *
+ * period - [IN] the history period *
+ * period_shift - [IN] the history period shift *
+ * start - [OUT] the period start time in seconds since *
+ * Epoch *
+ * end - [OUT] the period end time in seconds since *
+ * Epoch *
+ * error - [OUT] the error message if parsing failed *
+ * *
+ * Return value: SUCCEED - period was parsed successfully *
+ * FAIL - invalid time period was specified *
+ * *
+ * Comments: Daylight saving changes are applied when parsing ranges with *
+ * day+ used as period base (now/?). *
+ * *
+ * Example period_shift values: *
+ * now/d *
+ * now/d-1h *
+ * now/d+1h *
+ * now/d+1h/w *
+ * now/d/w/h+1h+2h *
+ * now-1d/h *
+ * *
+ * Comments: This is temporary solution to keep calculated checks working *
+ * until they are updated. *
+ * *
+ ******************************************************************************/
+static int trends_parse_range(time_t from, const char *period, const char *period_shift, int *start, int *end,
+ char **error)
+{
+ int period_num, period_hours[ZBX_TIME_UNIT_COUNT] = {0, 1, 24, 24 * 7, 24 * 30, 24 * 365};
+ zbx_time_unit_t period_unit;
+ size_t len;
+ struct tm tm_end, tm_start;
+ const char *p;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s() period:%s shift:%s", __func__, period, period_shift);
+
+ /* parse period */
+
+ if (SUCCEED != zbx_tm_parse_period(period, &len, &period_num, &period_unit, error))
+ return FAIL;
+
+ if ('\0' != period[len])
+ {
+ *error = zbx_dsprintf(*error, "unexpected character[s] in period \"%s\"", period + len);
+ return FAIL;
+ }
+
+ if (period_hours[period_unit] * period_num > 24 * 366)
+ {
+ *error = zbx_strdup(*error, "period is too large");
+ return FAIL;
+ }
+
+ /* parse period shift */
+
+ p = period_shift;
+
+ if (0 != strncmp(p, "now", ZBX_CONST_STRLEN("now")))
+ {
+ *error = zbx_strdup(*error, "period shift must begin with \"now\"");
+ return FAIL;
+ }
+
+ p += ZBX_CONST_STRLEN("now");
+
+ localtime_r(&from, &tm_end);
+
+ while ('\0' != *p)
+ {
+ zbx_time_unit_t unit;
+
+ if ('/' == *p)
+ {
+ if (ZBX_TIME_UNIT_UNKNOWN == (unit = zbx_tm_str_to_unit(++p)))
+ {
+ *error = zbx_dsprintf(*error, "unexpected character starting with \"%s\"", p);
+ return FAIL;
+ }
+
+ if (unit < period_unit)
+ {
+ *error = zbx_dsprintf(*error, "time units in period shift must be greater or equal"
+ " to period time unit");
+ return FAIL;
+ }
+
+ zbx_tm_round_down(&tm_end, unit);
+
+ /* unit is single character */
+ p++;
+ }
+ else if ('+' == *p || '-' == *p)
+ {
+ int num;
+ char op = *(p++);
+
+ if (FAIL == zbx_tm_parse_period(p, &len, &num, &unit, error))
+ return FAIL;
+
+ if (unit < period_unit)
+ {
+ *error = zbx_dsprintf(*error, "time units in period shift must be greater or equal"
+ " to period time unit");
+ return FAIL;
+ }
+
+ if ('+' == op)
+ zbx_tm_add(&tm_end, num, unit);
+ else
+ zbx_tm_sub(&tm_end, num, unit);
+
+ p += len;
+ }
+ else
+ {
+ *error = zbx_dsprintf(*error, "unexpected character starting with \"%s\"", p);
+ return FAIL;
+ }
+ }
+
+ tm_start = tm_end;
+
+ /* trends clock refers to the beginning of the hourly interval - subtract */
+ /* one hour to get the trends clock for the last hourly interval */
+ zbx_tm_sub(&tm_end, 1, ZBX_TIME_UNIT_HOUR);
+
+ if (-1 == (*end = mktime(&tm_end)))
+ {
+ *error = zbx_dsprintf(*error, "cannot calculate the period end time: %s", zbx_strerror(errno));
+ return FAIL;
+ }
+
+ if (abs((int)from - *end) > SEC_PER_YEAR * 26)
+ {
+ *error = zbx_strdup(*error, "period shift is too large");
+ return FAIL;
+ }
+
+ zbx_tm_sub(&tm_start, period_num, period_unit);
+ if (-1 == (*start = mktime(&tm_start)))
+ {
+ *error = zbx_dsprintf(*error, "cannot calculate the period start time: %s", zbx_strerror(errno));
+ return FAIL;
+ }
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s() start:%d end:%d", __func__, *start, *end);
+
+ return SUCCEED;
+}
+
+
+/******************************************************************************
+ * *
* Function: evaluate_TREND *
* *
* Purpose: evaluate trend* functions for the item *
@@ -2735,7 +2896,7 @@ static int evaluate_TREND(char **value, DC_ITEM *item, const char *func, const c
goto out;
}
- if (SUCCEED != zbx_trends_parse_range(ts->sec, period, period_shift, &start, &end, error))
+ if (SUCCEED != trends_parse_range(ts->sec, period, period_shift, &start, &end, error))
goto out;
switch (item->value_type)
diff --git a/src/libs/zbxserver/evalfunc2.c b/src/libs/zbxserver/evalfunc2.c
new file mode 100644
index 00000000000..d253b6ca0a3
--- /dev/null
+++ b/src/libs/zbxserver/evalfunc2.c
@@ -0,0 +1,2293 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2021 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.
+**/
+
+/*
+ * NOTE!!!!!
+ *
+ * This is temporary update of trigger functions to support changes introduced
+ * with new expression syntax.
+ * The old functions must be kept to avoid breaking calculated and aggregate checks.
+ * After those are updated, this code must be copied over the old implementation and
+ * unused code removed.
+ */
+
+#include "common.h"
+#include "db.h"
+#include "log.h"
+#include "zbxserver.h"
+#include "valuecache.h"
+#include "evalfunc.h"
+#include "zbxregexp.h"
+#include "zbxtrends.h"
+
+typedef enum
+{
+ ZBX_PARAM_OPTIONAL,
+ ZBX_PARAM_MANDATORY
+}
+zbx_param_type_t;
+
+typedef enum
+{
+ ZBX_VALUE_NONE,
+ ZBX_VALUE_SECONDS,
+ ZBX_VALUE_NVALUES
+}
+zbx_value_type_t;
+
+static const char *zbx_type_string(zbx_value_type_t type)
+{
+ switch (type)
+ {
+ case ZBX_VALUE_SECONDS:
+ return "sec";
+ case ZBX_VALUE_NVALUES:
+ return "num";
+ default:
+ THIS_SHOULD_NEVER_HAPPEN;
+ return "unknown";
+ }
+}
+
+/******************************************************************************
+ * *
+ * Function: get_function_parameter_int *
+ * *
+ * Purpose: get the value of sec|#num trigger function parameter *
+ * *
+ * Parameters: parameters - [IN] trigger function parameters *
+ * Nparam - [IN] specifies which parameter to extract *
+ * parameter_type - [IN] specifies whether parameter is mandatory *
+ * or optional *
+ * value - [OUT] parameter value (preserved as is if the *
+ * parameter is optional and empty) *
+ * type - [OUT] parameter value type (number of seconds *
+ * or number of values) *
+ * *
+ * Return value: SUCCEED - parameter is valid *
+ * FAIL - otherwise *
+ * *
+ ******************************************************************************/
+static int get_function_parameter_int(const char *parameters, int Nparam, zbx_param_type_t parameter_type,
+ int *value, zbx_value_type_t *type)
+{
+ char *parameter;
+ int ret = FAIL;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s() parameters:'%s' Nparam:%d", __func__, parameters, Nparam);
+
+ if (NULL == (parameter = zbx_function_get_param_dyn(parameters, Nparam)))
+ goto out;
+
+ if ('\0' == *parameter)
+ {
+ switch (parameter_type)
+ {
+ case ZBX_PARAM_OPTIONAL:
+ ret = SUCCEED;
+ break;
+ case ZBX_PARAM_MANDATORY:
+ break;
+ default:
+ THIS_SHOULD_NEVER_HAPPEN;
+ }
+ }
+ else if ('#' == *parameter)
+ {
+ *type = ZBX_VALUE_NVALUES;
+ if (SUCCEED == is_uint31(parameter + 1, value) && 0 < *value)
+ ret = SUCCEED;
+ }
+ else if ('-' == *parameter)
+ {
+ if (SUCCEED == is_time_suffix(parameter + 1, value, ZBX_LENGTH_UNLIMITED))
+ {
+ *value = -(*value);
+ *type = ZBX_VALUE_SECONDS;
+ ret = SUCCEED;
+ }
+ }
+ else if (SUCCEED == is_time_suffix(parameter, value, ZBX_LENGTH_UNLIMITED))
+ {
+ *type = ZBX_VALUE_SECONDS;
+ ret = SUCCEED;
+ }
+
+ if (SUCCEED == ret)
+ zabbix_log(LOG_LEVEL_DEBUG, "%s() type:%s value:%d", __func__, zbx_type_string(*type), *value);
+
+ zbx_free(parameter);
+out:
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+static int get_function_parameter_uint64(const char *parameters, int Nparam, zbx_uint64_t *value)
+{
+ char *parameter;
+ int ret = FAIL;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s() parameters:'%s' Nparam:%d", __func__, parameters, Nparam);
+
+ if (NULL == (parameter = zbx_function_get_param_dyn(parameters, Nparam)))
+ goto out;
+
+ if (SUCCEED == (ret = is_uint64(parameter, value)))
+ zabbix_log(LOG_LEVEL_DEBUG, "%s() value:" ZBX_FS_UI64, __func__, *value);
+
+ zbx_free(parameter);
+out:
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+static int get_function_parameter_float(const char *parameters, int Nparam, unsigned char flags, double *value)
+{
+ char *parameter;
+ int ret = FAIL;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s() parameters:'%s' Nparam:%d", __func__, parameters, Nparam);
+
+ if (NULL == (parameter = zbx_function_get_param_dyn(parameters, Nparam)))
+ goto out;
+
+ if (SUCCEED == (ret = is_double_suffix(parameter, flags)))
+ {
+ *value = str2double(parameter);
+ zabbix_log(LOG_LEVEL_DEBUG, "%s() value:" ZBX_FS_DBL, __func__, *value);
+ }
+
+ zbx_free(parameter);
+out:
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+static int get_function_parameter_str(const char *parameters, int Nparam, char **value)
+{
+ int ret = FAIL;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s() parameters:'%s' Nparam:%d", __func__, parameters, Nparam);
+
+ if (NULL == (*value = zbx_function_get_param_dyn(parameters, Nparam)))
+ goto out;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "%s() value:'%s'", __func__, *value);
+ ret = SUCCEED;
+out:
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: get_function_parameter_hist_range *
+ * *
+ * Purpose: get the value of sec|num + timeshift trigger function parameter *
+ * *
+ * Parameters: from - [IN] the function calculation time *
+ * parameters - [IN] trigger function parameters *
+ * Nparam - [IN] specifies which parameter to extract *
+ * value - [OUT] parameter value (preserved as is if the *
+ * parameter is optional and empty) *
+ * type - [OUT] parameter value type (number of seconds *
+ * or number of values) *
+ * timeshift - [OUT] the timeshift value (0 if absent) *
+ * *
+ * Return value: SUCCEED - parameter is valid *
+ * FAIL - otherwise *
+ * *
+ ******************************************************************************/
+static int get_function_parameter_hist_range(time_t from, const char *parameters, int Nparam, int *value,
+ zbx_value_type_t *type, int *timeshift)
+{
+ char *parameter = NULL, *shift;
+ int ret = FAIL;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s() parameters:'%s' Nparam:%d", __func__, parameters, Nparam);
+
+ if (NULL == (parameter = zbx_function_get_param_dyn(parameters, Nparam)))
+ goto out;
+
+ if (NULL != (shift = strchr(parameter, ':')))
+ *shift++ = '\0';
+
+ if ('\0' == *parameter)
+ {
+ *value = 0;
+ *type = ZBX_VALUE_NONE;
+ }
+ else if (0 == isdigit(parameter[strlen(parameter) - 1]))
+ {
+ if (SUCCEED != is_time_suffix(parameter, value, ZBX_LENGTH_UNLIMITED) || 0 > *value)
+ goto out;
+
+ *type = ZBX_VALUE_SECONDS;
+ }
+ else
+ {
+ if (SUCCEED != is_uint31(parameter, value))
+ goto out;
+ *type = ZBX_VALUE_NVALUES;
+ }
+
+ if (NULL != shift)
+ {
+ struct tm tm;
+ char *error = NULL;
+ time_t end;
+
+ if (SUCCEED != zbx_parse_timeshift(from, shift, &tm, &error))
+ {
+ zabbix_log(LOG_LEVEL_DEBUG, "%s() timeshift error:%s", __func__, error);
+ zbx_free(error);
+ goto out;
+ }
+
+ if (-1 == (end = mktime(&tm)))
+ {
+ zabbix_log(LOG_LEVEL_DEBUG, "%s() invalid timeshift value:%s", __func__, zbx_strerror(errno));
+ goto out;
+ }
+
+ if (end >= from)
+ {
+ zabbix_log(LOG_LEVEL_DEBUG, "%s() timeshift produced time in future", __func__);
+ goto out;
+ }
+
+ *timeshift = from - end;
+ }
+ else
+ *timeshift = 0;
+
+ ret = SUCCEED;
+ zabbix_log(LOG_LEVEL_DEBUG, "%s() type:%s value:%d timeshift:%d", __func__, zbx_type_string(*type), *value,
+ *timeshift);
+out:
+ zbx_free(parameter);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: evaluate_LOGEVENTID *
+ * *
+ * Purpose: evaluate function 'logeventid' for the item *
+ * *
+ * Parameters: item - item (performance metric) *
+ * parameter - regex string for event id matching *
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_LOGEVENTID(char **value, DC_ITEM *item, const char *parameters,
+ const zbx_timespec_t *ts, char **error)
+{
+ char *arg1 = NULL;
+ int ret = FAIL;
+ zbx_vector_ptr_t regexps;
+ zbx_history_record_t vc_value;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ zbx_vector_ptr_create(&regexps);
+
+ if (ITEM_VALUE_TYPE_LOG != item->value_type)
+ {
+ *error = zbx_strdup(*error, "invalid value type");
+ goto out;
+ }
+
+ if (1 < num_param(parameters))
+ {
+ *error = zbx_strdup(*error, "invalid number of parameters");
+ goto out;
+ }
+
+ if (SUCCEED != get_function_parameter_str(parameters, 1, &arg1))
+ {
+ *error = zbx_strdup(*error, "invalid first parameter");
+ goto out;
+ }
+
+ if ('@' == *arg1)
+ {
+ DCget_expressions_by_name(&regexps, arg1 + 1);
+
+ if (0 == regexps.values_num)
+ {
+ *error = zbx_dsprintf(*error, "global regular expression \"%s\" does not exist", arg1 + 1);
+ goto out;
+ }
+ }
+
+ if (SUCCEED == zbx_vc_get_value(item->itemid, item->value_type, ts, &vc_value))
+ {
+ char logeventid[16];
+ int regexp_ret;
+
+ zbx_snprintf(logeventid, sizeof(logeventid), "%d", vc_value.value.log->logeventid);
+
+ if (FAIL == (regexp_ret = regexp_match_ex(&regexps, logeventid, arg1, ZBX_CASE_SENSITIVE)))
+ {
+ *error = zbx_dsprintf(*error, "invalid regular expression \"%s\"", arg1);
+ }
+ else
+ {
+ if (ZBX_REGEXP_MATCH == regexp_ret)
+ *value = zbx_strdup(*value, "1");
+ else if (ZBX_REGEXP_NO_MATCH == regexp_ret)
+ *value = zbx_strdup(*value, "0");
+
+ ret = SUCCEED;
+ }
+
+ zbx_history_record_clear(&vc_value, item->value_type);
+ }
+ else
+ {
+ zabbix_log(LOG_LEVEL_DEBUG, "result for LOGEVENTID is empty");
+ *error = zbx_strdup(*error, "cannot get values from value cache");
+ }
+out:
+ zbx_free(arg1);
+
+ zbx_regexp_clean_expressions(&regexps);
+ zbx_vector_ptr_destroy(&regexps);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: evaluate_LOGSOURCE *
+ * *
+ * Purpose: evaluate function 'logsource' for the item *
+ * *
+ * Parameters: item - item (performance metric) *
+ * parameter - ignored *
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_LOGSOURCE(char **value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts,
+ char **error)
+{
+ char *arg1 = NULL;
+ int ret = FAIL;
+ zbx_vector_ptr_t regexps;
+ zbx_history_record_t vc_value;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ zbx_vector_ptr_create(&regexps);
+
+ if (ITEM_VALUE_TYPE_LOG != item->value_type)
+ {
+ *error = zbx_strdup(*error, "invalid value type");
+ goto out;
+ }
+
+ if (1 < num_param(parameters))
+ {
+ *error = zbx_strdup(*error, "invalid number of parameters");
+ goto out;
+ }
+
+ if (SUCCEED != get_function_parameter_str(parameters, 1, &arg1))
+ {
+ *error = zbx_strdup(*error, "invalid first parameter");
+ goto out;
+ }
+
+ if ('@' == *arg1)
+ {
+ DCget_expressions_by_name(&regexps, arg1 + 1);
+
+ if (0 == regexps.values_num)
+ {
+ *error = zbx_dsprintf(*error, "global regular expression \"%s\" does not exist", arg1 + 1);
+ goto out;
+ }
+ }
+
+ if (SUCCEED == zbx_vc_get_value(item->itemid, item->value_type, ts, &vc_value))
+ {
+ switch (regexp_match_ex(&regexps, vc_value.value.log->source, arg1, ZBX_CASE_SENSITIVE))
+ {
+ case ZBX_REGEXP_MATCH:
+ *value = zbx_strdup(*value, "1");
+ ret = SUCCEED;
+ break;
+ case ZBX_REGEXP_NO_MATCH:
+ *value = zbx_strdup(*value, "0");
+ ret = SUCCEED;
+ break;
+ case FAIL:
+ *error = zbx_dsprintf(*error, "invalid regular expression");
+ }
+
+ zbx_history_record_clear(&vc_value, item->value_type);
+ }
+ else
+ {
+ zabbix_log(LOG_LEVEL_DEBUG, "result for LOGSOURCE is empty");
+ *error = zbx_strdup(*error, "cannot get values from value cache");
+ }
+out:
+ zbx_free(arg1);
+
+ zbx_regexp_clean_expressions(&regexps);
+ zbx_vector_ptr_destroy(&regexps);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: evaluate_LOGSEVERITY *
+ * *
+ * Purpose: evaluate function 'logseverity' for the item *
+ * *
+ * Parameters: item - item (performance metric) *
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_LOGSEVERITY(char **value, DC_ITEM *item, const zbx_timespec_t *ts, char **error)
+{
+ int ret = FAIL;
+ zbx_history_record_t vc_value;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ if (ITEM_VALUE_TYPE_LOG != item->value_type)
+ {
+ *error = zbx_strdup(*error, "invalid value type");
+ goto out;
+ }
+
+ if (SUCCEED == zbx_vc_get_value(item->itemid, item->value_type, ts, &vc_value))
+ {
+ size_t value_alloc = 0, value_offset = 0;
+
+ zbx_snprintf_alloc(value, &value_alloc, &value_offset, "%d", vc_value.value.log->severity);
+ zbx_history_record_clear(&vc_value, item->value_type);
+
+ ret = SUCCEED;
+ }
+ else
+ {
+ zabbix_log(LOG_LEVEL_DEBUG, "result for LOGSEVERITY is empty");
+ *error = zbx_strdup(*error, "cannot get value from value cache");
+ }
+out:
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+#define OP_UNKNOWN -1
+#define OP_EQ 0
+#define OP_NE 1
+#define OP_GT 2
+#define OP_GE 3
+#define OP_LT 4
+#define OP_LE 5
+#define OP_LIKE 6
+#define OP_REGEXP 7
+#define OP_IREGEXP 8
+#define OP_BAND 9
+#define OP_MAX 10
+
+static void count_one_ui64(int *count, int op, zbx_uint64_t value, zbx_uint64_t pattern, zbx_uint64_t mask)
+{
+ switch (op)
+ {
+ case OP_EQ:
+ if (value == pattern)
+ (*count)++;
+ break;
+ case OP_NE:
+ if (value != pattern)
+ (*count)++;
+ break;
+ case OP_GT:
+ if (value > pattern)
+ (*count)++;
+ break;
+ case OP_GE:
+ if (value >= pattern)
+ (*count)++;
+ break;
+ case OP_LT:
+ if (value < pattern)
+ (*count)++;
+ break;
+ case OP_LE:
+ if (value <= pattern)
+ (*count)++;
+ break;
+ case OP_BAND:
+ if ((value & mask) == pattern)
+ (*count)++;
+ }
+}
+
+static void count_one_dbl(int *count, int op, double value, double pattern)
+{
+ switch (op)
+ {
+ case OP_EQ:
+ if (value > pattern - ZBX_DOUBLE_EPSILON && value < pattern + ZBX_DOUBLE_EPSILON)
+ (*count)++;
+ break;
+ case OP_NE:
+ if (!(value > pattern - ZBX_DOUBLE_EPSILON && value < pattern + ZBX_DOUBLE_EPSILON))
+ (*count)++;
+ break;
+ case OP_GT:
+ if (value >= pattern + ZBX_DOUBLE_EPSILON)
+ (*count)++;
+ break;
+ case OP_GE:
+ if (value > pattern - ZBX_DOUBLE_EPSILON)
+ (*count)++;
+ break;
+ case OP_LT:
+ if (value <= pattern - ZBX_DOUBLE_EPSILON)
+ (*count)++;
+ break;
+ case OP_LE:
+ if (value < pattern + ZBX_DOUBLE_EPSILON)
+ (*count)++;
+ }
+}
+
+static void count_one_str(int *count, int op, const char *value, const char *pattern, zbx_vector_ptr_t *regexps)
+{
+ int res;
+
+ switch (op)
+ {
+ case OP_EQ:
+ if (0 == strcmp(value, pattern))
+ (*count)++;
+ break;
+ case OP_NE:
+ if (0 != strcmp(value, pattern))
+ (*count)++;
+ break;
+ case OP_LIKE:
+ if (NULL != strstr(value, pattern))
+ (*count)++;
+ break;
+ case OP_REGEXP:
+ if (ZBX_REGEXP_MATCH == (res = regexp_match_ex(regexps, value, pattern, ZBX_CASE_SENSITIVE)))
+ (*count)++;
+ else if (FAIL == res)
+ *count = FAIL;
+ break;
+ case OP_IREGEXP:
+ if (ZBX_REGEXP_MATCH == (res = regexp_match_ex(regexps, value, pattern, ZBX_IGNORE_CASE)))
+ (*count)++;
+ else if (FAIL == res)
+ *count = FAIL;
+ }
+}
+
+/******************************************************************************
+ * *
+ * Function: evaluate_COUNT *
+ * *
+ * Purpose: evaluate function 'count' for the item *
+ * *
+ * Parameters: item - item (performance metric) *
+ * parameters - up to four comma-separated fields: *
+ * (1) number of seconds/values *
+ * (2) value to compare with (optional) *
+ * Becomes mandatory for numeric items if 3rd *
+ * parameter is specified and is not "regexp" *
+ * or "iregexp". With "band" can take one of *
+ * 2 forms: *
+ * - value_to_compare_with/mask *
+ * - mask *
+ * (3) comparison operator (optional) *
+ * (4) time shift (optional) *
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_COUNT(char **value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts, int limit,
+ char **error)
+{
+ int arg1, op = OP_UNKNOWN, numeric_search, nparams, count = 0, i, ret = FAIL;
+ int seconds = 0, nvalues = 0, time_shift;
+ char *arg2 = NULL, *arg3_2 = NULL, *arg3 = NULL, buf[ZBX_MAX_UINT64_LEN];
+ double arg3_dbl;
+ zbx_uint64_t arg3_ui64, arg3_2_ui64;
+ zbx_value_type_t arg1_type;
+ zbx_vector_ptr_t regexps;
+ zbx_vector_history_record_t values;
+ zbx_timespec_t ts_end = *ts;
+ size_t value_alloc = 0, value_offset = 0;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ zbx_vector_ptr_create(&regexps);
+ zbx_history_record_vector_create(&values);
+
+ numeric_search = (ITEM_VALUE_TYPE_UINT64 == item->value_type || ITEM_VALUE_TYPE_FLOAT == item->value_type);
+
+ if (4 < (nparams = num_param(parameters)))
+ {
+ *error = zbx_strdup(*error, "invalid number of parameters");
+ goto out;
+ }
+
+ if (SUCCEED != get_function_parameter_hist_range(ts->sec, parameters, 1, &arg1, &arg1_type, &time_shift) ||
+ ZBX_VALUE_NONE == arg1_type)
+ {
+ *error = zbx_strdup(*error, "invalid first parameter");
+ goto out;
+ }
+
+ if (2 <= nparams && SUCCEED != get_function_parameter_str(parameters, 2, &arg2))
+ {
+ *error = zbx_strdup(*error, "invalid second parameter");
+ goto out;
+ }
+
+ if (3 <= nparams && SUCCEED != get_function_parameter_str(parameters, 3, &arg3))
+ {
+ *error = zbx_strdup(*error, "invalid third parameter");
+ goto out;
+ }
+
+ ts_end.sec -= time_shift;
+
+ if (NULL == arg2 || '\0' == *arg2)
+ op = (0 != numeric_search ? OP_EQ : OP_LIKE);
+ else if (0 == strcmp(arg2, "eq"))
+ op = OP_EQ;
+ else if (0 == strcmp(arg2, "ne"))
+ op = OP_NE;
+ else if (0 == strcmp(arg2, "gt"))
+ op = OP_GT;
+ else if (0 == strcmp(arg2, "ge"))
+ op = OP_GE;
+ else if (0 == strcmp(arg2, "lt"))
+ op = OP_LT;
+ else if (0 == strcmp(arg2, "le"))
+ op = OP_LE;
+ else if (0 == strcmp(arg2, "like"))
+ op = OP_LIKE;
+ else if (0 == strcmp(arg2, "regexp"))
+ op = OP_REGEXP;
+ else if (0 == strcmp(arg2, "iregexp"))
+ op = OP_IREGEXP;
+ else if (0 == strcmp(arg2, "band"))
+ op = OP_BAND;
+
+ if (OP_UNKNOWN == op)
+ {
+ *error = zbx_dsprintf(*error, "operator \"%s\" is not supported for function COUNT", arg2);
+ goto out;
+ }
+
+ numeric_search = (0 != numeric_search && OP_REGEXP != op && OP_IREGEXP != op);
+
+ if (0 != numeric_search)
+ {
+ if (NULL != arg2 && '\0' != *arg2 && '\0' == *arg3)
+ {
+ *error = zbx_strdup(*error, "pattern must be provided along with operator for numeric values");
+ goto out;
+ }
+
+ if (OP_LIKE == op)
+ {
+ *error = zbx_dsprintf(*error, "operator \"%s\" is not supported for counting numeric values",
+ arg3);
+ goto out;
+ }
+
+ if (OP_BAND == op && ITEM_VALUE_TYPE_FLOAT == item->value_type)
+ {
+ *error = zbx_dsprintf(*error, "operator \"%s\" is not supported for counting float values",
+ arg3);
+ goto out;
+ }
+
+ if (OP_BAND == op && NULL != (arg3_2 = strchr(arg3, '/')))
+ {
+ *arg3_2 = '\0'; /* end of the 1st part of the 2nd parameter (number to compare with) */
+ arg3_2++; /* start of the 2nd part of the 2nd parameter (mask) */
+ }
+
+ if (NULL != arg3 && '\0' != *arg3)
+ {
+ if (ITEM_VALUE_TYPE_UINT64 == item->value_type)
+ {
+ if (OP_BAND != op)
+ {
+ if (SUCCEED != str2uint64(arg3, ZBX_UNIT_SYMBOLS, &arg3_ui64))
+ {
+ *error = zbx_dsprintf(*error, "\"%s\" is not a valid numeric unsigned"
+ " value", arg3);
+ goto out;
+ }
+ }
+ else
+ {
+ if (SUCCEED != is_uint64(arg3, &arg3_ui64))
+ {
+ *error = zbx_dsprintf(*error, "\"%s\" is not a valid numeric unsigned"
+ " value", arg3);
+ goto out;
+ }
+
+ if (NULL != arg3_2)
+ {
+ if (SUCCEED != is_uint64(arg3_2, &arg3_2_ui64))
+ {
+ *error = zbx_dsprintf(*error, "\"%s\" is not a valid numeric"
+ " unsigned value", arg3_2);
+ goto out;
+ }
+ }
+ else
+ arg3_2_ui64 = arg3_ui64;
+ }
+ }
+ else
+ {
+ if (SUCCEED != is_double_suffix(arg3, ZBX_FLAG_DOUBLE_SUFFIX))
+ {
+ *error = zbx_dsprintf(*error, "\"%s\" is not a valid numeric float value",
+ arg3);
+ goto out;
+ }
+
+ arg3_dbl = str2double(arg3);
+ }
+ }
+ }
+ else if (OP_LIKE != op && OP_REGEXP != op && OP_IREGEXP != op && OP_EQ != op && OP_NE != op)
+ {
+ *error = zbx_dsprintf(*error, "operator \"%s\" is not supported for counting textual values", arg2);
+ goto out;
+ }
+
+ if ((OP_REGEXP == op || OP_IREGEXP == op) && '@' == *arg3)
+ {
+ DCget_expressions_by_name(&regexps, arg3 + 1);
+
+ if (0 == regexps.values_num)
+ {
+ *error = zbx_dsprintf(*error, "global regular expression \"%s\" does not exist", arg3 + 1);
+ goto out;
+ }
+ }
+
+ switch (arg1_type)
+ {
+ case ZBX_VALUE_SECONDS:
+ seconds = arg1;
+ break;
+ case ZBX_VALUE_NVALUES:
+ nvalues = arg1;
+ break;
+ default:
+ THIS_SHOULD_NEVER_HAPPEN;
+ }
+
+ if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
+ {
+ *error = zbx_strdup(*error, "cannot get values from value cache");
+ goto out;
+ }
+
+ /* skip counting values one by one if both pattern and operator are empty or "" is searched in text values */
+ if ((NULL != arg3 && '\0' != *arg3) || (NULL != arg2 && '\0' != *arg2 &&
+ OP_LIKE != op && OP_REGEXP != op && OP_IREGEXP != op))
+ {
+ switch (item->value_type)
+ {
+ case ITEM_VALUE_TYPE_UINT64:
+ if (0 != numeric_search)
+ {
+ for (i = 0; i < values.values_num && count < limit; i++)
+ {
+ count_one_ui64(&count, op, values.values[i].value.ui64, arg3_ui64,
+ arg3_2_ui64);
+ }
+ }
+ else
+ {
+ for (i = 0; i < values.values_num && FAIL != count && count < limit; i++)
+ {
+ zbx_snprintf(buf, sizeof(buf), ZBX_FS_UI64,
+ values.values[i].value.ui64);
+ count_one_str(&count, op, buf, arg3, &regexps);
+ }
+ }
+ break;
+ case ITEM_VALUE_TYPE_FLOAT:
+ if (0 != numeric_search)
+ {
+ for (i = 0; i < values.values_num && count < limit; i++)
+ count_one_dbl(&count, op, values.values[i].value.dbl, arg3_dbl);
+ }
+ else
+ {
+ for (i = 0; i < values.values_num && FAIL != count && count < limit; i++)
+ {
+ zbx_snprintf(buf, sizeof(buf), ZBX_FS_DBL_EXT(4),
+ values.values[i].value.dbl);
+ count_one_str(&count, op, buf, arg3, &regexps);
+ }
+ }
+ break;
+ case ITEM_VALUE_TYPE_LOG:
+ for (i = 0; i < values.values_num && FAIL != count && count < limit; i++)
+ count_one_str(&count, op, values.values[i].value.log->value, arg3, &regexps);
+ break;
+ default:
+ for (i = 0; i < values.values_num && FAIL != count && count < limit; i++)
+ count_one_str(&count, op, values.values[i].value.str, arg3, &regexps);
+ }
+
+ if (FAIL == count)
+ {
+ *error = zbx_strdup(*error, "invalid regular expression");
+ goto out;
+ }
+ }
+ else
+ {
+ if ((count = values.values_num) > limit)
+ count = limit;
+ }
+
+ zbx_snprintf_alloc(value, &value_alloc, &value_offset, "%d", count);
+
+ ret = SUCCEED;
+out:
+ zbx_free(arg2);
+ zbx_free(arg3);
+
+ zbx_regexp_clean_expressions(&regexps);
+ zbx_vector_ptr_destroy(&regexps);
+
+ zbx_history_record_vector_destroy(&values, item->value_type);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+#undef OP_UNKNOWN
+#undef OP_EQ
+#undef OP_NE
+#undef OP_GT
+#undef OP_GE
+#undef OP_LT
+#undef OP_LE
+#undef OP_LIKE
+#undef OP_REGEXP
+#undef OP_IREGEXP
+#undef OP_BAND
+#undef OP_MAX
+
+/******************************************************************************
+ * *
+ * Function: evaluate_SUM *
+ * *
+ * Purpose: evaluate function 'sum' for the item *
+ * *
+ * Parameters: item - item (performance metric) *
+ * parameters - number of seconds/values and time shift (optional)*
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_SUM(char **value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts, char **error)
+{
+ int nparams, arg1, i, ret = FAIL, seconds = 0, nvalues = 0, time_shift;
+ zbx_value_type_t arg1_type;
+ zbx_vector_history_record_t values;
+ history_value_t result;
+ zbx_timespec_t ts_end = *ts;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ zbx_history_record_vector_create(&values);
+
+ if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
+ {
+ *error = zbx_strdup(*error, "invalid value type");
+ goto out;
+ }
+
+ if (1 != (nparams = num_param(parameters)))
+ {
+ *error = zbx_strdup(*error, "invalid number of parameters");
+ goto out;
+ }
+
+ if (SUCCEED != get_function_parameter_hist_range(ts->sec, parameters, 1, &arg1, &arg1_type, &time_shift) ||
+ ZBX_VALUE_NONE == arg1_type)
+ {
+ *error = zbx_strdup(*error, "invalid first parameter");
+ goto out;
+ }
+
+ ts_end.sec -= time_shift;
+
+ switch (arg1_type)
+ {
+ case ZBX_VALUE_SECONDS:
+ seconds = arg1;
+ break;
+ case ZBX_VALUE_NVALUES:
+ nvalues = arg1;
+ break;
+ default:
+ THIS_SHOULD_NEVER_HAPPEN;
+ }
+
+ if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
+ {
+ *error = zbx_strdup(*error, "cannot get values from value cache");
+ goto out;
+ }
+
+ if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
+ {
+ result.dbl = 0;
+
+ for (i = 0; i < values.values_num; i++)
+ result.dbl += values.values[i].value.dbl;
+ }
+ else
+ {
+ result.ui64 = 0;
+
+ for (i = 0; i < values.values_num; i++)
+ result.ui64 += values.values[i].value.ui64;
+ }
+
+ *value = zbx_history_value2str_dyn(&result, item->value_type);
+ ret = SUCCEED;
+out:
+ zbx_history_record_vector_destroy(&values, item->value_type);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: evaluate_AVG *
+ * *
+ * Purpose: evaluate function 'avg' for the item *
+ * *
+ * Parameters: item - item (performance metric) *
+ * parameters - number of seconds/values and time shift (optional)*
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_AVG(char **value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts, char **error)
+{
+ int nparams, arg1, ret = FAIL, i, seconds = 0, nvalues = 0, time_shift;
+ zbx_value_type_t arg1_type;
+ zbx_vector_history_record_t values;
+ zbx_timespec_t ts_end = *ts;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ zbx_history_record_vector_create(&values);
+
+ if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
+ {
+ *error = zbx_strdup(*error, "invalid value type");
+ goto out;
+ }
+
+ if (1 != (nparams = num_param(parameters)))
+ {
+ *error = zbx_strdup(*error, "invalid number of parameters");
+ goto out;
+ }
+
+ if (SUCCEED != get_function_parameter_hist_range(ts->sec, parameters, 1, &arg1, &arg1_type, &time_shift) ||
+ ZBX_VALUE_NONE == arg1_type)
+ {
+ *error = zbx_strdup(*error, "invalid first parameter");
+ goto out;
+ }
+
+ ts_end.sec -= time_shift;
+
+ switch (arg1_type)
+ {
+ case ZBX_VALUE_SECONDS:
+ seconds = arg1;
+ break;
+ case ZBX_VALUE_NVALUES:
+ nvalues = arg1;
+ break;
+ default:
+ THIS_SHOULD_NEVER_HAPPEN;
+ }
+
+ if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
+ {
+ *error = zbx_strdup(*error, "cannot get values from value cache");
+ goto out;
+ }
+
+ if (0 < values.values_num)
+ {
+ double avg = 0;
+ size_t value_alloc = 0, value_offset = 0;
+
+ if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
+ {
+ for (i = 0; i < values.values_num; i++)
+ avg += values.values[i].value.dbl / (i + 1) - avg / (i + 1);
+ }
+ else
+ {
+ for (i = 0; i < values.values_num; i++)
+ avg += values.values[i].value.ui64;
+
+ avg = avg / values.values_num;
+ }
+ zbx_snprintf_alloc(value, &value_alloc, &value_offset, ZBX_FS_DBL64, avg);
+
+ ret = SUCCEED;
+ }
+ else
+ {
+ zabbix_log(LOG_LEVEL_DEBUG, "result for AVG is empty");
+ *error = zbx_strdup(*error, "not enough data");
+ }
+out:
+ zbx_history_record_vector_destroy(&values, item->value_type);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: evaluate_LAST *
+ * *
+ * Purpose: evaluate functions 'last' and 'prev' for the item *
+ * *
+ * Parameters: value - dynamic buffer *
+ * item - item (performance metric) *
+ * parameters - Nth last value and time shift (optional) *
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_LAST(char **value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts,
+ char **error)
+{
+ int arg1 = 1, ret = FAIL, time_shift;
+ zbx_value_type_t arg1_type = ZBX_VALUE_NVALUES;
+ zbx_vector_history_record_t values;
+ zbx_timespec_t ts_end = *ts;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ zbx_history_record_vector_create(&values);
+
+ if (SUCCEED != get_function_parameter_hist_range(ts->sec, parameters, 1, &arg1, &arg1_type, &time_shift))
+ {
+ *error = zbx_strdup(*error, "invalid first parameter");
+ goto out;
+ }
+
+ if (ZBX_VALUE_NVALUES != arg1_type)
+ arg1 = 1; /* time or non parameter is defaulted to "last(0)" */
+
+ ts_end.sec -= time_shift;
+
+ if (SUCCEED == zbx_vc_get_values(item->itemid, item->value_type, &values, 0, arg1, &ts_end))
+ {
+ if (arg1 <= values.values_num)
+ {
+ char *tmp;
+
+ tmp = zbx_history_value2str_dyn(&values.values[arg1 - 1].value, item->value_type);
+
+ if (ITEM_VALUE_TYPE_STR == item->value_type ||
+ ITEM_VALUE_TYPE_TEXT == item->value_type ||
+ ITEM_VALUE_TYPE_LOG == item->value_type)
+ {
+ size_t len;
+ char *ptr;
+
+ len = zbx_get_escape_string_len(tmp, "\"\\");
+ ptr = *value = zbx_malloc(NULL, len + 3);
+ *ptr++ = '"';
+ zbx_escape_string(ptr, len + 1, tmp, "\"\\");
+ ptr += len;
+ *ptr++ = '"';
+ *ptr = '\0';
+ zbx_free(tmp);
+ }
+ else
+ *value = tmp;
+
+ ret = SUCCEED;
+ }
+ else
+ {
+ *error = zbx_strdup(*error, "not enough data");
+ goto out;
+ }
+ }
+ else
+ {
+ *error = zbx_strdup(*error, "cannot get values from value cache");
+ }
+out:
+ zbx_history_record_vector_destroy(&values, item->value_type);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: evaluate_MIN *
+ * *
+ * Purpose: evaluate function 'min' for the item *
+ * *
+ * Parameters: item - item (performance metric) *
+ * parameters - number of seconds/values and time shift (optional)*
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_MIN(char **value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts, char **error)
+{
+ int nparams, arg1, i, ret = FAIL, seconds = 0, nvalues = 0, time_shift;
+ zbx_value_type_t arg1_type;
+ zbx_vector_history_record_t values;
+ zbx_timespec_t ts_end = *ts;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ zbx_history_record_vector_create(&values);
+
+ if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
+ {
+ *error = zbx_strdup(*error, "invalid value type");
+ goto out;
+ }
+
+ if (1 != (nparams = num_param(parameters)))
+ {
+ *error = zbx_strdup(*error, "invalid number of parameters");
+ goto out;
+ }
+
+ if (SUCCEED != get_function_parameter_hist_range(ts->sec, parameters, 1, &arg1, &arg1_type, &time_shift) ||
+ ZBX_VALUE_NONE == arg1_type)
+ {
+ *error = zbx_strdup(*error, "invalid first parameter");
+ goto out;
+ }
+
+ ts_end.sec -= time_shift;
+
+ switch (arg1_type)
+ {
+ case ZBX_VALUE_SECONDS:
+ seconds = arg1;
+ break;
+ case ZBX_VALUE_NVALUES:
+ nvalues = arg1;
+ break;
+ default:
+ THIS_SHOULD_NEVER_HAPPEN;
+ }
+
+ if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
+ {
+ *error = zbx_strdup(*error, "cannot get values from value cache");
+ goto out;
+ }
+
+ if (0 < values.values_num)
+ {
+ int index = 0;
+
+ if (ITEM_VALUE_TYPE_UINT64 == item->value_type)
+ {
+ for (i = 1; i < values.values_num; i++)
+ {
+ if (values.values[i].value.ui64 < values.values[index].value.ui64)
+ index = i;
+ }
+ }
+ else
+ {
+ for (i = 1; i < values.values_num; i++)
+ {
+ if (values.values[i].value.dbl < values.values[index].value.dbl)
+ index = i;
+ }
+ }
+
+ *value = zbx_history_value2str_dyn(&values.values[index].value, item->value_type);
+ ret = SUCCEED;
+ }
+ else
+ {
+ zabbix_log(LOG_LEVEL_DEBUG, "result for MIN is empty");
+ *error = zbx_strdup(*error, "not enough data");
+ }
+out:
+ zbx_history_record_vector_destroy(&values, item->value_type);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: evaluate_MAX *
+ * *
+ * Purpose: evaluate function 'max' for the item *
+ * *
+ * Parameters: item - item (performance metric) *
+ * parameters - number of seconds/values and time shift (optional)*
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_MAX(char **value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts, char **error)
+{
+ int nparams, arg1, ret = FAIL, i, seconds = 0, nvalues = 0, time_shift;
+ zbx_value_type_t arg1_type;
+ zbx_vector_history_record_t values;
+ zbx_timespec_t ts_end = *ts;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ zbx_history_record_vector_create(&values);
+
+ if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
+ {
+ *error = zbx_strdup(*error, "invalid value type");
+ goto out;
+ }
+
+ if (1 != (nparams = num_param(parameters)))
+ {
+ *error = zbx_strdup(*error, "invalid number of parameters");
+ goto out;
+ }
+
+ if (SUCCEED != get_function_parameter_hist_range(ts->sec, parameters, 1, &arg1, &arg1_type, &time_shift) ||
+ ZBX_VALUE_NONE == arg1_type)
+ {
+ *error = zbx_strdup(*error, "invalid first parameter");
+ goto out;
+ }
+
+ ts_end.sec -= time_shift;
+
+ switch (arg1_type)
+ {
+ case ZBX_VALUE_SECONDS:
+ seconds = arg1;
+ break;
+ case ZBX_VALUE_NVALUES:
+ nvalues = arg1;
+ break;
+ default:
+ THIS_SHOULD_NEVER_HAPPEN;
+ }
+
+ if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
+ {
+ *error = zbx_strdup(*error, "cannot get values from value cache");
+ goto out;
+ }
+
+ if (0 < values.values_num)
+ {
+ int index = 0;
+
+ if (ITEM_VALUE_TYPE_UINT64 == item->value_type)
+ {
+ for (i = 1; i < values.values_num; i++)
+ {
+ if (values.values[i].value.ui64 > values.values[index].value.ui64)
+ index = i;
+ }
+ }
+ else
+ {
+ for (i = 1; i < values.values_num; i++)
+ {
+ if (values.values[i].value.dbl > values.values[index].value.dbl)
+ index = i;
+ }
+ }
+
+ *value = zbx_history_value2str_dyn(&values.values[index].value, item->value_type);
+
+ ret = SUCCEED;
+ }
+ else
+ {
+ zabbix_log(LOG_LEVEL_DEBUG, "result for MAX is empty");
+ *error = zbx_strdup(*error, "not enough data");
+ }
+out:
+ zbx_history_record_vector_destroy(&values, item->value_type);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+static int __history_record_float_compare(const zbx_history_record_t *d1, const zbx_history_record_t *d2)
+{
+ ZBX_RETURN_IF_NOT_EQUAL(d1->value.dbl, d2->value.dbl);
+
+ return 0;
+}
+
+static int __history_record_uint64_compare(const zbx_history_record_t *d1, const zbx_history_record_t *d2)
+{
+ ZBX_RETURN_IF_NOT_EQUAL(d1->value.ui64, d2->value.ui64);
+
+ return 0;
+}
+
+/******************************************************************************
+ * *
+ * Function: evaluate_PERCENTILE *
+ * *
+ * Purpose: evaluate function 'percentile' for the item *
+ * *
+ * Parameters: item - [IN] item (performance metric) *
+ * parameters - [IN] seconds/values, time shift (optional), *
+ * percentage *
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in *
+ * 'value' *
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_PERCENTILE(char **value, DC_ITEM *item, const char *parameters,
+ const zbx_timespec_t *ts, char **error)
+{
+ int nparams, arg1, time_shift, ret = FAIL, seconds = 0, nvalues = 0;
+ zbx_value_type_t arg1_type;
+ double percentage;
+ zbx_vector_history_record_t values;
+ zbx_timespec_t ts_end = *ts;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ zbx_history_record_vector_create(&values);
+
+ if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
+ {
+ *error = zbx_strdup(*error, "invalid value type");
+ goto out;
+ }
+
+ if (2 != (nparams = num_param(parameters)))
+ {
+ *error = zbx_strdup(*error, "invalid number of parameters");
+ goto out;
+ }
+
+ if (SUCCEED != get_function_parameter_hist_range(ts->sec, parameters, 1, &arg1, &arg1_type, &time_shift) ||
+ ZBX_VALUE_NONE == arg1_type)
+ {
+ *error = zbx_strdup(*error, "invalid first parameter");
+ goto out;
+ }
+
+
+ switch (arg1_type)
+ {
+ case ZBX_VALUE_SECONDS:
+ seconds = arg1;
+ break;
+ case ZBX_VALUE_NVALUES:
+ nvalues = arg1;
+ break;
+ default:
+ THIS_SHOULD_NEVER_HAPPEN;
+ }
+
+ ts_end.sec -= time_shift;
+
+ if (SUCCEED != get_function_parameter_float(parameters, 2, ZBX_FLAG_DOUBLE_PLAIN, &percentage) ||
+ 0.0 > percentage || 100.0 < percentage)
+ {
+ *error = zbx_strdup(*error, "invalid second parameter");
+ goto out;
+ }
+
+ if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
+ {
+ *error = zbx_strdup(*error, "cannot get values from value cache");
+ goto out;
+ }
+
+ if (0 < values.values_num)
+ {
+ int index;
+
+ if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
+ zbx_vector_history_record_sort(&values, (zbx_compare_func_t)__history_record_float_compare);
+ else
+ zbx_vector_history_record_sort(&values, (zbx_compare_func_t)__history_record_uint64_compare);
+
+ if (0 == percentage)
+ index = 1;
+ else
+ index = (int)ceil(values.values_num * (percentage / 100));
+
+ *value = zbx_history_value2str_dyn(&values.values[index - 1].value, item->value_type);
+
+ ret = SUCCEED;
+ }
+ else
+ {
+ zabbix_log(LOG_LEVEL_DEBUG, "result for PERCENTILE is empty");
+ *error = zbx_strdup(*error, "not enough data");
+ }
+out:
+ zbx_history_record_vector_destroy(&values, item->value_type);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: evaluate_NODATA *
+ * *
+ * Purpose: evaluate function 'nodata' for the item *
+ * *
+ * Parameters: item - item (performance metric) *
+ * parameter - number of seconds *
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_NODATA(char **value, DC_ITEM *item, const char *parameters, char **error)
+{
+ int arg1, num, period, lazy = 1, ret = FAIL;
+ zbx_value_type_t arg1_type;
+ zbx_vector_history_record_t values;
+ zbx_timespec_t ts;
+ char *arg2 = NULL;
+ zbx_proxy_suppress_t nodata_win;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ zbx_history_record_vector_create(&values);
+
+ if (2 < (num = num_param(parameters)))
+ {
+ *error = zbx_strdup(*error, "invalid number of parameters");
+ goto out;
+ }
+
+ if (SUCCEED != get_function_parameter_int(parameters, 1, ZBX_PARAM_MANDATORY, &arg1, &arg1_type) ||
+ ZBX_VALUE_SECONDS != arg1_type || 0 >= arg1)
+ {
+ *error = zbx_strdup(*error, "invalid first parameter");
+ goto out;
+ }
+
+ if (1 < num && (SUCCEED != get_function_parameter_str(parameters, 2, &arg2) ||
+ ('\0' != *arg2 && 0 != (lazy = strcmp("strict", arg2)))))
+ {
+ *error = zbx_strdup(*error, "invalid second parameter");
+ goto out;
+ }
+
+ zbx_timespec(&ts);
+ nodata_win.flags = ZBX_PROXY_SUPPRESS_DISABLE;
+
+ if (0 != item->host.proxy_hostid && 0 != lazy)
+ {
+ int lastaccess;
+
+ if (SUCCEED != DCget_proxy_nodata_win(item->host.proxy_hostid, &nodata_win, &lastaccess))
+ {
+ *error = zbx_strdup(*error, "cannot retrieve proxy last access");
+ goto out;
+ }
+
+ period = arg1 + (ts.sec - lastaccess);
+ }
+ else
+ period = arg1;
+
+ if (SUCCEED == zbx_vc_get_values(item->itemid, item->value_type, &values, period, 1, &ts) &&
+ 1 == values.values_num)
+ {
+ *value = zbx_strdup(*value, "0");
+ }
+ else
+ {
+ int seconds;
+
+ if (SUCCEED != DCget_data_expected_from(item->itemid, &seconds))
+ {
+ *error = zbx_strdup(*error, "item does not exist, is disabled or belongs to a disabled host");
+ goto out;
+ }
+
+ if (seconds + arg1 > ts.sec)
+ {
+ *error = zbx_strdup(*error,
+ "item does not have enough data after server start or item creation");
+ goto out;
+ }
+
+ if (0 != (nodata_win.flags & ZBX_PROXY_SUPPRESS_ACTIVE))
+ {
+ *error = zbx_strdup(*error, "historical data transfer from proxy is still in progress");
+ goto out;
+ }
+
+ *value = zbx_strdup(*value, "1");
+
+ if (0 != item->host.proxy_hostid && 0 != lazy)
+ {
+ zabbix_log(LOG_LEVEL_TRACE, "Nodata in %s() flag:%d values_num:%d start_time:%d period:%d",
+ __func__, nodata_win.flags, nodata_win.values_num, ts.sec - period, period);
+ }
+ }
+
+ ret = SUCCEED;
+out:
+ zbx_history_record_vector_destroy(&values, item->value_type);
+ zbx_free(arg2);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+
+/******************************************************************************
+ * *
+ * Function: evaluate_FUZZYTIME *
+ * *
+ * Purpose: evaluate function 'fuzzytime' for the item *
+ * *
+ * Parameters: item - item (performance metric) *
+ * parameter - number of seconds *
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_FUZZYTIME(char **value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts,
+ char **error)
+{
+ int arg1, ret = FAIL;
+ zbx_value_type_t arg1_type;
+ zbx_history_record_t vc_value;
+ zbx_uint64_t fuzlow, fuzhig;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
+ {
+ *error = zbx_strdup(*error, "invalid value type");
+ goto out;
+ }
+
+ if (1 < num_param(parameters))
+ {
+ *error = zbx_strdup(*error, "invalid number of parameters");
+ goto out;
+ }
+
+ if (SUCCEED != get_function_parameter_int(parameters, 1, ZBX_PARAM_MANDATORY, &arg1, &arg1_type) || 0 >= arg1)
+ {
+ *error = zbx_strdup(*error, "invalid first parameter");
+ goto out;
+ }
+
+ if (ZBX_VALUE_SECONDS != arg1_type || ts->sec <= arg1)
+ {
+ *error = zbx_strdup(*error, "invalid argument type or value");
+ goto out;
+ }
+
+ if (SUCCEED != zbx_vc_get_value(item->itemid, item->value_type, ts, &vc_value))
+ {
+ *error = zbx_strdup(*error, "cannot get value from value cache");
+ goto out;
+ }
+
+ fuzlow = (int)(ts->sec - arg1);
+ fuzhig = (int)(ts->sec + arg1);
+
+ if (ITEM_VALUE_TYPE_UINT64 == item->value_type)
+ {
+ if (vc_value.value.ui64 >= fuzlow && vc_value.value.ui64 <= fuzhig)
+ *value = zbx_strdup(*value, "1");
+ else
+ *value = zbx_strdup(*value, "0");
+ }
+ else
+ {
+ if (vc_value.value.dbl >= fuzlow && vc_value.value.dbl <= fuzhig)
+ *value = zbx_strdup(*value, "1");
+ else
+ *value = zbx_strdup(*value, "0");
+ }
+
+ zbx_history_record_clear(&vc_value, item->value_type);
+
+ ret = SUCCEED;
+out:
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: evaluate_BAND *
+ * *
+ * Purpose: evaluate logical bitwise function 'and' for the item *
+ * *
+ * Parameters: value - dynamic buffer *
+ * item - item (performance metric) *
+ * parameters - up to 3 comma-separated fields: *
+ * (1) same as the 1st parameter for function *
+ * evaluate_LAST() (see documentation of *
+ * trigger function last()), *
+ * (2) mask to bitwise AND with (mandatory), *
+ * (3) same as the 2nd parameter for function *
+ * evaluate_LAST() (see documentation of *
+ * trigger function last()). *
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_BAND(char **value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts,
+ char **error)
+{
+ char *last_parameters = NULL;
+ int nparams, ret = FAIL;
+ zbx_uint64_t last_uint64, mask;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ if (ITEM_VALUE_TYPE_UINT64 != item->value_type)
+ {
+ *error = zbx_strdup(*error, "invalid value type");
+ goto clean;
+ }
+
+ if (2 < (nparams = num_param(parameters)))
+ {
+ *error = zbx_strdup(*error, "invalid number of parameters");
+ goto clean;
+ }
+
+ if (SUCCEED != get_function_parameter_uint64(parameters, 2, &mask))
+ {
+ *error = zbx_strdup(*error, "invalid second parameter");
+ goto clean;
+ }
+
+ /* prepare the 1st and the 3rd parameter for passing to evaluate_LAST() */
+ last_parameters = zbx_function_get_param_dyn(parameters, 1);
+
+ if (SUCCEED == evaluate_LAST(value, item, last_parameters, ts, error))
+ {
+ ZBX_STR2UINT64(last_uint64, *value);
+ /* 'and' bit operation cannot be larger than the source value, */
+ /* so the result can just be copied in value buffer */
+ zbx_snprintf(*value, strlen(*value) + 1, ZBX_FS_UI64, last_uint64 & (zbx_uint64_t)mask);
+ ret = SUCCEED;
+ }
+
+ zbx_free(last_parameters);
+clean:
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: evaluate_FORECAST *
+ * *
+ * Purpose: evaluate function 'forecast' for the item *
+ * *
+ * Parameters: item - item (performance metric) *
+ * parameters - number of seconds/values and time shift (optional)*
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_FORECAST(char **value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts,
+ char **error)
+{
+ char *fit_str = NULL, *mode_str = NULL;
+ double *t = NULL, *x = NULL;
+ int nparams, time, arg1, i, ret = FAIL, seconds = 0, nvalues = 0, time_shift;
+ zbx_value_type_t time_type, arg1_type;
+ unsigned int k = 0;
+ zbx_vector_history_record_t values;
+ zbx_timespec_t zero_time;
+ zbx_fit_t fit;
+ zbx_mode_t mode;
+ zbx_timespec_t ts_end = *ts;
+ size_t value_alloc = 0, value_offset = 0;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ zbx_history_record_vector_create(&values);
+
+ if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
+ {
+ *error = zbx_strdup(*error, "invalid value type");
+ goto out;
+ }
+
+ if (2 > (nparams = num_param(parameters)) || nparams > 4)
+ {
+ *error = zbx_strdup(*error, "invalid number of parameters");
+ goto out;
+ }
+
+ if (SUCCEED != get_function_parameter_hist_range(ts->sec, parameters, 1, &arg1, &arg1_type, &time_shift) ||
+ ZBX_VALUE_NONE == arg1_type)
+ {
+ *error = zbx_strdup(*error, "invalid first parameter");
+ goto out;
+ }
+
+ if (SUCCEED != get_function_parameter_int(parameters, 2, ZBX_PARAM_MANDATORY, &time, &time_type) ||
+ ZBX_VALUE_SECONDS != time_type)
+ {
+ *error = zbx_strdup(*error, "invalid second parameter");
+ goto out;
+ }
+
+ if (4 <= nparams)
+ {
+ if (SUCCEED != get_function_parameter_str(parameters, 3, &fit_str) ||
+ SUCCEED != zbx_fit_code(fit_str, &fit, &k, error))
+ {
+ *error = zbx_strdup(*error, "invalid third parameter");
+ goto out;
+ }
+ }
+ else
+ {
+ fit = FIT_LINEAR;
+ }
+
+ if (4 == nparams)
+ {
+ if (SUCCEED != get_function_parameter_str(parameters, 4, &mode_str) ||
+ SUCCEED != zbx_mode_code(mode_str, &mode, error))
+ {
+ *error = zbx_strdup(*error, "invalid fourth parameter");
+ goto out;
+ }
+ }
+ else
+ {
+ mode = MODE_VALUE;
+ }
+
+ switch (arg1_type)
+ {
+ case ZBX_VALUE_SECONDS:
+ seconds = arg1;
+ break;
+ case ZBX_VALUE_NVALUES:
+ nvalues = arg1;
+ break;
+ default:
+ THIS_SHOULD_NEVER_HAPPEN;
+ }
+
+ ts_end.sec -= time_shift;
+
+ if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
+ {
+ *error = zbx_strdup(*error, "cannot get values from value cache");
+ goto out;
+ }
+
+ if (0 < values.values_num)
+ {
+ t = (double *)zbx_malloc(t, values.values_num * sizeof(double));
+ x = (double *)zbx_malloc(x, values.values_num * sizeof(double));
+
+ zero_time.sec = values.values[values.values_num - 1].timestamp.sec;
+ zero_time.ns = values.values[values.values_num - 1].timestamp.ns;
+
+ if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
+ {
+ for (i = 0; i < values.values_num; i++)
+ {
+ t[i] = values.values[i].timestamp.sec - zero_time.sec + 1.0e-9 *
+ (values.values[i].timestamp.ns - zero_time.ns + 1);
+ x[i] = values.values[i].value.dbl;
+ }
+ }
+ else
+ {
+ for (i = 0; i < values.values_num; i++)
+ {
+ t[i] = values.values[i].timestamp.sec - zero_time.sec + 1.0e-9 *
+ (values.values[i].timestamp.ns - zero_time.ns + 1);
+ x[i] = values.values[i].value.ui64;
+ }
+ }
+
+ zbx_snprintf_alloc(value, &value_alloc, &value_offset, ZBX_FS_DBL64, zbx_forecast(t, x,
+ values.values_num, ts->sec - zero_time.sec - 1.0e-9 * (zero_time.ns + 1), time, fit, k,
+ mode));
+ }
+ else
+ {
+ zabbix_log(LOG_LEVEL_DEBUG, "no data available");
+ zbx_snprintf_alloc(value, &value_alloc, &value_offset, ZBX_FS_DBL64, ZBX_MATH_ERROR);
+ }
+
+ ret = SUCCEED;
+out:
+ zbx_history_record_vector_destroy(&values, item->value_type);
+
+ zbx_free(fit_str);
+ zbx_free(mode_str);
+
+ zbx_free(t);
+ zbx_free(x);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: evaluate_TIMELEFT *
+ * *
+ * Purpose: evaluate function 'timeleft' for the item *
+ * *
+ * Parameters: item - item (performance metric) *
+ * parameters - number of seconds/values and time shift (optional)*
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_TIMELEFT(char **value, DC_ITEM *item, const char *parameters, const zbx_timespec_t *ts,
+ char **error)
+{
+ char *fit_str = NULL;
+ double *t = NULL, *x = NULL, threshold;
+ int nparams, arg1, i, ret = FAIL, seconds = 0, nvalues = 0, time_shift;
+ zbx_value_type_t arg1_type;
+ unsigned k = 0;
+ zbx_vector_history_record_t values;
+ zbx_timespec_t zero_time;
+ zbx_fit_t fit;
+ zbx_timespec_t ts_end = *ts;
+ size_t value_alloc = 0, value_offset = 0;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ zbx_history_record_vector_create(&values);
+
+ if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
+ {
+ *error = zbx_strdup(*error, "invalid value type");
+ goto out;
+ }
+
+ if (2 > (nparams = num_param(parameters)) || nparams > 3)
+ {
+ *error = zbx_strdup(*error, "invalid number of parameters");
+ goto out;
+ }
+
+ if (SUCCEED != get_function_parameter_hist_range(ts->sec, parameters, 1, &arg1, &arg1_type, &time_shift) ||
+ ZBX_VALUE_NONE == arg1_type)
+ {
+ *error = zbx_strdup(*error, "invalid first parameter");
+ goto out;
+ }
+
+ if (SUCCEED != get_function_parameter_float( parameters, 2, ZBX_FLAG_DOUBLE_SUFFIX, &threshold))
+ {
+ *error = zbx_strdup(*error, "invalid second parameter");
+ goto out;
+ }
+
+ if (4 == nparams)
+ {
+ if (SUCCEED != get_function_parameter_str(parameters, 3, &fit_str) ||
+ SUCCEED != zbx_fit_code(fit_str, &fit, &k, error))
+ {
+ *error = zbx_strdup(*error, "invalid third parameter");
+ goto out;
+ }
+ }
+ else
+ {
+ fit = FIT_LINEAR;
+ }
+
+ if ((FIT_EXPONENTIAL == fit || FIT_POWER == fit) && 0.0 >= threshold)
+ {
+ *error = zbx_strdup(*error, "exponential and power functions are always positive");
+ goto out;
+ }
+
+ switch (arg1_type)
+ {
+ case ZBX_VALUE_SECONDS:
+ seconds = arg1;
+ break;
+ case ZBX_VALUE_NVALUES:
+ nvalues = arg1;
+ break;
+ default:
+ THIS_SHOULD_NEVER_HAPPEN;
+ }
+
+ ts_end.sec -= time_shift;
+
+ if (FAIL == zbx_vc_get_values(item->itemid, item->value_type, &values, seconds, nvalues, &ts_end))
+ {
+ *error = zbx_strdup(*error, "cannot get values from value cache");
+ goto out;
+ }
+
+ if (0 < values.values_num)
+ {
+ t = (double *)zbx_malloc(t, values.values_num * sizeof(double));
+ x = (double *)zbx_malloc(x, values.values_num * sizeof(double));
+
+ zero_time.sec = values.values[values.values_num - 1].timestamp.sec;
+ zero_time.ns = values.values[values.values_num - 1].timestamp.ns;
+
+ if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
+ {
+ for (i = 0; i < values.values_num; i++)
+ {
+ t[i] = values.values[i].timestamp.sec - zero_time.sec + 1.0e-9 *
+ (values.values[i].timestamp.ns - zero_time.ns + 1);
+ x[i] = values.values[i].value.dbl;
+ }
+ }
+ else
+ {
+ for (i = 0; i < values.values_num; i++)
+ {
+ t[i] = values.values[i].timestamp.sec - zero_time.sec + 1.0e-9 *
+ (values.values[i].timestamp.ns - zero_time.ns + 1);
+ x[i] = values.values[i].value.ui64;
+ }
+ }
+
+ zbx_snprintf_alloc(value, &value_alloc, &value_offset, ZBX_FS_DBL64, zbx_timeleft(t, x,
+ values.values_num, ts->sec - zero_time.sec - 1.0e-9 * (zero_time.ns + 1), threshold,
+ fit, k));
+ }
+ else
+ {
+ zabbix_log(LOG_LEVEL_DEBUG, "no data available");
+ zbx_snprintf_alloc(value, &value_alloc, &value_offset, ZBX_FS_DBL64, ZBX_MATH_ERROR);
+ }
+
+ ret = SUCCEED;
+out:
+ zbx_history_record_vector_destroy(&values, item->value_type);
+
+ zbx_free(fit_str);
+
+ zbx_free(t);
+ zbx_free(x);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: evaluate_TREND *
+ * *
+ * Purpose: evaluate trend* functions for the item *
+ * *
+ * Parameters: value - [OUT] the function result *
+ * item - [IN] item (performance metric) *
+ * func - [IN] the trend function to evaluate *
+ * (avg, sum, count, delta, max, min) *
+ * parameters - [IN] function parameters *
+ * ts - [IN] the historical time when function must be *
+ * evaluated *
+ * *
+ * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
+ * FAIL - failed to evaluate function *
+ * *
+ ******************************************************************************/
+static int evaluate_TREND(char **value, DC_ITEM *item, const char *func, const char *parameters,
+ const zbx_timespec_t *ts, char **error)
+{
+ int ret = FAIL, start, end;
+ char *period = NULL, *period_shift = NULL;
+ const char *table;
+ double value_dbl;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+ if (SUCCEED != get_function_parameter_str(parameters, 1, &period))
+ {
+ *error = zbx_strdup(*error, "invalid first parameter");
+ goto out;
+ }
+
+ if (SUCCEED != get_function_parameter_str(parameters, 2, &period_shift))
+ {
+ *error = zbx_strdup(*error, "invalid second parameter");
+ goto out;
+ }
+
+ if (SUCCEED != zbx_trends_parse_range(ts->sec, parameters, &start, &end, error))
+ goto out;
+
+ switch (item->value_type)
+ {
+ case ITEM_VALUE_TYPE_FLOAT:
+ table = "trends";
+ break;
+ case ITEM_VALUE_TYPE_UINT64:
+ table = "trends_uint";
+ break;
+ default:
+ *error = zbx_strdup(*error, "unsupported value type");
+ goto out;
+ }
+
+ if (0 == strcmp(func, "avg"))
+ {
+ ret = zbx_trends_eval_avg(table, item->itemid, start, end, &value_dbl, error);
+ }
+ else if (0 == strcmp(func, "count"))
+ {
+ ret = zbx_trends_eval_count(table, item->itemid, start, end, &value_dbl, error);
+ }
+ else if (0 == strcmp(func, "delta"))
+ {
+ ret = zbx_trends_eval_delta(table, item->itemid, start, end, &value_dbl, error);
+ }
+ else if (0 == strcmp(func, "max"))
+ {
+ ret = zbx_trends_eval_max(table, item->itemid, start, end, &value_dbl, error);
+ }
+ else if (0 == strcmp(func, "min"))
+ {
+ ret = zbx_trends_eval_min(table, item->itemid, start, end, &value_dbl, error);
+ }
+ else if (0 == strcmp(func, "sum"))
+ {
+ ret = zbx_trends_eval_sum(table, item->itemid, start, end, &value_dbl, error);
+ }
+ else
+ {
+ *error = zbx_strdup(*error, "unknown trend function");
+ goto out;
+ }
+
+ if (SUCCEED == ret)
+ *value = zbx_dsprintf(*value, ZBX_FS_DBL64, value_dbl);
+out:
+ zbx_free(period);
+ zbx_free(period_shift);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+ return ret;
+}
+
+/******************************************************************************
+ * *
+ * Function: evaluate_function *
+ * *
+ * Purpose: evaluate function *
+ * *
+ * Parameters: item - item to calculate function for *
+ * function - function (for example, 'max') *
+ * parameter - parameter of the function *
+ * *
+ * Return value: SUCCEED - evaluated successfully, value contains its value *
+ * FAIL - evaluation failed *
+ * *
+ ******************************************************************************/
+int evaluate_function2(char **value, DC_ITEM *item, const char *function, const char *parameter,
+ const zbx_timespec_t *ts, char **error)
+{
+ int ret;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s() function:'%s:%s.%s(%s)' ts:'%s\'", __func__,
+ item->host.host, item->key_orig, function, parameter, zbx_timespec_str(ts));
+
+ if (0 == strcmp(function, "last"))
+ {
+ ret = evaluate_LAST(value, item, parameter, ts, error);
+ }
+ else if (0 == strcmp(function, "prev"))
+ {
+ ret = evaluate_LAST(value, item, "#2", ts, error);
+ }
+ else if (0 == strcmp(function, "min"))
+ {
+ ret = evaluate_MIN(value, item, parameter, ts, error);
+ }
+ else if (0 == strcmp(function, "max"))
+ {
+ ret = evaluate_MAX(value, item, parameter, ts, error);
+ }
+ else if (0 == strcmp(function, "avg"))
+ {
+ ret = evaluate_AVG(value, item, parameter, ts, error);
+ }
+ else if (0 == strcmp(function, "sum"))
+ {
+ ret = evaluate_SUM(value, item, parameter, ts, error);
+ }
+ else if (0 == strcmp(function, "percentile"))
+ {
+ ret = evaluate_PERCENTILE(value, item, parameter, ts, error);
+ }
+ else if (0 == strcmp(function, "count"))
+ {
+ ret = evaluate_COUNT(value, item, parameter, ts, ZBX_MAX_UINT31_1, error);
+ }
+ else if (0 == strcmp(function, "nodata"))
+ {
+ ret = evaluate_NODATA(value, item, parameter, error);
+ }
+ else if (0 == strcmp(function, "find"))
+ {
+ ret = evaluate_COUNT(value, item, parameter, ts, 1, error);
+ }
+ else if (0 == strcmp(function, "fuzzytime"))
+ {
+ ret = evaluate_FUZZYTIME(value, item, parameter, ts, error);
+ }
+ else if (0 == strcmp(function, "logeventid"))
+ {
+ ret = evaluate_LOGEVENTID(value, item, parameter, ts, error);
+ }
+ else if (0 == strcmp(function, "logseverity"))
+ {
+ ret = evaluate_LOGSEVERITY(value, item, ts, error);
+ }
+ else if (0 == strcmp(function, "logsource"))
+ {
+ ret = evaluate_LOGSOURCE(value, item, parameter, ts, error);
+ }
+ else if (0 == strcmp(function, "band"))
+ {
+ ret = evaluate_BAND(value, item, parameter, ts, error);
+ }
+ else if (0 == strcmp(function, "forecast"))
+ {
+ ret = evaluate_FORECAST(value, item, parameter, ts, error);
+ }
+ else if (0 == strcmp(function, "timeleft"))
+ {
+ ret = evaluate_TIMELEFT(value, item, parameter, ts, error);
+ }
+ else if (0 == strncmp(function, "trend", 5))
+ {
+ ret = evaluate_TREND(value, item, function + 5, parameter, ts, error);
+ }
+ else
+ {
+ *error = zbx_strdup(*error, "function is not supported");
+ ret = FAIL;
+ }
+
+ if (SUCCEED == ret)
+ del_zeros(*value);
+
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s value:'%s'", __func__, zbx_result_string(ret), ZBX_NULL2STR(*value));
+
+ return ret;
+}
diff --git a/src/libs/zbxserver/expression.c b/src/libs/zbxserver/expression.c
index 93ad8c92b22..0d4af94b683 100644
--- a/src/libs/zbxserver/expression.c
+++ b/src/libs/zbxserver/expression.c
@@ -5128,7 +5128,7 @@ static void zbx_evaluate_item_functions(zbx_hashset_t *funcs)
continue;
}
- if (SUCCEED != evaluate_function(&value, &items[i], func->function, func->parameter, &func->timespec,
+ if (SUCCEED != evaluate_function2(&value, &items[i], func->function, func->parameter, &func->timespec,
&error))
{
/* compose and store error message for future use */
diff --git a/src/libs/zbxtrends/trends.c b/src/libs/zbxtrends/trends.c
index 3ed8d841898..7e9286f0392 100644
--- a/src/libs/zbxtrends/trends.c
+++ b/src/libs/zbxtrends/trends.c
@@ -106,76 +106,39 @@ int zbx_trends_parse_base(const char *params, zbx_time_unit_t *base, char **erro
/******************************************************************************
* *
- * Function: zbx_trends_parse_range *
+ * Function: trends_parse_timeshift *
* *
- * Purpose: parse trend function period arguments into time range *
+ * Purpose: parse timeshift *
* *
- * Parameters: from - [IN] the time the period shift is calculated *
- * from *
- * period - [IN] the history period *
- * period_shift - [IN] the history period shift *
- * start - [OUT] the period start time in seconds since *
- * Epoch *
- * end - [OUT] the period end time in seconds since *
- * Epoch *
- * error - [OUT] the error message if parsing failed *
+ * Parameters: from - [IN] the start time *
+ * timeshift - [IN] the timeshift string *
+ * min_time_unit - [IN] minimum time unit that can be used *
+ * tm - [IN] the shifted time *
+ * error - [OUT] the error message if parsing failed *
* *
- * Return value: SUCCEED - period was parsed successfully *
- * FAIL - invalid time period was specified *
- * *
- * Comments: Daylight saving changes are applied when parsing ranges with *
- * day+ used as period base (now/?). *
- * *
- * Example period_shift values: *
- * now/d *
- * now/d-1h *
- * now/d+1h *
- * now/d+1h/w *
- * now/d/w/h+1h+2h *
- * now-1d/h *
+ * Return value: SUCCEED - time shift was parsed successfully *
+ * FAIL - otherwise *
* *
******************************************************************************/
-int zbx_trends_parse_range(time_t from, const char *period, const char *period_shift, int *start, int *end,
+static int trends_parse_timeshift(time_t from, const char *timeshift, zbx_time_unit_t min_time_unit, struct tm *tm,
char **error)
{
- int period_num, period_hours[ZBX_TIME_UNIT_COUNT] = {0, 1, 24, 24 * 7, 24 * 30, 24 * 365};
- zbx_time_unit_t period_unit;
size_t len;
- struct tm tm_end, tm_start;
const char *p;
- zabbix_log(LOG_LEVEL_DEBUG, "In %s() period:%s shift:%s", __func__, period, period_shift);
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s() shift:%s", __func__, timeshift);
- /* parse period */
-
- if (SUCCEED != zbx_tm_parse_period(period, &len, &period_num, &period_unit, error))
- return FAIL;
-
- if ('\0' != period[len])
- {
- *error = zbx_dsprintf(*error, "unexpected character[s] in period \"%s\"", period + len);
- return FAIL;
- }
-
- if (period_hours[period_unit] * period_num > 24 * 366)
- {
- *error = zbx_strdup(*error, "period is too large");
- return FAIL;
- }
-
- /* parse period shift */
-
- p = period_shift;
+ p = timeshift;
if (0 != strncmp(p, "now", ZBX_CONST_STRLEN("now")))
{
- *error = zbx_strdup(*error, "period shift must begin with \"now\"");
+ *error = zbx_strdup(*error, "time shift must begin with \"now\"");
return FAIL;
}
p += ZBX_CONST_STRLEN("now");
- localtime_r(&from, &tm_end);
+ localtime_r(&from, tm);
while ('\0' != *p)
{
@@ -189,14 +152,14 @@ int zbx_trends_parse_range(time_t from, const char *period, const char *period_s
return FAIL;
}
- if (unit < period_unit)
+ if (unit < min_time_unit)
{
- *error = zbx_dsprintf(*error, "time units in period shift must be greater or equal"
+ *error = zbx_dsprintf(*error, "time units in time shift must be greater or equal"
" to period time unit");
return FAIL;
}
- zbx_tm_round_down(&tm_end, unit);
+ zbx_tm_round_down(tm, unit);
/* unit is single character */
p++;
@@ -209,7 +172,7 @@ int zbx_trends_parse_range(time_t from, const char *period, const char *period_s
if (FAIL == zbx_tm_parse_period(p, &len, &num, &unit, error))
return FAIL;
- if (unit < period_unit)
+ if (unit < min_time_unit)
{
*error = zbx_dsprintf(*error, "time units in period shift must be greater or equal"
" to period time unit");
@@ -217,9 +180,9 @@ int zbx_trends_parse_range(time_t from, const char *period, const char *period_s
}
if ('+' == op)
- zbx_tm_add(&tm_end, num, unit);
+ zbx_tm_add(tm, num, unit);
else
- zbx_tm_sub(&tm_end, num, unit);
+ zbx_tm_sub(tm, num, unit);
p += len;
}
@@ -230,6 +193,94 @@ int zbx_trends_parse_range(time_t from, const char *period, const char *period_s
}
}
+ zabbix_log(LOG_LEVEL_DEBUG, "End of %s() %04d.%02d.%02d %02d:%02d:%02d", __func__, tm->tm_year + 1900,
+ tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ return SUCCEED;
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_parse_timeshift *
+ * *
+ * Purpose: parse timeshift *
+ * *
+ * Parameters: from - [IN] the start time *
+ * timeshift - [IN] the timeshift string *
+ * tm - [IN] the shifted time *
+ * error - [OUT] the error message if parsing failed *
+ * *
+ * Return value: SUCCEED - time shift was parsed successfully *
+ * FAIL - otherwise *
+ * *
+ ******************************************************************************/
+int zbx_parse_timeshift(time_t from, const char *timeshift, struct tm *tm, char **error)
+{
+ return trends_parse_timeshift(from, timeshift, ZBX_TIME_UNIT_UNKNOWN, tm, error);
+}
+
+/******************************************************************************
+ * *
+ * Function: zbx_trends_parse_range *
+ * *
+ * Purpose: parse trend function period arguments into time range *
+ * *
+ * Parameters: from - [IN] the time the period shift is calculated *
+ * from *
+ * period - [IN] the history period *
+ * period_shift - [IN] the history period shift *
+ * start - [OUT] the period start time in seconds since *
+ * Epoch *
+ * end - [OUT] the period end time in seconds since *
+ * Epoch *
+ * error - [OUT] the error message if parsing failed *
+ * *
+ * Return value: SUCCEED - period was parsed successfully *
+ * FAIL - invalid time period was specified *
+ * *
+ * Comments: Daylight saving changes are applied when parsing ranges with *
+ * day+ used as period base (now/?). *
+ * *
+ * Example period_shift values: *
+ * now/d *
+ * now/d-1h *
+ * now/d+1h *
+ * now/d+1h/w *
+ * now/d/w/h+1h+2h *
+ * now-1d/h *
+ * *
+ ******************************************************************************/
+int zbx_trends_parse_range(time_t from, const char *param, int *start, int *end, char **error)
+{
+ int period_num, period_hours[ZBX_TIME_UNIT_COUNT] = {0, 0, 0, 1, 24, 24 * 7, 24 * 30, 24 * 365};
+ zbx_time_unit_t period_unit;
+ size_t len;
+ struct tm tm_end, tm_start;
+
+ zabbix_log(LOG_LEVEL_DEBUG, "In %s() param:%s", __func__, param);
+
+ /* parse period */
+
+ if (SUCCEED != zbx_tm_parse_period(param, &len, &period_num, &period_unit, error))
+ return FAIL;
+
+ if ('\0' != param[len] && ':' != param[len])
+ {
+ *error = zbx_dsprintf(*error, "unexpected character[s] in period \"%s\"", param + len);
+ return FAIL;
+ }
+
+ if (period_hours[period_unit] * period_num > 24 * 366)
+ {
+ *error = zbx_strdup(*error, "period is too large");
+ return FAIL;
+ }
+
+ /* parse period shift */
+
+ if (SUCCEED != trends_parse_timeshift(from, param + len + 1, period_unit, &tm_end, error))
+ return FAIL;
+
tm_start = tm_end;
/* trends clock refers to the beginning of the hourly interval - subtract */
@@ -285,7 +336,7 @@ int zbx_trends_parse_nextcheck(time_t from, const char *period_shift, time_t *ne
struct tm tm;
zbx_time_unit_t base;
- if (SUCCEED != trends_parse_base(period_shift, &base, error))
+ if (SUCCEED != trends_parse_base(period_shift, &base, error) || ZBX_TIME_UNIT_HOUR > base)
return FAIL;
/* parse period shift */
diff --git a/tests/libs/zbxcommon/zbx_tm_add.yaml b/tests/libs/zbxcommon/zbx_tm_add.yaml
index 4c6c00d8db5..5e04bbea7ec 100644
--- a/tests/libs/zbxcommon/zbx_tm_add.yaml
+++ b/tests/libs/zbxcommon/zbx_tm_add.yaml
@@ -166,5 +166,53 @@ in:
param: 1d
out:
time: 2020-01-30 00:00:00 +00:00
+---
+test case: 2020-09-01 00:00:00 +03:00 + 1m
+in:
+ timezone: :Europe/Riga
+ time: 2020-09-01 00:00:00 +03:00
+ param: 1m
+out:
+ time: 2020-09-01 00:01:00 +03:00
+---
+test case: 2020-09-01 00:59:00 +03:00 + 1m
+in:
+ timezone: :Europe/Riga
+ time: 2020-09-01 00:59:00 +03:00
+ param: 1m
+out:
+ time: 2020-09-01 01:00:00 +03:00
+---
+test case: 2020-03-29 02:59:00 +02:00 + 1m
+in:
+ timezone: :Europe/Riga
+ time: 2020-03-29 02:59:00 +02:00
+ param: 1m
+out:
+ time: 2020-03-29 03:00:00 +03:00
+---
+test case: 2020-09-01 00:00:00 +03:00 + 1s
+in:
+ timezone: :Europe/Riga
+ time: 2020-09-01 00:00:00 +03:00
+ param: 1s
+out:
+ time: 2020-09-01 00:00:01 +03:00
+---
+test case: 2020-09-01 00:00:59 +03:00 + 1s
+in:
+ timezone: :Europe/Riga
+ time: 2020-09-01 00:00:59 +03:00
+ param: 1s
+out:
+ time: 2020-09-01 00:01:00 +03:00
+---
+test case: 2020-03-29 02:59:59 +02:00 + 1s
+in:
+ timezone: :Europe/Riga
+ time: 2020-03-29 02:59:59 +02:00
+ param: 1s
+out:
+ time: 2020-03-29 03:00:00 +03:00
...
diff --git a/tests/libs/zbxcommon/zbx_tm_round_down.yaml b/tests/libs/zbxcommon/zbx_tm_round_down.yaml
index 0ff6b745081..0f4f3e9871f 100644
--- a/tests/libs/zbxcommon/zbx_tm_round_down.yaml
+++ b/tests/libs/zbxcommon/zbx_tm_round_down.yaml
@@ -94,5 +94,21 @@ in:
base: w
out:
time: 2020-09-07 00:00:00 +03:00
+---
+test case: 2020-09-01 00:00:00 +03:00 / m
+in:
+ timezone: :Europe/Riga
+ time: 2020-09-01 00:00:00 +03:00
+ base: m
+out:
+ time: 2020-09-01 00:00:00 +03:00
+---
+test case: 2020-09-01 00:01:01 +03:00 / m
+in:
+ timezone: :Europe/Riga
+ time: 2020-09-01 00:01:01 +03:00
+ base: m
+out:
+ time: 2020-09-01 00:01:00 +03:00
...
diff --git a/tests/libs/zbxcommon/zbx_tm_round_up.yaml b/tests/libs/zbxcommon/zbx_tm_round_up.yaml
index fb803b6c52d..463bfe62617 100644
--- a/tests/libs/zbxcommon/zbx_tm_round_up.yaml
+++ b/tests/libs/zbxcommon/zbx_tm_round_up.yaml
@@ -70,5 +70,21 @@ in:
base: y
out:
time: 2021-01-01 00:00:00 +02:00
+---
+test case: 2020-09-01 00:00:00 +03:00 / m
+in:
+ timezone: :Europe/Riga
+ time: 2020-09-01 00:00:00 +03:00
+ base: m
+out:
+ time: 2020-09-01 00:00:00 +03:00
+---
+test case: 2020-09-01 00:00:01 +03:00 / m
+in:
+ timezone: :Europe/Riga
+ time: 2020-09-01 00:00:01 +03:00
+ base: m
+out:
+ time: 2020-09-01 00:01:00 +03:00
...
diff --git a/tests/libs/zbxcommon/zbx_tm_sub.yaml b/tests/libs/zbxcommon/zbx_tm_sub.yaml
index cee97408550..d9bb0fbccfe 100644
--- a/tests/libs/zbxcommon/zbx_tm_sub.yaml
+++ b/tests/libs/zbxcommon/zbx_tm_sub.yaml
@@ -174,4 +174,36 @@ in:
param: 1h
out:
time: 2019-12-31 23:00:00 +02:00
+---
+test case: 2020-09-01 12:00:00 +03:00 - 1m
+in:
+ timezone: :Europe/Riga
+ time: 2020-09-01 12:00:00 +03:00
+ param: 1m
+out:
+ time: 2020-09-01 11:59:00 +03:00
+---
+test case: 2020-10-25 03:00:00 +02:00 - 1m
+in:
+ timezone: :Europe/Riga
+ time: 2020-10-25 03:00:00 +02:00
+ param: 1m
+out:
+ time: 2020-10-25 02:59:00 +03:00
+---
+test case: 2020-09-01 12:00:00 +03:00 - 1s
+in:
+ timezone: :Europe/Riga
+ time: 2020-09-01 12:00:00 +03:00
+ param: 1s
+out:
+ time: 2020-09-01 11:59:59 +03:00
+---
+test case: 2020-10-25 03:00:00 +02:00 - 1s
+in:
+ timezone: :Europe/Riga
+ time: 2020-10-25 03:00:00 +02:00
+ param: 1s
+out:
+ time: 2020-10-25 02:59:59 +03:00
...
diff --git a/tests/libs/zbxserver/evaluate_function.c b/tests/libs/zbxserver/evaluate_function.c
index 0ae935bf135..dc4e30870bf 100644
--- a/tests/libs/zbxserver/evaluate_function.c
+++ b/tests/libs/zbxserver/evaluate_function.c
@@ -97,7 +97,7 @@ void zbx_mock_test_entry(void **state)
zbx_vcmock_set_time(handle, "time");
ts = zbx_vcmock_get_ts();
- if (SUCCEED != (returned_ret = evaluate_function(&returned_value, &item, function, params, &ts, &error)))
+ if (SUCCEED != (returned_ret = evaluate_function2(&returned_value, &item, function, params, &ts, &error)))
printf("evaluate_function returned error: %s\n", error);
expected_ret = zbx_mock_str_to_return_code(zbx_mock_get_parameter_string("out.return"));
@@ -122,5 +122,7 @@ void zbx_mock_test_entry(void **state)
}
zbx_free(returned_value);
+ zbx_vcmock_ds_destroy();
+
ZBX_UNUSED(state);
}
diff --git a/tests/libs/zbxserver/evaluate_function.yaml b/tests/libs/zbxserver/evaluate_function.yaml
index aa6ce9db17f..ca67c24eaa1 100644
--- a/tests/libs/zbxserver/evaluate_function.yaml
+++ b/tests/libs/zbxserver/evaluate_function.yaml
@@ -16,7 +16,7 @@ out:
return: SUCCEED
value: 0.2
---
-test case: Evaluate last(#2) <- 0.1, 0.2
+test case: Evaluate last(2) <- 0.1, 0.2
in:
history:
- itemid: 1
@@ -28,7 +28,7 @@ in:
ts: 2017-01-10 10:00:30.000000000 +00:00
time: 2017-01-10 10:10:00.000000000 +00:00
function: last
- params: '#2'
+ params: '2'
out:
return: SUCCEED
value: 0.1
@@ -114,7 +114,7 @@ out:
return: SUCCEED
value: '"\"c:\\\""'
---
-test case: Evaluate abschange() <- 0.1, 0.2
+test case: Evaluate last(:now-10m) <- 0.1, 0.2
in:
history:
- itemid: 1
@@ -125,114 +125,13 @@ in:
- value: 0.2
ts: 2017-01-10 10:00:30.000000000 +00:00
time: 2017-01-10 10:10:00.000000000 +00:00
- function: abschange
- params: ''
+ function: last
+ params: :now-10m
out:
return: SUCCEED
value: 0.1
---
-test case: Evaluate abschange() <- 10, 7
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_UINT64
- data:
- - value: 10
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: 7
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: abschange
- params: ''
-out:
- return: SUCCEED
- value: 3
----
-test case: Evaluate abschange() <- 'a', 'b'
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_STR
- data:
- - value: a
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: b
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: abschange
- params: ''
-out:
- return: SUCCEED
- value: 1
----
-test case: Evaluate abschange() <- 'x', 'x'
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_TEXT
- data:
- - value: x
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: x
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: abschange
- params: ''
-out:
- return: SUCCEED
- value: 0
----
-test case: Evaluate abschange() <- @log 'a', 'b'
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_LOG
- data:
- - value: a
- source:
- logeventid: 1
- severity: 1
- timestamp: 2
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: b
- source:
- logeventid: 2
- severity: 1
- timestamp: 2
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: abschange
- params: ''
-out:
- return: SUCCEED
- value: 1
----
-test case: Evaluate abschange() <- @log 'x', 'x'
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_LOG
- data:
- - value: x
- source:
- logeventid: 1
- severity: 1
- timestamp: 2
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: x
- source:
- logeventid: 2
- severity: 1
- timestamp: 2
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: abschange
- params: ''
-out:
- return: SUCCEED
- value: 0
----
-test case: Evaluate avg(#2)
+test case: Evaluate avg(2)
in:
history:
- itemid: 1
@@ -250,7 +149,7 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: avg
- params: '#2'
+ params: 2
out:
return: SUCCEED
value: 4.5
@@ -273,12 +172,12 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: avg
- params: '3m'
+ params: 3m
out:
return: SUCCEED
value: 4
---
-test case: Evaluate avg(#2,1m)
+test case: Evaluate avg(2:now-1m)
in:
history:
- itemid: 1
@@ -296,12 +195,12 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: avg
- params: '#2,1m'
+ params: 2:now-1m
out:
return: SUCCEED
value: 3.5
---
-test case: Evaluate band(#1,1)
+test case: Evaluate band(1,1)
in:
history:
- itemid: 1
@@ -319,12 +218,12 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: band
- params: '#1,1'
+ params: '1,1'
out:
return: SUCCEED
value: 1
---
-test case: Evaluate band(#2,1)
+test case: Evaluate band(2,1)
in:
history:
- itemid: 1
@@ -342,12 +241,12 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: band
- params: '#2,1'
+ params: '2,1'
out:
return: SUCCEED
value: 0
---
-test case: Evaluate band(2m,2,1m)
+test case: Evaluate band(2:now-1m,2)
in:
history:
- itemid: 1
@@ -365,130 +264,12 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: band
- params: '#2,2,1m'
+ params: '2:now-1m,2'
out:
return: SUCCEED
value: 2
---
-test case: Evaluate change() <- 0.1, 0.2
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_FLOAT
- data:
- - value: 0.1
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: 0.2
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: change
- params: ''
-out:
- return: SUCCEED
- value: 0.1
----
-test case: Evaluate change() <- 10, 7
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_UINT64
- data:
- - value: 10
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: 7
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: change
- params: ''
-out:
- return: SUCCEED
- value: -3
----
-test case: Evaluate change() <- 'a', 'b'
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_STR
- data:
- - value: a
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: b
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: change
- params: ''
-out:
- return: SUCCEED
- value: 1
----
-test case: Evaluate change() <- 'x', 'x'
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_TEXT
- data:
- - value: x
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: x
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: change
- params: ''
-out:
- return: SUCCEED
- value: 0
----
-test case: Evaluate change() <- @log 'a', 'b'
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_LOG
- data:
- - value: a
- source:
- logeventid: 1
- severity: 1
- timestamp: 2
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: b
- source:
- logeventid: 2
- severity: 1
- timestamp: 2
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: change
- params: ''
-out:
- return: SUCCEED
- value: 1
----
-test case: Evaluate change() <- @log 'x', 'x'
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_LOG
- data:
- - value: x
- source:
- logeventid: 1
- severity: 1
- timestamp: 2
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: x
- source:
- logeventid: 2
- severity: 1
- timestamp: 2
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: change
- params: ''
-out:
- return: SUCCEED
- value: 0
----
-test case: Evaluate count(#3,4,ge)
+test case: Evaluate count(3,ge,4)
in:
history:
- itemid: 1
@@ -506,12 +287,12 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: count
- params: '#3,4,ge'
+ params: '3,ge,4'
out:
return: SUCCEED
value: 2
---
-test case: Evaluate count(#3,o,like)
+test case: Evaluate count(5m,like,"o")
in:
history:
- itemid: 1
@@ -529,12 +310,12 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: count
- params: '5m,"o",like'
+ params: '5m,like,"o"'
out:
return: SUCCEED
value: 2
---
-test case: Evaluate count(#3,o$,regexp)
+test case: Evaluate count(5m,regexp,"o$")
in:
history:
- itemid: 1
@@ -552,12 +333,12 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: count
- params: '5m,"o$",regexp'
+ params: '5m,regexp,"o$"'
out:
return: SUCCEED
value: 1
---
-test case: Evaluate count(#3,o,iregexp)
+test case: Evaluate count(5m,iregexp,"o")
in:
history:
- itemid: 1
@@ -575,12 +356,12 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: count
- params: '5m,"o",iregexp'
+ params: '5m,iregexp,"o"'
out:
return: SUCCEED
value: 3
---
-test case: Evaluate count(#3,1/3,band)
+test case: Evaluate count(3,band,1/3)
in:
history:
- itemid: 1
@@ -598,12 +379,12 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: count
- params: '5m,1/3,band'
+ params: '5m,band,1/3'
out:
return: SUCCEED
value: 2
---
-test case: Evaluate count(#3,2/3,band)
+test case: Evaluate count(5m,band,"2/3")
in:
history:
- itemid: 1
@@ -621,270 +402,12 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: count
- params: '5m,2/3,band'
-out:
- return: SUCCEED
- value: 1
----
-test case: Evaluate date()
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_UINT64
- data:
- - value: 1
- ts: 2017-01-10 10:01:00.000000000 +00:00
- time: 2017-12-23 12:34:56.000000000 +00:00
- function: date
- params: ''
-out:
- return: SUCCEED
- value: 20171223
----
-test case: Evaluate dayofmonth()
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_UINT64
- data:
- - value: 1
- ts: 2017-01-10 10:01:00.000000000 +00:00
- time: 2017-12-23 12:34:53.000000000 +00:00
- function: dayofmonth
- params: ''
-out:
- return: SUCCEED
- value: 23
----
-test case: Evaluate dayofweek()
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_UINT64
- data:
- - value: 1
- ts: 2017-01-10 10:01:00.000000000 +00:00
- time: 2020-03-17 12:34:53.000000000 +00:00
- function: dayofweek
- params: ''
-out:
- return: SUCCEED
- value: 2
----
-test case: Evaluate time()
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_UINT64
- data:
- - value: 1
- ts: 2017-01-10 10:01:00.000000000 +00:00
- time: 2017-12-23 12:34:56.000000000 +00:00
- function: time
- params: ''
-out:
- return: SUCCEED
- value: 123456
----
-test case: Evaluate delta(#4)
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_UINT64
- data:
- - value: 0
- ts: 2017-01-10 10:01:00.000000000 +00:00
- - value: 2
- ts: 2017-01-10 10:02:00.000000000 +00:00
- - value: 3
- ts: 2017-01-10 10:03:00.000000000 +00:00
- - value: 4
- ts: 2017-01-10 10:04:00.000000000 +00:00
- - value: 5
- ts: 2017-01-10 10:05:00.000000000 +00:00
- time: 2017-01-10 10:05:00.000000000 +00:00
- function: delta
- params: '#4'
-out:
- return: SUCCEED
- value: 3
----
-test case: Evaluate delta(4m,1m)
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_UINT64
- data:
- - value: 0
- ts: 2017-01-10 10:01:00.000000000 +00:00
- - value: 2
- ts: 2017-01-10 10:02:00.000000000 +00:00
- - value: 3
- ts: 2017-01-10 10:03:00.000000000 +00:00
- - value: 4
- ts: 2017-01-10 10:04:00.000000000 +00:00
- - value: 5
- ts: 2017-01-10 10:05:00.000000000 +00:00
- time: 2017-01-10 10:05:00.000000000 +00:00
- function: delta
- params: '4m,1m'
-out:
- return: SUCCEED
- value: 4
----
-test case: Evaluate diff() <- 0.1, 0.2
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_FLOAT
- data:
- - value: 0.1
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: 0.2
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: diff
- params: ''
-out:
- return: SUCCEED
- value: 1
----
-test case: Evaluate diff() <- 0.123, 0.123
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_FLOAT
- data:
- - value: 0.123
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: 0.123
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: diff
- params: ''
-out:
- return: SUCCEED
- value: 0
----
-test case: Evaluate diff() <- 10, 7
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_UINT64
- data:
- - value: 10
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: 7
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: diff
- params: ''
-out:
- return: SUCCEED
- value: 1
----
-test case: Evaluate diff() <- 1234567890, 1234567890
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_UINT64
- data:
- - value: 1234567890
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: 1234567890
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: diff
- params: ''
-out:
- return: SUCCEED
- value: 0
----
-test case: Evaluate diff() <- 'a', 'b'
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_STR
- data:
- - value: a
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: b
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: diff
- params: ''
-out:
- return: SUCCEED
- value: 1
----
-test case: Evaluate diff() <- 'x', 'x'
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_TEXT
- data:
- - value: x
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: x
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: diff
- params: ''
-out:
- return: SUCCEED
- value: 0
----
-test case: Evaluate diff() <- @log 'a', 'b'
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_LOG
- data:
- - value: a
- source:
- logeventid: 1
- severity: 1
- timestamp: 2
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: b
- source:
- logeventid: 2
- severity: 1
- timestamp: 2
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: diff
- params: ''
+ params: '5m,band,2/3'
out:
return: SUCCEED
value: 1
---
-test case: Evaluate diff() <- @log 'x', 'x'
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_LOG
- data:
- - value: x
- source:
- logeventid: 1
- severity: 1
- timestamp: 2
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: x
- source:
- logeventid: 2
- severity: 1
- timestamp: 2
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: diff
- params: ''
-out:
- return: SUCCEED
- value: 0
----
-test case: Evaluate forecast(#5,,1h)
+test case: Evaluate forecast(5,1h)
in:
history:
- itemid: 1
@@ -902,12 +425,12 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: forecast
- params: '#5,,1h'
+ params: '5,1h'
out:
return: SUCCEED
value: 65
---
-test case: Evaluate forecast(#5,1h,1h)
+test case: Evaluate forecast(5:now-1h,1h)
in:
history:
- itemid: 1
@@ -925,12 +448,12 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: forecast
- params: '#5,1h,1h'
+ params: '5:now-1h,1h'
out:
return: SUCCEED
value: -1
---
-test case: Evaluate fuzzytime(1) < @uint64
+test case: Evaluate fuzzytime(1s) < @uint64
in:
history:
- itemid: 1
@@ -940,12 +463,12 @@ in:
ts: 2017-01-10 10:01:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: fuzzytime
- params: '1'
+ params: '1s'
out:
return: SUCCEED
value: 0
---
-test case: Evaluate fuzzytime(1) < @float
+test case: Evaluate fuzzytime(1s) < @float
in:
history:
- itemid: 1
@@ -955,12 +478,12 @@ in:
ts: 2017-01-10 10:01:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: fuzzytime
- params: '1'
+ params: '1s'
out:
return: SUCCEED
value: 0
---
-test case: Evaluate iregexp(^o,#5)
+test case: Evaluate find(5,"iregexp","^o")
in:
history:
- itemid: 1
@@ -971,13 +494,13 @@ in:
- value: Two
ts: 2017-01-10 10:02:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
- function: iregexp
- params: '^o,#5'
+ function: find
+ params: '5,"iregexp","^o"'
out:
return: SUCCEED
value: 1
---
-test case: Evaluate regexp(^o,#5)
+test case: Evaluate find(5,"regexp","^o")
in:
history:
- itemid: 1
@@ -988,13 +511,13 @@ in:
- value: Two
ts: 2017-01-10 10:02:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
- function: regexp
- params: '^o,#5'
+ function: find
+ params: '5,"regexp","^o"'
out:
return: SUCCEED
value: 0
---
-test case: Evaluate str(o,#5)
+test case: Evaluate find(5,"like","o")
in:
history:
- itemid: 1
@@ -1005,13 +528,13 @@ in:
- value: Two
ts: 2017-01-10 10:02:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
- function: str
- params: 'o,#5'
+ function: find
+ params: '5,"like","o"'
out:
return: SUCCEED
value: 1
---
-test case: Evaluate logeventid(^12)
+test case: Evaluate logeventid("^12")
in:
history:
- itemid: 1
@@ -1025,12 +548,12 @@ in:
ts: 2017-01-10 10:00:00.000000000 +00:00
time: 2017-01-10 10:10:00.000000000 +00:00
function: logeventid
- params: '^12'
+ params: '"^12"'
out:
return: SUCCEED
value: 1
---
-test case: Evaluate logeventid(^34)
+test case: Evaluate logeventid("^34")
in:
history:
- itemid: 1
@@ -1044,7 +567,7 @@ in:
ts: 2017-01-10 10:00:00.000000000 +00:00
time: 2017-01-10 10:10:00.000000000 +00:00
function: logeventid
- params: '^34'
+ params: '"^34"'
out:
return: SUCCEED
value: 0
@@ -1068,7 +591,7 @@ out:
return: SUCCEED
value: 4
---
-test case: Evaluate logsource('(Application|System)') <- Application
+test case: Evaluate logsource("(Application|System)") <- Application
in:
history:
- itemid: 1
@@ -1147,7 +670,7 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: max
- params: '5m,2m'
+ params: '5m:now-2m'
out:
return: SUCCEED
value: 3
@@ -1193,7 +716,7 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: min
- params: '4m,2m'
+ params: '4m:now-2m'
out:
return: SUCCEED
value: 1
@@ -1228,22 +751,7 @@ out:
return: SUCCEED
value: 0
---
-test case: Evaluate now()
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_UINT64
- data:
- - value: 1
- ts: 2017-01-10 10:01:00.000000000 +00:00
- time: 2017-01-10 10:05:00.000000000 +00:00
- function: now
- params: ''
-out:
- return: SUCCEED
- value: 1484042700
----
-test case: Evaluate percentile(5m,,100)
+test case: Evaluate percentile(5m,100)
in:
history:
- itemid: 1
@@ -1261,12 +769,12 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: percentile
- params: '5m,,100'
+ params: '5m,100'
out:
return: SUCCEED
value: 5
---
-test case: Evaluate percentile(5m,,50)
+test case: Evaluate percentile(5m,50)
in:
history:
- itemid: 1
@@ -1284,132 +792,89 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: percentile
- params: '5m,,50'
+ params: '5m,50'
out:
return: SUCCEED
value: 3
---
-test case: Evaluate prev() <- 0.1, 0.2
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_FLOAT
- data:
- - value: 0.1
- ts: 2017-01-10 10:00:00.000000000 +00:00
- - value: 0.2
- ts: 2017-01-10 10:00:30.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: prev
- params: ''
-out:
- return: SUCCEED
- value: 0.1
----
-test case: Evaluate strlen()
+test case: Evaluate sum(4)
in:
history:
- itemid: 1
- value type: ITEM_VALUE_TYPE_STR
+ value type: ITEM_VALUE_TYPE_UINT64
data:
- - value: One
+ - value: 1
ts: 2017-01-10 10:01:00.000000000 +00:00
- - value: Two
+ - value: 2
ts: 2017-01-10 10:02:00.000000000 +00:00
- - value: Three
+ - value: 3
ts: 2017-01-10 10:03:00.000000000 +00:00
- - value: Four
+ - value: 4
ts: 2017-01-10 10:04:00.000000000 +00:00
- - value: Five
+ - value: 5
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
- function: strlen
- params: ''
+ function: sum
+ params: '4'
out:
return: SUCCEED
- value: 4
+ value: 14
---
-test case: Evaluate strlen(1m)
+test case: Evaluate sum(4m:now-1m)
in:
history:
- itemid: 1
- value type: ITEM_VALUE_TYPE_STR
+ value type: ITEM_VALUE_TYPE_UINT64
data:
- - value: One
+ - value: 1
ts: 2017-01-10 10:01:00.000000000 +00:00
- - value: Two
+ - value: 2
ts: 2017-01-10 10:02:00.000000000 +00:00
- - value: Three
+ - value: 3
ts: 2017-01-10 10:03:00.000000000 +00:00
- - value: Four
+ - value: 4
ts: 2017-01-10 10:04:00.000000000 +00:00
- - value: Five
+ - value: 5
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
- function: strlen
- params: '1m'
+ function: sum
+ params: '4m:now-1m'
out:
return: SUCCEED
- value: 4
+ value: 10
---
-test case: Evaluate strlen(,2m)
+test case: Evaluate sum(2m)
in:
history:
- itemid: 1
- value type: ITEM_VALUE_TYPE_STR
+ value type: ITEM_VALUE_TYPE_UINT64
data:
- - value: One
+ - value: 1
ts: 2017-01-10 10:01:00.000000000 +00:00
- - value: Two
+ - value: 2
+ ts: 2017-01-10 10:01:30.000000000 +00:00
+ - value: 3
ts: 2017-01-10 10:02:00.000000000 +00:00
- - value: Three
+ - value: 4
+ ts: 2017-01-10 10:02:30.000000000 +00:00
+ - value: 5
ts: 2017-01-10 10:03:00.000000000 +00:00
- - value: Four
+ - value: 6
+ ts: 2017-01-10 10:03:30.000000000 +00:00
+ - value: 7
ts: 2017-01-10 10:04:00.000000000 +00:00
- - value: Five
- ts: 2017-01-10 10:05:00.000000000 +00:00
- time: 2017-01-10 10:05:00.000000000 +00:00
- function: strlen
- params: ',2m'
-out:
- return: SUCCEED
- value: 5
----
-test case: Evaluate strlen() <- 😓
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_STR
- data:
- - value: 😓
+ - value: 8
+ ts: 2017-01-10 10:04:30.000000000 +00:00
+ - value: 9
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
- function: strlen
- params: ''
-out:
- return: SUCCEED
- value: 1
----
-test case: Evaluate strlen() <- @log
-in:
- history:
- - itemid: 1
- value type: ITEM_VALUE_TYPE_LOG
- data:
- - value: xyz
- source:
- logeventid: 1
- severity: 1
- timestamp: 2
- ts: 2017-01-10 10:00:00.000000000 +00:00
- time: 2017-01-10 10:10:00.000000000 +00:00
- function: strlen
- params: ''
+ function: sum
+ params: '2m'
out:
return: SUCCEED
- value: 3
+ value: 30
---
-test case: Evaluate sum(#4)
+test case: Evaluate sum(2)
in:
history:
- itemid: 1
@@ -1418,21 +883,29 @@ in:
- value: 1
ts: 2017-01-10 10:01:00.000000000 +00:00
- value: 2
- ts: 2017-01-10 10:02:00.000000000 +00:00
+ ts: 2017-01-10 10:01:30.000000000 +00:00
- value: 3
- ts: 2017-01-10 10:03:00.000000000 +00:00
+ ts: 2017-01-10 10:02:00.000000000 +00:00
- value: 4
- ts: 2017-01-10 10:04:00.000000000 +00:00
+ ts: 2017-01-10 10:02:30.000000000 +00:00
- value: 5
+ ts: 2017-01-10 10:03:00.000000000 +00:00
+ - value: 6
+ ts: 2017-01-10 10:03:30.000000000 +00:00
+ - value: 7
+ ts: 2017-01-10 10:04:00.000000000 +00:00
+ - value: 8
+ ts: 2017-01-10 10:04:30.000000000 +00:00
+ - value: 9
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: sum
- params: '#4'
+ params: '2'
out:
return: SUCCEED
- value: 14
+ value: 17
---
-test case: Evaluate sum(4m,1m)
+test case: Evaluate sum(2m:now-1m)
in:
history:
- itemid: 1
@@ -1441,36 +914,60 @@ in:
- value: 1
ts: 2017-01-10 10:01:00.000000000 +00:00
- value: 2
- ts: 2017-01-10 10:02:00.000000000 +00:00
+ ts: 2017-01-10 10:01:30.000000000 +00:00
- value: 3
- ts: 2017-01-10 10:03:00.000000000 +00:00
+ ts: 2017-01-10 10:02:00.000000000 +00:00
- value: 4
- ts: 2017-01-10 10:04:00.000000000 +00:00
+ ts: 2017-01-10 10:02:30.000000000 +00:00
- value: 5
+ ts: 2017-01-10 10:03:00.000000000 +00:00
+ - value: 6
+ ts: 2017-01-10 10:03:30.000000000 +00:00
+ - value: 7
+ ts: 2017-01-10 10:04:00.000000000 +00:00
+ - value: 8
+ ts: 2017-01-10 10:04:30.000000000 +00:00
+ - value: 9
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: sum
- params: '4m,1m'
+ params: '2m:now-1m'
out:
return: SUCCEED
- value: 10
+ value: 22
---
-test case: Evaluate time()
+test case: Evaluate sum(2:now-1m)
in:
history:
- itemid: 1
value type: ITEM_VALUE_TYPE_UINT64
data:
- value: 1
- ts: 2017-01-10 10:00:00.000000000 +00:00
- time: 2017-12-23 12:34:56.000000000 +00:00
- function: time
- params: ''
+ ts: 2017-01-10 10:01:00.000000000 +00:00
+ - value: 2
+ ts: 2017-01-10 10:01:30.000000000 +00:00
+ - value: 3
+ ts: 2017-01-10 10:02:00.000000000 +00:00
+ - value: 4
+ ts: 2017-01-10 10:02:30.000000000 +00:00
+ - value: 5
+ ts: 2017-01-10 10:03:00.000000000 +00:00
+ - value: 6
+ ts: 2017-01-10 10:03:30.000000000 +00:00
+ - value: 7
+ ts: 2017-01-10 10:04:00.000000000 +00:00
+ - value: 8
+ ts: 2017-01-10 10:04:30.000000000 +00:00
+ - value: 9
+ ts: 2017-01-10 10:05:00.000000000 +00:00
+ time: 2017-01-10 10:05:00.000000000 +00:00
+ function: sum
+ params: '2:now-1m'
out:
return: SUCCEED
- value: 123456
+ value: 13
---
-test case: Evaluate timeleft(5m,,65)
+test case: Evaluate timeleft(5m,65)
in:
history:
- itemid: 1
@@ -1488,7 +985,7 @@ in:
ts: 2017-01-10 10:05:00.000000000 +00:00
time: 2017-01-10 10:05:00.000000000 +00:00
function: timeleft
- params: '5m,,65'
+ params: '5m,65'
out:
return: SUCCEED
value: 3600
diff --git a/tests/libs/zbxtrends/zbx_trends_parse_range.c b/tests/libs/zbxtrends/zbx_trends_parse_range.c
index 7a2eea47f95..f1d6c1fea55 100644
--- a/tests/libs/zbxtrends/zbx_trends_parse_range.c
+++ b/tests/libs/zbxtrends/zbx_trends_parse_range.c
@@ -51,7 +51,7 @@ DB_RESULT __wrap_DBselect(const char *fmt, ...)
void zbx_mock_test_entry(void **state)
{
- const char *period, *shift;
+ const char *param;
int expected_ret, returned_ret, start, end;
char *error = NULL;
zbx_timespec_t ts_from, ts_start, ts_end, ts;
@@ -66,11 +66,10 @@ void zbx_mock_test_entry(void **state)
if (ZBX_MOCK_SUCCESS != zbx_strtime_to_timespec(zbx_mock_get_parameter_string("in.time"), &ts_from))
fail_msg("Invalid input time format");
- period = zbx_mock_get_parameter_string("in.period");
- shift = zbx_mock_get_parameter_string("in.shift");
+ param = zbx_mock_get_parameter_string("in.param");
expected_ret = zbx_mock_str_to_return_code(zbx_mock_get_parameter_string("out.return"));
- returned_ret = zbx_trends_parse_range(ts_from.sec, period, shift, &start, &end, &error);
+ returned_ret = zbx_trends_parse_range(ts_from.sec, param, &start, &end, &error);
if (FAIL == returned_ret)
{
diff --git a/tests/libs/zbxtrends/zbx_trends_parse_range.yaml b/tests/libs/zbxtrends/zbx_trends_parse_range.yaml
index 2f2202322fb..aabcd17d562 100644
--- a/tests/libs/zbxtrends/zbx_trends_parse_range.yaml
+++ b/tests/libs/zbxtrends/zbx_trends_parse_range.yaml
@@ -1,8 +1,7 @@
---
test case: Invalid period ''
in:
- period:
- shift: now/h
+ param: :now/h
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -10,8 +9,7 @@ out:
---
test case: Invalid period 'h'
in:
- period: h
- shift: now/h
+ param: h:now/h
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -19,8 +17,7 @@ out:
---
test case: Invalid period '1'
in:
- period: 1
- shift: now/h
+ param: 1:now/h
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -28,8 +25,7 @@ out:
---
test case: Invalid period '1H'
in:
- period: 1H
- shift: now/h
+ param: 1H:now/h
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -37,8 +33,7 @@ out:
---
test case: Invalid period '0h'
in:
- period: 0h
- shift: now/h
+ param: 0h:now/h
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -46,8 +41,7 @@ out:
---
test case: Invalid period '12345678901234567890h'
in:
- period: 12345678901234567890h
- shift: now/h
+ param: 12345678901234567890h:now/h
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -55,8 +49,7 @@ out:
---
test case: Valid period '1h'
in:
- period: 1h
- shift: now/h
+ param: 1h:now/h
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -66,8 +59,7 @@ out:
---
test case: Invalid period shift '/h'
in:
- period: 1h
- shift: /h
+ param: 1h:/h
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -75,8 +67,7 @@ out:
---
test case: Invalid period shift 'now-1'
in:
- period: 1h
- shift: now-1
+ param: 1h:now-1
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -84,8 +75,7 @@ out:
---
test case: Invalid period shift 'now/h - 1'
in:
- period: 1h
- shift: now/h - 1
+ param: 1h:now/h - 1
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -93,8 +83,7 @@ out:
---
test case: Invalid period shift 'now/h-1'
in:
- period: 1h
- shift: now/h-1
+ param: 1h:now/h-1
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -102,8 +91,7 @@ out:
---
test case: Invalid period shift 'now/h - 1h'
in:
- period: 1h
- shift: now/h - 1h
+ param: 1h:now/h - 1h
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -111,8 +99,7 @@ out:
---
test case: Invalid period shift 'now/m-1m'
in:
- period: 1h
- shift: now/m-1m
+ param: 1h:now/m-1m
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -120,8 +107,7 @@ out:
---
test case: Valid parameters '1h,now/h-1h'
in:
- period: 1h
- shift: now/h-1h
+ param: 1h:now/h-1h
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -131,8 +117,7 @@ out:
---
test case: Valid parameters '1h,now/d'
in:
- period: 1h
- shift: now/d
+ param: 1h:now/d
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -142,8 +127,7 @@ out:
---
test case: Valid parameters '1h,now/h' from 2020-09-01 10:00:00.000000000 +03:00
in:
- period: 1h
- shift: now/h
+ param: 1h:now/h
timezone: :Europe/Riga
time: 2020-09-01 10:00:00.000000000 +03:00
out:
@@ -153,8 +137,7 @@ out:
---
test case: Valid parameters '1h,now/d' from 2020-09-01 10:00:00.000000000 +03:00
in:
- period: 1h
- shift: now/d
+ param: 1h:now/d
timezone: :Europe/Riga
time: 2020-09-01 10:00:00.000000000 +03:00
out:
@@ -164,8 +147,7 @@ out:
---
test case: Valid parameters '1h,now/h-1d' from 2020-09-01 10:00:00.000000000 +03:00
in:
- period: 1h
- shift: now/h-1d
+ param: 1h:now/h-1d
timezone: :Europe/Riga
time: 2020-09-01 10:00:00.000000000 +03:00
out:
@@ -175,8 +157,7 @@ out:
---
test case: Valid parameters '1d,now/w-6d' from 2020-09-01 10:00:00.000000000 +03:00
in:
- period: 1d
- shift: now/w-6d
+ param: 1d:now/w-6d
timezone: :Europe/Riga
time: 2020-09-01 10:00:00.000000000 +03:00
out:
@@ -186,8 +167,7 @@ out:
---
test case: Valid parameters '1d,now/M-1M+6d/w+1d' from 2020-09-18 10:00:00.000000000 +03:00
in:
- period: 1d
- shift: now/M-1M+6d/w+1d
+ param: 1d:now/M-1M+6d/w+1d
timezone: :Europe/Riga
time: 2020-09-18 10:00:00.000000000 +03:00
out:
@@ -197,8 +177,7 @@ out:
---
test case: Valid parameters '1w,now/M' from 2020-09-18 10:00:00.000000000 +03:00
in:
- period: 1w
- shift: now/M
+ param: 1w:now/M
timezone: :Europe/Riga
time: 2020-09-18 10:00:00.000000000 +03:00
out:
@@ -208,8 +187,7 @@ out:
---
test case: Valid parameters '1M,now/M' from 2020-09-18 10:00:00.000000000 +03:00
in:
- period: 1M
- shift: now/M
+ param: 1M:now/M
timezone: :Europe/Riga
time: 2020-09-18 10:00:00.000000000 +03:00
out:
@@ -219,8 +197,7 @@ out:
---
test case: Valid parameters '1M,now/M-1M' from 2020-09-18 10:00:00.000000000 +03:00
in:
- period: 1M
- shift: now/M-1M
+ param: 1M:now/M-1M
timezone: :Europe/Riga
time: 2020-09-18 10:00:00.000000000 +03:00
out:
@@ -230,8 +207,7 @@ out:
---
test case: Valid parameters '1M,now/M-2M' from 2020-09-18 10:00:00.000000000 +03:00
in:
- period: 1M
- shift: now/M-2M
+ param: 1M:now/M-2M
timezone: :Europe/Riga
time: 2020-09-18 10:00:00.000000000 +03:00
out:
@@ -241,8 +217,7 @@ out:
---
test case: Valid parameters '1d,now/y' from 2020-09-18 10:00:00.000000000 +03:00
in:
- period: 1d
- shift: now/y
+ param: 1d:now/y
timezone: :Europe/Riga
time: 2020-09-18 10:00:00.000000000 +03:00
out:
@@ -252,8 +227,7 @@ out:
---
test case: Valid parameters '1h,now-1d' from 2020-09-01 10:00:00.000000000 +03:00
in:
- period: 1h
- shift: now-1d
+ param: 1h:now-1d
timezone: :Europe/Riga
time: 2020-09-01 10:00:00.000000000 +03:00
out:
@@ -263,8 +237,7 @@ out:
---
test case: Valid parameters '3h,now-1d/h' from 2020-09-01 10:30:00.000000000 +03:00
in:
- period: 3h
- shift: now-1d/h
+ param: 3h:now-1d/h
timezone: :Europe/Riga
time: 2020-09-01 10:30:00.000000000 +03:00
out:
@@ -274,8 +247,7 @@ out:
---
test case: Valid parameters '3h,now+1d-3d/w' from 2020-09-01 10:30:00.000000000 +03:00
in:
- period: 3h
- shift: now+1d-3d/w
+ param: 3h:now+1d-3d/w
timezone: :Europe/Riga
time: 2020-09-01 10:30:00.000000000 +03:00
out:
@@ -285,8 +257,7 @@ out:
---
test case: Invalid parameters '1M,now/h' from 2020-09-18 10:00:00.000000000 +03:00
in:
- period: 1M
- shift: now/h
+ param: 1M:now/h
timezone: :Europe/Riga
time: 2020-09-18 10:00:00.000000000 +03:00
out:
@@ -294,8 +265,7 @@ out:
---
test case: Invalid parameters '1M,now/d' from 2020-09-18 10:00:00.000000000 +03:00
in:
- period: 1M
- shift: now/d
+ param: 1M:now/d
timezone: :Europe/Riga
time: 2020-09-18 10:00:00.000000000 +03:00
out:
@@ -303,8 +273,7 @@ out:
---
test case: Invalid parameters '1M,now/w' from 2020-09-18 10:00:00.000000000 +03:00
in:
- period: 1M
- shift: now/w
+ param: 1M:now/w
timezone: :Europe/Riga
time: 2020-09-18 10:00:00.000000000 +03:00
out:
@@ -312,8 +281,7 @@ out:
---
test case: Invalid parameters '1M,now/M-1h' from 2020-09-18 10:00:00.000000000 +03:00
in:
- period: 1M
- shift: now/M-1h
+ param: 1M:now/M-1h
timezone: :Europe/Riga
time: 2020-09-18 10:00:00.000000000 +03:00
out:
@@ -321,8 +289,7 @@ out:
---
test case: Invalid parameters '1M,now/M-1d' from 2020-09-18 10:00:00.000000000 +03:00
in:
- period: 1M
- shift: now/M-1d
+ param: 1M:now/M-1d
timezone: :Europe/Riga
time: 2020-09-18 10:00:00.000000000 +03:00
out:
@@ -330,8 +297,7 @@ out:
---
test case: Valid period '1y'
in:
- period: 1y
- shift: now/y
+ param: 1y:now/y
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -341,8 +307,7 @@ out:
---
test case: Valid period '12M'
in:
- period: 12M
- shift: now/y
+ param: 12M:now/y
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -352,8 +317,7 @@ out:
---
test case: Valid period '366d'
in:
- period: 366d
- shift: now/y
+ param: 366d:now/y
timezone: :Europe/Riga
time: 2021-09-01 00:00:00.000000000 +03:00
out:
@@ -363,8 +327,7 @@ out:
---
test case: Valid period '8784h'
in:
- period: 8784h
- shift: now/y
+ param: 8784h:now/y
timezone: :Europe/Riga
time: 2021-09-01 00:00:00.000000000 +03:00
out:
@@ -374,8 +337,7 @@ out:
---
test case: Invalid period '2y'
in:
- period: 2y
- shift: now/y
+ param: 2y:now/y
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -383,8 +345,7 @@ out:
---
test case: Invalid period '13M'
in:
- period: 13M
- shift: now/y
+ param: 13M:now/y
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -392,8 +353,7 @@ out:
---
test case: Invalid period '367d'
in:
- period: 367d
- shift: now/y
+ param: 367d:now/y
timezone: :Europe/Riga
time: 2020-09-01 00:00:00.000000000 +03:00
out:
@@ -401,8 +361,7 @@ out:
---
test case: Invalid period '8785h'
in:
- period: 8785h
- shift: now/y
+ param: 8785h:now/y
timezone: :Europe/Riga
time: 2021-09-01 00:00:00.000000000 +03:00
out:
@@ -410,8 +369,7 @@ out:
---
test case: Invalid shift '26y'
in:
- period: 1h
- shift: now/y-26y
+ param: 1h:now/y-26y
timezone: :Europe/Riga
time: 2021-09-01 00:00:00.000000000 +03:00
out:
@@ -419,8 +377,7 @@ out:
---
test case: Valid shift '25y'
in:
- period: 1h
- shift: now/y-25y
+ param: 1h:now/y-25y
timezone: :Europe/Riga
time: 2021-09-01 00:00:00.000000000 +03:00
out:
@@ -428,10 +385,9 @@ out:
end: 1995-12-31 23:00:00.000000000 +02:00
return: SUCCEED
---
-test case: Valid parameters '1h,now/M+6d/w+1h' from 2020-09-23 00:59:46.000000000 +03:00
+test case: Valid parameters '1h:now/M+6d/w+1h' from 2020-09-23 00:59:46.000000000 +03:00
in:
- period: 1h
- shift: now/M+6d/w+1h
+ param: 1h:now/M+6d/w+1h
timezone: :Europe/Riga
time: 2020-09-23 00:59:46.000000000 +03:00
out:
diff --git a/ui/include/defines.inc.php b/ui/include/defines.inc.php
index dc248420834..9cd8687be99 100644
--- a/ui/include/defines.inc.php
+++ b/ui/include/defines.inc.php
@@ -21,7 +21,7 @@
define('ZABBIX_VERSION', '5.4.0alpha1');
define('ZABBIX_API_VERSION', '5.4.0');
define('ZABBIX_EXPORT_VERSION', '5.4');
-define('ZABBIX_DB_VERSION', 5030026);
+define('ZABBIX_DB_VERSION', 5030025);
define('ZABBIX_COPYRIGHT_FROM', '2001');
define('ZABBIX_COPYRIGHT_TO', '2021');