-
Sy
chevron_right
Поддержка нескольких типов хранилищ в сервере Zabbix 3.4
pubsub.slavino.sk / sysadmblog · Sunday, 8 November, 2020 - 08:00 edit · 7 minutes
В файле конфигурации сервера Zabbix это может выглядеть следующим образом:
HistoryStorage=clickhouse,http://zabbix:zabbix@localhost:8123/?database=zabbixГотовую заплатку с реализацией раздельного выбора типа хранилища для каждой из таблиц истории можно найти по ссылке zabbix3_4_12_server_storage_per_table.patch .
HistoryUintStorage=clickhouse,http://zabbix:zabbix@localhost:8123/?database=zabbix
HistoryStrStorage=elastic,http://hostnameelastic:9200
HistoryTextStorage=elastic,http://hostnameelastic:9200
HistoryLogStorage=elastic,http://hostnameelastic:9200
Ниже в логическом порядке описываются изменения, вносимые этой заплаткой.
Кстати, заплатки описываются так подробно по двум обстоятельствам:
- Несмотря на то, что Zabbix - это программное обеспечение со свободным исходным кодом, разработку этого программного обеспечения ведёт коммерческая организация. Эта коммерческая компания зарабатывает деньги на поддержке своего продукта и у неё нет желания заниматься поддержкой дополнительных спорных функций, внесённых в код сторонними разработчиками. Представьте, что какой-то Вася реализовал в Zabbix поддержку хранения исторических данных в том же Clickhouse. Клиент, оплативший коммерческую поддержку Zabbix, устанавливает себе Zabbix и пытается воспользоваться ClickHouse в качестве хранилища исторических данных. Даже если с кодом Васи нет никаких проблем и он аккуратно написан, у клиента может возникнуть множество самых разных проблем, связанных с эксплуатацией непосредственно самого ClickHouse. В компании нет специалистов, знакомых с Clickhouse, поэтому компания будет вынуждена отказать клиенту в поддержке. Возникнет вопрос - за что же тогда платит клиент, если компания не осуществляет поддержку функций, реализованных в её продукте? Вот поэтому разработчики Zabbix обычно не принимают в исходный код своего продукта никаких заплаток, вносящих в код продукта глобальные изменения. Zabbix, являясь программным обеспечением со свободным исходным кодом, фактически не принадлежит сообществу, а принадлежит коммерческой компании.
- Из заплатки самой по себе не так легко понять логику вносимых ей изменений. Если понадобится адаптировать заплатку к другой версии Zabbix, то нужно будет разбираться в имеющейся заплатке и исходном коде той версии Zabbix, для которой эта заплатка была сделана, а потом повторить все эти изменения в другой версии Zabbix. Описание, подобное приведённому ниже, должно помочь во-первых, понять логику изменений, вносимых заплаткой, а во-вторых, помочь внести подобные изменения мелкими кусочками в другую версию Zabbix.
Доработка файла конфигурации
Задекларируем наши намерения, доработав соответствующим образом пример файла конфигурации conf/zabbix_server.conf: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
@@ -133,19 +133,40 @@ DBUser=zabbix
# Default (for MySQL):
# DBPort=3306
-### Option: HistoryStorageURL
-# History storage HTTP[S] URL.
+### Option: HistoryStorage
+# Storage type and HTTP[S] URL for double type values history.
#
# Mandatory: no
# Default:
-# HistoryStorageURL=
+# HistoryStorage=
-### Option: HistoryStorageTypes
-# Comma separated list of value types to be sent to the history storage.
+### Option: HistoryUintStorage
+# Storage type and HTTP[S] URL for unsigned integer type values history.
#
# Mandatory: no
# Default:
-# HistoryStorageTypes=uint,dbl,str,log,text
+# HistoryUintStorage=
+
+### Option: HistoryStrStorage
+# Storage type and HTTP[S] URL for string type values history.
+#
+# Mandatory: no
+# Default:
+# HistoryStrStorage=
+
+### Option: HistoryTextStorage
+# Storage type and HTTP[S] URL for text type values history.
+#
+# Mandatory: no
+# Default:
+# HistoryTextStorage=
+
+### Option: HistoryLogStorage
+# Storage type and HTTP[S] URL for log type values history.
+#
+# Mandatory: no
+# Default:
+# HistoryLogStorage=
############ ADVANCED PARAMETERS ################
Доработка сервера Zabbix и Zabbix-прокси
Теперь удалим поддержку чтения опций конфигурации HistoryStorageUrl и HistoryStorageOpts из исходного текста сервера Zabbix в файле src/zabbix_server/server.c и добавим в него поддержку чтения новых опций конфигурации HistoryStorage, HistoryUintStorage, HistoryStrStorage, HistoryTextStorage, HistoryLogStorage:Index: zabbix-3.4.12-1+buster/src/zabbix_server/server.cПоскольку Zabbix-прокси реализован на основе сервера Zabbix, аналогичные фиктивные изменения нужно внести в исходный код Zabbix-прокси в файле src/zabbix_proxy/proxy.c:
===================================================================
--- zabbix-3.4.12-1+buster.orig/src/zabbix_server/server.c
+++ zabbix-3.4.12-1+buster/src/zabbix_server/server.c
@@ -258,8 +258,11 @@ char *CONFIG_TLS_PSK_FILE = NULL;
#endif
char *CONFIG_SOCKET_PATH = NULL;
-char *CONFIG_HISTORY_STORAGE_URL = NULL;
-char *CONFIG_HISTORY_STORAGE_OPTS = NULL;
+char *CONFIG_HISTORY_STORAGE = NULL;
+char *CONFIG_HISTORY_UINT_STORAGE = NULL;
+char *CONFIG_HISTORY_STR_STORAGE = NULL;
+char *CONFIG_HISTORY_TEXT_STORAGE = NULL;
+char *CONFIG_HISTORY_LOG_STORAGE = NULL;
int get_process_info_by_thread(int local_server_num, unsigned char *local_process_type, int *local_process_num);
@@ -438,9 +441,6 @@ static void zbx_set_defaults(void)
if (NULL == CONFIG_SSL_KEY_LOCATION)
CONFIG_SSL_KEY_LOCATION = zbx_strdup(CONFIG_SSL_KEY_LOCATION, DATADIR "/zabbix/ssl/keys");
-
- if (NULL == CONFIG_HISTORY_STORAGE_OPTS)
- CONFIG_HISTORY_STORAGE_OPTS = zbx_strdup(CONFIG_HISTORY_STORAGE_OPTS, "uint,dbl,str,log,text");
#endif
#ifdef HAVE_SQLITE3
@@ -499,8 +499,11 @@ static void zbx_validate_config(ZBX_TASK
err |= (FAIL == check_cfg_feature_str("SSLCALocation", CONFIG_SSL_CA_LOCATION, "cURL library"));
err |= (FAIL == check_cfg_feature_str("SSLCertLocation", CONFIG_SSL_CERT_LOCATION, "cURL library"));
err |= (FAIL == check_cfg_feature_str("SSLKeyLocation", CONFIG_SSL_KEY_LOCATION, "cURL library"));
- err |= (FAIL == check_cfg_feature_str("HistoryStorageURL", CONFIG_HISTORY_STORAGE_URL, "cURL library"));
- err |= (FAIL == check_cfg_feature_str("HistoryStorageTypes", CONFIG_HISTORY_STORAGE_OPTS, "cURL library"));
+ err |= (FAIL == check_cfg_feature_str("HistoryStorage", CONFIG_HISTORY_STORAGE, "cURL library"));
+ err |= (FAIL == check_cfg_feature_str("HistoryUintStorage", CONFIG_HISTORY_UINT_STORAGE, "cURL library"));
+ err |= (FAIL == check_cfg_feature_str("HistoryStrStorage", CONFIG_HISTORY_STR_STORAGE, "cURL library"));
+ err |= (FAIL == check_cfg_feature_str("HistoryTextStorage", CONFIG_HISTORY_TEXT_STORAGE, "cURL library"));
+ err |= (FAIL == check_cfg_feature_str("HistoryLogStorage", CONFIG_HISTORY_LOG_STORAGE, "cURL library"));
#endif
#if !defined(HAVE_LIBXML2) || !defined(HAVE_LIBCURL)
@@ -696,9 +699,15 @@ static void zbx_load_config(ZBX_TASK_EX
PARM_OPT, 1, 100},
{"StartPreprocessors", &CONFIG_PREPROCESSOR_FORKS, TYPE_INT,
PARM_OPT, 1, 1000},
- {"HistoryStorageURL", &CONFIG_HISTORY_STORAGE_URL, TYPE_STRING,
+ {"HistoryStorage", &CONFIG_HISTORY_STORAGE, TYPE_STRING,
+ PARM_OPT, 0, 0},
+ {"HistoryUintStorage", &CONFIG_HISTORY_UINT_STORAGE, TYPE_STRING,
+ PARM_OPT, 0, 0},
+ {"HistoryStrStorage", &CONFIG_HISTORY_STR_STORAGE, TYPE_STRING,
+ PARM_OPT, 0, 0},
+ {"HistoryTextStorage", &CONFIG_HISTORY_TEXT_STORAGE, TYPE_STRING,
PARM_OPT, 0, 0},
- {"HistoryStorageTypes", &CONFIG_HISTORY_STORAGE_OPTS, TYPE_STRING_LIST,
+ {"HistoryLogStorage", &CONFIG_HISTORY_LOG_STORAGE, TYPE_STRING,
PARM_OPT, 0, 0},
{NULL}
};
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
@@ -251,8 +251,11 @@ char *CONFIG_TLS_PSK_FILE = NULL;
char *CONFIG_SOCKET_PATH = NULL;
-char *CONFIG_HISTORY_STORAGE_URL = NULL;
-char *CONFIG_HISTORY_STORAGE_OPTS = NULL;
+char *CONFIG_HISTORY_STORAGE = NULL;
+char *CONFIG_HISTORY_UINT_STORAGE = NULL;
+char *CONFIG_HISTORY_STR_STORAGE = NULL;
+char *CONFIG_HISTORY_TEXT_STORAGE = NULL;
+char *CONFIG_HISTORY_LOG_STORAGE = NULL;
int get_process_info_by_thread(int local_server_num, unsigned char *local_process_type, int *local_process_num);
Доработка основы библиотеки zbxhistory
Суть вносимых изменений особенно наглядно можно увидеть в следующей заплатке для файла src/libs/zbxhistory/history.c. Вместо использования фиксированного URL для всех таблиц из переменной CONFIG_HISTORY_STORAGE_URL и переменной CONFIG_HISTORY_STORAGE_OPTS, которая предписывает использовать этот URL для таблиц указанных в ней типов, мы определяем тип хранилища для каждой из таблиц и вызываем функцию инициализации соответствующего модуля, передавая ей URL для доступа к этой конкретной таблице:Index: zabbix-3.4.12-1+buster/src/libs/zbxhistory/history.cВ доработанном коде функции zbx_history_init добавлен закомментированный участок, обозначающий будущую поддержку хранилища ClickHouse.
===================================================================
--- zabbix-3.4.12-1+buster.orig/src/libs/zbxhistory/history.c
+++ zabbix-3.4.12-1+buster/src/libs/zbxhistory/history.c
@@ -27,8 +27,11 @@
ZBX_VECTOR_IMPL(history_record, zbx_history_record_t);
-extern char *CONFIG_HISTORY_STORAGE_URL;
-extern char *CONFIG_HISTORY_STORAGE_OPTS;
+extern char *CONFIG_HISTORY_STORAGE;
+extern char *CONFIG_HISTORY_UINT_STORAGE;
+extern char *CONFIG_HISTORY_STR_STORAGE;
+extern char *CONFIG_HISTORY_TEXT_STORAGE;
+extern char *CONFIG_HISTORY_LOG_STORAGE;
zbx_history_iface_t history_ifaces[ITEM_VALUE_TYPE_MAX];
@@ -46,16 +49,23 @@ zbx_history_iface_t history_ifaces[ITEM_
int zbx_history_init(char **error)
{
int i, ret;
- /* TODO: support per value type specific configuration */
-
- const char *opts[] = {"dbl", "str", "log", "uint", "text"};
+ char *elastic_url;
+ const char *opts[] = {
+ CONFIG_HISTORY_STORAGE,
+ CONFIG_HISTORY_STR_STORAGE,
+ CONFIG_HISTORY_LOG_STORAGE,
+ CONFIG_HISTORY_UINT_STORAGE,
+ CONFIG_HISTORY_TEXT_STORAGE
+ };
for (i = 0; i < ITEM_VALUE_TYPE_MAX; i++)
{
- if (NULL == CONFIG_HISTORY_STORAGE_URL || NULL == strstr(CONFIG_HISTORY_STORAGE_OPTS, opts[i]))
- ret = zbx_history_sql_init(&history_ifaces[i], i, error);
+ if (elastic_url = zbx_strstartswith(opts[i], "elastic,"))
+ ret = zbx_history_elastic_init(&history_ifaces[i], i, elastic_url, error);
+ /*else if (clickhouse_url = zbx_strstartswith(opts[i], "clickhouse,"))
+ ret = zbx_history_clickhouse_init(&history_ifaces[i], i, clickhouse_url, error);*/
else
- ret = zbx_history_elastic_init(&history_ifaces[i], i, error);
+ ret = zbx_history_sql_init(&history_ifaces[i], i, error);
if (FAIL == ret)
return FAIL;
Из кода удалён комментарий о необходимости реализовать раздельную возможность настройки типов хранилищ для каждой из таблиц, потому что именно это мы сейчас и делаем.
В коде используется новая функция zbx_startswith для проверки, что строка начинается с указанного префикса.
При доработке изменилась сигнатура функции zbx_history_elastic_init, теперь ей передаётся дополнительный аргумент - elastic_url.
Остановимся поподробнее на двух последних обстоятельствах.
Новая функция zbx_startswith
Во-первых, добавим объявление новой функции zbx_startswith в файл include/common.h и её реализацию в файл src/libs/zbxcommon/str.c:Index: zabbix-3.4.12-1+buster/include/common.h
===================================================================
--- zabbix-3.4.12-1+buster.orig/include/common.h
+++ zabbix-3.4.12-1+buster/include/common.h
@@ -1114,6 +1114,7 @@ char *zbx_time2str(time_t time);
#define ZBX_NULL2STR(str) (NULL != str ? str : "(null)")
#define ZBX_NULL2EMPTY_STR(str) (NULL != (str) ? (str) : "")
+char *zbx_strstartswith(const char *str, const char *prefix);
char *zbx_strcasestr(const char *haystack, const char *needle);
int cmp_key_id(const char *key_1, const char *key_2);
int zbx_strncasecmp(const char *s1, const char *s2, size_t n);
Index: zabbix-3.4.12-1+buster/src/libs/zbxcommon/str.c
===================================================================
--- zabbix-3.4.12-1+buster.orig/src/libs/zbxcommon/str.c
+++ zabbix-3.4.12-1+buster/src/libs/zbxcommon/str.c
@@ -1827,6 +1827,38 @@ char *zbx_time2str(time_t time)
return buffer;
}
+/******************************************************************************
+ * *
+ * Function: zbx_startswith *
+ * *
+ * Purpose: compare start of string str with string prefix *
+ * *
+ * Parameters: str - [IN] null terminated source string *
+ * prefix - [IN] null terminated prefix string *
+ * *
+ * Return value: pointer to rest of str or NULL, if prefix not found *
+ * *
+ * Author: Vladimir Stupin *
+ * *
+ ******************************************************************************/
+char *zbx_strstartswith(const char *str, const char *prefix)
+{
+ if (NULL == prefix)
+ return (char *)str;
+
+ if (NULL == str)
+ return NULL;
+
+ while ('\0' != *prefix)
+ {
+ if ('\0' == *str || *str != *prefix)
+ return NULL;
+ str++;
+ prefix++;
+ }
+ return (char *)str;
+}
+
int zbx_strncasecmp(const char *s1, const char *s2, size_t n)
{
if (NULL == s1 && NULL == s2)
Доработка поддержки Elasticsearch
Во-вторых, изменим объявление функции zbx_history_elastic_init в заголовочном файле src/libs/zbxhistory/history.h:Index: zabbix-3.4.12-1+buster/src/libs/zbxhistory/history.hОсталось лишь соответствующим образом изменить реализацию этой функции в файле src/libs/zbxhistory/history_elastic.c:
===================================================================
--- zabbix-3.4.12-1+buster.orig/src/libs/zbxhistory/history.h
+++ zabbix-3.4.12-1+buster/src/libs/zbxhistory/history.h
@@ -47,6 +47,6 @@ struct zbx_history_iface
int zbx_history_sql_init(zbx_history_iface_t *hist, unsigned char value_type, char **error);
/* elastic hist */
-int zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type, char **error);
+int zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type, const char *url, char **error);
#endif
Index: zabbix-3.4.12-1+buster/src/libs/zbxhistory/history_elastic.c
===================================================================
--- zabbix-3.4.12-1+buster.orig/src/libs/zbxhistory/history_elastic.c
+++ zabbix-3.4.12-1+buster/src/libs/zbxhistory/history_elastic.c
@@ -37,8 +37,6 @@
const char *value_type_str[] = {"dbl", "str", "log", "uint", "text"};
-extern char *CONFIG_HISTORY_STORAGE_URL;
-
typedef struct
{
char *base_url;
@@ -912,7 +910,7 @@ static void elastic_flush(zbx_history_if
* FAIL - otherwise *
* *
************************************************************************************/
-int zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type, char **error)
+int zbx_history_elastic_init(zbx_history_iface_t *hist, unsigned char value_type, const char *url, char **error)
{
zbx_elastic_data_t *data;
@@ -924,7 +922,7 @@ int zbx_history_elastic_init(zbx_history
data = zbx_malloc(NULL, sizeof(zbx_elastic_data_t));
memset(data, 0, sizeof(zbx_elastic_data_t));
- data->base_url = zbx_strdup(NULL, CONFIG_HISTORY_STORAGE_URL);
+ data->base_url = zbx_strdup(NULL, url);
zbx_rtrim(data->base_url, "/");
data->buf = NULL;
data->post_url = NULL;