本帖最后由 坎蒂丝_Swan 于 2014-12-14 19:41 编辑
问题导读 问题1:联合报警器状态评估具体是怎样实现的? 问题2:如果想要制定合适的联合报警器评估方法,要如何改写相关方法?
ceilometer报警器状态评估方式之联合报警器状态评估的具体实现
ceilometer报警系统中实现了两种报警器状态评估方式,即联合报警器状态评估和单一报警器状态评估,这篇帖子将会解析联合报警器状态评估的具体实现,即/ceilometer/alarm/evaluator/combination.py中类CombinationEvaluator所实现的内容。在这个类所实现的若干方法中,所有方法都被方法evaluate所调用,最终实现联合报警器状态的评估操作,我们来看看这个类所有重要方法的实现。
1 def _get_alarm_state(self, alarm_id)
- def _get_alarm_state(self, alarm_id):
- """
- 通过客户端获取指定ID的报警器的状态;
- """
- try:
- alarm = self._client.alarms.get(alarm_id)
- except Exception:
- LOG.exception(_('alarm retrieval failed'))
- return None
- return alarm.state
复制代码
方法小结:
这个方法实现通过客户端获取指定ID的报警器的状态;
2 def _sufficient_states(self, alarm, states)
- def _sufficient_states(self, alarm, states):
- """
- 确认指定联合报警器有足够多的数据用于评估操作;
-
- 1.获取联合报警器中,所有状态为'insufficient data'的报警器列表;
- 2.如果存在部分报警器的数据状态是'insufficient data',则令sufficient = 0;
- 如果所有报警器的数据状态都不是'insufficient data',则令sufficient = 1;
- 3.如果有部分报警器的数据状态是'insufficient data',
- 并且联合报警器的数据状态不是'insufficient data',
- 则设置联合报警器的数据状态为'insufficient data';
- 4.返回sufficient值,表示联合报警器中所有报警器是否有足够的数据用于报警评估操作;
- 如果sufficient = 1,表示联合报警器中所有报警器有足够的数据用于报警评估;
- 如果sufficient = 0,表示联合报警器中部分报警器不满足报警评估的数据条件;
- """
-
- """
- alarms_missing_states:表示所有数据状态为'insufficient data'的报警器列表;
- """
- alarms_missing_states = [alarm_id for alarm_id, state in states
- if not state or state == evaluator.UNKNOWN]
-
- """
- sufficient = 0:说明存在部分报警器的数据状态是'insufficient data';
- sufficient = 1:说明所有报警器的数据状态都不是'insufficient data';
- """
- sufficient = len(alarms_missing_states) == 0
- """
- 如果有部分报警器的数据状态是'insufficient data',
- 并且联合报警器的数据状态不是'insufficient data',
- 则设置联合报警器的数据状态为'insufficient data';
- """
- if not sufficient and alarm.state != evaluator.UNKNOWN:
- reason = _('Alarms %(alarm_ids)s'
- ' are in unknown state') % \
- {'alarm_ids': ",".join(alarms_missing_states)}
- reason_data = self._reason_data(alarms_missing_states)
-
- """
- 刷新报警器的状态为指定的状态;
- 设置联合报警器alarm的状态为UNKNOWN(UNKNOWN = 'insufficient data');
- """
- self._refresh(alarm, evaluator.UNKNOWN, reason, reason_data)
-
- """
- 如果返回值为1,说明所有报警器的数据状态都不是'insufficient data';
- 如果返回值为0,说明存在部分报警器的数据状态是'insufficient data',
- (此时已经设置联合报警器的数据状态为'insufficient data');
- """
- return sufficient
复制代码
方法小结: 确认指定联合报警器有足够多的数据用于评估操作;
1.获取联合报警器中,所有状态为'insufficient data'的报警器列表;
2.如果存在部分报警器的数据状态是'insufficient data',则令sufficient = 0;
如果所有报警器的数据状态都不是'insufficient data',则令sufficient = 1;
3.如果有部分报警器的数据状态是'insufficient data',
并且联合报警器的数据状态不是'insufficient data',
则设置联合报警器的数据状态为'insufficient data';
4.返回sufficient值,表示联合报警器中所有报警器是否有足够的数据用于报警评估操作;
如果sufficient = 1,表示联合报警器中所有报警器有足够的数据用于报警评估;
如果sufficient = 0,表示联合报警器中部分报警器不满足报警评估的数据条件;
3 def _transition(self, alarm, underlying_states)
- def _transition(self, alarm, underlying_states):
- """
- 此方法实现对联合报警器进行报警评估操作,并刷新报警器的状态为ALARM或OK;
- 只有当所有报警器的状态都不是'insufficient data'的时候,会调用此方法;
- """
- op = alarm.rule['operator']
-
- """
- COMPARATORS = {'and': all, 'or': any}
- 这里提供了两种报警器评估方法:
- 第一种是当所有报警器的报警状态均为alarm时,联合报警器的状态为alarm;
- 第二种是只要有任何报警器的报警状态为alarm,联合报警器的状态为alarm;
- 所以这里根据系统选择的报警器评估方法op,实现评估联合报警器的报警状态;
- 报警器的报警状态也只有两个alarm和ok;
- """
- if COMPARATORS[op](s == evaluator.ALARM
- for __, s in underlying_states):
- state = evaluator.ALARM
- else:
- state = evaluator.OK
-
- """
- 更新联合报警器的报警状态为上面评估的结果;
- """
- continuous = alarm.repeat_actions
- reason, reason_data = self._reason(alarm, state, underlying_states)
- if alarm.state != state or continuous:
- self._refresh(alarm, state, reason, reason_data)
复制代码
方法小结:
1.系统提供了两种报警器评估方法: COMPARATORS = {'and': all, 'or': any} 第一种是当所有报警器的报警状态均为alarm时,联合报警器的状态为alarm;
第二种是只要有任何报警器的报警状态为alarm,联合报警器的状态为alarm; 所以如果想要制定合适的联合报警器评估方法,可以对这里进行改写;
2.系统设定的报警器的报警状态有两个:alarm和ok;
4 def evaluate(self, alarm)
这个方法最终实现联合报警器状态的评估操作,上面的方法实际上都被这个方法所调用,为联合报警器的评估实现了若干操作;
- def evaluate(self, alarm):
- """
- 根据所有报警器的数据状态,对联合报警器的报警状态进行评估操作;
- 1.通过客户端获取联合报警器中所有报警器的数据状态;
- 2.确认指定联合报警器有足够多的数据用于评估操作;
- 3.如果联合报警器有足够多的数据用于评估操作,则实现对联合报警器进行报警评估操
- 作,并刷新报警器的状态为ALARM或OK;
- """
- if not self.within_time_constraint(alarm):
- LOG.debug(_('Attempted to evaluate alarm %s, but it is not '
- 'within its time constraint.') % alarm.alarm_id)
- return
-
- """
- 通过客户端获取联合报警器中所有报警器的数据状态;
- """
- states = zip(alarm.rule['alarm_ids'],
- itertools.imap(self._get_alarm_state,
- alarm.rule['alarm_ids']))
-
- """
- 确认指定联合报警器有足够多的数据用于评估操作;
- 如果返回值为1,表示联合报警器中所有报警器有足够的数据用于报警评估;
- 如果返回值为0,表示联合报警器中部分报警器不满足报警评估的数据条件;
-
- 当返回值为1,即联合报警器中所有报警器有足够的数据用于报警评估时,
- 实现对联合报警器进行报警评估操作,并刷新报警器的状态为ALARM或OK;
- """
- if self._sufficient_states(alarm, states):
- # 只有当所有报警器的状态都不是'insufficient data'的时候,会调用此方法;
- # 此方法实现转换报警器的状态为ALARM或OK;
- self._transition(alarm, states)
复制代码
方法小结:
根据所有报警器的数据状态,对联合报警器的报警状态进行评估操作;
1.通过客户端获取联合报警器中所有报警器的数据状态;
2.确认指定联合报警器有足够多的数据用于评估操作;
3.如果联合报警器有足够多的数据用于评估操作,则实现对联合报警器进行报警评估操作,并刷新报警器的状态为ALARM或OK;
ceilometer报警器状态评估方式之单一报警器状态评估的具体实现
这篇帖子将会解析单一报警器状态评估的具体实现,即/ceilometer/alarm/evaluator/threshold.py中类ThresholdEvaluator所实现的内容。在这个类所实现的若干方法中,所有方法都被方法evaluate所调用,最终实现单一报警器状态的评估操作,我们来看看这个类所有重要方法的实现。
1 def _statistics(self, alarm, query)
- def _statistics(self, alarm, query):
- """
- 获取query和meter_name(meter_name=alarm.rule['meter_name'])指定的监控统计数据列表;
- client_class是Client(ceilometerclient/v2/client.py),从Client的属性可以看出statistics是StatisticsManager(ceilometerclient/v2/statistics.py),它的list函数被调用,传入的参数是alarm的meter_name(在alarm的属性中可以看到),查询条件query,以及alarm的period;
- 最终的返回结果为根据query和period制定的查询条件查询meter_name指定的metrics的结果;
-
- 通过客户端通过HTTP协议GET方法获取符合查询条件的statistics列表;
- 最终的返回结果为meter_name指定的metrics的结果statistics列表;
- """
- LOG.debug(_('stats query %s') % query)
- try:
- return self._client.statistics.list(
- meter_name=alarm.rule['meter_name'], q=query,
- period=alarm.rule['period'])
- except Exception:
- LOG.exception(_('alarm stats retrieval failed'))
- return []
复制代码
方法小结:
通过客户端通过HTTP协议GET方法获取符合查询条件的statistics列表;
最终的返回结果为meter_name指定的metrics的结果statistics列表;
2 def _sufficient(self, alarm, statistics)
- def _sufficient(self, alarm, statistics):
- """
- 确保报警器评估具有足够的数据(仲裁人数);
- 1.根据统计数据的数目来判断是否有足够的数据用于报警器的评估(最小值要大于1);
- 2.如果sufficient为0说明用于仲裁的数目不够,则需要刷新报警器的状态为'insufficient data';
- """
-
- """
- 根据统计数据的数目来判断是否有足够的数据用于报警器的评估(最小值要大于1);
- """
- sufficient = len(statistics) >= self.quorum
-
- """
- 如果sufficient为0说明用于仲裁的数目不够,则需要刷新报警器的状态为'insufficient data';
- """
- if not sufficient and alarm.state != evaluator.UNKNOWN:
- reason = _('%d datapoints are unknown') % alarm.rule[
- 'evaluation_periods']
- reason_data = self._reason_data('unknown',
- alarm.rule['evaluation_periods'],
- None)
- self._refresh(alarm, evaluator.UNKNOWN, reason, reason_data)
- return sufficient
复制代码
方法小结:
确保报警器评估具有足够的数据(仲裁人数);
1.根据统计数据的数目来判断是否有足够的数据用于报警器的评估(最小值要大于1);
2.如果sufficient为0说明用于仲裁的数目不够,则需要刷新报警器的状态为'insufficient data';
3 def _transition(self, alarm, statistics, compared)
- def _transition(self, alarm, statistics, compared):
- """
- 根据statistics是否满足触发报警器条件,来更新报警器报警状态(alarm或ok);
- 1.验证所有的statistics是否满足触发报警器的条件;
- * 所有的statistics均满足触发报警器条件;
- * 所有的statistics均不满足触发报警器条件;
- * 报警器的数据状态为'insufficient data'(数据不充足);
- 2.如果所有的statistics均满足报警条件,则说明需触发报警,报警器的状态设置为'alarm';
- 3.如果所有的statistics均不满足报警条天,则说明报警器处于正常状态,报警器的状态设置为'ok';
- 4.如果当前报警器的状态为'insufficient data'(数据不充足),则根据最后一个statistics,来判断报警器的发展状态的趋势,进而确定报警器的报警状态;
- * 如果最后一个statistics符合触发报警器的条件,则说明报警器有转换为ALARM状态的趋势,则设置报警器的报警状态为alarm;
- * 如果最后一个statistics不符合触发报警器的条件,则说明报警器有转换为OK状态的趋势,则设置报警器的报警状态为ok;
- """
-
- """
- 如果distilled为true,说明所有的statistics均满足触发报警器条件;
- """
- distilled = all(compared)
-
-
- """
- 如果unequivocal为true,说明所有的statistics均满足或均不满足触发报警器条件;
- """
- unequivocal = distilled or not any(compared)
- """
- 验证报警器的状态是否为'insufficient data'(数据不充足);
- """
- unknown = alarm.state == evaluator.UNKNOWN
- # repeat_actions:表示每个评估周期都要重新触发的actions;
- continuous = alarm.repeat_actions
-
- """
- 如果所有的statistics均满足报警条件,则说明需触发报警,报警器的状态设置为'alarm';
- 如果所有的statistics均不满足报警条天,则说明报警器处于正常状态,报警器的状态设置为'ok';
- """
- if unequivocal:
- """
- 如果所有的statistics均满足报警条件,则说明需触发报警,报警器的状态设置为'alarm';
- 如果所有的statistics均不满足报警条天,则说明报警器处于正常状态,报警器的状态设置为'ok';
- """
- state = evaluator.ALARM if distilled else evaluator.OK
- reason, reason_data = self._reason(alarm, statistics,
- distilled, state)
-
- """
- 如果报警器的状态和要赋予的状态不同,或者continuous为true,则需要刷新报警器的状态为指定状态;
- """
- if alarm.state != state or continuous:
- self._refresh(alarm, state, reason, reason_data)
-
- """
- 如果当前报警器的状态为'insufficient data',则进一步根据最后一个statistics,来判断报警器的发展状态的趋势;
- """
- elif unknown or continuous:
- """
- 如果当前状态为UNKNOWN,则根据趋势改变状态,即观察最后一个statistics,
- 如果它为true,说明最后一个statistics符合触发报警器的条件,则说明报警器有转换为ALARM状态的趋势,
- 如果它为false,说明最后一个statistics不符合触发报警器的条件,则说明报警器有转换为OK状态的趋势;
- """
- trending_state = evaluator.ALARM if compared[-1] else evaluator.OK
-
- """
- 如果当前报警器的状态为'insufficient data',则采用trending_state作为报警器的状态;
- """
- state = trending_state if unknown else alarm.state
- reason, reason_data = self._reason(alarm, statistics,
- distilled, state)
- """
- 实现刷新报警器的状态为指定状态;
- """
- self._refresh(alarm, state, reason, reason_data)
复制代码
方法小结:
根据statistics是否满足触发报警器条件,来更新报警器报警状态(alarm或ok);
1.验证所有的statistics是否满足触发报警器的条件;
* 所有的statistics均满足触发报警器条件;
* 所有的statistics均不满足触发报警器条件;
* 报警器的数据状态为'insufficient data'(数据不充足);
2.如果所有的statistics均满足报警条件,则说明需触发报警,报警器的状态设置为'alarm';
3.如果所有的statistics均不满足报警条天,则说明报警器处于正常状态,报警器的状态设置为'ok';
4.如果当前报警器的状态为'insufficient data'(数据不充足),则根据最后一个statistics,来判断报警器的发展状态的趋势,进而确定报警器的报警状态;
* 如果最后一个statistics符合触发报警器的条件,则说明报警器有转换为ALARM状态的趋势,则设置报警器的报警状态为alarm;
* 如果最后一个statistics不符合触发报警器的条件,则说明报警器有转换为OK状态的趋势,则设置报警器的报警状态为ok;
4 def evaluate(self, alarm)
这个方法最终实现单一报警器状态的评估操作,上面的方法实际上都被这个方法所调用,为单一报警器的评估实现了若干操作(具体实现可以见代码注释);
- def evaluate(self, alarm):
- """
- 根据报警器获取指定的metrics的结果statistics列表;
- 根据statistics是否满足触发报警器条件,来更新报警器的状态;
- """
- if not self.within_time_constraint(alarm):
- LOG.debug(_('Attempted to evaluate alarm %s, but it is not '
- 'within its time constraint.') % alarm.alarm_id)
- return
-
- # 参照alarm的属性,alarm.rule['query']是
- # metadata.user_metadata.server_group == WebServerGroup;
- # 该方法计算evaluate操作的时间段;
- # 在query的内容中添加时间段为[start,now]的条件,
- # 最后返回更改后的query;
- query = self._bound_duration(
- alarm,
- alarm.rule['query']
- )
-
- """
- _statistics:获取query和meter_name(meter_name=alarm.rule['meter_name'])指定的监控统计数据列表;
- 通过客户端通过HTTP协议GET方法获取符合查询条件的statistics列表;
- 最终的返回结果为meter_name指定的metrics的结果statistics列表;
- 对获取的监控数据列表进行数据的除错处理;
- """
- statistics = self._sanitize(
- alarm,
- self._statistics(alarm, query)
- )
-
- # _sufficient:确保报警器评估具有足够的仲裁数据(根据statistics数目);
- # _sufficient方法用来判断返回的查询结果statistics是否够支持evaluate,其中的quorum为statistics的最小长度,默认为1:
-
- """
- 确保报警器评估具有足够的数据(仲裁人数);
- 根据statistics是否满足触发报警器条件,来更新报警器的报警状态(alarm或ok);
- """
- if self._sufficient(alarm, statistics):
- def _compare(stat):
- op = COMPARATORS[alarm.rule['comparison_operator']]
- value = getattr(stat, alarm.rule['statistic'])
- """
- 获取规定的触发报警器的数值限制;
- """
- limit = alarm.rule['threshold']
- LOG.debug(_('comparing value %(value)s against threshold'
- ' %(limit)s') %
- {'value': value, 'limit': limit})
- return op(value, limit)
-
- """
- 根据statistics是否满足触发报警器条件,来更新报警器的报警状态(alarm或ok);
- """
- self._transition(alarm,
- statistics,
- map(_compare, statistics))
复制代码
Ceilometer项目源码分析----ceilometer项目源码结构分析
Ceilometer项目源码分析----ceilometer报警器服务的实现概览
Ceilometer项目源码分析----ceilometer报警器状态评估方式
Ceilometer项目源码分析----ceilometer分布式报警系统的具体实现
Ceilometer项目源码分析----ceilometer-alarm-notifier服务的初始化和启动
Ceilometer项目源码分析----ceilometer-alarm-evaluator服务的初始化和启动
Ceilometer项目源码分析----ceilometer-agent-central服务的初始化和启动
Ceilometer项目源码分析----ceilometer-agent-compute服务的初始化和启动
Ceilometer项目源码分析----ceilometer-agent-notification服务的初始化和启动
Ceilometer项目源码分析----ceilometer-collector服务的初始化和启动
|