This is an automated email from the ASF dual-hosted git repository.

gongchao pushed a commit to branch integte-extern-alarm
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git

commit 12b55e66012a17a537117f9cb47508c04656c350
Author: tomsun28 <tomsu...@outlook.com>
AuthorDate: Fri Jan 10 17:48:14 2025 +0800

    [improve] init
    
    Signed-off-by: tomsun28 <tomsu...@outlook.com>
---
 .../alert/controller/AlertReportController.java    |  43 ++--
 .../alert/dto/CloudAlertReportAbstract.java        |  78 -------
 .../hertzbeat/alert/dto/TenCloudAlertReport.java   | 227 ---------------------
 .../alert/dto/TencentCloudExternAlert.java         | 128 ++++++++++++
 .../enums/CloudServiceAlarmInformationEnum.java    |  52 -----
 .../hertzbeat/alert/service/AlertService.java      |  13 --
 .../alert/service/ExternAlertService.java          |  37 ++++
 .../alert/service/impl/AlertServiceImpl.java       |  41 ----
 .../service/impl/DefaultExternAlertService.java    |  52 +++++
 .../service/impl/PrometheusExternAlertService.java |  54 +++++
 .../service/impl/TencentExternAlertService.java    |  55 +++++
 .../controller/AlertReportControllerTest.java      |  12 +-
 .../hertzbeat/alert/service/AlertServiceTest.java  |  36 ----
 .../doc/alert-integration/prometheus.en-US.md      |   7 +
 .../doc/alert-integration/prometheus.zh-CN.md      |  32 +++
 .../assets/doc/alert-integration/tencent.zh-TW.md  |   9 +
 16 files changed, 404 insertions(+), 472 deletions(-)

diff --git 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/controller/AlertReportController.java
 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/controller/AlertReportController.java
index c33ab07a81..58d21199de 100644
--- 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/controller/AlertReportController.java
+++ 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/controller/AlertReportController.java
@@ -20,12 +20,12 @@ package org.apache.hertzbeat.alert.controller;
 import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
+import java.util.List;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.alert.service.AlertService;
-import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
+import org.apache.hertzbeat.alert.service.ExternAlertService;
 import org.apache.hertzbeat.common.entity.dto.Message;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
+import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -40,23 +40,28 @@ import 
org.springframework.web.bind.annotation.RestController;
 @RequestMapping(path = "/api/alerts/report", produces = 
{APPLICATION_JSON_VALUE})
 @Slf4j
 public class AlertReportController {
+    
+    private final List<ExternAlertService> externAlertServiceList;
 
-    @Autowired
-    private AlertService alertService;
-
-    @PostMapping("/{cloud}")
-    @Operation(summary = "Interface for reporting external alarm information 
of cloud service")
-    public ResponseEntity<Message<Void>> 
addNewAlertReportFromCloud(@PathVariable("cloud") String cloudServiceName,
-                                                                    
@RequestBody String alertReport) {
-        alertService.addNewAlertReportFromCloud(cloudServiceName, alertReport);
-        return ResponseEntity.ok(Message.success("Add report success"));
+    public AlertReportController(List<ExternAlertService> 
externAlertServiceList) {
+        this.externAlertServiceList = externAlertServiceList;
     }
-    
-    @PostMapping
-    @Operation(summary = "Interface for reporting external and general alarm 
information",
-            description = "The interface is used to report external and 
general alarm information")
-    public ResponseEntity<Message<Void>> addNewAlertReport(@RequestBody 
SingleAlert alertReport) {
-        alertService.addNewAlertReport(alertReport);
-        return ResponseEntity.ok(Message.success("Add report success"));
+
+    @PostMapping("/{source}")
+    @Operation(summary = "Api for receive external alarm information")
+    public ResponseEntity<Message<Void>> 
receiveExternAlert(@PathVariable(value = "source", required = false) String 
source, 
+                                                            @RequestBody 
String content) {
+        log.info("Receive extern alert from source: {}, content: {}", source, 
content);
+        if (!StringUtils.hasText(source)) {
+            source = "default";
+        }
+        for (ExternAlertService externAlertService : externAlertServiceList) {
+            if (externAlertService.supportSource().equals(source)) {
+                externAlertService.addExternAlert(content);
+                return ResponseEntity.ok(Message.success("Add extern alert 
success"));
+            }
+        }
+        log.warn("Not support extern alert from source: {}", source);
+        return ResponseEntity.ok(Message.success("Not support the " + source + 
" source alert"));
     }
 }
diff --git 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/CloudAlertReportAbstract.java
 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/CloudAlertReportAbstract.java
deleted file mode 100644
index eeecd5acb4..0000000000
--- 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/CloudAlertReportAbstract.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.hertzbeat.alert.dto;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import java.util.Map;
-import org.apache.hertzbeat.common.entity.dto.AlertReport;
-
-/**
- * Abstract parent of cloud service alarm information
- * {@link AlertReport} - The method corresponds to the parameter of this class 
one by one. For details about the method, see this class
- */
-public abstract class CloudAlertReportAbstract {
-
-    /**
-     * This parameter specifies the alarm name when a cloud alarm is converted 
to an internal alarm
-     */
-    @JsonIgnore
-    public abstract String getAlertName();
-
-    /**
-     * Interval when a cloud alarm is converted to an internal alarm
-     */
-    @JsonIgnore
-    public abstract Integer getAlertDuration();
-
-    /**
-     * Specifies the alarm time when a cloud alarm is converted to an internal 
alarm
-     */
-    @JsonIgnore
-    public abstract long getAlertTime();
-
-    /**
-     * Severity of an alarm when a cloud alarm is converted to an internal 
alarm
-     */
-    @JsonIgnore
-    public abstract Integer getPriority();
-
-    /**
-     * This parameter specifies the alarm type when a cloud alarm is converted 
to an internal alarm
-     */
-    @JsonIgnore
-    public abstract Integer getReportType();
-
-    /**
-     * Alarm label information about a cloud alarm that is converted to an 
internal alarm
-     */
-    @JsonIgnore
-    public abstract Map<String, String> getLabels();
-
-    /**
-     * Alarm labels when a cloud alarm is converted to an internal alarm
-     */
-    @JsonIgnore
-    public abstract Map<String, String> getAnnotations();
-
-    /**
-     * This topic describes the alarm content when a cloud alarm is converted 
to an internal alarm
-     */
-    @JsonIgnore
-    public abstract String getContent();
-
-}
diff --git 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/TenCloudAlertReport.java
 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/TenCloudAlertReport.java
deleted file mode 100644
index 99846e6a14..0000000000
--- 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/TenCloudAlertReport.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.hertzbeat.alert.dto;
-
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import java.io.Serializable;
-import java.util.Map;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NoArgsConstructor;
-import org.apache.hertzbeat.alert.util.DateUtil;
-
-/**
- *
- * Tencent cloud alarm entity class
- */
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-@EqualsAndHashCode(callSuper = true)
-@Builder
-public class TenCloudAlertReport extends CloudAlertReportAbstract implements 
Serializable {
-    @JsonProperty("sessionID")
-    private String sessionId;
-    private String alarmStatus;
-    private String alarmType;
-    private AlarmObjInfo alarmObjInfo;
-    private AlarmPolicyInfo alarmPolicyInfo;
-    private String firstOccurTime;
-    private int durationTime;
-    private String recoverTime;
-
-    /**
-     * Alarm Object information
-     */
-    @Data
-    @AllArgsConstructor
-    @NoArgsConstructor
-    public static class AlarmObjInfo {
-        private String region;
-        private String namespace;
-        @JsonProperty("appID")
-        private String appId;
-        private String uin;
-        private Dimensions dimensions;
-    }
-
-    /**
-     *  Uniform Resource ID information
-     */
-    @Data
-    @AllArgsConstructor
-    @NoArgsConstructor
-    public static class Dimensions {
-        @JsonProperty("unInstanceID")
-        private String unInstanceId;
-        @JsonProperty("objID")
-        private String objId;
-    }
-
-    /**
-     * Alarm policy information
-     */
-    @Data
-    @AllArgsConstructor
-    @NoArgsConstructor
-    public static class AlarmPolicyInfo {
-        @JsonProperty("policyID")
-        private String policyId;
-        private String policyType;
-        private String policyName;
-        @JsonProperty("policyTypeCName")
-        private String policyTypeCname;
-        private Conditions conditions;
-    }
-
-    /**
-     * Parameters of indicator alarms
-     */
-    @Data
-    @AllArgsConstructor
-    @NoArgsConstructor
-    public static class Conditions {
-        // alarm metrics parameters
-        private String metricName;
-        private String metricShowName;
-        private String calcType;
-        private String calcValue;
-        private String calcUnit;
-        private String currentValue;
-        private String historyValue;
-        private String unit;
-        private String period;
-        private String periodNum;
-        private String alarmNotifyType;
-        private long alarmNotifyPeriod;
-
-        // alarm event parameters
-        private String productName;
-        private String productShowName;
-        private String eventName;
-        private String eventShowName;
-    }
-
-    @Override
-    public String getAlertName() {
-        return "TenCloud|腾讯云";
-    }
-
-    @Override
-    public Integer getAlertDuration() {
-        return this.durationTime;
-    }
-
-    @Override
-    public long getAlertTime() {
-
-        return DateUtil.getTimeStampFromFormat(getFirstOccurTime(), 
"yyyy-MM-dd HH:mm:ss")
-                .orElse(0L);
-    }
-
-    @Override
-    public Integer getPriority() {
-        return 1;
-    }
-
-    @Override
-    public Integer getReportType() {
-        return 1;
-    }
-
-    @Override
-    public Map<String, String> getLabels() {
-        return Map.of("app", "TenCloud");
-    }
-
-    @Override
-    public Map<String, String> getAnnotations() {
-        return Map.of("app", "TenCloud");
-    }
-
-    /**
-     * Transaction alarm
-     */
-    private static final String EVENT = "event";
-
-    /**
-     * Indicator alarm
-     */
-    private static final String METRIC = "metric";
-
-    /**
-     * If the following alarm types increase, the entity class can be divided 
into a parent class and multiple subclasses, and then the method can be 
implemented in the subclass
-     * Since there are only two, it will not be split for the time being
-     */
-    @Override
-    public String getContent() {
-        StringBuilder contentBuilder = new StringBuilder();
-        // Check Type.
-        if (EVENT.equals(getAlarmType())) {
-            contentBuilder
-                    .append("[")
-                    .append("告警状态 | ")
-                    .append("0".equals(alarmStatus) ? "恢复" : "告警")
-                    .append("]\n")
-                    .append("[")
-                    .append("告警对象信息 | ")
-                    .append(getAlarmObjInfo().getRegion() == null ? "" : 
"region:" + getAlarmObjInfo().getRegion())
-                    
.append(";").append("appId:").append(getAlarmObjInfo().getAppId())
-                    
.append(";").append("uni:").append(getAlarmObjInfo().getUin())
-                    
.append(";").append("unInstanceId:").append(getAlarmObjInfo().getDimensions().getUnInstanceId())
-                    .append("]\n")
-                    .append("[")
-                    .append("告警策略组信息 | ")
-                    .append("名称:").append(getAlarmPolicyInfo().getPolicyName())
-                    .append(";")
-                    
.append("策略类型展示名称:").append(getAlarmPolicyInfo().getConditions().getProductName())
-                    
.append(",").append(getAlarmPolicyInfo().getConditions().getProductShowName())
-                    .append(";")
-                    
.append("事件告警名称:").append(getAlarmPolicyInfo().getConditions().getEventName())
-                    
.append(",").append(getAlarmPolicyInfo().getConditions().getEventShowName())
-                    .append("]");
-        } else if (METRIC.equals(getAlarmType())) {
-            contentBuilder
-                    .append("[")
-                    .append("告警对象:")
-                    .append(getAlarmObjInfo().getRegion() == null ? "" : 
getAlarmObjInfo().getRegion())
-                    .append(getAlarmObjInfo().getRegion() == null ? "" : "|")
-                    .append(getAlarmObjInfo().getNamespace())
-                    .append("]")
-                    .append("[")
-                    .append("告警内容:")
-                    
.append(getAlarmPolicyInfo().getPolicyTypeCname()).append("|")
-                    
.append(getAlarmPolicyInfo().getConditions().getMetricShowName()).append("|")
-                    
.append(getAlarmPolicyInfo().getConditions().getMetricName())
-                    .append(getAlarmPolicyInfo().getConditions().getCalcType())
-                    
.append(getAlarmPolicyInfo().getConditions().getCalcValue())
-                    .append(getAlarmPolicyInfo().getConditions().getCalcUnit())
-                    .append("]")
-                    .append("[")
-                    .append("当前数据")
-                    
.append(getAlarmPolicyInfo().getConditions().getCurrentValue())
-                    .append(getAlarmPolicyInfo().getConditions().getCalcUnit())
-                    .append("]");
-        }
-        return contentBuilder.toString();
-    }
-
-}
diff --git 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/TencentCloudExternAlert.java
 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/TencentCloudExternAlert.java
new file mode 100644
index 0000000000..f97448b36d
--- /dev/null
+++ 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/TencentCloudExternAlert.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hertzbeat.alert.dto;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ *
+ * Tencent cloud alarm entity class
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+public class TencentCloudExternAlert {
+    @JsonProperty("sessionID")
+    private String sessionId;
+    private String alarmStatus;
+    private String alarmType;
+    private AlarmObjInfo alarmObjInfo;
+    private AlarmPolicyInfo alarmPolicyInfo;
+    private String firstOccurTime;
+    private int durationTime;
+    private String recoverTime;
+
+    /**
+     * Alarm Object information
+     */
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class AlarmObjInfo {
+        private String region;
+        private String namespace;
+        @JsonProperty("appID")
+        private String appId;
+        private String uin;
+        private Dimensions dimensions;
+    }
+
+    /**
+     *  Uniform Resource ID information
+     */
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class Dimensions {
+        @JsonProperty("unInstanceID")
+        private String unInstanceId;
+        @JsonProperty("objID")
+        private String objId;
+    }
+
+    /**
+     * Alarm policy information
+     */
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class AlarmPolicyInfo {
+        @JsonProperty("policyID")
+        private String policyId;
+        private String policyType;
+        private String policyName;
+        @JsonProperty("policyTypeCName")
+        private String policyTypeCname;
+        private Conditions conditions;
+    }
+
+    /**
+     * Parameters of indicator alarms
+     */
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class Conditions {
+        // alarm metrics parameters
+        private String metricName;
+        private String metricShowName;
+        private String calcType;
+        private String calcValue;
+        private String calcUnit;
+        private String currentValue;
+        private String historyValue;
+        private String unit;
+        private String period;
+        private String periodNum;
+        private String alarmNotifyType;
+        private long alarmNotifyPeriod;
+
+        // alarm event parameters
+        private String productName;
+        private String productShowName;
+        private String eventName;
+        private String eventShowName;
+    }
+
+    /**
+     * Transaction alarm
+     */
+    private static final String EVENT = "event";
+
+    /**
+     * Indicator alarm
+     */
+    private static final String METRIC = "metric";
+
+}
diff --git 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/enums/CloudServiceAlarmInformationEnum.java
 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/enums/CloudServiceAlarmInformationEnum.java
deleted file mode 100644
index ebaeb0ae32..0000000000
--- 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/enums/CloudServiceAlarmInformationEnum.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.hertzbeat.alert.enums;
-
-import java.util.Arrays;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import org.apache.hertzbeat.alert.dto.CloudAlertReportAbstract;
-import org.apache.hertzbeat.alert.dto.TenCloudAlertReport;
-
-/**
- * Cloud server alarm enum
- */
-@AllArgsConstructor
-@Getter
-public enum CloudServiceAlarmInformationEnum {
-
-    TencentCloud("tencloud", TenCloudAlertReport.class);
-
-    /**
-     * cloud service name
-     */
-    private final String cloudServiceName;
-
-    /**
-     * cloud service body
-     */
-    private final Class<? extends CloudAlertReportAbstract> 
cloudServiceAlarmInformationEntity;
-
-    public static CloudServiceAlarmInformationEnum 
getEnumFromCloudServiceName(String name) {
-        return Arrays.stream(CloudServiceAlarmInformationEnum.values())
-                .filter(cloudService -> 
cloudService.cloudServiceName.equals(name))
-                .findFirst()
-                .orElse(null);
-    }
-
-}
diff --git 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/AlertService.java
 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/AlertService.java
index 9fedb48a6a..ea5c9bb9a2 100644
--- 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/AlertService.java
+++ 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/AlertService.java
@@ -83,17 +83,4 @@ public interface AlertService {
      * @return Alarm statistics information 
      */
     AlertSummary getAlertsSummary();
-
-    /**
-     * A third party reports an alarm 
-     * @param alertReport The alarm information 
-     */
-    void addNewAlertReport(SingleAlert alertReport);
-
-    /**
-     * Save external alarms of cloud services
-     * @param cloudServiceName cloud service name,Such as tencloud
-     * @param alertReport alert report json string
-     */
-    void addNewAlertReportFromCloud(String cloudServiceName, String 
alertReport);
 }
diff --git 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/ExternAlertService.java
 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/ExternAlertService.java
new file mode 100644
index 0000000000..346b0b2d5a
--- /dev/null
+++ 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/ExternAlertService.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hertzbeat.alert.service;
+
+/**
+ * Extern alert service for prometheus, cloud and so on
+ */
+public interface ExternAlertService {
+
+    /**
+     * Save external alarms of services
+     * @param content alert report json string
+     */
+    void addExternAlert(String content);
+
+
+    /**
+     * Support source: prometheus, tencent ...
+     * @return source name
+     */
+    String supportSource();
+}
diff --git 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertServiceImpl.java
 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertServiceImpl.java
index aadc4551d7..80bb95258b 100644
--- 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertServiceImpl.java
+++ 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlertServiceImpl.java
@@ -23,20 +23,15 @@ import java.math.RoundingMode;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Optional;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.hertzbeat.alert.dao.GroupAlertDao;
 import org.apache.hertzbeat.alert.dao.SingleAlertDao;
 import org.apache.hertzbeat.alert.dto.AlertSummary;
-import org.apache.hertzbeat.alert.dto.CloudAlertReportAbstract;
-import org.apache.hertzbeat.alert.enums.CloudServiceAlarmInformationEnum;
 import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce;
 import org.apache.hertzbeat.alert.service.AlertService;
 import org.apache.hertzbeat.common.constants.CommonConstants;
 import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
 import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
-import org.apache.hertzbeat.common.util.JsonUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
@@ -208,40 +203,4 @@ public class AlertServiceImpl implements AlertService {
         }
         return alertSummary;
     }
-
-    @Override
-    public void addNewAlertReport(SingleAlert alert) {
-        // todo add alarm information to the alarm center
-        alarmCommonReduce.reduceAndSendAlarm(alert);
-    }
-
-    @Override
-    public void addNewAlertReportFromCloud(String cloudServiceName, String 
alertReport) {
-        CloudServiceAlarmInformationEnum cloudService = 
CloudServiceAlarmInformationEnum
-                .getEnumFromCloudServiceName(cloudServiceName);
-
-        SingleAlert alert = null;
-        if (cloudService != null) {
-            try {
-                CloudAlertReportAbstract cloudAlertReport = JsonUtil
-                        .fromJson(alertReport, 
cloudService.getCloudServiceAlarmInformationEntity());
-                assert cloudAlertReport != null;
-                Map<String, String> labels = cloudAlertReport.getLabels();
-                labels.put("source", cloudServiceName);
-                labels.put("alertname", cloudAlertReport.getAlertName());
-                
-                alert = SingleAlert.builder()
-                        .content(cloudAlertReport.getContent())
-                        .labels(labels)
-                        .annotations(cloudAlertReport.getAnnotations())
-                        .status("firing")
-                        .activeAt(cloudAlertReport.getAlertTime())
-                        .build();
-            } catch (Exception e) {
-                log.error("[alert report] parse cloud service alarm content 
failed! cloud service: {} conrent: {}",
-                        cloudService.name(), alertReport);
-            }
-        }
-        Optional.ofNullable(alert).ifPresent(this::addNewAlertReport);
-    }
 }
diff --git 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/DefaultExternAlertService.java
 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/DefaultExternAlertService.java
new file mode 100644
index 0000000000..1d875b93b0
--- /dev/null
+++ 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/DefaultExternAlertService.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hertzbeat.alert.service.impl;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce;
+import org.apache.hertzbeat.alert.service.ExternAlertService;
+import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
+import org.apache.hertzbeat.common.util.JsonUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * Default external alarm service impl
+ */
+@Slf4j
+@Service
+public class DefaultExternAlertService implements ExternAlertService {
+
+    @Autowired
+    private AlarmCommonReduce alarmCommonReduce;
+    
+    @Override
+    public void addExternAlert(String content) {
+        SingleAlert alert = JsonUtil.fromJson(content, SingleAlert.class);
+        if (alert == null) {
+            log.warn("parse extern alert content failed! content: {}", 
content);
+            return;
+        }
+        alarmCommonReduce.reduceAndSendAlarm(alert);
+    }
+
+    @Override
+    public String supportSource() {
+        return "default";
+    }
+}
diff --git 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/PrometheusExternAlertService.java
 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/PrometheusExternAlertService.java
new file mode 100644
index 0000000000..a1b6a32c85
--- /dev/null
+++ 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/PrometheusExternAlertService.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hertzbeat.alert.service.impl;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce;
+import org.apache.hertzbeat.alert.service.ExternAlertService;
+import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
+import org.apache.hertzbeat.common.util.JsonUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * Default external alarm service impl
+ */
+@Slf4j
+@Service
+public class PrometheusExternAlertService implements ExternAlertService {
+
+    @Autowired
+    private AlarmCommonReduce alarmCommonReduce;
+
+
+    @Override
+    public void addExternAlert(String content) {
+        SingleAlert alert = JsonUtil.fromJson(content, SingleAlert.class);
+        // todo parse prometheus alert content
+        if (alert == null) {
+            log.warn("parse extern alert content failed! content: {}", 
content);
+            return;
+        }
+        alarmCommonReduce.reduceAndSendAlarm(alert);
+    }
+
+    @Override
+    public String supportSource() {
+        return "prometheus";
+    }
+}
diff --git 
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/TencentExternAlertService.java
 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/TencentExternAlertService.java
new file mode 100644
index 0000000000..6b7a978deb
--- /dev/null
+++ 
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/TencentExternAlertService.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hertzbeat.alert.service.impl;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.hertzbeat.alert.dto.TencentCloudExternAlert;
+import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce;
+import org.apache.hertzbeat.alert.service.ExternAlertService;
+import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
+import org.apache.hertzbeat.common.util.JsonUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * Default external alarm service impl
+ */
+@Slf4j
+@Service
+public class TencentExternAlertService implements ExternAlertService {
+
+    @Autowired
+    private AlarmCommonReduce alarmCommonReduce;
+    
+    @Override
+    public void addExternAlert(String content) {
+        TencentCloudExternAlert report = JsonUtil.fromJson(content, 
TencentCloudExternAlert.class);
+        if (report == null) {
+            log.warn("parse extern alert content failed! content: {}", 
content);
+            return;
+        }
+        // todo convert TenCloudAlertReport to SingleAlert
+        SingleAlert alert = new SingleAlert();
+        alarmCommonReduce.reduceAndSendAlarm(alert);
+    }
+
+    @Override
+    public String supportSource() {
+        return "tencent";
+    }
+}
diff --git 
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/AlertReportControllerTest.java
 
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/AlertReportControllerTest.java
index 60a1b40d40..79a7e9bcc9 100644
--- 
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/AlertReportControllerTest.java
+++ 
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/controller/AlertReportControllerTest.java
@@ -21,7 +21,7 @@ import static 
org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 import static 
org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
 import static 
org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 import java.util.HashMap;
-import org.apache.hertzbeat.alert.dto.TenCloudAlertReport;
+import org.apache.hertzbeat.alert.dto.TencentCloudExternAlert;
 import org.apache.hertzbeat.alert.service.AlertService;
 import org.apache.hertzbeat.common.constants.CommonConstants;
 import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
@@ -58,17 +58,17 @@ class AlertReportControllerTest {
 
     @Test
     void addNewAlertReportTencent() throws Exception {
-        TenCloudAlertReport.Dimensions dimensions = new 
TenCloudAlertReport.Dimensions();
+        TencentCloudExternAlert.Dimensions dimensions = new 
TencentCloudExternAlert.Dimensions();
         dimensions.setUnInstanceId("3333");
 
-        TenCloudAlertReport.AlarmObjInfo alarmObjInfo = new 
TenCloudAlertReport.AlarmObjInfo();
+        TencentCloudExternAlert.AlarmObjInfo alarmObjInfo = new 
TencentCloudExternAlert.AlarmObjInfo();
         alarmObjInfo.setRegion("Guangzhou");
         alarmObjInfo.setNamespace("Guangzhou1");
         alarmObjInfo.setAppId("1111");
         alarmObjInfo.setUin("2222");
         alarmObjInfo.setDimensions(dimensions);
 
-        TenCloudAlertReport.Conditions conditions = new 
TenCloudAlertReport.Conditions();
+        TencentCloudExternAlert.Conditions conditions = new 
TencentCloudExternAlert.Conditions();
         conditions.setMetricName("xx");
         conditions.setMetricShowName("xxx");
         conditions.setCalcType("a");
@@ -81,12 +81,12 @@ class AlertReportControllerTest {
         conditions.setEventName("CVS");
         conditions.setEventShowName("Core error");
 
-        TenCloudAlertReport.AlarmPolicyInfo alarmPolicyInfo = new 
TenCloudAlertReport.AlarmPolicyInfo();
+        TencentCloudExternAlert.AlarmPolicyInfo alarmPolicyInfo = new 
TencentCloudExternAlert.AlarmPolicyInfo();
         alarmPolicyInfo.setPolicyTypeCname("x");
         alarmPolicyInfo.setPolicyName("Test1");
         alarmPolicyInfo.setConditions(conditions);
 
-        TenCloudAlertReport report = TenCloudAlertReport.builder()
+        TencentCloudExternAlert report = TencentCloudExternAlert.builder()
                 .sessionId("123")
                 .alarmStatus("1")
                 .alarmType("event")
diff --git 
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertServiceTest.java
 
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertServiceTest.java
index c4e077008d..2c7f5afe75 100644
--- 
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertServiceTest.java
+++ 
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AlertServiceTest.java
@@ -21,23 +21,19 @@ package org.apache.hertzbeat.alert.service;
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import org.apache.hertzbeat.alert.dao.GroupAlertDao;
 import org.apache.hertzbeat.alert.dao.SingleAlertDao;
-import org.apache.hertzbeat.alert.dto.TenCloudAlertReport;
 import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce;
 import org.apache.hertzbeat.alert.service.impl.AlertServiceImpl;
 import org.apache.hertzbeat.common.constants.CommonConstants;
 import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
-import org.apache.hertzbeat.common.util.JsonUtil;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
@@ -97,36 +93,4 @@ class AlertServiceTest {
         assertDoesNotThrow(() -> alertService.getAlertsSummary());
         assertNotNull(alertService.getAlertsSummary());
     }
-
-    @Test
-    void addNewAlertReport() {
-        SingleAlert alertReport = SingleAlert.builder()
-                .fingerprint("fingerprint")
-                .labels(new HashMap<>())
-                .annotations(new HashMap<>())
-                .content("content")
-                .status("firing")
-                .triggerTimes(1)
-                .startAt(1734005477630L)
-                .activeAt(1734005477630L)
-                .build();
-        assertDoesNotThrow(() -> alertService.addNewAlertReport(alertReport));
-        verify(alarmCommonReduce, 
times(1)).reduceAndSendAlarm(any(SingleAlert.class));
-    }
-
-    @Test
-    void addNewAlertReportFromCloud() {
-        TenCloudAlertReport alertReport = TenCloudAlertReport.builder()
-                .firstOccurTime("2024-08-01 11:30:00")
-                .durationTime(100)
-                .build();
-        String reportJson = JsonUtil.toJson(alertReport);
-        assertDoesNotThrow(() -> 
alertService.addNewAlertReportFromCloud("tencloud", reportJson));
-        verify(alarmCommonReduce, 
times(1)).reduceAndSendAlarm(any(SingleAlert.class));
-
-        alertService.addNewAlertReportFromCloud("alicloud", reportJson);
-        reset(alarmCommonReduce);
-        verify(alarmCommonReduce, 
times(0)).reduceAndSendAlarm(any(SingleAlert.class));
-
-    }
 }
diff --git a/web-app/src/assets/doc/alert-integration/prometheus.en-US.md 
b/web-app/src/assets/doc/alert-integration/prometheus.en-US.md
index e69de29bb2..b876d8a96d 100644
--- a/web-app/src/assets/doc/alert-integration/prometheus.en-US.md
+++ b/web-app/src/assets/doc/alert-integration/prometheus.en-US.md
@@ -0,0 +1,7 @@
+# Prometheus Alert Integration
+
+HertzBeat is fully compatible with Prometheus alert data format. You can 
configure Prometheus alerting rules to send alerts to HertzBeat.
+
+## Prometheus Alert Configuration
+
+Add the following configuration to your Prometheus configuration file:
diff --git a/web-app/src/assets/doc/alert-integration/prometheus.zh-CN.md 
b/web-app/src/assets/doc/alert-integration/prometheus.zh-CN.md
index e69de29bb2..50880bd187 100644
--- a/web-app/src/assets/doc/alert-integration/prometheus.zh-CN.md
+++ b/web-app/src/assets/doc/alert-integration/prometheus.zh-CN.md
@@ -0,0 +1,32 @@
+## 告警字段說明
+
+- `alert`: 告警規則名稱
+- `expr`: 告警觸發條件表達式
+- `for`: 告警持續時間閾值
+- `labels`: 告警標籤
+  - `severity`: 告警級別 (warning, critical)
+- `annotations`: 告警註釋信息
+  - `summary`: 告警摘要
+  - `description`: 告警詳細描述
+
+## 驗證配置
+
+1. 確保 Prometheus 配置正確並重新加載配置
+   ```bash
+   curl -X POST http://localhost:9090/-/reload
+   ```
+
+2. 檢查 Prometheus 告警規則狀態
+   ```bash
+   curl http://localhost:9090/api/v1/rules
+   ```
+
+3. 觸發測試告警並在 HertzBeat 告警中心查看
+
+## 常見問題
+
+1. 確保 HertzBeat URL 可以被 Prometheus 服務器訪問
+2. 檢查 Prometheus 日誌中是否有告警發送失敗的錯誤信息
+3. 驗證告警規則表達式的正確性
+
+更多信息請參考 [Prometheus 
告警配置文檔](https://prometheus.io/docs/alerting/latest/configuration/)
diff --git a/web-app/src/assets/doc/alert-integration/tencent.zh-TW.md 
b/web-app/src/assets/doc/alert-integration/tencent.zh-TW.md
index e69de29bb2..a607d164c7 100644
--- a/web-app/src/assets/doc/alert-integration/tencent.zh-TW.md
+++ b/web-app/src/assets/doc/alert-integration/tencent.zh-TW.md
@@ -0,0 +1,9 @@
+## 验证配置
+
+1. 确保 Prometheus 配置正确并重新加载配置
+2. 触发一个测试告警
+3. 在 HertzBeat 告警中心查看是否收到告警
+
+更多信息请参考 [Prometheus 
官方文档](https://prometheus.io/docs/alerting/latest/configuration/)
+
+## Alert Rule Example


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@hertzbeat.apache.org
For additional commands, e-mail: notifications-h...@hertzbeat.apache.org


Reply via email to