private void calculate()

in hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/calculate/RealTimeAlertCalculator.java [135:264]


    private void calculate(CollectRep.MetricsData metricsData) {
        long currentTimeMilli = System.currentTimeMillis();
        String instance = String.valueOf(metricsData.getId());
        String instanceName = metricsData.getInstanceName();
        String instanceHost = metricsData.getInstanceHost();
        String app = metricsData.getApp();
        String metrics = metricsData.getMetrics();
        int priority = metricsData.getPriority();
        int code = metricsData.getCode().getNumber();
        Map<String, String> labels = metricsData.getLabels();
        Map<String, String> annotations = metricsData.getAnnotations();
        List<AlertDefine> thresholds = this.alertDefineService.getRealTimeAlertDefines();
        // Filter thresholds by app, metrics, labels and instance
        thresholds = filterThresholdsByAppAndMetrics(thresholds, app, metrics, labels, instance, priority);
        if (thresholds.isEmpty()) {
            return;
        }
        Map<String, Object> commonContext = new HashMap<>(8);
        commonContext.put(KEY_INSTANCE, instance);
        commonContext.put(KEY_INSTANCE_NAME, instanceName);
        commonContext.put(KEY_INSTANCE_HOST, instanceHost);
        commonContext.put(KEY_APP, app);
        commonContext.put(KEY_PRIORITY, priority);
        commonContext.put(KEY_CODE, code);
        commonContext.put(KEY_METRICS, metrics);
        commonContext.put(KEY_LABELS, String.join(",", kvLabelsToKvStringSet(labels)));
        if (priority == 0) {
            commonContext.put(KEY_AVAILABLE, metricsData.getCode() == CollectRep.Code.SUCCESS ? UP : DOWN);
        }
        if (labels != null) {
            commonContext.putAll(labels);
        }
        List<CollectRep.Field> fields = metricsData.getFields();
        Map<String, Object> fieldValueMap = new HashMap<>(8);
        int valueRowCount = metricsData.getValuesCount();
        for (AlertDefine define : thresholds) {
            if (define.getLabels() == null) {
                define.setLabels(new HashMap<>(8));
            }
            if (define.getAnnotations() == null) {
                define.setAnnotations(new HashMap<>(8));
            }
            fieldValueMap.clear();
            fieldValueMap.putAll(commonContext);
            final String expr = define.getExpr();
            if (StringUtils.isBlank(expr)) {
                continue;
            }
            Map<String, String> commonFingerPrints = new HashMap<>(8);
            commonFingerPrints.put(CommonConstants.LABEL_INSTANCE, instance);
            // here use the alert name as finger, not care the alert name may be changed
            commonFingerPrints.put(CommonConstants.LABEL_ALERT_NAME, define.getName());
            commonFingerPrints.put(CommonConstants.LABEL_INSTANCE_NAME, instanceName);
            commonFingerPrints.put(CommonConstants.LABEL_INSTANCE_HOST, instanceHost);
            commonFingerPrints.putAll(define.getLabels());
            if (labels != null) {
                commonFingerPrints.putAll(labels);
            }
            {
                // trigger the expr before the metrics data, due the available up down or others
                try {
                    boolean match = execAlertExpression(fieldValueMap, expr, true);
                    try {
                        if (match) {
                            // If the threshold rule matches, the number of times the threshold has been triggered is determined and an alarm is triggered
                            afterThresholdRuleMatch(currentTimeMilli, commonFingerPrints, fieldValueMap, define, annotations);
                        } else {
                            handleRecoveredAlert(commonFingerPrints);
                        }
                        // if this threshold pre compile success, ignore blew
                        continue;
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                    }
                } catch (Exception ignored) {}
            }
            Map<String, String> fingerPrints = new HashMap<>(8);
            for (CollectRep.ValueRow valueRow : metricsData.getValues()) {
                if (CollectionUtils.isEmpty(valueRow.getColumnsList())) {
                    continue;
                }
                fieldValueMap.clear();
                fieldValueMap.put(KEY_ROW, valueRowCount);
                fieldValueMap.putAll(commonContext);
                fingerPrints.clear();
                fingerPrints.putAll(commonFingerPrints);
                for (int index = 0; index < valueRow.getColumnsList().size(); index++) {
                    String valueStr = valueRow.getColumns(index);
                    if (CommonConstants.NULL_VALUE.equals(valueStr)) {
                        continue;
                    }
                    
                    final CollectRep.Field field = fields.get(index);
                    final int fieldType = field.getType();

                    if (fieldType == CommonConstants.TYPE_NUMBER) {
                        final Double doubleValue;
                        if ((doubleValue = CommonUtil.parseStrDouble(valueStr)) != null) {
                            fieldValueMap.put(field.getName(), doubleValue);
                        }
                    } else if (fieldType == CommonConstants.TYPE_TIME) {
                        final Integer integerValue;
                        if ((integerValue = CommonUtil.parseStrInteger(valueStr)) != null) {
                            fieldValueMap.put(field.getName(), integerValue);
                        }
                    } else {
                        if (StringUtils.isNotEmpty(valueStr)) {
                            fieldValueMap.put(field.getName(), valueStr);
                        }
                    }

                    if (field.getLabel()) {
                        fingerPrints.put(field.getName(), valueStr);
                    }
                }
                try {
                    boolean match = execAlertExpression(fieldValueMap, expr, false);
                    try {
                        if (match) {
                            afterThresholdRuleMatch(currentTimeMilli, fingerPrints, fieldValueMap, define, annotations);
                        } else {
                            handleRecoveredAlert(fingerPrints);
                        }
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                    }
                } catch (Exception ignored) {}
            }
        }
    }