В файле конфигурации сервера Zabbix это может выглядеть следующим образом:
HistoryStorage=clickhouse,http://zabbix:zabbix@localhost:8123/?database=zabbix HistoryUintStorage=clickhouse,http://zabbix:zabbix@localhost:8123/?database=zabbix HistoryStrStorage=elastic,http://hostnameelastic:9200 HistoryTextStorage=elastic,http://hostnameelastic:9200 HistoryLogStorage=elastic,http://hostnameelastic:9200Готовую заплатку с реализацией раздельного выбора типа хранилища для каждой из таблиц истории можно найти по ссылке zabbix3_4_12_server_storage_per_table.patch.
Ниже в логическом порядке описываются изменения, вносимые этой заплаткой.
Кстати, заплатки описываются так подробно по двум обстоятельствам:
- Несмотря на то, что 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-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} };Поскольку Zabbix-прокси реализован на основе сервера Zabbix, аналогичные фиктивные изменения нужно внести в исходный код Zabbix-прокси в файле src/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 @@ -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 =================================================================== --- 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_history_init добавлен закомментированный участок, обозначающий будущую поддержку хранилища ClickHouse.
Из кода удалён комментарий о необходимости реализовать раздельную возможность настройки типов хранилищ для каждой из таблиц, потому что именно это мы сейчас и делаем.
В коде используется новая функция 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 =================================================================== --- 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Осталось лишь соответствующим образом изменить реализацию этой функции в файле src/libs/zbxhistory/history_elastic.c:
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;
2 комментария:
гляньте Glaber
Эти заметки сделаны на основе Glaber. Я смотрел доработанные исходники, но они мне не нравились своей неаккуратностью и срезанием углов. Поэтому решил посмотреть и сделать лучше.
Но не стоит считать эти статьи попытками как-то самоутвердиться за чужой счёт. С большим уважением отношусь к людям, умеющим делать что-то новое, пусть и не аккуратно. К сожалению, я так не умею. Я по натуре не первопроходец, а доводчик.
Отправить комментарий