Browse Source

feat: 自定义Prometheus短信报警提醒webhook

TwoKe945 2 years ago
commit
10efe4790f
23 changed files with 885 additions and 0 deletions
  1. 33 0
      .gitignore
  2. 59 0
      pom.xml
  3. 14 0
      src/main/java/com/cqxf/prometheus/alert/PrometheusSmsAlertApplication.java
  4. 60 0
      src/main/java/com/cqxf/prometheus/alert/annotations/RequestRestController.java
  5. 55 0
      src/main/java/com/cqxf/prometheus/alert/api/PrometheusAlertController.java
  6. 18 0
      src/main/java/com/cqxf/prometheus/alert/config/PrometheusAlertProperties.java
  7. 15 0
      src/main/java/com/cqxf/prometheus/alert/config/RestTemplateConfig.java
  8. 8 0
      src/main/java/com/cqxf/prometheus/alert/constant/Constant.java
  9. 37 0
      src/main/java/com/cqxf/prometheus/alert/entity/alert/Alerts.java
  10. 11 0
      src/main/java/com/cqxf/prometheus/alert/entity/alert/Annotations.java
  11. 10 0
      src/main/java/com/cqxf/prometheus/alert/entity/alert/CommonAnnotations.java
  12. 39 0
      src/main/java/com/cqxf/prometheus/alert/entity/alert/PrometheusAlert.java
  13. 13 0
      src/main/java/com/cqxf/prometheus/alert/entity/message/Result.java
  14. 27 0
      src/main/java/com/cqxf/prometheus/alert/entity/message/SendCqxfMessageRequest.java
  15. 26 0
      src/main/java/com/cqxf/prometheus/alert/entity/message/SendCqxfMessageResponse.java
  16. 18 0
      src/main/java/com/cqxf/prometheus/alert/service/MessageService.java
  17. 7 0
      src/main/java/com/cqxf/prometheus/alert/service/PrometheusAlertService.java
  18. 56 0
      src/main/java/com/cqxf/prometheus/alert/service/impl/CqxfSmsMessageServiceImpl.java
  19. 66 0
      src/main/java/com/cqxf/prometheus/alert/service/impl/PrometheusAlertServiceImpl.java
  20. 21 0
      src/main/java/com/cqxf/prometheus/alert/service/impl/TestSmsMessageServiceImpl.java
  21. 262 0
      src/main/java/com/cqxf/prometheus/alert/utils/AppContext.java
  22. 9 0
      src/main/resources/application.yml
  23. 21 0
      src/test/java/com/cqxf/prometheus/alert/PrometheusSmsAlertApplicationTests.java

+ 33 - 0
.gitignore

@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

+ 59 - 0
pom.xml

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.7.10</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.cqxf.prometheus.alert</groupId>
+    <artifactId>prometheus-sms-alert</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>prometheus-sms-alert</name>
+    <description>prometheus-sms-alert</description>
+    <properties>
+        <java.version>1.8</java.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                        </exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 14 - 0
src/main/java/com/cqxf/prometheus/alert/PrometheusSmsAlertApplication.java

@@ -0,0 +1,14 @@
+package com.cqxf.prometheus.alert;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@SpringBootApplication
+public class PrometheusSmsAlertApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(PrometheusSmsAlertApplication.class, args);
+    }
+
+}

+ 60 - 0
src/main/java/com/cqxf/prometheus/alert/annotations/RequestRestController.java

@@ -0,0 +1,60 @@
+package com.cqxf.prometheus.alert.annotations;
+
+
+import org.springframework.core.annotation.AliasFor;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Controller
+@ResponseBody
+@RequestMapping
+public @interface RequestRestController {
+
+    /**
+     * Assign a name to this mapping.
+     * <p><b>Supported at the type level as well as at the method level!</b>
+     * When used on both levels, a combined name is derived by concatenation
+     * with "#" as separator.
+     * @see org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder
+     * @see org.springframework.web.servlet.handler.HandlerMethodMappingNamingStrategy
+     */
+    @AliasFor(annotation = RequestMapping.class)
+    String name() default "";
+
+    /**
+     * The primary mapping expressed by this annotation.
+     * <p>This is an alias for {@link #path}. For example,
+     * {@code @RequestMapping("/foo")} is equivalent to
+     * {@code @RequestMapping(path="/foo")}.
+     * <p><b>Supported at the type level as well as at the method level!</b>
+     * When used at the type level, all method-level mappings inherit
+     * this primary mapping, narrowing it for a specific handler method.
+     * <p><strong>NOTE</strong>: A handler method that is not mapped to any path
+     * explicitly is effectively mapped to an empty path.
+     */
+    @AliasFor(annotation = RequestMapping.class)
+    String[] value() default {};
+
+    /**
+     * The path mapping URIs (e.g. {@code "/profile"}).
+     * <p>Ant-style path patterns are also supported (e.g. {@code "/profile/**"}).
+     * At the method level, relative paths (e.g. {@code "edit"}) are supported
+     * within the primary mapping expressed at the type level.
+     * Path mapping URIs may contain placeholders (e.g. <code>"/${profile_path}"</code>).
+     * <p><b>Supported at the type level as well as at the method level!</b>
+     * When used at the type level, all method-level mappings inherit
+     * this primary mapping, narrowing it for a specific handler method.
+     * <p><strong>NOTE</strong>: A handler method that is not mapped to any path
+     * explicitly is effectively mapped to an empty path.
+     * @since 4.2
+     */
+    @AliasFor(annotation = RequestMapping.class)
+    String[] path() default {};
+
+}

+ 55 - 0
src/main/java/com/cqxf/prometheus/alert/api/PrometheusAlertController.java

@@ -0,0 +1,55 @@
+package com.cqxf.prometheus.alert.api;
+
+import com.cqxf.prometheus.alert.annotations.RequestRestController;
+import com.cqxf.prometheus.alert.entity.alert.PrometheusAlert;
+import com.cqxf.prometheus.alert.service.MessageService;
+import com.cqxf.prometheus.alert.service.PrometheusAlertService;
+import com.cqxf.prometheus.alert.utils.AppContext;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.io.IOException;
+import java.util.Optional;
+
+@Slf4j
+@RequestRestController("/sms/webhook")
+@RequiredArgsConstructor
+public class PrometheusAlertController {
+
+    private final PrometheusAlertService prometheusAlertService;
+    private final AppContext appContext;
+
+    @PostMapping("/send")
+    public void send(@RequestBody String alert) throws IOException {
+        System.out.println(alert);
+        ObjectMapper objectMapper = new ObjectMapper();
+        JsonParser parser = objectMapper.createParser(alert);
+        prometheusAlertService.send(parser.readValueAs(PrometheusAlert.class));
+    }
+
+    @GetMapping("/version")
+    public String version() {
+        log.info("version: {}", "1.0.0");
+        return "1.0.0";
+    }
+
+    @GetMapping("/test-send/{service}")
+    public String testSend(@PathVariable String service) {
+        try {
+            Optional<MessageService> serviceOptional = Optional.ofNullable(appContext.getBean(service, MessageService.class));
+            MessageService messageService = serviceOptional.orElseThrow(() -> new RuntimeException("没有找到指定的服务"));
+            messageService.send("18580550924", "测试发送");
+            return "测试发送成功";
+        } catch (Exception e) {
+            return e.getMessage();
+        }
+    }
+}

+ 18 - 0
src/main/java/com/cqxf/prometheus/alert/config/PrometheusAlertProperties.java

@@ -0,0 +1,18 @@
+package com.cqxf.prometheus.alert.config;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@ConfigurationProperties(prefix = "prometheus-alert")
+@Configuration
+@Getter
+@Setter
+public class PrometheusAlertProperties {
+
+    private String activeSmsService;
+    private String[] managers;
+
+
+}

+ 15 - 0
src/main/java/com/cqxf/prometheus/alert/config/RestTemplateConfig.java

@@ -0,0 +1,15 @@
+package com.cqxf.prometheus.alert.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+@Configuration
+public class RestTemplateConfig{
+
+    @Bean
+    public RestTemplate restTemplate() {
+        return new RestTemplate();
+    }
+
+}

+ 8 - 0
src/main/java/com/cqxf/prometheus/alert/constant/Constant.java

@@ -0,0 +1,8 @@
+package com.cqxf.prometheus.alert.constant;
+
+public interface Constant {
+
+    String FIRING = "firing";
+    String RESOLVED = "resolved";
+
+}

+ 37 - 0
src/main/java/com/cqxf/prometheus/alert/entity/alert/Alerts.java

@@ -0,0 +1,37 @@
+package com.cqxf.prometheus.alert.entity.alert;
+import com.cqxf.prometheus.alert.constant.Constant;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.Map;
+
+@Data
+public class Alerts {
+
+    private String status;
+    private Map<String, String> labels;
+    private Annotations annotations;
+    private Date startsAt;
+    private Date endsAt;
+    private String generatorURL;
+    private String fingerprint;
+
+
+    /**
+     * 报警
+     * @return
+     */
+    public boolean isFiring() {
+        return Constant.FIRING.equals(this.status);
+    }
+
+    /**
+     * 恢复
+     * @return
+     */
+    public boolean isResolved() {
+        return Constant.RESOLVED.equals(this.status);
+    }
+
+
+}

+ 11 - 0
src/main/java/com/cqxf/prometheus/alert/entity/alert/Annotations.java

@@ -0,0 +1,11 @@
+package com.cqxf.prometheus.alert.entity.alert;
+
+import lombok.Data;
+
+@Data
+public class Annotations {
+
+    private String description;
+    private String summary;
+
+}

+ 10 - 0
src/main/java/com/cqxf/prometheus/alert/entity/alert/CommonAnnotations.java

@@ -0,0 +1,10 @@
+package com.cqxf.prometheus.alert.entity.alert;
+
+import lombok.Data;
+
+@Data
+public class CommonAnnotations {
+
+    private String description;
+    private String summary;
+}

+ 39 - 0
src/main/java/com/cqxf/prometheus/alert/entity/alert/PrometheusAlert.java

@@ -0,0 +1,39 @@
+package com.cqxf.prometheus.alert.entity.alert;
+import com.cqxf.prometheus.alert.constant.Constant;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class PrometheusAlert {
+
+    private String receiver;
+    private String status;
+    private List<Alerts> alerts;
+    private Map<String, String> groupLabels;
+    private Map<String, String> commonLabels;
+    private CommonAnnotations commonAnnotations;
+    private String externalURL;
+    private String version;
+    private String groupKey;
+    private int truncatedAlerts;
+
+    /**
+     * 是否已处理
+     * @return
+     */
+    public boolean isFiring() {
+        return Constant.FIRING.equals(this.status);
+    }
+
+    /**
+     * 是否已处理
+     * @return
+     */
+    public boolean isResolved() {
+        return Constant.RESOLVED.equals(this.status);
+    }
+
+
+}

+ 13 - 0
src/main/java/com/cqxf/prometheus/alert/entity/message/Result.java

@@ -0,0 +1,13 @@
+package com.cqxf.prometheus.alert.entity.message;
+
+import lombok.*;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+@Builder
+public class Result {
+    public String code;
+    public String msg;
+}

+ 27 - 0
src/main/java/com/cqxf/prometheus/alert/entity/message/SendCqxfMessageRequest.java

@@ -0,0 +1,27 @@
+/**
+  * Copyright 2023 ab173.com 
+  */
+package com.cqxf.prometheus.alert.entity.message;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * Auto-generated: 2023-04-17 12:33:5
+ *
+ * @author ab173.com (info@ab173.com)
+ * @website http://www.ab173.com/json/
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class SendCqxfMessageRequest {
+
+    private String phone;
+    private String content;
+    private String remark;
+
+}

+ 26 - 0
src/main/java/com/cqxf/prometheus/alert/entity/message/SendCqxfMessageResponse.java

@@ -0,0 +1,26 @@
+/**
+  * Copyright 2023 ab173.com 
+  */
+package com.cqxf.prometheus.alert.entity.message;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * Auto-generated: 2023-04-17 12:33:5
+ *
+ * @author ab173.com (info@ab173.com)
+ * @website http://www.ab173.com/json/
+ */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class SendCqxfMessageResponse {
+
+    public String code;
+    public Result data;
+
+}

+ 18 - 0
src/main/java/com/cqxf/prometheus/alert/service/MessageService.java

@@ -0,0 +1,18 @@
+package com.cqxf.prometheus.alert.service;
+
+import java.util.List;
+
+/**
+ * 消息发送服务
+ */
+public interface MessageService {
+
+    void send(String to, String content);
+
+    default void send(List<String> tos, String content) {
+        send(tos.toArray(new String[tos.size()]), content);
+    }
+
+    void send(String[] tos, String content);
+
+}

+ 7 - 0
src/main/java/com/cqxf/prometheus/alert/service/PrometheusAlertService.java

@@ -0,0 +1,7 @@
+package com.cqxf.prometheus.alert.service;
+
+import com.cqxf.prometheus.alert.entity.alert.PrometheusAlert;
+
+public interface PrometheusAlertService {
+    void send(PrometheusAlert prometheusAlert);
+}

+ 56 - 0
src/main/java/com/cqxf/prometheus/alert/service/impl/CqxfSmsMessageServiceImpl.java

@@ -0,0 +1,56 @@
+package com.cqxf.prometheus.alert.service.impl;
+
+import com.cqxf.prometheus.alert.entity.message.SendCqxfMessageRequest;
+import com.cqxf.prometheus.alert.entity.message.SendCqxfMessageResponse;
+import com.cqxf.prometheus.alert.service.MessageService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+
+/**
+ * 重庆消防短信调用
+ */
+@Component("cqxfSms")
+@Slf4j
+public class CqxfSmsMessageServiceImpl implements MessageService {
+
+    @Autowired
+    private RestTemplate restTemplate;
+
+    @Value("${prometheus-alert.cqxfSms.url}")
+    private String url;
+
+    @Override
+    public void send(String to, String content) {
+        log.info("发送至:{};消息体:{}", to, content);
+        SendCqxfMessageRequest ctx = SendCqxfMessageRequest.builder()
+                .phone(to)
+                .content(content)
+                .remark("资源运维监控")
+                .build();
+        ParameterizedTypeReference<SendCqxfMessageResponse> responseType = new ParameterizedTypeReference<SendCqxfMessageResponse>() {
+        };
+        ResponseEntity<SendCqxfMessageResponse> responseEntity = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<SendCqxfMessageRequest>(ctx), responseType);
+        SendCqxfMessageResponse response = responseEntity.getBody();
+        log.info("短信接口返回内容,response={}", response);
+        if (response == null) {
+            log.warn("电话号码{},短信发送失败!", ctx.getPhone());
+        }
+        String code = response.getCode();
+        if (!"0".equals(code)) {
+            log.warn("电话号码{},短信发送失败!", ctx.getPhone());
+        }
+    }
+
+    @Override
+    public void send(String[] tos, String content) {
+        send(String.join("," , tos), content);
+    }
+}

+ 66 - 0
src/main/java/com/cqxf/prometheus/alert/service/impl/PrometheusAlertServiceImpl.java

@@ -0,0 +1,66 @@
+package com.cqxf.prometheus.alert.service.impl;
+
+import com.cqxf.prometheus.alert.config.PrometheusAlertProperties;
+import com.cqxf.prometheus.alert.entity.alert.Alerts;
+import com.cqxf.prometheus.alert.entity.alert.PrometheusAlert;
+import com.cqxf.prometheus.alert.service.MessageService;
+import com.cqxf.prometheus.alert.service.PrometheusAlertService;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+@Component
+public class PrometheusAlertServiceImpl implements PrometheusAlertService, ApplicationContextAware {
+
+
+    private MessageService messageService;
+
+    private CacheMap cacheMap = new CacheMap();
+
+    @Autowired
+    private PrometheusAlertProperties properties;
+
+    @Override
+    public void send(PrometheusAlert prometheusAlert) {
+        Optional<List<Alerts>> optionalAlerts = Optional.ofNullable(prometheusAlert.getAlerts());
+        optionalAlerts.ifPresent(alerts -> {
+            alerts.forEach(item -> {
+                String instance = item.getLabels().get("instance") + ":" + prometheusAlert.getGroupLabels().get("alertname");
+                if (item.isFiring()) {
+                    if (!cacheMap.isSend(instance)) {
+                        messageService.send(properties.getManagers(), "【"+item.getLabels().get("job") + "】" + item.getAnnotations().getDescription());
+                        cacheMap.put(instance, Boolean.TRUE);
+                    }
+                } else if (item.isResolved()) {
+                    if (cacheMap.isSend(instance)) {
+                       cacheMap.put(instance, Boolean.FALSE);
+                    }
+                }
+            });
+        });
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        this.messageService = applicationContext.getBean(properties.getActiveSmsService(), MessageService.class);
+    }
+
+    static class CacheMap extends HashMap<String, Boolean> {
+
+        public boolean isSend(String key) {
+            if (containsKey(key)) {
+                return get(key);
+            }
+            return false;
+        }
+
+
+    }
+}

+ 21 - 0
src/main/java/com/cqxf/prometheus/alert/service/impl/TestSmsMessageServiceImpl.java

@@ -0,0 +1,21 @@
+package com.cqxf.prometheus.alert.service.impl;
+
+import com.cqxf.prometheus.alert.service.MessageService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Slf4j
+@Component("testSms")
+public class TestSmsMessageServiceImpl implements MessageService {
+    @Override
+    public void send(String to, String content) {
+        log.info("发送至:{};消息体:{}", to, content);
+    }
+
+    @Override
+    public void send(String[] tos, String content) {
+        send(String.join(",", tos), content);
+    }
+}

+ 262 - 0
src/main/java/com/cqxf/prometheus/alert/utils/AppContext.java

@@ -0,0 +1,262 @@
+package com.cqxf.prometheus.alert.utils;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.MessageSourceResolvable;
+import org.springframework.context.NoSuchMessageException;
+import org.springframework.core.ResolvableType;
+import org.springframework.core.env.Environment;
+import org.springframework.core.io.Resource;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.util.Locale;
+import java.util.Map;
+
+@Component("appContext")
+public class AppContext implements ApplicationContextAware, ApplicationContext{
+
+    private ApplicationContext applicationContext;
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        this.applicationContext = applicationContext;
+    }
+
+
+    @Override
+    public String getId() {
+        return applicationContext.getId();
+    }
+
+    @Override
+    public String getApplicationName() {
+        return applicationContext.getApplicationName();
+    }
+
+    @Override
+    public String getDisplayName() {
+        return applicationContext.getDisplayName();
+    }
+
+    @Override
+    public long getStartupDate() {
+        return applicationContext.getStartupDate();
+    }
+
+    @Override
+    public ApplicationContext getParent() {
+        return applicationContext.getParent();
+    }
+
+    @Override
+    public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
+        return applicationContext.getAutowireCapableBeanFactory();
+    }
+
+    @Override
+    public BeanFactory getParentBeanFactory() {
+        return applicationContext.getParentBeanFactory();
+    }
+
+    @Override
+    public boolean containsLocalBean(String s) {
+        return applicationContext.containsLocalBean(s);
+    }
+
+    @Override
+    public boolean containsBeanDefinition(String s) {
+        return applicationContext.containsBeanDefinition(s);
+    }
+
+    @Override
+    public int getBeanDefinitionCount() {
+        return applicationContext.getBeanDefinitionCount();
+    }
+
+    @Override
+    public String[] getBeanDefinitionNames() {
+        return applicationContext.getBeanDefinitionNames();
+    }
+
+    @Override
+    public <T> ObjectProvider<T> getBeanProvider(Class<T> aClass, boolean b) {
+        return applicationContext.getBeanProvider(aClass, b);
+    }
+
+    @Override
+    public <T> ObjectProvider<T> getBeanProvider(ResolvableType resolvableType, boolean b) {
+        return applicationContext.getBeanProvider(resolvableType, b);
+    }
+
+    @Override
+    public String[] getBeanNamesForType(ResolvableType resolvableType) {
+        return applicationContext.getBeanNamesForType(resolvableType);
+    }
+
+    @Override
+    public String[] getBeanNamesForType(ResolvableType resolvableType, boolean b, boolean b1) {
+        return applicationContext.getBeanNamesForType(resolvableType, b, b1);
+    }
+
+    @Override
+    public String[] getBeanNamesForType(Class<?> aClass) {
+        return applicationContext.getBeanNamesForType(aClass);
+    }
+
+    @Override
+    public String[] getBeanNamesForType(Class<?> aClass, boolean b, boolean b1) {
+        return  applicationContext.getBeanNamesForType(aClass, b, b1);
+    }
+
+    @Override
+    public <T> Map<String, T> getBeansOfType(Class<T> aClass) throws BeansException {
+        return  applicationContext.getBeansOfType(aClass);
+    }
+
+    @Override
+    public <T> Map<String, T> getBeansOfType(Class<T> aClass, boolean b, boolean b1) throws BeansException {
+        return  applicationContext.getBeansOfType(aClass, b, b1);
+    }
+
+    @Override
+    public String[] getBeanNamesForAnnotation(Class<? extends Annotation> aClass) {
+        return  applicationContext.getBeanNamesForAnnotation(aClass);
+    }
+
+    @Override
+    public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> aClass) throws BeansException {
+        return applicationContext.getBeansWithAnnotation(aClass);
+    }
+
+    @Override
+    public <A extends Annotation> A findAnnotationOnBean(String s, Class<A> aClass) throws NoSuchBeanDefinitionException {
+        return applicationContext.findAnnotationOnBean(s, aClass);
+    }
+
+    @Override
+    public <A extends Annotation> A findAnnotationOnBean(String s, Class<A> aClass, boolean b) throws NoSuchBeanDefinitionException {
+        return applicationContext.findAnnotationOnBean(s, aClass, b);
+    }
+
+    @Override
+    public Object getBean(String s) throws BeansException {
+        return applicationContext.getBean(s);
+    }
+
+    @Override
+    public <T> T getBean(String s, Class<T> aClass) throws BeansException {
+        return applicationContext.getBean(s, aClass);
+    }
+
+    @Override
+    public Object getBean(String s, Object... objects) throws BeansException {
+        return applicationContext.getBean(s, objects);
+    }
+
+    @Override
+    public <T> T getBean(Class<T> aClass) throws BeansException {
+        return  applicationContext.getBean(aClass);
+    }
+
+    @Override
+    public <T> T getBean(Class<T> aClass, Object... objects) throws BeansException {
+        return  applicationContext.getBean(aClass, objects);
+    }
+
+    @Override
+    public <T> ObjectProvider<T> getBeanProvider(Class<T> aClass) {
+        return  applicationContext.getBeanProvider(aClass);
+    }
+
+    @Override
+    public <T> ObjectProvider<T> getBeanProvider(ResolvableType resolvableType) {
+        return  applicationContext.getBeanProvider(resolvableType);
+    }
+
+    @Override
+    public boolean containsBean(String s) {
+        return applicationContext.containsBean(s);
+    }
+
+    @Override
+    public boolean isSingleton(String s) throws NoSuchBeanDefinitionException {
+        return  applicationContext.isSingleton(s);
+    }
+
+    @Override
+    public boolean isPrototype(String s) throws NoSuchBeanDefinitionException {
+        return  applicationContext.isPrototype(s);
+    }
+
+    @Override
+    public boolean isTypeMatch(String s, ResolvableType resolvableType) throws NoSuchBeanDefinitionException {
+        return applicationContext.isTypeMatch(s, resolvableType);
+    }
+
+    @Override
+    public boolean isTypeMatch(String s, Class<?> aClass) throws NoSuchBeanDefinitionException {
+        return applicationContext.isTypeMatch(s, aClass);
+    }
+
+    @Override
+    public Class<?> getType(String s) throws NoSuchBeanDefinitionException {
+        return applicationContext.getType(s);
+    }
+
+    @Override
+    public Class<?> getType(String s, boolean b) throws NoSuchBeanDefinitionException {
+        return applicationContext.getType(s, b);
+    }
+
+    @Override
+    public String[] getAliases(String s) {
+        return applicationContext.getAliases(s);
+    }
+
+    @Override
+    public void publishEvent(Object event) {
+        applicationContext.publishEvent(event);
+    }
+
+    @Override
+    public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
+        return applicationContext.getMessage(code, args, defaultMessage, locale);
+    }
+
+    @Override
+    public String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException {
+        return applicationContext.getMessage(code, args, locale);
+    }
+
+    @Override
+    public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
+        return applicationContext.getMessage(resolvable, locale);
+    }
+
+    @Override
+    public Environment getEnvironment() {
+        return applicationContext.getEnvironment();
+    }
+
+    @Override
+    public Resource[] getResources(String locationPattern) throws IOException {
+        return applicationContext.getResources(locationPattern);
+    }
+
+    @Override
+    public Resource getResource(String location) {
+        return applicationContext.getResource(location);
+    }
+
+    @Override
+    public ClassLoader getClassLoader() {
+        return applicationContext.getClassLoader();
+    }
+}

+ 9 - 0
src/main/resources/application.yml

@@ -0,0 +1,9 @@
+server:
+  port: 8060
+
+prometheus-alert:
+  active-sms-service: cqxfSms # cqxfSms testSms
+  managers:
+    - 18580550924
+  cqxfSms:
+    url: http://183.66.101.45:8087/job/sendMsg

+ 21 - 0
src/test/java/com/cqxf/prometheus/alert/PrometheusSmsAlertApplicationTests.java

@@ -0,0 +1,21 @@
+package com.cqxf.prometheus.alert;
+
+import com.cqxf.prometheus.alert.service.MessageService;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import javax.annotation.Resource;
+
+@SpringBootTest
+class PrometheusSmsAlertApplicationTests {
+
+    @Resource(name = "cqxfSms")
+    private MessageService messageService;
+
+    @Test
+    void contextLoads() {
+        messageService.send("18580550924", "测试消息发送");
+    }
+
+}