diff options
author | Vladislavs Sokurenko <vladislavs.sokurenko@zabbix.com> | 2021-07-13 16:51:57 +0300 |
---|---|---|
committer | Vladislavs Sokurenko <vladislavs.sokurenko@zabbix.com> | 2021-07-13 16:51:57 +0300 |
commit | dc036b08686ecc15f06ab144b86d9fb230cc4cf6 (patch) | |
tree | 6b5e72947af1fe19b0e7222b0dcdaf59289e9790 | |
parent | fe2644f05f9f9fe6dbffd17281b1d2612abd436d (diff) |
........S. [ZBXNEXT-6755] added support of service root cause macro
-rw-r--r-- | include/db.h | 6 | ||||
-rw-r--r-- | include/service_protocol.h | 8 | ||||
-rw-r--r-- | include/zbxservice.h | 2 | ||||
-rw-r--r-- | src/libs/zbxserver/expression.c | 41 | ||||
-rw-r--r-- | src/libs/zbxservice/service.c | 3 | ||||
-rw-r--r-- | src/libs/zbxservice/service_protocol.c | 70 | ||||
-rw-r--r-- | src/zabbix_server/escalator/escalator.c | 64 | ||||
-rw-r--r-- | src/zabbix_server/service/service_manager.c | 49 |
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); } |