Временный запрет на чтение данных из таблиц истории при запуске Zabbix 3.4

В статье Предзагрузка кэша значений при запуске сервера Zabbix я уже анонсировал эту функциональность и теперь настало время описать соответствующую заплатку.

Готовую заплатку с реализацией временного запрета на чтение данных из таблиц истори при запуске сервера Zabbix можно найти по ссылке zabbix3_4_12_valuecache_grace_period.patch.

В файл конфигурации conf/zabbix_server.conf добавим опцию с названием DBSyncersGracePeriod, которая будет принимать время с момента запуска сервера в секундах, в течение которого чтение данных из хранилищ истории будет запрещено:

Index: zabbix-3.4.12-1+buster/conf/zabbix_server.conf
===================================================================
--- zabbix-3.4.12-1+buster.orig/conf/zabbix_server.conf
+++ zabbix-3.4.12-1+buster/conf/zabbix_server.conf
@@ -413,6 +413,14 @@ DBUser=zabbix
 # Default:
 # StartDBSyncers=4
 
+### Option: DBSyncersGracePeriod
+#       Time after server startup, during which reading from history storage will be prohibited.
+#
+# Mandatory: no
+# Range: 0-86400
+# Default:
+# DBSyncersGracePeriod=0
+
 ### Option: HistoryCacheSize
 #      Size of history cache, in bytes.
 #      Shared memory size for storing history data.

Теперь добавим в сервер Zabbix загрузку этой опции из файла конфигурации. Отредактируем файл src/zabbix_server/server.c следующим образом:

Index: zabbix-3.4.12-1+buster/src/zabbix_server/server.c
===================================================================
--- zabbix-3.4.12-1+buster.orig/src/zabbix_server/server.c
+++ zabbix-3.4.12-1+buster/src/zabbix_server/server.c
@@ -176,6 +176,8 @@ int CONFIG_HOUSEKEEPING_FREQUENCY   = 1;
 int    CONFIG_MAX_HOUSEKEEPER_DELETE   = 5000;         /* applies for every separate field value */
 int    CONFIG_HISTSYNCER_FORKS         = 4;
 int    CONFIG_HISTSYNCER_FREQUENCY     = 1;
+int    CONFIG_HISTSYNCER_GRACE_PERIOD  = 0;
+
 int    CONFIG_CONFSYNCER_FORKS         = 1;
 int    CONFIG_CONFSYNCER_FREQUENCY     = 60;
 
@@ -556,6 +558,8 @@ static void zbx_load_config(ZBX_TASK_EX
                        MANDATORY,      MIN,                    MAX */
                {"StartDBSyncers",              &CONFIG_HISTSYNCER_FORKS,               TYPE_INT,
                        PARM_OPT,       1,                      100},
+               {"DBSyncersGracePeriod",        &CONFIG_HISTSYNCER_GRACE_PERIOD,        TYPE_INT,
+                       PARM_OPT,       0,                      SEC_PER_DAY},
                {"StartDiscoverers",            &CONFIG_DISCOVERER_FORKS,               TYPE_INT,
                        PARM_OPT,       0,                      250},
                {"StartHTTPPollers",            &CONFIG_HTTPPOLLER_FORKS,               TYPE_INT,

Внесём аналогичные фиктивные изменения в Zabbix-прокси, отредактировав файл src/libs/zabbix_proxy/proxy.c следующим образом:

Index: zabbix-3.4.12-1+buster/src/zabbix_proxy/proxy.c
===================================================================
--- zabbix-3.4.12-1+buster.orig/src/zabbix_proxy/proxy.c
+++ zabbix-3.4.12-1+buster/src/zabbix_proxy/proxy.c
@@ -173,6 +173,7 @@ int CONFIG_PROXYDATA_FREQUENCY      = 1;
 
 int    CONFIG_HISTSYNCER_FORKS         = 4;
 int    CONFIG_HISTSYNCER_FREQUENCY     = 1;
+int    CONFIG_HISTSYNCER_GRACE_PERIOD  = 0;
 int    CONFIG_CONFSYNCER_FORKS         = 1;
 
 int    CONFIG_VMWARE_FORKS             = 0;

К счастью, в исходном коде уже имеется переменная CONFIG_SERVER_STARTUP_TIME, содержащая отметку времени запуска сервера Zabbix. Осталось только внести условие в функцию zbx_history_get_values в файле src/libs/zbxhistory/history.c:

Index: zabbix-3.4.12-1+buster/src/libs/zbxhistory/history.c
===================================================================
--- zabbix-3.4.12-1+buster.orig/src/libs/zbxhistory/history.c
+++ zabbix-3.4.12-1+buster/src/libs/zbxhistory/history.c
@@ -34,6 +34,9 @@ extern char   *CONFIG_HISTORY_STR_STORAGE;
 extern char    *CONFIG_HISTORY_TEXT_STORAGE;
 extern char    *CONFIG_HISTORY_LOG_STORAGE;
 
+extern int     CONFIG_SERVER_STARTUP_TIME;
+extern int     CONFIG_HISTSYNCER_GRACE_PERIOD;
+
 zbx_history_iface_t    history_ifaces[ITEM_VALUE_TYPE_MAX];
 
 /************************************************************************************
@@ -162,6 +165,12 @@ int        zbx_history_get_values(zbx_uint64_t
        int                     ret, pos;
        zbx_history_iface_t     *writer = &history_ifaces[value_type];
 
+       if (time(NULL) - CONFIG_SERVER_STARTUP_TIME < CONFIG_HISTSYNCER_GRACE_PERIOD)
+       {
+               zabbix_log(LOG_LEVEL_DEBUG, "waiting for cache load, exiting");
+               return FAIL;
+       }
+
        zabbix_log(LOG_LEVEL_DEBUG, "In %s() itemid:" ZBX_FS_UI64 " value_type:%d start:%d count:%d end:%d",
                        __function_name, itemid, value_type, start, count, end);

Я пробовал возвращать ответ SUCCEED, как это сделано в Glaber, но в таком случае срабатывают триггеры с функцией str. Видимо в таком случае функция str считает, что значение есть, но оно пустое. В итоге функция не находит искомую подстроку и срабатывает триггер. Если же возвращать ответ FAIL, как это сделано в заплатке выше, триггеры и вычисляемые элементы данных в подобных случаях просто переходят в неподдерживаемое состояние.

Написать автору