浏览代码

完善分析类的日报警逻辑

andyliu 2 周之前
父节点
当前提交
d61e67d475

+ 47 - 0
src/main/java/com/shkpr/service/warncore/bizhandler/CommToolHandler.java

@@ -0,0 +1,47 @@
+package com.shkpr.service.warncore.bizhandler;
+
+import com.shkpr.service.warncore.commtools.CommTool;
+import com.shkpr.service.warncore.dto.OrdWarnRuleCondition;
+import org.springframework.util.StringUtils;
+
+public class CommToolHandler {
+    /**
+     * 原始值匹配规则条件
+     * @param originValue
+     * @param condition
+     * @return -1: 未知错误;0 -- 未匹配;1 -- 已匹配
+     */
+    public static int matchedToRuleItem(String originValue, OrdWarnRuleCondition condition){
+        if (StringUtils.isEmpty(originValue))//指定字段为空串,可表示未匹配
+            return 0;
+        int matched = -1;
+        try {
+            int nRes = CommTool.compareFloat(originValue, condition.getThreshold());
+            if (nRes == 0){
+                if ("!=".equals(condition.getMethod())){
+                    matched = 0;
+                }else if (condition.getMethod().contains("=")){
+                    matched = 1;
+                }else
+                    matched = 0;
+            }else if (nRes > 0){
+                if ("!=".equals(condition.getMethod())){
+                    matched = 1;
+                }else if (condition.getMethod().contains(">")){
+                    matched = 1;
+                }else
+                    matched = 0;
+            }else {
+                if ("!=".equals(condition.getMethod())){
+                    matched = 1;
+                }else if (condition.getMethod().contains("<")){
+                    matched = 1;
+                }else
+                    matched = 0;
+            }
+        }catch (Exception e){
+            matched = -1;
+        }
+        return matched;
+    }
+}

+ 5 - 45
src/main/java/com/shkpr/service/warncore/bizhandler/SiteDataWarnHandler.java

@@ -84,9 +84,9 @@ public class SiteDataWarnHandler {
             }
 
             if (doForTodayBefore){//只分析昨日23:00:00-23:59:59的数据
-                conditionMinUTC = conditionMinUTC - TimeTool.MS_ONE_DAY;//针对昨日:触发规则列表中第一个时段的起始时刻
                 queryBeginUTC = TimeTool.getTodayBeginUTC()-TimeTool.MS_ONE_HOUR;
                 queryEndUTC = TimeTool.getTodayBeginUTC()-TimeTool.MS_ONE_SEC;
+                conditionMinUTC = Math.min(conditionMinUTC-TimeTool.MS_ONE_DAY, queryBeginUTC);//针对昨日:触发规则列表中第一个时段的起始时刻
             }else {
                 findStartClock = findStartClock-1;
                 for (int i=rules.size()-1;i>=0;i--){
@@ -146,46 +146,6 @@ public class SiteDataWarnHandler {
         return code;
     }
 
-    /**
-     * 原始值匹配规则条件
-     * @param originValue
-     * @param condition
-     * @return -1: 未知错误;0 -- 未匹配;1 -- 已匹配
-     */
-    private static int matchedToRuleItem(String originValue, OrdWarnRuleCondition condition){
-        if (StringUtils.isEmpty(originValue))//指定字段为空串,可表示未匹配
-            return 0;
-        int matched = -1;
-        try {
-            int nRes = CommTool.compareFloat(originValue, condition.getThreshold());
-            if (nRes == 0){
-                if ("!=".equals(condition.getMethod())){
-                    matched = 0;
-                }else if (condition.getMethod().contains("=")){
-                    matched = 1;
-                }else
-                    matched = 0;
-            }else if (nRes > 0){
-                if ("!=".equals(condition.getMethod())){
-                    matched = 1;
-                }else if (condition.getMethod().contains(">")){
-                    matched = 1;
-                }else
-                    matched = 0;
-            }else {
-                if ("!=".equals(condition.getMethod())){
-                    matched = 1;
-                }else if (condition.getMethod().contains("<")){
-                    matched = 1;
-                }else
-                    matched = 0;
-            }
-        }catch (Exception e){
-            matched = -1;
-        }
-        return matched;
-    }
-
     //处理站点的实时样本曲线
     private static ResponseCode analysisDataForRealBySet(OrdWarnPlanDetail planDetail, List<OrdWarnPlanRules> rules, OrdWarnPlanTempStep thisTempStep){
         ResponseCode code = ResponseCode.RESULT_NORMAL;
@@ -257,7 +217,7 @@ public class SiteDataWarnHandler {
                             break;
                         }
                     }
-                    int pkRes = matchedToRuleItem(originValue, condition);
+                    int pkRes = CommToolHandler.matchedToRuleItem(originValue, condition);
                     if (pkRes == -1){
                         step = String.format("Compare value exception error");
                         code = ResponseCode.RESULT_BAD;
@@ -322,7 +282,7 @@ public class SiteDataWarnHandler {
                         //[!!!]do not change the FirstMatchSampleTime[!!!]
                     }
                 }else {//之前有预警事件
-                    if (thisTempStep.getLastEventAction() >= 2){//之前的预警事件已处理,则可认为进行重新计数
+                    if (planDetail.getMergeToEvent() == 0 || thisTempStep.getLastEventAction() >= 2){//之前的预警事件已处理,则可认为进行重新计数
                         thisTempStep.setLastCompareSampleTime(sampleRecordTm);
                         thisTempStep.setLastCompareSampleResult(1);
                         thisTempStep.setFirstMatchSampleTime(sampleRecordTm);
@@ -430,7 +390,7 @@ public class SiteDataWarnHandler {
                             break;
                         }
                     }
-                    int pkRes = matchedToRuleItem(originValue, condition);
+                    int pkRes = CommToolHandler.matchedToRuleItem(originValue, condition);
                     if (pkRes == -1){
                         step = String.format("Compare value exception error");
                         code = ResponseCode.RESULT_BAD;
@@ -522,7 +482,7 @@ public class SiteDataWarnHandler {
                         //[!!!]do not change the FirstMatchSampleTime[!!!]
                     }
                 }else {//之前有预警事件
-                    if (thisTempStep.getLastEventAction() >= 2){//之前的预警事件已处理,则可认为进行重新计数
+                    if (planDetail.getMergeToEvent() == 0 || thisTempStep.getLastEventAction() >= 2){//之前的预警事件已处理,则可认为进行重新计数
                         thisTempStep.setLastCompareSampleTime(sampleRecordTm);
                         thisTempStep.setLastCompareSampleResult(1);
                         thisTempStep.setFirstMatchSampleTime(sampleRecordTm);

+ 237 - 0
src/main/java/com/shkpr/service/warncore/bizhandler/ZoneDataWarnHandler.java

@@ -1,7 +1,244 @@
 package com.shkpr.service.warncore.bizhandler;
 
+import com.shkpr.service.warncore.commtools.CommTool;
+import com.shkpr.service.warncore.commtools.TimeTool;
+import com.shkpr.service.warncore.constants.CommFieldStatus;
+import com.shkpr.service.warncore.dbdao.DBMgrProxy;
+import com.shkpr.service.warncore.dbdao.services.intef.OrdWarnPlanInfoDBService;
+import com.shkpr.service.warncore.dbdao.services.intef.OrdWarnPlanRulesDBService;
+import com.shkpr.service.warncore.dbdao.tables.OrdWarnPlanInfoTable;
+import com.shkpr.service.warncore.dto.*;
+import org.springframework.util.StringUtils;
+
+import java.util.*;
+
 /**
  * 分区分析统计数据处理
  */
 public class ZoneDataWarnHandler {
+    private static OrdWarnPlanInfoDBService getWarnPlanInfoDBService(){
+        return DBMgrProxy.getInstance().applyXXXApi(OrdWarnPlanInfoDBService.class);
+    }
+
+    private static OrdWarnPlanRulesDBService getWarnPlanRuleDBService(){
+        return DBMgrProxy.getInstance().applyXXXApi(OrdWarnPlanRulesDBService.class);
+    }
+
+    public static ResponseCode handlerDataByDay(OrdWarnPlanDetail planDetail, List<OrdWarnPlanRules> rules){
+        ResponseCode code = ResponseCode.RESULT_NORMAL;
+        String step = "Start to pre analysis.";
+        if (getWarnPlanInfoDBService().existsLineEx(OrdWarnPlanInfoTable.R_INFO.TABLE
+                , new HashMap<String, Object>(){{put(OrdWarnPlanInfoTable.R_INFO.STATUS, CommFieldStatus.ENABLE);
+                    put(OrdWarnPlanInfoTable.R_INFO.UNIQUE_ID, planDetail.getUid());
+                    put(OrdWarnPlanInfoTable.R_INFO.VERSION, planDetail.getVersion());
+                }}, null, "") <= 0){
+            step = "Plan is changed,do analysis next time";
+            code = ResponseCode.RESULT_BAD;
+        }
+
+        final long curUTCTm = TimeTool.getCurMsUTC();
+        final int preDayInYear = TimeTool.getYearIndex(curUTCTm-TimeTool.MS_ONE_DAY);//日分析时,分析前一日所在的年份
+        final int preDayInMonth = TimeTool.getMonthIndex(curUTCTm-TimeTool.MS_ONE_DAY);//日分析时,分析前一日所在的月份
+
+        long queryBeginUTC = 0L, conditionMinUTC = 0L;
+        long queryEndUTC = TimeTool.getTodayBeginUTC();
+        OrdWarnPlanTempStep thisStepTempRes = new OrdWarnPlanTempStep(planDetail);
+        do {
+            int findStartRange = -1;
+            for (int i=rules.size()-1;i>=0;i--){
+                if (preDayInMonth >= rules.get(i).getStart() && preDayInMonth <= rules.get(i).getEnd()){
+                    findStartRange = rules.get(i).getStart();
+                }
+            }
+            if (findStartRange < 0){
+                step = "Not in time range,do analysis next time";
+                code = ResponseCode.RESULT_BAD;
+                break;
+            }
+            findStartRange = findStartRange-1;
+            for (int i=rules.size()-1;i>=0;i--){
+                if (findStartRange <= 0)
+                    break;
+                if (findStartRange == rules.get(i).getEnd())
+                    findStartRange = rules.get(i).getStart()-1;
+            }
+
+            queryBeginUTC = TimeTool.convertDateStr2BeginUTC(String.format("%d-%2d-01 00:00:00", preDayInYear, findStartRange+1));
+            conditionMinUTC = queryBeginUTC;
+            long before3Day = queryEndUTC-TimeTool.MS_ONE_DAY*3;//最多只往前分析3天
+            if (before3Day > queryBeginUTC)
+                queryBeginUTC = before3Day;
+
+            if (thisStepTempRes.getLastCompareSampleTime() <= 0L
+                    || thisStepTempRes.getLastCompareSampleTime() < queryBeginUTC) {//从未分析过则重新计数)
+                thisStepTempRes.resetData();
+            }else if (thisStepTempRes.getLastCompareSampleTime() >= queryBeginUTC) {
+                queryBeginUTC = thisStepTempRes.getLastCompareSampleTime() + TimeTool.MS_ONE_DAY;
+            }
+            if (queryBeginUTC >= queryEndUTC){
+                step = "Time is invalid,do analysis next time";
+                code = ResponseCode.RESULT_BAD;
+                break;
+            }
+
+            thisStepTempRes.setDoForTodayBefore(true);
+            thisStepTempRes.setQueryBeginUTC(queryBeginUTC);
+            thisStepTempRes.setQueryEndUTC(queryEndUTC);
+            thisStepTempRes.setConditionMinUTC(conditionMinUTC);
+
+            if (!StringUtils.isEmpty(planDetail.getLastEventId())){
+                //向数据库中快速查询事件最近处理阶段action的值
+                //并赋值给thisTempStep
+            }
+
+            return analysisDataByDay(planDetail, rules, thisStepTempRes);
+        }while (false);
+        return code;
+    }
+
+    private static ResponseCode analysisDataByDay(OrdWarnPlanDetail planDetail, List<OrdWarnPlanRules> rules, OrdWarnPlanTempStep thisTempStep){
+        ResponseCode code = ResponseCode.RESULT_NORMAL;
+        String step = "Start to deep analysis";
+        long curTime = TimeTool.getCurMsUTC();
+        final String zoneId = rules.get(0).getObjId();
+        List<DateKeyValue> zoneStatsData = null;//要求数据按date升序
+        Map<String, Long> eventId2NewEndUTC = new HashMap<>();//需要更新预警事件的样本截止时间
+
+        do {
+            String[] storeTagAndBackTag = rules.get(0).getConditions().get(0).getFormat().split("@");
+            if (storeTagAndBackTag == null || storeTagAndBackTag.length < 2){
+                step = String.format("Format param valid in rules");
+                code = ResponseCode.RESULT_BAD;
+                break;
+            }
+            //数据库获取数据
+
+            if (zoneStatsData == null){
+                step = String.format("Get zone stats data failed");
+                code = ResponseCode.RESULT_BAD;
+                break;
+            }
+            if (CommTool.listSize(zoneStatsData) <= 0){//数据条目缺失可认为,还在等待录入则跳过
+                step = String.format("Get zone stats data empty");
+                code = ResponseCode.RESULT_BAD;
+                break;
+            }
+
+            for (DateKeyValue sampleItem:zoneStatsData){
+                long sampleRecordTm = TimeTool.convertDateStr2UTC(sampleItem.getDate());
+                if (sampleRecordTm <= 0L)
+                    continue;
+
+                boolean matched = false;
+                OrdWarnPlanRules findRule = null;
+                int sampleTmInMonth = TimeTool.getMonthIndex(sampleRecordTm);
+                for (OrdWarnPlanRules ruleItem:rules){
+                    if (sampleTmInMonth <= ruleItem.getEnd() && sampleTmInMonth >= ruleItem.getStart()){
+                        findRule = ruleItem;
+                        break;
+                    }
+                }
+                if (findRule == null)
+                    continue;
+
+                for (OrdWarnRuleCondition condition:findRule.getConditions()){
+                    String originValue = "";
+                    String backTag = storeTagAndBackTag[1];
+                    if (backTag.equals(sampleItem.getKey()))
+                        originValue = sampleItem.getValue();
+
+                    int pkRes = CommToolHandler.matchedToRuleItem(originValue, condition);
+                    if (pkRes == -1){
+                        step = String.format("Compare value exception error");
+                        code = ResponseCode.RESULT_BAD;
+                        break;
+                    }else {
+                        matched = matched || (pkRes==1?true:false);
+                    }
+                }
+                if (code != ResponseCode.RESULT_NORMAL)
+                    break;
+
+                if (!matched){//本次没有匹配成功
+                    thisTempStep.setLastCompareSampleTime(sampleRecordTm);
+                    thisTempStep.setLastCompareSampleResult(0);
+                    thisTempStep.setFirstMatchSampleTime(0L);
+                    thisTempStep.setLastEventId("");
+                    thisTempStep.setLastEventTime(0L);
+                    continue;
+                }//本次匹配成功进入下一步
+
+                long triggerEventPeriodSwitch = planDetail.getFrequency()*planDetail.getThreshold();//触发预警事件的最小时长(单位:天)
+                if (thisTempStep.getLastCompareSampleResult() <= 0){//上一次没有匹配成功
+                    thisTempStep.setLastCompareSampleTime(sampleRecordTm);
+                    thisTempStep.setLastCompareSampleResult(1);
+                    thisTempStep.setFirstMatchSampleTime(sampleRecordTm);
+                    if (triggerEventPeriodSwitch <= 1){//触发事件
+                        thisTempStep.setLastEventId("新事件ID");
+                        thisTempStep.setLastEventTime(curTime);
+                        thisTempStep.setLastEventAction(1);
+                    }
+                    continue;
+                }//上一次匹配成功了进入下一步
+
+                long diffMatch = (sampleRecordTm-thisTempStep.getLastCompareSampleTime())/TimeTool.MS_ONE_DAY;//两个最近匹配样本之间的采集时间差(单位:天)
+                if (diffMatch > triggerEventPeriodSwitch){//两个最近匹配样本间缺失的数据太多、或跨了天、或跨了时段,可认为重新计数
+                    thisTempStep.setLastCompareSampleTime(sampleRecordTm);
+                    thisTempStep.setLastCompareSampleResult(1);
+                    thisTempStep.setFirstMatchSampleTime(sampleRecordTm);
+                    if (triggerEventPeriodSwitch <= 1){//触发事件
+                        thisTempStep.setLastEventId("新事件ID");
+                        thisTempStep.setLastEventTime(curTime);
+                        thisTempStep.setLastEventAction(1);
+                    }else {
+                        thisTempStep.setLastEventId("");
+                        thisTempStep.setLastEventTime(0L);
+                    }
+                    continue;
+                }//两个最近匹配样本间隔很近,可认为是持续匹配,则进入下一步
+
+                long matchLen = (thisTempStep.getFirstMatchSampleTime()<=0)?0:((sampleRecordTm-thisTempStep.getFirstMatchSampleTime())/TimeTool.MS_ONE_DAY);//样本匹配的持续时长(单位:天)
+                if (StringUtils.isEmpty(thisTempStep.getLastEventId())){//之前无预警事件
+                    if (matchLen < triggerEventPeriodSwitch){//还得持续等待,达不到触发事件的累计时长
+                        thisTempStep.setLastCompareSampleTime(sampleRecordTm);
+                        thisTempStep.setLastCompareSampleResult(1);
+                        if (thisTempStep.getFirstMatchSampleTime() <= 0){
+                            thisTempStep.setFirstMatchSampleTime(sampleRecordTm);
+                            if (triggerEventPeriodSwitch <= 1){//补充触发事件
+                                thisTempStep.setLastEventId("新事件ID");
+                                thisTempStep.setLastEventTime(curTime);
+                                thisTempStep.setLastEventAction(1);
+                            }
+                        }
+                    }else {//触发一个新的事件
+                        thisTempStep.setLastCompareSampleTime(sampleRecordTm);
+                        thisTempStep.setLastCompareSampleResult(1);
+                        thisTempStep.setLastEventId("新事件ID");
+                        thisTempStep.setLastEventTime(curTime);
+                        thisTempStep.setLastEventAction(1);
+                        //[!!!]do not change the FirstMatchSampleTime[!!!]
+                    }
+                }else {//之前有预警事件
+                    if (planDetail.getMergeToEvent() == 0 || thisTempStep.getLastEventAction() >= 2){//之前的预警事件已处理,则可认为进行重新计数
+                        thisTempStep.setLastCompareSampleTime(sampleRecordTm);
+                        thisTempStep.setLastCompareSampleResult(1);
+                        thisTempStep.setFirstMatchSampleTime(sampleRecordTm);
+                        if (triggerEventPeriodSwitch <= 1){//触发事件
+                            thisTempStep.setLastEventId("新事件ID");
+                            thisTempStep.setLastEventTime(curTime);
+                            thisTempStep.setLastEventAction(1);
+                        }else {
+                            thisTempStep.setLastEventId("");
+                            thisTempStep.setLastEventTime(0L);
+                        }
+                    }else {//之前的预警事件未处理,则更新预警事件的样本截止时刻
+                        thisTempStep.setLastCompareSampleTime(sampleRecordTm);
+                        thisTempStep.setLastCompareSampleResult(1);
+                        eventId2NewEndUTC.put(thisTempStep.getLastEventId(), sampleRecordTm);
+                    }
+                }
+            }
+        }while (false);
+        return code;
+    }
 }

+ 16 - 0
src/main/java/com/shkpr/service/warncore/commtools/TimeTool.java

@@ -549,4 +549,20 @@ public class TimeTool {
         }catch (Exception e){e.printStackTrace();}
         return arrDay;
     }
+
+    public static int getMonthIndex(long utc){
+        if (!isMsUTC(utc))
+            utc = utc*1000;
+        Instant instant = Instant.ofEpochMilli(utc);
+        ZonedDateTime utcDateTime = instant.atZone(ZoneOffset.UTC);
+        return utcDateTime.getMonthValue();
+    }
+
+    public static int getYearIndex(long utc){
+        if (!isMsUTC(utc))
+            utc = utc*1000;
+        Instant instant = Instant.ofEpochMilli(utc);
+        ZonedDateTime utcDateTime = instant.atZone(ZoneOffset.UTC);
+        return utcDateTime.getYear();
+    }
 }

+ 14 - 0
src/main/java/com/shkpr/service/warncore/dto/DateKeyValue.java

@@ -0,0 +1,14 @@
+package com.shkpr.service.warncore.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class DateKeyValue extends KeyValue{
+    private String date = "";
+
+    public DateKeyValue() {
+        super();
+    }
+}

+ 2 - 1
src/main/java/com/shkpr/service/warncore/dto/OrdWarnPlanDetail.java

@@ -27,13 +27,14 @@ public class OrdWarnPlanDetail {
     private int status = 0;
     private int version = 0;
     private String objSrc = "";
-    private String doPeriodUnit = "";
+    private String doPeriodUnit = "";//hour/month
     private String doPickWay = "";
     private String doDb = "";
     private String doTime = "";
     private String ending = "";
     private int dayTriggerTimes = 0;
     private int dayTriggerUpperTimes = -1;
+    private int mergeToEvent = 1;//触发规则时是否合并到上一个会处理的事件上: 0--不合并;1--合并
 
     public OrdWarnPlanDetail() {
     }