zabbix-agent2/src/zabbix_server/service/service_manager.c
/******************************************************************************
 *                                                                            *
 * Function: service_get_causes                                               *
 *                                                                            *
 * Purpose: get services that caused the target service to be in the          *
 *          specified severity state                                          *
 *                                                                            *
 * Parameters: service   - [IN] the service                                   *
 *             severity  - [IN] the required severity (-1 if there is no      *
 *                              minimum severity required)                    *
 *             eventids  - [OUT] the root cause events                        *
 *                                                                            *
 * Comments: The returned list includes children, grandchildren etc           *
 *                                                                            *
 ******************************************************************************/
service_get_causes

Purpose: get services that caused the target service to be in the
specified severity state

Parameters: service   - [IN] the service
severity  - [IN] the required severity (-1 if there is no
minimum severity required)
eventids  - [OUT] the root cause events

Comments: The returned list includes children, grandchildren etc
service_get_causes Purpose : get services that caused the target service to be in the specified severity state Parameters : service - [ IN ] the service severity - [ IN ] the required severity ( - 1 if there is no minimum severity required ) eventids - [ OUT ] the root cause events Comments : The returned list includes children grandchildren etc
static void	service_get_causes(const zbx_service_t *service, int severity, zbx_vector_uint64_t *eventids)
{
	int			i, min_severity;
	zbx_vector_ptr_t	causes;
	zbx_service_rule_t	*n_rule = NULL, *w_rule = NULL;
	if (ZBX_SERVICE_STATUS_OK != severity)
	{
		switch (service->propagation_rule)
		{
			case ZBX_SERVICE_STATUS_PROPAGATION_INCREASE:
				min_severity = severity - service->propagation_value;
				if (ZBX_SERVICE_STATUS_OK >= min_severity)
					min_severity = ZBX_SERVICE_STATUS_OK + 1;
				severity = min_severity;
				break;
			case ZBX_SERVICE_STATUS_PROPAGATION_DECREASE:
				min_severity = severity + service->propagation_value;
				if (TRIGGER_SEVERITY_COUNT <= min_severity)
					min_severity = TRIGGER_SEVERITY_COUNT - 1;
				severity = min_severity;
				break;
			case ZBX_SERVICE_STATUS_PROPAGATION_FIXED:
				min_severity = TRIGGER_SEVERITY_NOT_CLASSIFIED;
				severity = ZBX_SERVICE_STATUS_OK;
				break;
			default:
				min_severity = severity;
		}
	}
	else
		min_severity = TRIGGER_SEVERITY_NOT_CLASSIFIED;
	if (0 == service->children.values_num)
	{
		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];
			if (service_problem->severity >= min_severity)
				zbx_vector_uint64_append(eventids, service_problem->eventid);
		}
		return;
	}
	zbx_vector_ptr_create(&causes);
	if (service_get_main_status(service) >= min_severity)
	{
		for (i = 0; i < service->children.values_num; i++)
		{
			zbx_service_t	*child = (zbx_service_t *)service->children.values[i];
			int		child_status;
			if (SUCCEED != service_get_status(child, &child_status) ||
					ZBX_SERVICE_STATUS_OK == child_status)
			{
				continue;
			}
			if (ZBX_SERVICE_STATUS_CALC_MOST_CRITICAL_ALL == service->algorithm)
				service_add_cause(&causes, child, ZBX_SERVICE_STATUS_OK);
			if (ZBX_SERVICE_STATUS_CALC_MOST_CRITICAL_ONE == service->algorithm &&
					child_status >= min_severity)
			{
				service_add_cause(&causes, child, severity);
			}
		}
	}
	for (i = 0; i < service->status_rules.values_num; i++)
	{
		zbx_service_rule_t	*rule = (zbx_service_rule_t *)service->status_rules.values[i];
		if (rule->new_status < min_severity)
			continue;
		if (ZBX_SERVICE_STATUS_OK == service_get_rule_status(service, rule))
			continue;
		switch (rule->type)
		{
			case ZBX_SERVICE_STATUS_RULE_TYPE_N_GE:
			case ZBX_SERVICE_STATUS_RULE_TYPE_NP_GE:
			case ZBX_SERVICE_STATUS_RULE_TYPE_N_L:
			case ZBX_SERVICE_STATUS_RULE_TYPE_NP_L:
				if (NULL == n_rule || rule->limit_status < n_rule->limit_status)
					n_rule = rule;
				break;
			default:
				if (NULL == w_rule || rule->limit_status < w_rule->limit_status)
					w_rule = rule;
				break;
		}
	}
	if (NULL != n_rule)
	{
		int			total_weight, total_num;
		zbx_vector_ptr_t	children;
		zbx_vector_ptr_create(&children);
		service_get_children_by_status(service, n_rule->limit_status, &children, &total_weight, &total_num);
		for (i = 0; i < children.values_num; i++)
			service_add_cause(&causes, (zbx_service_t *)children.values[i], n_rule->limit_status);
		zbx_vector_ptr_destroy(&children);
	}
	if (NULL != w_rule)
	{
		int			total_weight, total_num;
		zbx_vector_ptr_t	children;
		zbx_vector_ptr_create(&children);
		service_get_children_by_status(service, w_rule->limit_status, &children, &total_weight, &total_num);
		for (i = 0; i < children.values_num; i++)
		{
			zbx_service_t	*child = (zbx_service_t *)children.values[i];
			if (0 == child->weight)
				continue;
			service_add_cause(&causes, child, w_rule->limit_status);
		}
		zbx_vector_ptr_destroy(&children);
	}
	for (i = 0; i < causes.values_num; i++)
	{
		zbx_service_severity_t	*cause = (zbx_service_severity_t *)causes.values[i];
		service_get_causes(cause->service, cause->severity, eventids);
	}
	zbx_vector_ptr_clear_ext(&causes, zbx_ptr_free);
	zbx_vector_ptr_destroy(&causes);
}
static void service_get_causes ( const zbx_service_t * service , int severity , zbx_vector_uint64_t * eventids ) { int i , min_severity ; zbx_vector_ptr_t causes ; zbx_service_rule_t * n_rule = NULL , * w_rule = NULL ; if ( ZBX_SERVICE_STATUS_OK != severity ) { switch ( service -> propagation_rule ) { case ZBX_SERVICE_STATUS_PROPAGATION_INCREASE : min_severity = severity - service -> propagation_value ; if ( ZBX_SERVICE_STATUS_OK >= min_severity ) min_severity = ZBX_SERVICE_STATUS_OK + 1 ; severity = min_severity ; break ; case ZBX_SERVICE_STATUS_PROPAGATION_DECREASE : min_severity = severity + service -> propagation_value ; if ( TRIGGER_SEVERITY_COUNT <= min_severity ) min_severity = TRIGGER_SEVERITY_COUNT - 1 ; severity = min_severity ; break ; case ZBX_SERVICE_STATUS_PROPAGATION_FIXED : min_severity = TRIGGER_SEVERITY_NOT_CLASSIFIED ; severity = ZBX_SERVICE_STATUS_OK ; break ; default : min_severity = severity ; } } else min_severity = TRIGGER_SEVERITY_NOT_CLASSIFIED ; if ( 0 == service -> children . values_num ) { 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 ] ; if ( service_problem -> severity >= min_severity ) zbx_vector_uint64_append ( eventids , service_problem -> eventid ) ; } return ; } zbx_vector_ptr_create ( & causes ) ; if ( service_get_main_status ( service ) >= min_severity ) { for ( i = 0 ; i < service -> children . values_num ; i ++ ) { zbx_service_t * child = ( zbx_service_t * ) service -> children . values [ i ] ; int child_status ; if ( SUCCEED != service_get_status ( child , & child_status ) || ZBX_SERVICE_STATUS_OK == child_status ) { continue ; } if ( ZBX_SERVICE_STATUS_CALC_MOST_CRITICAL_ALL == service -> algorithm ) service_add_cause ( & causes , child , ZBX_SERVICE_STATUS_OK ) ; if ( ZBX_SERVICE_STATUS_CALC_MOST_CRITICAL_ONE == service -> algorithm && child_status >= min_severity ) { service_add_cause ( & causes , child , severity ) ; } } } for ( i = 0 ; i < service -> status_rules . values_num ; i ++ ) { zbx_service_rule_t * rule = ( zbx_service_rule_t * ) service -> status_rules . values [ i ] ; if ( rule -> new_status < min_severity ) continue ; if ( ZBX_SERVICE_STATUS_OK == service_get_rule_status ( service , rule ) ) continue ; switch ( rule -> type ) { case ZBX_SERVICE_STATUS_RULE_TYPE_N_GE : case ZBX_SERVICE_STATUS_RULE_TYPE_NP_GE : case ZBX_SERVICE_STATUS_RULE_TYPE_N_L : case ZBX_SERVICE_STATUS_RULE_TYPE_NP_L : if ( NULL == n_rule || rule -> limit_status < n_rule -> limit_status ) n_rule = rule ; break ; default : if ( NULL == w_rule || rule -> limit_status < w_rule -> limit_status ) w_rule = rule ; break ; } } if ( NULL != n_rule ) { int total_weight , total_num ; zbx_vector_ptr_t children ; zbx_vector_ptr_create ( & children ) ; service_get_children_by_status ( service , n_rule -> limit_status , & children , & total_weight , & total_num ) ; for ( i = 0 ; i < children . values_num ; i ++ ) service_add_cause ( & causes , ( zbx_service_t * ) children . values [ i ] , n_rule -> limit_status ) ; zbx_vector_ptr_destroy ( & children ) ; } if ( NULL != w_rule ) { int total_weight , total_num ; zbx_vector_ptr_t children ; zbx_vector_ptr_create ( & children ) ; service_get_children_by_status ( service , w_rule -> limit_status , & children , & total_weight , & total_num ) ; for ( i = 0 ; i < children . values_num ; i ++ ) { zbx_service_t * child = ( zbx_service_t * ) children . values [ i ] ; if ( 0 == child -> weight ) continue ; service_add_cause ( & causes , child , w_rule -> limit_status ) ; } zbx_vector_ptr_destroy ( & children ) ; } for ( i = 0 ; i < causes . values_num ; i ++ ) { zbx_service_severity_t * cause = ( zbx_service_severity_t * ) causes . values [ i ] ; service_get_causes ( cause -> service , cause -> severity , eventids ) ; } zbx_vector_ptr_clear_ext ( & causes , zbx_ptr_free ) ; zbx_vector_ptr_destroy ( & causes ) ; }
Function: service_get_causes                                               
                                                                            
 Purpose: get services that caused the target service to be in the          
          specified severity state                                          
                                                                            
 Parameters: service   - [IN] the service                                   
             severity  - [IN] the required severity (-1 if there is no      
                              minimum severity required)                    
             eventids  - [OUT] the root cause events                        
                                                                            
 Comments: The returned list includes children, grandchildren etc
Function : service_get_causes Purpose : get services that caused the target service to be in the specified severity state Parameters : service - [ IN ] the service severity - [ IN ] the required severity ( - 1 if there is no minimum severity required ) eventids - [ OUT ] the root cause events Comments : The returned list includes children grandchildren etc
/* calculate the minimum severity by reversing propagation rule */ /* check if the rule can return status of acceptable severity */ /* cause is only added once, even if weight based rule is covered by the count based rule */