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