Ceilometer項目源碼分析----ceilometer報警器狀態評估方式之單一報警器狀態評估的具體實現

感謝朋友支持本博客,歡迎共同探討交流,由於能力和時間有限,錯誤之處在所難免,歡迎指正!

如果轉載,請保留作者信息。
博客地址:http://blog.csdn.net/gaoxingnengjisuan
郵箱地址:[email protected]

PS:最近沒有登錄博客,很多朋友的留言沒有看見,這裏道歉!還有就是本人較少上QQ,可以郵件交流。


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))

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章