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:
authorVladislavs Sokurenko <vladislavs.sokurenko@zabbix.com>2021-07-13 16:51:57 +0300
committerVladislavs Sokurenko <vladislavs.sokurenko@zabbix.com>2021-07-13 16:51:57 +0300
commitdc036b08686ecc15f06ab144b86d9fb230cc4cf6 (patch)
tree6b5e72947af1fe19b0e7222b0dcdaf59289e9790
parentfe2644f05f9f9fe6dbffd17281b1d2612abd436d (diff)
........S. [ZBXNEXT-6755] added support of service root cause macro
-rw-r--r--include/db.h6
-rw-r--r--include/service_protocol.h8
-rw-r--r--include/zbxservice.h2
-rw-r--r--src/libs/zbxserver/expression.c41
-rw-r--r--src/libs/zbxservice/service.c3
-rw-r--r--src/libs/zbxservice/service_protocol.c70
-rw-r--r--src/zabbix_server/escalator/escalator.c64
-rw-r--r--src/zabbix_server/service/service_manager.c49
8 files changed, 224 insertions, 19 deletions
diff --git a/include/db.h b/include/db.h
index e3a29ad76d4..495fd0c00e3 100644
--- a/include/db.h
+++ b/include/db.h
@@ -341,8 +341,10 @@ DB_TRIGGER;
typedef struct
{
- zbx_uint64_t serviceid;
- char *name;
+ zbx_uint64_t serviceid;
+ char *name;
+ zbx_vector_uint64_t eventids;
+ zbx_vector_ptr_t events;
}
DB_SERVICE;
diff --git a/include/service_protocol.h b/include/service_protocol.h
index 26974d6d70d..0dcc2c47b04 100644
--- a/include/service_protocol.h
+++ b/include/service_protocol.h
@@ -25,6 +25,10 @@
#include "zbxalgo.h"
#include "dbcache.h"
+#include "log.h"
+#include "zbxalgo.h"
+#include "zbxservice.h"
+
void zbx_service_serialize(unsigned char **data, size_t *data_alloc, size_t *data_offset, zbx_uint64_t eventid,
int clock, int ns, int value, int severity, const zbx_vector_ptr_t *tags);
void zbx_service_deserialize(const unsigned char *data, zbx_uint32_t size, zbx_vector_ptr_t *events);
@@ -33,4 +37,8 @@ void zbx_service_serialize_problem_tags(unsigned char **data, size_t *data_alloc
void zbx_service_deserialize_problem_tags(const unsigned char *data, zbx_uint32_t size, zbx_vector_ptr_t *events);
void zbx_service_serialize_id(unsigned char **data, size_t *data_alloc, size_t *data_offset, zbx_uint64_t id);
void zbx_service_deserialize_ids(const unsigned char *data, zbx_uint32_t size, zbx_vector_uint64_t *ids);
+void zbx_service_serialize_rootcause(unsigned char **data, size_t *data_alloc, size_t *data_offset,
+ zbx_uint64_t serviceid, const zbx_vector_uint64_t *eventids);
+void zbx_service_deserialize_rootcause(const unsigned char *data, zbx_uint32_t size,
+ zbx_vector_service_t *services);
#endif
diff --git a/include/zbxservice.h b/include/zbxservice.h
index 5321f054582..c9097e0baba 100644
--- a/include/zbxservice.h
+++ b/include/zbxservice.h
@@ -25,6 +25,8 @@
#include "db.h"
#include "zbxipcservice.h"
+ZBX_VECTOR_DECL(service, DB_SERVICE)
+
#define ZBX_IPC_SERVICE_SERVICE "service"
#define ZBX_IPC_SERVICE_SERVICE_PROBLEMS 1
#define ZBX_IPC_SERVICE_SERVICE_PROBLEMS_TAGS 2
diff --git a/src/libs/zbxserver/expression.c b/src/libs/zbxserver/expression.c
index 3c65441ace2..63491445521 100644
--- a/src/libs/zbxserver/expression.c
+++ b/src/libs/zbxserver/expression.c
@@ -1542,7 +1542,6 @@ static int get_autoreg_value_by_event(const DB_EVENT *event, char **replace_to,
#define MVAR_EVENT_UPDATE_STATUS MVAR_EVENT_UPDATE "STATUS}"
#define MVAR_EVENT_UPDATE_NSEVERITY MVAR_EVENT_UPDATE "NSERVERITY}"
#define MVAR_EVENT_UPDATE_SEVERITY MVAR_EVENT_UPDATE "SERVERITY}"
-#define MVAR_EVENT_SERVICE_NAME MVAR_EVENT "SERVICE.NAME}"
#define MVAR_ESC_HISTORY "{ESC.HISTORY}"
#define MVAR_PROXY_NAME "{PROXY.NAME}"
@@ -1585,6 +1584,9 @@ static int get_autoreg_value_by_event(const DB_EVENT *event, char **replace_to,
#define MVAR_ITEM_LOG_NSEVERITY MVAR_ITEM_LOG "NSEVERITY}"
#define MVAR_ITEM_LOG_EVENTID MVAR_ITEM_LOG "EVENTID}"
+#define MVAR_SERVICE_NAME "{SERVICE.NAME}"
+#define MVAR_SERVICE_ROOTCAUSE "{SERVICE.ROOTCAUSE}"
+
#define MVAR_TRIGGER_DESCRIPTION "{TRIGGER.DESCRIPTION}"
#define MVAR_TRIGGER_COMMENT "{TRIGGER.COMMENT}" /* deprecated */
#define MVAR_TRIGGER_ID "{TRIGGER.ID}"
@@ -2295,6 +2297,37 @@ static void get_event_value(const char *macro, const DB_EVENT *event, char **rep
}
}
+static void get_rootcause(const DB_SERVICE *service, char **replace_to)
+{
+ int i;
+ char *d = "";
+
+ for (i = 0; i < service->events.values_num; i++)
+ {
+ DB_EVENT *event;
+ char *host = NULL, *severity = NULL, *tags = NULL;
+
+ event = (DB_EVENT *)service->events.values[i];
+
+ if (FAIL == DBget_trigger_value(&event->trigger, &host, 1, ZBX_REQUEST_HOST_HOST))
+ goto next;
+
+ if (FAIL == get_trigger_severity_name(event->severity, &severity))
+ goto next;
+
+ get_event_tags(event, &tags);
+
+ *replace_to = zbx_strdcatf(*replace_to, "%sHost: \"%s\" Problem name: \"%s\" Severity: \"%s\""
+ " Age: %s Problem tags: \"%s\"", d, host, event->name, severity,
+ zbx_age2str(time(NULL) - event->clock), tags);
+ d = "\n";
+next:
+ zbx_free(host);
+ zbx_free(severity);
+ zbx_free(tags);
+ }
+}
+
/******************************************************************************
* *
* Function: get_history_log_value *
@@ -4058,7 +4091,7 @@ static int substitute_simple_macros_impl(const zbx_uint64_t *actionid, const DB_
if (FAIL == get_trigger_severity_name(service_alarm->value, &replace_to))
replace_to = zbx_strdup(replace_to, "unknown");
}
- else if (0 == strcmp(m, MVAR_EVENT_SERVICE_NAME))
+ else if (0 == strcmp(m, MVAR_SERVICE_NAME))
{
replace_to = zbx_strdup(replace_to, event->service->name);
}
@@ -4077,6 +4110,10 @@ static int substitute_simple_macros_impl(const zbx_uint64_t *actionid, const DB_
if (NULL != alert)
replace_to = zbx_strdup(replace_to, alert->message);
}
+ else if (0 == strcmp(m, MVAR_SERVICE_ROOTCAUSE))
+ {
+ get_rootcause(event->service, &replace_to);
+ }
}
}
else if (0 != (macro_type & (MACRO_TYPE_TRIGGER_DESCRIPTION | MACRO_TYPE_TRIGGER_COMMENTS |
diff --git a/src/libs/zbxservice/service.c b/src/libs/zbxservice/service.c
index f6cd30083c8..6eabfaf7ffb 100644
--- a/src/libs/zbxservice/service.c
+++ b/src/libs/zbxservice/service.c
@@ -22,6 +22,9 @@
#include "zbxipcservice.h"
#include "service_protocol.h"
+#include "../../libs/zbxalgo/vectorimpl.h"
+ZBX_VECTOR_IMPL(service, DB_SERVICE)
+
void zbx_service_flush(zbx_uint32_t code, unsigned char *data, zbx_uint32_t size)
{
static zbx_ipc_socket_t socket;
diff --git a/src/libs/zbxservice/service_protocol.c b/src/libs/zbxservice/service_protocol.c
index 68504f26737..7b5cf3e34a0 100644
--- a/src/libs/zbxservice/service_protocol.c
+++ b/src/libs/zbxservice/service_protocol.c
@@ -241,3 +241,73 @@ void zbx_service_deserialize_ids(const unsigned char *data, zbx_uint32_t size, z
zbx_vector_uint64_append(eventids, eventid);
}
}
+
+void zbx_service_serialize_rootcause(unsigned char **data, size_t *data_alloc, size_t *data_offset,
+ zbx_uint64_t serviceid, const zbx_vector_uint64_t *eventids)
+{
+ zbx_uint32_t data_len = 0;
+ int i;
+ unsigned char *ptr;
+
+ zbx_serialize_prepare_value(data_len, serviceid);
+ zbx_serialize_prepare_value(data_len, eventids->values_num);
+
+ for (i = 0; i < eventids->values_num; i++)
+ zbx_serialize_prepare_value(data_len, eventids->values[i]);
+
+ if (NULL != *data)
+ {
+ while (data_len > *data_alloc - *data_offset)
+ {
+ *data_alloc *= 2;
+ *data = (unsigned char *)zbx_realloc(*data, *data_alloc);
+ }
+ }
+ else
+ *data = (unsigned char *)zbx_malloc(NULL, (*data_alloc = MAX(1024, data_len)));
+
+ ptr = *data + *data_offset;
+ *data_offset += data_len;
+
+ ptr += zbx_serialize_value(ptr, serviceid);
+ ptr += zbx_serialize_value(ptr, eventids->values_num);
+
+ for (i = 0; i < eventids->values_num; i++)
+ ptr += zbx_serialize_value(ptr, eventids->values[i]);
+}
+
+void zbx_service_deserialize_rootcause(const unsigned char *data, zbx_uint32_t size,
+ zbx_vector_service_t *services)
+{
+ const unsigned char *end = data + size;
+
+ while (data < end)
+ {
+ DB_SERVICE *service, service_local;
+ int values_num, i;
+
+ data += zbx_deserialize_value(data, &service_local.serviceid);
+ data += zbx_deserialize_value(data, &values_num);
+
+ if (FAIL == (i = zbx_vector_service_bsearch(services, service_local, ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
+ service = NULL;
+ else
+ service = &services->values[i];
+
+ if (0 == values_num)
+ continue;
+
+ if (NULL != service)
+ zbx_vector_uint64_reserve(&service->eventids, values_num);
+
+ for (i = 0; i < values_num; i++)
+ {
+ zbx_uint64_t eventid;
+
+ data += zbx_deserialize_value(data, &eventid);
+
+ if (NULL != service)
+ zbx_vector_uint64_append(&service->eventids, eventid);
+ }
+ }
+}
diff --git a/src/zabbix_server/escalator/escalator.c b/src/zabbix_server/escalator/escalator.c
index 5e8a71a852d..245b8c03459 100644
--- a/src/zabbix_server/escalator/escalator.c
+++ b/src/zabbix_server/escalator/escalator.c
@@ -83,9 +83,6 @@ zbx_tag_filter_t;
ZBX_VECTOR_DECL(service_alarm, zbx_service_alarm_t)
ZBX_VECTOR_IMPL(service_alarm, zbx_service_alarm_t)
-ZBX_VECTOR_DECL(service, DB_SERVICE)
-ZBX_VECTOR_IMPL(service, DB_SERVICE)
-
typedef enum
{
ZBX_VC_UPDATE_STATS,
@@ -2382,7 +2379,7 @@ static void add_ack_escalation_r_eventids(zbx_vector_ptr_t *escalations, zbx_vec
zbx_vector_uint64_destroy(&r_eventids);
}
-static void get_services_by_serviceids(const zbx_vector_uint64_t *serviceids)
+static void get_services_rootcause_eventids(const zbx_vector_uint64_t *serviceids, zbx_vector_service_t *services)
{
unsigned char *data = NULL;
size_t data_alloc = 0, data_offset = 0;
@@ -2397,21 +2394,24 @@ static void get_services_by_serviceids(const zbx_vector_uint64_t *serviceids)
zbx_ipc_message_init(&response);
zbx_service_send(ZBX_IPC_SERVICE_SERVICE_ROOTCAUSE, data, data_offset, &response);
+ zbx_service_deserialize_rootcause(response.data, response.size, services);
zbx_ipc_message_clean(&response);
zbx_free(data);
}
-static void db_get_services(const zbx_vector_ptr_t *escalations, zbx_vector_service_t *services)
+static void db_get_services(const zbx_vector_ptr_t *escalations, zbx_vector_service_t *services,
+ zbx_vector_ptr_t *events)
{
DB_RESULT result;
DB_ROW row;
char *sql = NULL;
size_t sql_alloc = 0, sql_offset = 0;
- zbx_vector_uint64_t serviceids;
- int i, index;
+ zbx_vector_uint64_t serviceids, eventids;
+ int i, j, index;
zbx_vector_uint64_create(&serviceids);
+ zbx_vector_uint64_create(&eventids);
for (i = 0; i < escalations->values_num; i++)
{
@@ -2435,7 +2435,7 @@ static void db_get_services(const zbx_vector_ptr_t *escalations, zbx_vector_serv
result = DBselect(
"select serviceid,name"
" from services"
- " where%s",
+ " where%s order by serviceid",
sql);
while (NULL != (row = DBfetch(result)))
@@ -2444,16 +2444,48 @@ static void db_get_services(const zbx_vector_ptr_t *escalations, zbx_vector_serv
ZBX_STR2UINT64(service.serviceid, row[0]);
service.name = zbx_strdup(NULL, row[1]);
+ zbx_vector_uint64_create(&service.eventids);
+ zbx_vector_ptr_create(&service.events);
zbx_vector_service_append(services, service);
}
DBfree_result(result);
}
- get_services_by_serviceids(&serviceids);
-
zbx_free(sql);
+ get_services_rootcause_eventids(&serviceids, services);
+
+ for (i = 0; i < services->values_num; i++)
+ {
+ DB_SERVICE *service = &services->values[i];
+
+ for (j = 0; j < service->eventids.values_num; j++)
+ zbx_vector_uint64_append(&eventids, service->eventids.values[j]);
+ }
+
+ if (0 != eventids.values_num)
+ {
+ zbx_db_get_events_by_eventids(&eventids, events);
+
+ for (i = 0; i < services->values_num; i++)
+ {
+ DB_SERVICE *service = &services->values[i];
+
+ for (j = 0; j < service->eventids.values_num; j++)
+ {
+ if (FAIL == (index = zbx_vector_ptr_bsearch(events, &service->eventids.values[j],
+ ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
+ {
+ continue;
+ }
+
+ zbx_vector_ptr_append(&service->events, (DB_EVENT *)events->values[index]);
+ }
+ }
+ }
+
+ zbx_vector_uint64_destroy(&eventids);
zbx_vector_uint64_destroy(&serviceids);
}
@@ -2520,7 +2552,7 @@ static int process_db_escalations(int now, int *nextcheck, zbx_vector_ptr_t *esc
{
int i, ret;
zbx_vector_uint64_t escalationids;
- zbx_vector_ptr_t diffs, actions, events;
+ zbx_vector_ptr_t diffs, actions, events, events_rootcause;
zbx_escalation_diff_t *diff;
zbx_vector_uint64_pair_t event_pairs;
zbx_vector_service_alarm_t service_alarms;
@@ -2535,13 +2567,14 @@ static int process_db_escalations(int now, int *nextcheck, zbx_vector_ptr_t *esc
zbx_vector_uint64_pair_create(&event_pairs);
zbx_vector_service_alarm_create(&service_alarms);
zbx_vector_service_create(&services);
+ zbx_vector_ptr_create(&events_rootcause);
add_ack_escalation_r_eventids(escalations, eventids, &event_pairs);
get_db_actions_info(actionids, &actions);
zbx_db_get_events_by_eventids(eventids, &events);
get_db_service_alarms(escalations, &service_alarms);
- db_get_services(escalations, &services);
+ db_get_services(escalations, &services, &events_rootcause);
for (i = 0; i < escalations->values_num; i++)
{
@@ -2830,11 +2863,18 @@ out:
zbx_vector_ptr_clear_ext(&events, (zbx_clean_func_t)zbx_db_free_event);
zbx_vector_ptr_destroy(&events);
+ zbx_vector_ptr_clear_ext(&events_rootcause, (zbx_clean_func_t)zbx_db_free_event);
+ zbx_vector_ptr_destroy(&events_rootcause);
+
zbx_vector_uint64_pair_destroy(&event_pairs);
zbx_vector_service_alarm_destroy(&service_alarms);
for (i = 0; i < services.values_num; i++)
+ {
zbx_free(services.values[i].name);
+ zbx_vector_ptr_destroy(&services.values[i].events);
+ zbx_vector_uint64_destroy(&services.values[i].eventids);
+ }
zbx_vector_service_destroy(&services);
diff --git a/src/zabbix_server/service/service_manager.c b/src/zabbix_server/service/service_manager.c
index 15e1e647ea5..0f88ce4774b 100644
--- a/src/zabbix_server/service/service_manager.c
+++ b/src/zabbix_server/service/service_manager.c
@@ -2218,15 +2218,58 @@ static void process_events(zbx_vector_ptr_t *events, zbx_service_manager_t *serv
zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
}
-static void process_rootcause(zbx_ipc_message_t *message, zbx_service_manager_t *service_manager,
+static void get_service_rootcause(zbx_service_t *service, zbx_vector_uint64_t *eventids)
+{
+ int i;
+
+ for (i = 0; i < service->service_problems.values_num; i++)
+ {
+ zbx_service_problem_t *service_problem;
+
+ service_problem = (zbx_service_problem_t *)service->service_problems.values[i];
+ zbx_vector_uint64_append(eventids, service_problem->eventid);
+ }
+
+ for (i = 0; i < service->children.values_num; i++)
+ {
+ zbx_service_t *child = (zbx_service_t *)service->children.values[i];
+
+ get_service_rootcause(child, eventids);
+ }
+}
+static void process_rootcause(const zbx_ipc_message_t *message, zbx_service_manager_t *service_manager,
zbx_ipc_client_t *client)
{
- zbx_vector_uint64_t serviceids;
+ zbx_vector_uint64_t serviceids, eventids;
+ int i;
+ unsigned char *data = NULL;
+ size_t data_alloc = 0, data_offset = 0;
zbx_vector_uint64_create(&serviceids);
+ zbx_vector_uint64_create(&eventids);
zbx_service_deserialize_ids(message->data, message->size, &serviceids);
- zbx_ipc_client_send(client, ZBX_IPC_SERVICE_SERVICE_ROOTCAUSE, NULL, 0);
+
+ for (i = 0; i < serviceids.values_num; i++)
+ {
+ zbx_service_t *service, service_local = {.serviceid = serviceids.values[i]};
+
+ if (NULL == (service = zbx_hashset_search(&service_manager->services, &service_local)))
+ continue;
+
+ get_service_rootcause(service, &eventids);
+
+ if (0 == eventids.values_num)
+ continue;
+
+ zbx_service_serialize_rootcause(&data, &data_alloc, &data_offset, serviceids.values[i], &eventids);
+ zbx_vector_uint64_clear(&eventids);
+ }
+
+ zbx_ipc_client_send(client, ZBX_IPC_SERVICE_SERVICE_ROOTCAUSE, data, data_offset);
+
+ zbx_free(data);
+ zbx_vector_uint64_destroy(&eventids);
zbx_vector_uint64_destroy(&serviceids);
}