diff options
author | Andris Zeila <andris.zeila@zabbix.com> | 2018-10-22 15:59:38 +0300 |
---|---|---|
committer | Andris Zeila <andris.zeila@zabbix.com> | 2018-10-22 15:59:38 +0300 |
commit | 3b3bcb51117fa60afe901de4a20a373e4e8bde13 (patch) | |
tree | 2bb6dc07e01ece00f3a8b602c066771333984f52 | |
parent | 755091f798cc252aa5ea437b6d8ad7c444ffba89 (diff) |
........S. [ZBXNEXT-4724] reworked preprocessing step history storage to support multiple history based steps
-rw-r--r-- | include/dbcache.h | 9 | ||||
-rw-r--r-- | src/libs/zbxdbcache/dbconfig.h | 2 | ||||
-rw-r--r-- | src/zabbix_server/preprocessor/Makefile.am | 3 | ||||
-rw-r--r-- | src/zabbix_server/preprocessor/item_preproc.c | 86 | ||||
-rw-r--r-- | src/zabbix_server/preprocessor/item_preproc.h | 2 | ||||
-rw-r--r-- | src/zabbix_server/preprocessor/preproc_history.c | 70 | ||||
-rw-r--r-- | src/zabbix_server/preprocessor/preproc_history.h | 50 | ||||
-rw-r--r-- | src/zabbix_server/preprocessor/preproc_manager.c | 79 | ||||
-rw-r--r-- | src/zabbix_server/preprocessor/preproc_worker.c | 51 | ||||
-rw-r--r-- | src/zabbix_server/preprocessor/preprocessing.c | 187 | ||||
-rw-r--r-- | src/zabbix_server/preprocessor/preprocessing.h | 10 | ||||
-rw-r--r-- | tests/zabbix_server/preprocessor/zbx_item_preproc.c | 44 | ||||
-rw-r--r-- | tests/zabbix_server/preprocessor/zbx_item_preproc.yaml | 30 |
13 files changed, 424 insertions, 199 deletions
diff --git a/include/dbcache.h b/include/dbcache.h index 5a4af26d77c..3343ac5759f 100644 --- a/include/dbcache.h +++ b/include/dbcache.h @@ -467,15 +467,6 @@ ZBX_DC_TREND; typedef struct { - zbx_uint64_t itemid; - zbx_timespec_t timestamp; - zbx_variant_t value; - unsigned char value_type; -} -zbx_item_history_value_t; - -typedef struct -{ zbx_uint64_t itemid; history_value_t value; zbx_uint64_t lastlogsize; diff --git a/src/libs/zbxdbcache/dbconfig.h b/src/libs/zbxdbcache/dbconfig.h index 4b1532a36dc..eab59441cd7 100644 --- a/src/libs/zbxdbcache/dbconfig.h +++ b/src/libs/zbxdbcache/dbconfig.h @@ -261,8 +261,6 @@ typedef struct } ZBX_DC_HTTPITEM; -typedef zbx_item_history_value_t ZBX_DC_DELTAITEM; - #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) typedef struct { diff --git a/src/zabbix_server/preprocessor/Makefile.am b/src/zabbix_server/preprocessor/Makefile.am index c2236b8e72b..c8ba4542bf7 100644 --- a/src/zabbix_server/preprocessor/Makefile.am +++ b/src/zabbix_server/preprocessor/Makefile.am @@ -8,7 +8,8 @@ libpreprocessor_a_SOURCES = \ preproc_manager.c preproc_manager.h \ item_preproc.c \ item_preproc.h \ - preprocessing.c preprocessing.h + preprocessing.c preprocessing.h \ + preproc_history.c preproc_history.h libpreprocessor_a_CFLAGS = \ @LIBXML2_CFLAGS@ diff --git a/src/zabbix_server/preprocessor/item_preproc.c b/src/zabbix_server/preprocessor/item_preproc.c index b7a8c7f217f..1873161e694 100644 --- a/src/zabbix_server/preprocessor/item_preproc.c +++ b/src/zabbix_server/preprocessor/item_preproc.c @@ -214,33 +214,34 @@ static int item_preproc_multiplier(unsigned char value_type, zbx_variant_t *valu * * * Purpose: execute delta type preprocessing operation * * * - * Parameters: value - [IN/OUT] the value to process * - * ts - [IN] the value timestamp * - * op_type - [IN] the operation type * - * hvalue - [IN] the item historical data * + * Parameters: value - [IN/OUT] the value to process * + * ts - [IN] the value timestamp * + * op_type - [IN] the operation type * + * history_value - [IN] the item historical data * + * history_ts - [IN] the historical data timestamp * * * * Return value: SUCCEED - the value was calculated successfully * * FAIL - otherwise * * * ******************************************************************************/ static int item_preproc_delta_float(zbx_variant_t *value, const zbx_timespec_t *ts, unsigned char op_type, - zbx_item_history_value_t *hvalue) + const zbx_variant_t *history_value, const zbx_timespec_t *history_ts) { - if (0 == hvalue->timestamp.sec || hvalue->value.data.dbl > value->data.dbl) + if (0 == history_ts->sec || history_value->data.dbl > value->data.dbl) return FAIL; switch (op_type) { case ZBX_PREPROC_DELTA_SPEED: - if (0 <= zbx_timespec_compare(&hvalue->timestamp, ts)) + if (0 <= zbx_timespec_compare(history_ts, ts)) return FAIL; - value->data.dbl = (value->data.dbl - hvalue->value.data.dbl) / - ((ts->sec - hvalue->timestamp.sec) + - (double)(ts->ns - hvalue->timestamp.ns) / 1000000000); + value->data.dbl = (value->data.dbl - history_value->data.dbl) / + ((ts->sec - history_ts->sec) + + (double)(ts->ns - history_ts->ns) / 1000000000); break; case ZBX_PREPROC_DELTA_VALUE: - value->data.dbl = value->data.dbl - hvalue->value.data.dbl; + value->data.dbl = value->data.dbl - history_value->data.dbl; break; } @@ -253,33 +254,34 @@ static int item_preproc_delta_float(zbx_variant_t *value, const zbx_timespec_t * * * * Purpose: execute delta type preprocessing operation * * * - * Parameters: value - [IN/OUT] the value to process * - * ts - [IN] the value timestamp * - * op_type - [IN] the operation type * - * hvalue - [IN] the item historical data * + * Parameters: value - [IN/OUT] the value to process * + * ts - [IN] the value timestamp * + * op_type - [IN] the operation type * + * history_value - [IN] the item historical data * + * history_ts - [IN] the historical data timestamp * * * * Return value: SUCCEED - the value was calculated successfully * * FAIL - otherwise * * * ******************************************************************************/ static int item_preproc_delta_uint64(zbx_variant_t *value, const zbx_timespec_t *ts, unsigned char op_type, - zbx_item_history_value_t *hvalue) + const zbx_variant_t *history_value, const zbx_timespec_t *history_ts) { - if (0 == hvalue->timestamp.sec || hvalue->value.data.ui64 > value->data.ui64) + if (0 == history_ts->sec || history_value->data.ui64 > value->data.ui64) return FAIL; switch (op_type) { case ZBX_PREPROC_DELTA_SPEED: - if (0 <= zbx_timespec_compare(&hvalue->timestamp, ts)) + if (0 <= zbx_timespec_compare(history_ts, ts)) return FAIL; - value->data.ui64 = (value->data.ui64 - hvalue->value.data.ui64) / - ((ts->sec - hvalue->timestamp.sec) + - (double)(ts->ns - hvalue->timestamp.ns) / 1000000000); + value->data.ui64 = (value->data.ui64 - history_value->data.ui64) / + ((ts->sec - history_ts->sec) + + (double)(ts->ns - history_ts->ns) / 1000000000); break; case ZBX_PREPROC_DELTA_VALUE: - value->data.ui64 = value->data.ui64 - hvalue->value.data.ui64; + value->data.ui64 = value->data.ui64 - history_value->data.ui64; break; } @@ -296,8 +298,8 @@ static int item_preproc_delta_uint64(zbx_variant_t *value, const zbx_timespec_t * value - [IN/OUT] the value to process * * ts - [IN] the value timestamp * * op_type - [IN] the operation type * - * history_value - [IN] historical data of item with delta * - * preprocessing operation * + * history_value - [IN/OUT] the historical (previuous) data * + * history_ts - [IN/OUT] the timestamp of the historical data * * errmsg - [OUT] error message * * * * Return value: SUCCEED - the value was calculated successfully * @@ -305,7 +307,7 @@ static int item_preproc_delta_uint64(zbx_variant_t *value, const zbx_timespec_t * * ******************************************************************************/ static int item_preproc_delta(unsigned char value_type, zbx_variant_t *value, const zbx_timespec_t *ts, - unsigned char op_type, zbx_item_history_value_t *history_value, char **errmsg) + unsigned char op_type, zbx_variant_t *history_value, zbx_timespec_t *history_ts, char **errmsg) { int ret = FAIL; zbx_variant_t value_num; @@ -316,21 +318,21 @@ static int item_preproc_delta(unsigned char value_type, zbx_variant_t *value, co zbx_variant_clear(value); zbx_variant_set_variant(value, &value_num); - if (ZBX_VARIANT_DBL == value->type || ZBX_VARIANT_DBL == history_value->value.type) + if (ZBX_VARIANT_DBL == value->type || ZBX_VARIANT_DBL == history_value->type) { zbx_variant_convert(value, ZBX_VARIANT_DBL); - zbx_variant_convert(&history_value->value, ZBX_VARIANT_DBL); - ret = item_preproc_delta_float(value, ts, op_type, history_value); + zbx_variant_convert(history_value, ZBX_VARIANT_DBL); + ret = item_preproc_delta_float(value, ts, op_type, history_value, history_ts); } else { zbx_variant_convert(value, ZBX_VARIANT_UI64); - zbx_variant_convert(&history_value->value, ZBX_VARIANT_UI64); - ret = item_preproc_delta_uint64(value, ts, op_type, history_value); + zbx_variant_convert(history_value, ZBX_VARIANT_UI64); + ret = item_preproc_delta_uint64(value, ts, op_type, history_value, history_ts); } - history_value->timestamp = *ts; - zbx_variant_set_variant(&history_value->value, &value_num); + *history_ts = *ts; + zbx_variant_set_variant(history_value, &value_num); zbx_variant_clear(&value_num); if (SUCCEED != ret) @@ -357,12 +359,15 @@ static int item_preproc_delta(unsigned char value_type, zbx_variant_t *value, co * * ******************************************************************************/ static int item_preproc_delta_value(unsigned char value_type, zbx_variant_t *value, const zbx_timespec_t *ts, - zbx_item_history_value_t *history_value, char **errmsg) + zbx_variant_t *history_value, zbx_timespec_t *history_ts, char **errmsg) { char *err = NULL; - if (SUCCEED == item_preproc_delta(value_type, value, ts, ZBX_PREPROC_DELTA_VALUE, history_value, &err)) + if (SUCCEED == item_preproc_delta(value_type, value, ts, ZBX_PREPROC_DELTA_VALUE, history_value, history_ts, + &err)) + { return SUCCEED; + } *errmsg = zbx_dsprintf(*errmsg, "cannot calculate delta (simple change) for value \"%s\" of type" " \"%s\": %s", zbx_variant_value_desc(value), zbx_variant_type_desc(value), err); @@ -390,12 +395,15 @@ static int item_preproc_delta_value(unsigned char value_type, zbx_variant_t *val * * ******************************************************************************/ static int item_preproc_delta_speed(unsigned char value_type, zbx_variant_t *value, const zbx_timespec_t *ts, - zbx_item_history_value_t *history_value, char **errmsg) + zbx_variant_t *history_value, zbx_timespec_t *history_ts, char **errmsg) { char *err = NULL; - if (SUCCEED == item_preproc_delta(value_type, value, ts, ZBX_PREPROC_DELTA_SPEED, history_value, &err)) + if (SUCCEED == item_preproc_delta(value_type, value, ts, ZBX_PREPROC_DELTA_SPEED, history_value, history_ts, + &err)) + { return SUCCEED; + } *errmsg = zbx_dsprintf(*errmsg, "cannot calculate delta (speed per second) for value \"%s\" of type" " \"%s\": %s", zbx_variant_value_desc(value), zbx_variant_type_desc(value), err); @@ -1380,7 +1388,7 @@ out: * * ******************************************************************************/ int zbx_item_preproc(int index, unsigned char value_type, zbx_variant_t *value, const zbx_timespec_t *ts, - const zbx_preproc_op_t *op, zbx_item_history_value_t *history_value, char **error) + const zbx_preproc_op_t *op, zbx_variant_t *history_value, zbx_timespec_t *history_ts, char **error) { int ret, error_handler = op->error_handler; char *errmsg = NULL; @@ -1412,10 +1420,10 @@ int zbx_item_preproc(int index, unsigned char value_type, zbx_variant_t *value, ret = item_preproc_hex2dec(value, &errmsg); break; case ZBX_PREPROC_DELTA_VALUE: - ret = item_preproc_delta_value(value_type, value, ts, history_value, &errmsg); + ret = item_preproc_delta_value(value_type, value, ts, history_value, history_ts, &errmsg); break; case ZBX_PREPROC_DELTA_SPEED: - ret = item_preproc_delta_speed(value_type, value, ts, history_value, &errmsg); + ret = item_preproc_delta_speed(value_type, value, ts, history_value, history_ts, &errmsg); break; case ZBX_PREPROC_XPATH: ret = item_preproc_xpath(value, op->params, &errmsg); diff --git a/src/zabbix_server/preprocessor/item_preproc.h b/src/zabbix_server/preprocessor/item_preproc.h index d0ae247f73d..044b856adde 100644 --- a/src/zabbix_server/preprocessor/item_preproc.h +++ b/src/zabbix_server/preprocessor/item_preproc.h @@ -23,7 +23,7 @@ #include "dbcache.h" int zbx_item_preproc(int index, unsigned char value_type, zbx_variant_t *value, const zbx_timespec_t *ts, - const zbx_preproc_op_t *op, zbx_item_history_value_t *history_value, char **errmsg); + const zbx_preproc_op_t *op, zbx_variant_t *history_value, zbx_timespec_t *history_ts, char **error); int zbx_item_preproc_convert_value_to_numeric(zbx_variant_t *value_num, const zbx_variant_t *value, unsigned char value_type, char **errmsg); diff --git a/src/zabbix_server/preprocessor/preproc_history.c b/src/zabbix_server/preprocessor/preproc_history.c new file mode 100644 index 00000000000..5ee22321764 --- /dev/null +++ b/src/zabbix_server/preprocessor/preproc_history.c @@ -0,0 +1,70 @@ +/* +** Zabbix +** Copyright (C) 2001-2018 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + +#include "common.h" +#include "log.h" + +#include "preproc_history.h" + +void zbx_preproc_op_history_free(zbx_preproc_op_history_t *ophistory) +{ + zbx_variant_clear(&ophistory->value); + zbx_free(ophistory); +} + +const zbx_preproc_op_history_t *zbx_preproc_history_get_value(zbx_vector_ptr_t *history, int type) +{ + int i; + zbx_preproc_op_history_t *ophistory; + + for (i = 0; i < history->values_num; i++) + { + ophistory = (zbx_preproc_op_history_t *)history->values[i]; + + if (ophistory->type == type) + return ophistory; + } + + return NULL; +} + +void zbx_preproc_history_set_value(zbx_vector_ptr_t *history, int type, const zbx_variant_t *data, + const zbx_timespec_t *ts) +{ + int i; + zbx_preproc_op_history_t *ophistory; + + for (i = 0; i < history->values_num; i++) + { + ophistory = (zbx_preproc_op_history_t *)history->values[i]; + + if (ophistory->type == type) + break; + } + + if (i == history->values_num) + { + ophistory = zbx_malloc(NULL, sizeof(zbx_preproc_op_history_t)); + ophistory->type = type; + zbx_vector_ptr_append(history, ophistory); + } + + zbx_variant_set_variant(&ophistory->value, data); + ophistory->ts = *ts; +} diff --git a/src/zabbix_server/preprocessor/preproc_history.h b/src/zabbix_server/preprocessor/preproc_history.h new file mode 100644 index 00000000000..3c38121ca09 --- /dev/null +++ b/src/zabbix_server/preprocessor/preproc_history.h @@ -0,0 +1,50 @@ +/* +** Zabbix +** Copyright (C) 2001-2018 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_PREPROC_HISTORY_H +#define ZABBIX_PREPROC_HISTORY_H + +#include "common.h" +#include "dbcache.h" + +#define ZBX_PREPROC_TYPE_NONE 0 +#define ZBX_PREPROC_TYPE_DELTA 1 +#define ZBX_PREPROC_TYPE_THROTTLE 2 + +typedef struct +{ + unsigned char type; + zbx_variant_t value; + zbx_timespec_t ts; +} +zbx_preproc_op_history_t; + +typedef struct +{ + zbx_uint64_t itemid; + zbx_vector_ptr_t history; +} +zbx_preproc_history_t; + +void zbx_preproc_op_history_free(zbx_preproc_op_history_t *ophistory); +const zbx_preproc_op_history_t *zbx_preproc_history_get_value(zbx_vector_ptr_t *history, int type); +void zbx_preproc_history_set_value(zbx_vector_ptr_t *history, int type, const zbx_variant_t *data, + const zbx_timespec_t *ts); + +#endif diff --git a/src/zabbix_server/preprocessor/preproc_manager.c b/src/zabbix_server/preprocessor/preproc_manager.c index 0ab0727ac29..4f714660eae 100644 --- a/src/zabbix_server/preprocessor/preproc_manager.c +++ b/src/zabbix_server/preprocessor/preproc_manager.c @@ -31,6 +31,7 @@ #include "preprocessing.h" #include "preproc_manager.h" #include "linked_list.h" +#include "preproc_history.h" extern unsigned char process_type, program_type; extern int server_num, process_num, CONFIG_PREPROCESSOR_FORKS; @@ -138,32 +139,12 @@ static void request_free_steps(zbx_preprocessing_request_t *request) ******************************************************************************/ static void preprocessor_sync_configuration(zbx_preprocessing_manager_t *manager) { - const char *__function_name = "preprocessor_sync_configuration"; - zbx_hashset_iter_t iter; - zbx_preproc_item_t *item, item_local; - zbx_item_history_value_t *history_value; - int ts; + const char *__function_name = "preprocessor_sync_configuration"; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); - ts = manager->cache_ts; DCconfig_get_preprocessable_items(&manager->item_config, &manager->cache_ts); - if (ts != manager->cache_ts) - { - zbx_hashset_iter_reset(&manager->history_cache, &iter); - while (NULL != (history_value = (zbx_item_history_value_t *)zbx_hashset_iter_next(&iter))) - { - item_local.itemid = history_value->itemid; - if (NULL == (item = (zbx_preproc_item_t *)zbx_hashset_search(&manager->item_config, &item_local)) || - history_value->value_type != item->value_type) - { - /* history value is removed if item was removed/disabled or item value type changed */ - zbx_hashset_iter_remove(&iter); - } - } - } - zabbix_log(LOG_LEVEL_DEBUG, "End of %s() item config size: %d, history cache size: %d", __function_name, manager->item_config.num_data, manager->history_cache.num_data); } @@ -281,8 +262,11 @@ static zbx_preprocessing_worker_t *preprocessor_get_free_worker(zbx_preprocessin static zbx_uint32_t preprocessor_create_task(zbx_preprocessing_manager_t *manager, zbx_preprocessing_request_t *request, unsigned char **task) { - zbx_uint32_t size; - zbx_variant_t value; + zbx_uint32_t size; + zbx_variant_t value; + zbx_preproc_history_t *vault; + zbx_vector_ptr_t *phistory; + if (ISSET_LOG(request->value.result)) zbx_variant_set_str(&value, request->value.result->log->value); @@ -297,9 +281,16 @@ static zbx_uint32_t preprocessor_create_task(zbx_preprocessing_manager_t *manage else THIS_SHOULD_NEVER_HAPPEN; + if (NULL != (vault = (zbx_preproc_history_t *)zbx_hashset_search(&manager->history_cache, + &request->value.itemid))) + { + phistory = &vault->history; + } + else + phistory = NULL; + size = zbx_preprocessor_pack_task(task, request->value.itemid, request->value_type, request->value.ts, &value, - (zbx_item_history_value_t *)zbx_hashset_search(&manager->history_cache, &request->value.itemid), - request->steps, request->steps_num); + phistory, request->steps, request->steps_num); return size; } @@ -854,33 +845,38 @@ static void preprocessor_add_result(zbx_preprocessing_manager_t *manager, zbx_ip zbx_preprocessing_request_t *request; zbx_variant_t value; char *error; - zbx_item_history_value_t *history_value, *cached_value; zbx_delta_item_index_t *index; + zbx_vector_ptr_t history; + zbx_preproc_history_t *vault; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); worker = preprocessor_get_worker_by_client(manager, client); request = (zbx_preprocessing_request_t *)worker->queue_item->data; - zbx_preprocessor_unpack_result(&value, &history_value, &error, message->data); + zbx_vector_ptr_create(&history); + zbx_preprocessor_unpack_result(&value, &history, &error, message->data); - if (NULL != history_value) + if (NULL != (vault = (zbx_preproc_history_t *)zbx_hashset_search(&manager->history_cache, + &request->value.itemid))) { - history_value->itemid = request->value.itemid; - history_value->value_type = request->value_type; + zbx_vector_ptr_clear_ext(&vault->history, (zbx_clean_func_t)zbx_preproc_op_history_free); + } - if (NULL != (cached_value = (zbx_item_history_value_t *)zbx_hashset_search(&manager->history_cache, history_value))) + if (0 != history.values_num) + { + if (NULL == vault) { - if (0 < zbx_timespec_compare(&history_value->timestamp, &cached_value->timestamp)) - { - /* history_value can only be numeric so it can be copied without extra memory */ - /* allocation */ - cached_value->timestamp = history_value->timestamp; - cached_value->value = history_value->value; - } + zbx_preproc_history_t history_local; + + history_local.itemid = request->value.itemid; + vault = (zbx_preproc_history_t *)zbx_hashset_insert(&manager->history_cache, &history_local, + sizeof(history_local)); + zbx_vector_ptr_create(&vault->history); } - else - zbx_hashset_insert(&manager->history_cache, history_value, sizeof(zbx_item_history_value_t)); + + zbx_vector_ptr_append_array(&vault->history, history.values, history.values_num); + zbx_vector_ptr_clear(&history); } request->state = REQUEST_STATE_DONE; @@ -901,13 +897,14 @@ static void preprocessor_add_result(zbx_preprocessing_manager_t *manager, zbx_ip worker->queue_item = NULL; zbx_variant_clear(&value); - zbx_free(history_value); manager->preproc_num--; preprocessor_assign_tasks(manager); preprocessing_flush_queue(manager); + zbx_vector_ptr_destroy(&history); + zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); } diff --git a/src/zabbix_server/preprocessor/preproc_worker.c b/src/zabbix_server/preprocessor/preproc_worker.c index 7ed797fbf98..01ce364d4de 100644 --- a/src/zabbix_server/preprocessor/preproc_worker.c +++ b/src/zabbix_server/preprocessor/preproc_worker.c @@ -28,6 +28,7 @@ #include "sysinfo.h" #include "preproc_worker.h" #include "item_preproc.h" +#include "preproc_history.h" extern unsigned char process_type, program_type; extern int server_num, process_num; @@ -47,50 +48,56 @@ static void worker_preprocess_value(zbx_ipc_socket_t *socket, zbx_ipc_message_t zbx_uint32_t size = 0; unsigned char *data = NULL, value_type; zbx_uint64_t itemid; - zbx_variant_t value, value_num; + zbx_variant_t value; int i, steps_num; char *error = NULL; zbx_timespec_t *ts; - zbx_item_history_value_t *history_value, history_value_local; zbx_preproc_op_t *steps; + zbx_vector_ptr_t history_in, history_out; + const zbx_preproc_op_history_t *ophistory; - zbx_preprocessor_unpack_task(&itemid, &value_type, &ts, &value, &history_value, &steps, &steps_num, + zbx_vector_ptr_create(&history_in); + zbx_vector_ptr_create(&history_out); + + zbx_preprocessor_unpack_task(&itemid, &value_type, &ts, &value, &history_in, &steps, &steps_num, message->data); for (i = 0; i < steps_num; i++) { zbx_preproc_op_t *op = &steps[i]; + zbx_variant_t history_value; + zbx_timespec_t history_ts; - if ((ZBX_PREPROC_DELTA_VALUE == op->type || ZBX_PREPROC_DELTA_SPEED == op->type) && - NULL == history_value) + if (NULL != (ophistory = zbx_preproc_history_get_value(&history_in, op->type))) { - if (FAIL != zbx_item_preproc_convert_value_to_numeric(&value_num, &value, value_type, &error)) - { - history_value_local.timestamp = *ts; - zbx_variant_set_variant(&history_value_local.value, &value_num); - history_value = &history_value_local; - } - - zbx_variant_clear(&value); - break; + history_value = ophistory->value; + history_ts = ophistory->ts; + } + else + { + zbx_variant_set_none(&history_value); + history_ts.sec = 0; + history_ts.ns = 0; } - if (SUCCEED != zbx_item_preproc(i + 1, value_type, &value, ts, op, history_value, &error)) + if (SUCCEED != zbx_item_preproc(i + 1, value_type, &value, ts, op, &history_value, &history_ts, &error)) break; + if (ZBX_VARIANT_NONE != history_value.type) + zbx_preproc_history_set_value(&history_out, op->type, &history_value, &history_ts); + + zbx_variant_clear(&history_value); + if (ZBX_VARIANT_NONE == value.type) break; } - size = zbx_preprocessor_pack_result(&data, &value, history_value, error); + size = zbx_preprocessor_pack_result(&data, &value, &history_out, error); zbx_variant_clear(&value); zbx_free(error); zbx_free(ts); zbx_free(steps); - if (history_value != &history_value_local) - zbx_free(history_value); - if (FAIL == zbx_ipc_socket_write(socket, ZBX_IPC_PREPROCESSOR_RESULT, data, size)) { zabbix_log(LOG_LEVEL_CRIT, "cannot send preprocessing result"); @@ -98,6 +105,12 @@ static void worker_preprocess_value(zbx_ipc_socket_t *socket, zbx_ipc_message_t } zbx_free(data); + + zbx_vector_ptr_clear_ext(&history_out, (zbx_clean_func_t)zbx_preproc_op_history_free); + zbx_vector_ptr_destroy(&history_out); + + zbx_vector_ptr_clear_ext(&history_in, (zbx_clean_func_t)zbx_preproc_op_history_free); + zbx_vector_ptr_destroy(&history_in); } ZBX_THREAD_ENTRY(preprocessing_worker_thread, args) diff --git a/src/zabbix_server/preprocessor/preprocessing.c b/src/zabbix_server/preprocessor/preprocessing.c index bd76aabfc19..fba4ad704a8 100644 --- a/src/zabbix_server/preprocessor/preprocessing.c +++ b/src/zabbix_server/preprocessor/preprocessing.c @@ -26,6 +26,7 @@ #include "preproc.h" #include "preprocessing.h" +#include "preproc_history.h" #define PACKED_FIELD_RAW 0 #define PACKED_FIELD_STRING 1 @@ -147,6 +148,7 @@ static zbx_uint32_t preprocessor_pack_value(zbx_ipc_message_t *message, zbx_prep if (NULL != value->result) { + *offset++ = PACKED_FIELD(&value->result->lastlogsize, sizeof(zbx_uint64_t)); *offset++ = PACKED_FIELD(&value->result->ui64, sizeof(zbx_uint64_t)); *offset++ = PACKED_FIELD(&value->result->dbl, sizeof(double)); @@ -183,7 +185,7 @@ static zbx_uint32_t preprocessor_pack_value(zbx_ipc_message_t *message, zbx_prep * value_type - [IN] item value type * * ts - [IN] value timestamp * * value - [IN] item value * - * history_value - [IN] history data for delta preprocessing * + * history - [IN] history data (can be NULL) * * steps - [IN] preprocessing steps * * steps_num - [IN] preprocessing step count * * * @@ -191,21 +193,24 @@ static zbx_uint32_t preprocessor_pack_value(zbx_ipc_message_t *message, zbx_prep * * ******************************************************************************/ zbx_uint32_t zbx_preprocessor_pack_task(unsigned char **data, zbx_uint64_t itemid, unsigned char value_type, - zbx_timespec_t *ts, zbx_variant_t *value, zbx_item_history_value_t *history_value, + zbx_timespec_t *ts, zbx_variant_t *value, const zbx_vector_ptr_t *history, const zbx_preproc_op_t *steps, int steps_num) { zbx_packed_field_t *offset, *fields; - unsigned char ts_marker, history_marker; + unsigned char ts_marker; zbx_uint32_t size; int i; zbx_ipc_message_t message; + unsigned char history_num; + + history_num = (NULL != history ? history->values_num : 0); /* 14 is a max field count (without preprocessing step fields) */ - fields = (zbx_packed_field_t *)zbx_malloc(NULL, (14 + steps_num * 4) * sizeof(zbx_packed_field_t)); + fields = (zbx_packed_field_t *)zbx_malloc(NULL, (10 + steps_num * 4 + history_num * 5) + * sizeof(zbx_packed_field_t)); offset = fields; ts_marker = (NULL != ts); - history_marker = (NULL != history_value); *offset++ = PACKED_FIELD(&itemid, sizeof(zbx_uint64_t)); *offset++ = PACKED_FIELD(&value_type, sizeof(unsigned char)); @@ -237,28 +242,34 @@ zbx_uint32_t zbx_preprocessor_pack_task(unsigned char **data, zbx_uint64_t itemi THIS_SHOULD_NEVER_HAPPEN; } - *offset++ = PACKED_FIELD(&history_marker, sizeof(unsigned char)); - if (NULL != history_value) + *offset++ = PACKED_FIELD(&history_num, sizeof(unsigned char)); + for (i = 0; i < history_num; i++) { - *offset++ = PACKED_FIELD(&history_value->value_type, sizeof(unsigned char)); - *offset++ = PACKED_FIELD(&history_value->value.type, sizeof(unsigned char)); + zbx_preproc_op_history_t *ophistory = (zbx_preproc_op_history_t *)history->values[i]; + + *offset++ = PACKED_FIELD(&ophistory->type, sizeof(unsigned char)); + *offset++ = PACKED_FIELD(&ophistory->value.type, sizeof(unsigned char)); - switch (history_value->value.type) + switch (ophistory->value.type) { case ZBX_VARIANT_UI64: - *offset++ = PACKED_FIELD(&history_value->value.data.ui64, sizeof(zbx_uint64_t)); + *offset++ = PACKED_FIELD(&ophistory->value.data.ui64, sizeof(zbx_uint64_t)); break; case ZBX_VARIANT_DBL: - *offset++ = PACKED_FIELD(&history_value->value.data.dbl, sizeof(double)); + *offset++ = PACKED_FIELD(&ophistory->value.data.dbl, sizeof(double)); + break; + + case ZBX_VARIANT_STR: + *offset++ = PACKED_FIELD(ophistory->value.data.str, 0); break; default: THIS_SHOULD_NEVER_HAPPEN; } - *offset++ = PACKED_FIELD(&history_value->timestamp.sec, sizeof(int)); - *offset++ = PACKED_FIELD(&history_value->timestamp.ns, sizeof(int)); + *offset++ = PACKED_FIELD(&ophistory->ts.sec, sizeof(int)); + *offset++ = PACKED_FIELD(&ophistory->ts.ns, sizeof(int)); } *offset++ = PACKED_FIELD(&steps_num, sizeof(int)); @@ -288,22 +299,30 @@ zbx_uint32_t zbx_preprocessor_pack_task(unsigned char **data, zbx_uint64_t itemi * * * Parameters: data - [OUT] memory buffer for packed data * * value - [IN] result value * - * history_value - [IN] item history data * + * history - [IN] item history data * * error - [IN] preprocessing error * * * * Return value: size of packed data * * * ******************************************************************************/ zbx_uint32_t zbx_preprocessor_pack_result(unsigned char **data, zbx_variant_t *value, - zbx_item_history_value_t *history_value, char *error) + const zbx_vector_ptr_t *history, char *error) { zbx_packed_field_t *offset, fields[8]; /* 8 - max field count */ - unsigned char history_marker; + unsigned char history_num; zbx_uint32_t size; zbx_ipc_message_t message; + int i; offset = fields; - history_marker = (NULL != history_value); + + if (255 < history->values_num) + { + THIS_SHOULD_NEVER_HAPPEN; + exit(EXIT_FAILURE); + } + + history_num = history->values_num; *offset++ = PACKED_FIELD(&value->type, sizeof(unsigned char)); @@ -322,28 +341,35 @@ zbx_uint32_t zbx_preprocessor_pack_result(unsigned char **data, zbx_variant_t *v break; } - *offset++ = PACKED_FIELD(&history_marker, sizeof(unsigned char)); + *offset++ = PACKED_FIELD(&history_num, sizeof(unsigned char)); - if (NULL != history_value) + for (i = 0; i < history_num; i++) { - *offset++ = PACKED_FIELD(&history_value->value.type, sizeof(unsigned char)); + zbx_preproc_op_history_t *ophistory = (zbx_preproc_op_history_t *)history->values[i]; - switch (history_value->value.type) + *offset++ = PACKED_FIELD(&ophistory->type, sizeof(unsigned char)); + *offset++ = PACKED_FIELD(&ophistory->value.type, sizeof(unsigned char)); + + switch (ophistory->value.type) { case ZBX_VARIANT_UI64: - *offset++ = PACKED_FIELD(&history_value->value.data.ui64, sizeof(zbx_uint64_t)); + *offset++ = PACKED_FIELD(&ophistory->value.data.ui64, sizeof(zbx_uint64_t)); break; case ZBX_VARIANT_DBL: - *offset++ = PACKED_FIELD(&history_value->value.data.dbl, sizeof(double)); + *offset++ = PACKED_FIELD(&ophistory->value.data.dbl, sizeof(double)); + break; + + case ZBX_VARIANT_STR: + *offset++ = PACKED_FIELD(ophistory->value.data.str, 0); break; default: THIS_SHOULD_NEVER_HAPPEN; } - *offset++ = PACKED_FIELD(&history_value->timestamp.sec, sizeof(int)); - *offset++ = PACKED_FIELD(&history_value->timestamp.ns, sizeof(int)); + *offset++ = PACKED_FIELD(&ophistory->ts.sec, sizeof(int)); + *offset++ = PACKED_FIELD(&ophistory->ts.ns, sizeof(int)); } *offset++ = PACKED_FIELD(error, 0); @@ -436,20 +462,19 @@ zbx_uint32_t zbx_preprocessor_unpack_value(zbx_preproc_item_value_t *value, unsi * value_type - [OUT] item value type * * ts - [OUT] value timestamp * * value - [OUT] item value * - * history_value - [OUT] history data for delta preprocessing * + * history - [OUT] history data * * steps - [OUT] preprocessing steps * * steps_num - [OUT] preprocessing step count * * data - [IN] IPC data buffer * * * ******************************************************************************/ void zbx_preprocessor_unpack_task(zbx_uint64_t *itemid, unsigned char *value_type, zbx_timespec_t **ts, - zbx_variant_t *value, zbx_item_history_value_t **history_value, zbx_preproc_op_t **steps, + zbx_variant_t *value, zbx_vector_ptr_t *history, zbx_preproc_op_t **steps, int *steps_num, const unsigned char *data) { zbx_uint32_t value_len; const unsigned char *offset = data; - unsigned char ts_marker, history_marker; - zbx_item_history_value_t *hvalue = NULL; + unsigned char ts_marker, history_num; zbx_timespec_t *timespec = NULL; int i; @@ -486,33 +511,43 @@ void zbx_preprocessor_unpack_task(zbx_uint64_t *itemid, unsigned char *value_typ THIS_SHOULD_NEVER_HAPPEN; } - offset += zbx_deserialize_char(offset, &history_marker); - if (0 != history_marker) - { - hvalue = (zbx_item_history_value_t *)zbx_malloc(NULL, sizeof(zbx_item_history_value_t)); + offset += zbx_deserialize_char(offset, &history_num); - offset += zbx_deserialize_char(offset, &hvalue->value_type); - offset += zbx_deserialize_char(offset, &hvalue->value.type); + if (0 != history_num) + { + zbx_vector_ptr_reserve(history, history_num); - switch (hvalue->value.type) + for (i = 0; i < history_num; i++) { - case ZBX_VARIANT_UI64: - offset += zbx_deserialize_uint64(offset, &hvalue->value.data.ui64); - break; + zbx_preproc_op_history_t *ophistory; - case ZBX_VARIANT_DBL: - offset += zbx_deserialize_double(offset, &hvalue->value.data.dbl); - break; + ophistory = zbx_malloc(NULL, sizeof(zbx_preproc_op_history_t)); - default: - THIS_SHOULD_NEVER_HAPPEN; - } + offset += zbx_deserialize_char(offset, &ophistory->type); + offset += zbx_deserialize_char(offset, &ophistory->value.type); + + switch (ophistory->value.type) + { + case ZBX_VARIANT_UI64: + offset += zbx_deserialize_uint64(offset, &ophistory->value.data.ui64); + break; + case ZBX_VARIANT_DBL: + offset += zbx_deserialize_double(offset, &ophistory->value.data.dbl); + break; + case ZBX_VARIANT_STR: + offset += zbx_deserialize_str(offset, &ophistory->value.data.str, value_len); + break; + default: + THIS_SHOULD_NEVER_HAPPEN; + } - offset += zbx_deserialize_int(offset, &hvalue->timestamp.sec); - offset += zbx_deserialize_int(offset, &hvalue->timestamp.ns); + offset += zbx_deserialize_int(offset, &ophistory->ts.sec); + offset += zbx_deserialize_int(offset, &ophistory->ts.ns); + + zbx_vector_ptr_append(history, ophistory); + } } - *history_value = hvalue; offset += zbx_deserialize_int(offset, steps_num); if (0 < *steps_num) { @@ -536,18 +571,17 @@ void zbx_preprocessor_unpack_task(zbx_uint64_t *itemid, unsigned char *value_typ * Purpose: unpack preprocessing task data from IPC data buffer * * * * Parameters: value - [OUT] result value * - * history_value - [OUT] item history data * + * history - [OUT] item history data * * error - [OUT] preprocessing error * * data - [IN] IPC data buffer * * * ******************************************************************************/ -void zbx_preprocessor_unpack_result(zbx_variant_t *value, zbx_item_history_value_t **history_value, char **error, +void zbx_preprocessor_unpack_result(zbx_variant_t *value, zbx_vector_ptr_t *history, char **error, const unsigned char *data) { zbx_uint32_t value_len; const unsigned char *offset = data; - unsigned char history_marker; - zbx_item_history_value_t *hvalue = NULL; + unsigned char history_num; offset += zbx_deserialize_char(offset, &value->type); @@ -566,32 +600,43 @@ void zbx_preprocessor_unpack_result(zbx_variant_t *value, zbx_item_history_value break; } - offset += zbx_deserialize_char(offset, &history_marker); - if (0 != history_marker) + offset += zbx_deserialize_char(offset, &history_num); + if (0 != history_num) { - hvalue = (zbx_item_history_value_t *)zbx_malloc(NULL, sizeof(zbx_item_history_value_t)); + int i; - offset += zbx_deserialize_char(offset, &hvalue->value.type); + zbx_vector_ptr_reserve(history, history_num); - switch (hvalue->value.type) + for (i = 0; i < history_num; i++) { - case ZBX_VARIANT_UI64: - offset += zbx_deserialize_uint64(offset, &hvalue->value.data.ui64); - break; + zbx_preproc_op_history_t *ophistory; - case ZBX_VARIANT_DBL: - offset += zbx_deserialize_double(offset, &hvalue->value.data.dbl); - break; + ophistory = zbx_malloc(NULL, sizeof(zbx_preproc_op_history_t)); - default: - THIS_SHOULD_NEVER_HAPPEN; - } + offset += zbx_deserialize_char(offset, &ophistory->type); + offset += zbx_deserialize_char(offset, &ophistory->value.type); - offset += zbx_deserialize_int(offset, &hvalue->timestamp.sec); - offset += zbx_deserialize_int(offset, &hvalue->timestamp.ns); - } + switch (ophistory->value.type) + { + case ZBX_VARIANT_UI64: + offset += zbx_deserialize_uint64(offset, &ophistory->value.data.ui64); + break; + case ZBX_VARIANT_DBL: + offset += zbx_deserialize_double(offset, &ophistory->value.data.dbl); + break; + case ZBX_VARIANT_STR: + offset += zbx_deserialize_str(offset, &ophistory->value.data.str, value_len); + break; + default: + THIS_SHOULD_NEVER_HAPPEN; + } + + offset += zbx_deserialize_int(offset, &ophistory->ts.sec); + offset += zbx_deserialize_int(offset, &ophistory->ts.ns); - *history_value = hvalue; + zbx_vector_ptr_append(history, ophistory); + } + } (void)zbx_deserialize_str(offset, error, value_len); } diff --git a/src/zabbix_server/preprocessor/preprocessing.h b/src/zabbix_server/preprocessor/preprocessing.h index 202ae6a55e1..23063ba7754 100644 --- a/src/zabbix_server/preprocessor/preprocessing.h +++ b/src/zabbix_server/preprocessor/preprocessing.h @@ -45,16 +45,16 @@ typedef struct zbx_preproc_item_value_t; zbx_uint32_t zbx_preprocessor_pack_task(unsigned char **data, zbx_uint64_t itemid, unsigned char value_type, - zbx_timespec_t *ts, zbx_variant_t *value, zbx_item_history_value_t *history_value, + zbx_timespec_t *ts, zbx_variant_t *value, const zbx_vector_ptr_t *history, const zbx_preproc_op_t *steps, int steps_num); zbx_uint32_t zbx_preprocessor_pack_result(unsigned char **data, zbx_variant_t *value, - zbx_item_history_value_t *history_value, char *error); + const zbx_vector_ptr_t *history, char *error); zbx_uint32_t zbx_preprocessor_unpack_value(zbx_preproc_item_value_t *value, unsigned char *data); void zbx_preprocessor_unpack_task(zbx_uint64_t *itemid, unsigned char *value_type, zbx_timespec_t **ts, - zbx_variant_t *value, zbx_item_history_value_t **history_value, zbx_preproc_op_t **steps, + zbx_variant_t *value, zbx_vector_ptr_t *history, zbx_preproc_op_t **steps, int *steps_num, const unsigned char *data); -void zbx_preprocessor_unpack_result(zbx_variant_t *value, zbx_item_history_value_t **history_value, - char **error, const unsigned char *data); +void zbx_preprocessor_unpack_result(zbx_variant_t *value, zbx_vector_ptr_t *history, char **error, + const unsigned char *data); #endif /* ZABBIX_PREPROCESSING_H */ diff --git a/tests/zabbix_server/preprocessor/zbx_item_preproc.c b/tests/zabbix_server/preprocessor/zbx_item_preproc.c index 42eef3902e2..8c5dd999295 100644 --- a/tests/zabbix_server/preprocessor/zbx_item_preproc.c +++ b/tests/zabbix_server/preprocessor/zbx_item_preproc.c @@ -90,13 +90,13 @@ static int str_to_preproc_error_handler(const char *str) return FAIL; } -static void read_value(const char *path, unsigned char *value_type, zbx_timespec_t *ts, - zbx_variant_t *value) +static void read_value(const char *path, unsigned char *value_type, zbx_variant_t *value, zbx_timespec_t *ts) { zbx_mock_handle_t handle; handle = zbx_mock_get_parameter_handle(path); - *value_type = zbx_mock_str_to_value_type(zbx_mock_get_object_member_string(handle, "value_type")); + if (NULL != value_type) + *value_type = zbx_mock_str_to_value_type(zbx_mock_get_object_member_string(handle, "value_type")); zbx_strtime_to_timespec(zbx_mock_get_object_member_string(handle, "time"), ts); zbx_variant_set_str(value, zbx_strdup(NULL, zbx_mock_get_object_member_string(handle, "data"))); } @@ -126,27 +126,30 @@ static void read_step(const char *path, zbx_preproc_op_t *op) void zbx_mock_test_entry(void **state) { - zbx_variant_t value; + zbx_variant_t value, history_value; unsigned char value_type; - zbx_timespec_t ts; - zbx_item_history_value_t history, *phistory = NULL; + zbx_timespec_t ts, history_ts, expected_history_ts; zbx_preproc_op_t op; int returned_ret, expected_ret; char *error = NULL; ZBX_UNUSED(state); - read_value("in.value", &value_type, &ts, &value); + read_value("in.value", &value_type, &value, &ts); read_step("in.step", &op); if (ZBX_MOCK_SUCCESS == zbx_mock_parameter_exists("in.history")) { - history.itemid = 0; - read_value("in.history", &history.value_type, &history.timestamp, &history.value); - phistory = &history; + read_value("in.history", NULL, &history_value, &history_ts); + } + else + { + zbx_variant_set_none(&history_value); + history_ts.sec = 0; + history_ts.ns = 0; } - returned_ret = zbx_item_preproc(0, value_type, &value, &ts, &op, phistory, &error); + returned_ret = zbx_item_preproc(0, value_type, &value, &ts, &op, &history_value, &history_ts, &error); expected_ret = zbx_mock_str_to_return_code(zbx_mock_get_parameter_string("out.return")); zbx_mock_assert_result_eq("zbx_item_preproc() return", expected_ret, returned_ret); @@ -167,6 +170,25 @@ void zbx_mock_test_entry(void **state) if (ZBX_VARIANT_NONE != value.type) fail_msg("expected empty value, but got %s", zbx_variant_value_desc(&value)); } + + if (ZBX_MOCK_SUCCESS == zbx_mock_parameter_exists("out.history")) + { + if (ZBX_VARIANT_NONE == history_value.type) + fail_msg("preprocessing history was empty value"); + + zbx_variant_convert(&history_value, ZBX_VARIANT_STR); + del_zeros(history_value.data.str); + zbx_mock_assert_str_eq("preprocessing step history value", + zbx_mock_get_parameter_string("out.history.data"), history_value.data.str); + + zbx_strtime_to_timespec(zbx_mock_get_parameter_string("out.history.time"), &expected_history_ts); + zbx_mock_assert_timespec_eq("preprocessing step history time", &expected_history_ts, &history_ts); + } + else + { + if (ZBX_VARIANT_NONE != history_value.type) + fail_msg("expected empty value, but got %s", zbx_variant_value_desc(&history_value)); + } } if (FAIL == returned_ret && ZBX_MOCK_SUCCESS == zbx_mock_parameter_exists("out.error")) diff --git a/tests/zabbix_server/preprocessor/zbx_item_preproc.yaml b/tests/zabbix_server/preprocessor/zbx_item_preproc.yaml index d1c5f09ca4f..127ccbe057b 100644 --- a/tests/zabbix_server/preprocessor/zbx_item_preproc.yaml +++ b/tests/zabbix_server/preprocessor/zbx_item_preproc.yaml @@ -577,6 +577,9 @@ in: out: return: SUCCEED value: 5 + history: + data: 10 + time: 2017-10-29 03:15:00 +03:00 --- test case: deltavalue(-4.5, 5.5) in: @@ -593,6 +596,9 @@ in: out: return: SUCCEED value: 10 + history: + time: 2017-10-29 03:15:00 +03:00 + data: 5.5 --- test case: deltavalue(10, 10) in: @@ -609,6 +615,9 @@ in: out: return: SUCCEED value: 0 + history: + time: 2017-10-29 03:15:00 +03:00 + data: 10 --- test case: deltavalue(10, 9) in: @@ -624,6 +633,9 @@ in: type: ZBX_PREPROC_DELTA_VALUE out: return: SUCCEED + history: + time: 2017-10-29 03:15:00 +03:00 + data: 0 --- test case: deltavalue(0, 1.5) in: @@ -640,6 +652,9 @@ in: out: return: SUCCEED value: 1.5 + history: + time: 2017-10-29 03:15:00 +03:00 + data: 1.5 --- test case: deltaspeed(2, 1, 10s) in: @@ -655,6 +670,9 @@ in: type: ZBX_PREPROC_DELTA_SPEED out: return: SUCCEED + history: + time: 2017-10-29 03:15:00 +03:00 + data: 1 --- test case: deltaspeed(1, 2, -10s) in: @@ -670,6 +688,9 @@ in: type: ZBX_PREPROC_DELTA_SPEED out: return: SUCCEED + history: + time: 2017-10-29 03:15:00 +03:00 + data: 2 --- test case: deltaspeed(1, 2, 10s) in: @@ -686,6 +707,9 @@ in: out: return: SUCCEED value: 0.1 + history: + time: 2017-10-29 03:15:00 +03:00 + data: 2 --- test case: deltaspeed(2, 3, 10s) in: @@ -702,6 +726,9 @@ in: out: return: SUCCEED value: 0 + history: + time: 2017-10-29 03:15:00 +03:00 + data: 3 --- test case: deltaspeed(2, 3, 1s) in: @@ -718,6 +745,9 @@ in: out: return: SUCCEED value: 1 + history: + time: 2017-10-29 03:15:00 +03:00 + data: 3 --- test case: xpath1 in: |