当前位置: 移动技术网 > IT编程>开发语言>Java > pinpoint web报警机制算法解析

pinpoint web报警机制算法解析

2018年08月20日  | 移动技术网IT编程  | 我要评论

背景:

  见上一篇文章

  我们在使用pinpoint的报警功能的时候,发现如果持续一段时间内一直存在异常情况,但是并不是每一分钟都会接受到pinpoint的报警邮件,而是有一个时间间隔的,本文旨在分析其报警的策略算法。

相关类:

1)checkresult,该类代表了报警历史,是存储在数据库当中的。

该类与此算法有关的字段有3个,分别为detected,sequencecount,timingcount。

detected代表是否报警过,sequencecount代表已经进行检查的次数,timingcount代表第几次检查应该报警。

2)alarmchecker,该类代表了一次检查的结果,是在内存中的临时对象。

该类与此算法有关的字段有1个,分别为detected。

detected代表此次是否有异常情况

 

alarmchecker的detected字段和checkresult的detected字段含义稍有区别,请注意区分

算法步骤:

1.当alarmchecker的detected字段为true 的时候(此次有异常情况),则根据isturntosendalarm方法来判断此次是否应该报警:

1)检查checkresult报警历史中的detected来查看历史上是否报警过,如果没有,则返回true

2)如果detected == true,则代表历史上报过警,sequencecount和timingcount是否相差1,如果是则返回true,否则返回false

 

2.更新checkresult记录:

1)删除原先的记录

2)如果alarmchecker.detected == false,则插入一条“新”记录,detected为false,sequencecount为0,timingcount为1。

3)如果alarmchecker.detected == true,则插入一条“旧”记录,detected为true,sequencecount在原先的基础上+1,timingcount如果和sequencecount相等则在原先的基础上乘2再加1,否则不变。

 

源码:[现在看看源码会比较清晰了]

alarmwriter

package com.navercorp.pinpoint.web.alarm;

import java.util.list;
import java.util.map;

import org.springframework.batch.item.itemwriter;
import org.springframework.beans.factory.annotation.autowired;

import com.navercorp.pinpoint.web.alarm.checker.alarmchecker;
import com.navercorp.pinpoint.web.alarm.vo.checkerresult;
import com.navercorp.pinpoint.web.service.alarmservice;

/**
 * @author minwoo.jung
 */
public class alarmwriter implements itemwriter<alarmchecker> {

    @autowired(required = false)
    private alarmmessagesender alarmmessagesender = new emptymessagesender();

    @autowired
    private alarmservice alarmservice;

    @override
    public void write(list<? extends alarmchecker> checkers) throws exception {
        map<string, checkerresult> beforecheckerresults = alarmservice.selectbeforecheckerresults(checkers.get(0).getrule().getapplicationid());

        for (alarmchecker checker : checkers) {
            checkerresult beforecheckerresult = beforecheckerresults.get(checker.getrule().getcheckername());

            if (beforecheckerresult == null) {
                beforecheckerresult = new checkerresult(checker.getrule().getapplicationid(), checker.getrule().getcheckername(), false, 0, 1);
            }

            if (checker.isdetected()) {
                sendalarmmessage(beforecheckerresult, checker);
            }

            alarmservice.updatebeforecheckerresult(beforecheckerresult, checker);
        }
    }

    // 防止重复报警
    private void sendalarmmessage(checkerresult beforecheckerresult, alarmchecker checker) {
        if (isturntosendalarm(beforecheckerresult)) {
            if (checker.issmssend()) {
                alarmmessagesender.sendsms(checker, beforecheckerresult.getsequencecount() + 1);
            }
            if (checker.isemailsend()) {
                alarmmessagesender.sendemail(checker, beforecheckerresult.getsequencecount() + 1);
            }
        }

    }

    private boolean isturntosendalarm(checkerresult beforecheckerresult) {
        // 之前没报过警就报警
        if (!beforecheckerresult.isdetected()) {
            return true;
        }
        // 如果之前报过警,则延迟报警;检查sequencecount和timingcount是否相差1。
        int sequencecount = beforecheckerresult.getsequencecount() + 1;

        if (sequencecount == beforecheckerresult.gettimingcount()) {
            return true;
        }

        return false;
    }
}

  alarmservice.updatebeforecheckerresult方法

@override
    public void updatebeforecheckerresult(checkerresult beforecheckerresult, alarmchecker checker) {
        alarmdao.deletecheckerresult(beforecheckerresult);
        
        if (checker.isdetected()) {
            beforecheckerresult.setdetected(true);
            // 更新下次应该报警的时间点
            beforecheckerresult.incresecount();
            alarmdao.insertcheckerresult(beforecheckerresult);
        } else {
            alarmdao.insertcheckerresult(new checkerresult(checker.getrule().getapplicationid(), checker.getrule().getcheckername(), false, 0, 1));
        }
        
         
    }

  beforecheckerresult.incresecount()方法

// 延时报警,防止每分钟都报警,引起轰炸
    public void incresecount() {
        // sequencecount为检查的次数
        ++sequencecount;
        // timingcount代表检查次数达到timingcount则报警
        // 如果此次已经报警,则延迟下次报警的时间
        if (sequencecount == timingcount) {
            timingcount = sequencecount * 2 + 1;
        }
    }

 

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网