分享

Ceilometer项目源码分析----ceilometer报警器状态评估方式

坎蒂丝_Swan 发表于 2014-12-12 21:40:03 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 0 13974
本帖最后由 坎蒂丝_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)

  1. def _get_alarm_state(self, alarm_id):  
  2.     """
  3.     通过客户端获取指定ID的报警器的状态;
  4.     """  
  5.     try:  
  6.         alarm = self._client.alarms.get(alarm_id)  
  7.     except Exception:  
  8.         LOG.exception(_('alarm retrieval failed'))  
  9.         return None  
  10.     return alarm.state  
复制代码

方法小结:
这个方法实现通过客户端获取指定ID的报警器的状态;

2 def _sufficient_states(self, alarm, states)

  1. def _sufficient_states(self, alarm, states):  
  2.     """
  3.     确认指定联合报警器有足够多的数据用于评估操作;
  4.          
  5.     1.获取联合报警器中,所有状态为'insufficient data'的报警器列表;
  6.     2.如果存在部分报警器的数据状态是'insufficient data',则令sufficient = 0;
  7.       如果所有报警器的数据状态都不是'insufficient data',则令sufficient = 1;
  8.     3.如果有部分报警器的数据状态是'insufficient data',
  9.       并且联合报警器的数据状态不是'insufficient data',
  10.       则设置联合报警器的数据状态为'insufficient data';
  11.     4.返回sufficient值,表示联合报警器中所有报警器是否有足够的数据用于报警评估操作;
  12.       如果sufficient = 1,表示联合报警器中所有报警器有足够的数据用于报警评估;
  13.       如果sufficient = 0,表示联合报警器中部分报警器不满足报警评估的数据条件;
  14.     """  
  15.          
  16.     """
  17.     alarms_missing_states:表示所有数据状态为'insufficient data'的报警器列表;
  18.     """  
  19.     alarms_missing_states = [alarm_id for alarm_id, state in states  
  20.                                  if not state or state == evaluator.UNKNOWN]  
  21.          
  22.     """
  23.     sufficient = 0:说明存在部分报警器的数据状态是'insufficient data';
  24.     sufficient = 1:说明所有报警器的数据状态都不是'insufficient data';
  25.     """  
  26.     sufficient = len(alarms_missing_states) == 0  
  27.     """
  28.     如果有部分报警器的数据状态是'insufficient data',
  29.     并且联合报警器的数据状态不是'insufficient data',
  30.     则设置联合报警器的数据状态为'insufficient data';
  31.     """  
  32.     if not sufficient and alarm.state != evaluator.UNKNOWN:  
  33.         reason = _('Alarms %(alarm_ids)s'  
  34.                    ' are in unknown state') % \  
  35.             {'alarm_ids': ",".join(alarms_missing_states)}  
  36.         reason_data = self._reason_data(alarms_missing_states)  
  37.               
  38.         """
  39.         刷新报警器的状态为指定的状态;
  40.         设置联合报警器alarm的状态为UNKNOWN(UNKNOWN = 'insufficient data');
  41.         """  
  42.         self._refresh(alarm, evaluator.UNKNOWN, reason, reason_data)  
  43.          
  44.     """
  45.     如果返回值为1,说明所有报警器的数据状态都不是'insufficient data';
  46.     如果返回值为0,说明存在部分报警器的数据状态是'insufficient data',
  47.     (此时已经设置联合报警器的数据状态为'insufficient data');
  48.     """  
  49.     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)

  1. def _transition(self, alarm, underlying_states):  
  2.     """
  3.     此方法实现对联合报警器进行报警评估操作,并刷新报警器的状态为ALARM或OK;
  4.     只有当所有报警器的状态都不是'insufficient data'的时候,会调用此方法;
  5.     """  
  6.     op = alarm.rule['operator']  
  7.          
  8.     """
  9.     COMPARATORS = {'and': all, 'or': any}
  10.     这里提供了两种报警器评估方法:
  11.     第一种是当所有报警器的报警状态均为alarm时,联合报警器的状态为alarm;
  12.     第二种是只要有任何报警器的报警状态为alarm,联合报警器的状态为alarm;
  13.     所以这里根据系统选择的报警器评估方法op,实现评估联合报警器的报警状态;
  14.     报警器的报警状态也只有两个alarm和ok;
  15.     """  
  16.     if COMPARATORS[op](s == evaluator.ALARM  
  17.                        for __, s in underlying_states):  
  18.         state = evaluator.ALARM  
  19.     else:  
  20.         state = evaluator.OK  
  21.   
  22.     """
  23.     更新联合报警器的报警状态为上面评估的结果;
  24.     """  
  25.     continuous = alarm.repeat_actions  
  26.     reason, reason_data = self._reason(alarm, state, underlying_states)  
  27.     if alarm.state != state or continuous:  
  28.         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)

    这个方法最终实现联合报警器状态的评估操作,上面的方法实际上都被这个方法所调用,为联合报警器的评估实现了若干操作;

  1. def evaluate(self, alarm):  
  2.     """
  3.     根据所有报警器的数据状态,对联合报警器的报警状态进行评估操作;
  4.     1.通过客户端获取联合报警器中所有报警器的数据状态;
  5.     2.确认指定联合报警器有足够多的数据用于评估操作;
  6.     3.如果联合报警器有足够多的数据用于评估操作,则实现对联合报警器进行报警评估操   
  7.       作,并刷新报警器的状态为ALARM或OK;
  8.     """  
  9.     if not self.within_time_constraint(alarm):  
  10.         LOG.debug(_('Attempted to evaluate alarm %s, but it is not '  
  11.                     'within its time constraint.') % alarm.alarm_id)  
  12.         return  
  13.   
  14.     """
  15.     通过客户端获取联合报警器中所有报警器的数据状态;
  16.     """  
  17.     states = zip(alarm.rule['alarm_ids'],  
  18.                  itertools.imap(self._get_alarm_state,  
  19.                                 alarm.rule['alarm_ids']))  
  20.   
  21.     """
  22.     确认指定联合报警器有足够多的数据用于评估操作;
  23.     如果返回值为1,表示联合报警器中所有报警器有足够的数据用于报警评估;
  24.     如果返回值为0,表示联合报警器中部分报警器不满足报警评估的数据条件;
  25.          
  26.     当返回值为1,即联合报警器中所有报警器有足够的数据用于报警评估时,
  27.     实现对联合报警器进行报警评估操作,并刷新报警器的状态为ALARM或OK;
  28.     """  
  29.     if self._sufficient_states(alarm, states):  
  30.         # 只有当所有报警器的状态都不是'insufficient data'的时候,会调用此方法;  
  31.         # 此方法实现转换报警器的状态为ALARM或OK;  
  32.         self._transition(alarm, states)  
复制代码

方法小结:
根据所有报警器的数据状态,对联合报警器的报警状态进行评估操作;
1.通过客户端获取联合报警器中所有报警器的数据状态;

2.确认指定联合报警器有足够多的数据用于评估操作;

3.如果联合报警器有足够多的数据用于评估操作,则实现对联合报警器进行报警评估操作,并刷新报警器的状态为ALARM或OK;



ceilometer报警器状态评估方式之单一报警器状态评估的具体实现



    这篇帖子将会解析单一报警器状态评估的具体实现,即/ceilometer/alarm/evaluator/threshold.py中类ThresholdEvaluator所实现的内容。在这个类所实现的若干方法中,所有方法都被方法evaluate所调用,最终实现单一报警器状态的评估操作,我们来看看这个类所有重要方法的实现。

1 def _statistics(self, alarm, query)

  1. def _statistics(self, alarm, query):
  2. """
  3. 获取query和meter_name(meter_name=alarm.rule['meter_name'])指定的监控统计数据列表;
  4. client_class是Client(ceilometerclient/v2/client.py),从Client的属性可以看出statistics是StatisticsManager(ceilometerclient/v2/statistics.py),它的list函数被调用,传入的参数是alarm的meter_name(在alarm的属性中可以看到),查询条件query,以及alarm的period;
  5. 最终的返回结果为根据query和period制定的查询条件查询meter_name指定的metrics的结果;
  6. 通过客户端通过HTTP协议GET方法获取符合查询条件的statistics列表;
  7. 最终的返回结果为meter_name指定的metrics的结果statistics列表;
  8. """
  9. LOG.debug(_('stats query %s') % query)
  10. try:
  11. return self._client.statistics.list(
  12. meter_name=alarm.rule['meter_name'], q=query,
  13. period=alarm.rule['period'])
  14. except Exception:
  15. LOG.exception(_('alarm stats retrieval failed'))
  16. return []
复制代码

方法小结:


通过客户端通过HTTP协议GET方法获取符合查询条件的statistics列表;
最终的返回结果为meter_name指定的metrics的结果statistics列表;

2 def _sufficient(self, alarm, statistics)

  1. def _sufficient(self, alarm, statistics):
  2. """
  3. 确保报警器评估具有足够的数据(仲裁人数);
  4. 1.根据统计数据的数目来判断是否有足够的数据用于报警器的评估(最小值要大于1);
  5. 2.如果sufficient为0说明用于仲裁的数目不够,则需要刷新报警器的状态为'insufficient data';
  6. """
  7. """
  8. 根据统计数据的数目来判断是否有足够的数据用于报警器的评估(最小值要大于1);
  9. """
  10. sufficient = len(statistics) >= self.quorum
  11. """
  12. 如果sufficient为0说明用于仲裁的数目不够,则需要刷新报警器的状态为'insufficient data';
  13. """
  14. if not sufficient and alarm.state != evaluator.UNKNOWN:
  15. reason = _('%d datapoints are unknown') % alarm.rule[
  16. 'evaluation_periods']
  17. reason_data = self._reason_data('unknown',
  18. alarm.rule['evaluation_periods'],
  19. None)
  20. self._refresh(alarm, evaluator.UNKNOWN, reason, reason_data)
  21. return sufficient
复制代码

方法小结:


确保报警器评估具有足够的数据(仲裁人数);

1.根据统计数据的数目来判断是否有足够的数据用于报警器的评估(最小值要大于1);

2.如果sufficient为0说明用于仲裁的数目不够,则需要刷新报警器的状态为'insufficient data';


3 def _transition(self, alarm, statistics, compared)

  1. def _transition(self, alarm, statistics, compared):
  2. """
  3. 根据statistics是否满足触发报警器条件,来更新报警器报警状态(alarm或ok);
  4. 1.验证所有的statistics是否满足触发报警器的条件;
  5. * 所有的statistics均满足触发报警器条件;
  6. * 所有的statistics均不满足触发报警器条件;
  7. * 报警器的数据状态为'insufficient data'(数据不充足);
  8. 2.如果所有的statistics均满足报警条件,则说明需触发报警,报警器的状态设置为'alarm';
  9. 3.如果所有的statistics均不满足报警条天,则说明报警器处于正常状态,报警器的状态设置为'ok';
  10. 4.如果当前报警器的状态为'insufficient data'(数据不充足),则根据最后一个statistics,来判断报警器的发展状态的趋势,进而确定报警器的报警状态;
  11. * 如果最后一个statistics符合触发报警器的条件,则说明报警器有转换为ALARM状态的趋势,则设置报警器的报警状态为alarm;
  12. * 如果最后一个statistics不符合触发报警器的条件,则说明报警器有转换为OK状态的趋势,则设置报警器的报警状态为ok;
  13. """
  14. """
  15. 如果distilled为true,说明所有的statistics均满足触发报警器条件;
  16. """
  17. distilled = all(compared)
  18. """
  19. 如果unequivocal为true,说明所有的statistics均满足或均不满足触发报警器条件;
  20. """
  21. unequivocal = distilled or not any(compared)
  22. """
  23. 验证报警器的状态是否为'insufficient data'(数据不充足);
  24. """
  25. unknown = alarm.state == evaluator.UNKNOWN
  26. # repeat_actions:表示每个评估周期都要重新触发的actions;
  27. continuous = alarm.repeat_actions
  28. """
  29. 如果所有的statistics均满足报警条件,则说明需触发报警,报警器的状态设置为'alarm';
  30. 如果所有的statistics均不满足报警条天,则说明报警器处于正常状态,报警器的状态设置为'ok';
  31. """
  32. if unequivocal:
  33. """
  34. 如果所有的statistics均满足报警条件,则说明需触发报警,报警器的状态设置为'alarm';
  35. 如果所有的statistics均不满足报警条天,则说明报警器处于正常状态,报警器的状态设置为'ok';
  36. """
  37. state = evaluator.ALARM if distilled else evaluator.OK
  38. reason, reason_data = self._reason(alarm, statistics,
  39. distilled, state)
  40. """
  41. 如果报警器的状态和要赋予的状态不同,或者continuous为true,则需要刷新报警器的状态为指定状态;
  42. """
  43. if alarm.state != state or continuous:
  44. self._refresh(alarm, state, reason, reason_data)
  45. """
  46. 如果当前报警器的状态为'insufficient data',则进一步根据最后一个statistics,来判断报警器的发展状态的趋势;
  47. """
  48. elif unknown or continuous:
  49. """
  50. 如果当前状态为UNKNOWN,则根据趋势改变状态,即观察最后一个statistics,
  51. 如果它为true,说明最后一个statistics符合触发报警器的条件,则说明报警器有转换为ALARM状态的趋势,
  52. 如果它为false,说明最后一个statistics不符合触发报警器的条件,则说明报警器有转换为OK状态的趋势;
  53. """
  54. trending_state = evaluator.ALARM if compared[-1] else evaluator.OK
  55. """
  56. 如果当前报警器的状态为'insufficient data',则采用trending_state作为报警器的状态;
  57. """
  58. state = trending_state if unknown else alarm.state
  59. reason, reason_data = self._reason(alarm, statistics,
  60. distilled, state)
  61. """
  62. 实现刷新报警器的状态为指定状态;
  63. """
  64. 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)


    这个方法最终实现单一报警器状态的评估操作,上面的方法实际上都被这个方法所调用,为单一报警器的评估实现了若干操作(具体实现可以见代码注释);

  1. def evaluate(self, alarm):
  2. """
  3. 根据报警器获取指定的metrics的结果statistics列表;
  4. 根据statistics是否满足触发报警器条件,来更新报警器的状态;
  5. """
  6. if not self.within_time_constraint(alarm):
  7. LOG.debug(_('Attempted to evaluate alarm %s, but it is not '
  8. 'within its time constraint.') % alarm.alarm_id)
  9. return
  10. # 参照alarm的属性,alarm.rule['query']是
  11. # metadata.user_metadata.server_group == WebServerGroup;
  12. # 该方法计算evaluate操作的时间段;
  13. # 在query的内容中添加时间段为[start,now]的条件,
  14. # 最后返回更改后的query;
  15. query = self._bound_duration(
  16. alarm,
  17. alarm.rule['query']
  18. )
  19. """
  20. _statistics:获取query和meter_name(meter_name=alarm.rule['meter_name'])指定的监控统计数据列表;
  21. 通过客户端通过HTTP协议GET方法获取符合查询条件的statistics列表;
  22. 最终的返回结果为meter_name指定的metrics的结果statistics列表;
  23. 对获取的监控数据列表进行数据的除错处理;
  24. """
  25. statistics = self._sanitize(
  26. alarm,
  27. self._statistics(alarm, query)
  28. )
  29. # _sufficient:确保报警器评估具有足够的仲裁数据(根据statistics数目);
  30. # _sufficient方法用来判断返回的查询结果statistics是否够支持evaluate,其中的quorum为statistics的最小长度,默认为1:
  31. """
  32. 确保报警器评估具有足够的数据(仲裁人数);
  33. 根据statistics是否满足触发报警器条件,来更新报警器的报警状态(alarm或ok);
  34. """
  35. if self._sufficient(alarm, statistics):
  36. def _compare(stat):
  37. op = COMPARATORS[alarm.rule['comparison_operator']]
  38. value = getattr(stat, alarm.rule['statistic'])
  39. """
  40. 获取规定的触发报警器的数值限制;
  41. """
  42. limit = alarm.rule['threshold']
  43. LOG.debug(_('comparing value %(value)s against threshold'
  44. ' %(limit)s') %
  45. {'value': value, 'limit': limit})
  46. return op(value, limit)
  47. """
  48. 根据statistics是否满足触发报警器条件,来更新报警器的报警状态(alarm或ok);
  49. """
  50. self._transition(alarm,
  51. statistics,
  52. 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服务的初始化和启动


欢迎加入about云群90371779322273151432264021 ,云计算爱好者群,亦可关注about云腾讯认证空间||关注本站微信

没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条