diff --git a/alerter/pom.xml b/alerter/pom.xml index 1c6b56b..f216a80 100644 --- a/alerter/pom.xml +++ b/alerter/pom.xml @@ -15,4 +15,82 @@ + + + + com.usthe.tancloud + common + 1.0-SNAPSHOT + + + + org.springframework.boot + spring-boot-starter-web + provided + + + org.springframework.boot + spring-boot-autoconfigure + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + org.springframework.boot + spring-boot-starter-jdbc + provided + + + org.springframework.boot + spring-boot-starter-data-jpa + provided + + + + org.springframework.boot + spring-boot-starter-validation + provided + + + + com.influxdb + influxdb-client-java + 3.4.0 + + + + org.apache.kafka + kafka-clients + 3.0.0 + + + + io.lettuce + lettuce-core + provided + + + + io.springfox + springfox-boot-starter + provided + + + + com.googlecode.aviator + aviator + 5.2.7 + + + + org.springframework.cloud + spring-cloud-starter-openfeign + 3.0.5 + provided + + + \ No newline at end of file diff --git a/alerter/src/main/java/com/usthe/alert/controller/AlertDefineController.java b/alerter/src/main/java/com/usthe/alert/controller/AlertDefineController.java new file mode 100644 index 0000000..7f613ae --- /dev/null +++ b/alerter/src/main/java/com/usthe/alert/controller/AlertDefineController.java @@ -0,0 +1,91 @@ +package com.usthe.alert.controller; + +import com.usthe.alert.pojo.entity.AlertDefine; +import com.usthe.alert.service.AlertDefineService; +import com.usthe.common.entity.dto.Message; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +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.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +import java.util.Map; + +import static com.usthe.common.util.CommonConstants.MONITOR_NOT_EXIST; +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +/** + * 告警定义管理API + * @author tom + * @date 2021/12/9 10:32 + */ +@Api(tags = "告警定义管理API") +@RestController +@RequestMapping(path = "/alert/define", produces = {APPLICATION_JSON_VALUE}) +public class AlertDefineController { + + @Autowired + private AlertDefineService alertDefineService; + + @PostMapping + @ApiOperation(value = "新增告警定义", notes = "新增一个告警定义") + public ResponseEntity> addNewAlertDefine(@Valid @RequestBody AlertDefine alertDefine) { + // 校验请求数据 + alertDefineService.validate(alertDefine, false); + alertDefineService.addAlertDefine(alertDefine); + return ResponseEntity.ok(new Message<>("Add success")); + } + + @PutMapping + @ApiOperation(value = "修改告警定义", notes = "修改一个已存在告警定义") + public ResponseEntity> modifyAlertDefine(@Valid @RequestBody AlertDefine alertDefine) { + // 校验请求数据 + alertDefineService.validate(alertDefine, true); + alertDefineService.modifyAlertDefine(alertDefine); + return ResponseEntity.ok(new Message<>("Modify success")); + } + + @GetMapping(path = "/{id}") + @ApiOperation(value = "查询告警定义", notes = "根据告警定义ID获取告警定义信息") + public ResponseEntity> getAlertDefine( + @ApiParam(value = "告警定义ID", example = "6565463543") @PathVariable("id") long id) { + // 获取监控信息 + AlertDefine alertDefine = alertDefineService.getAlertDefine(id); + Message.MessageBuilder messageBuilder = Message.builder(); + if (alertDefine == null) { + messageBuilder.code(MONITOR_NOT_EXIST).msg("AlertDefine not exist."); + } else { + messageBuilder.data(alertDefine); + } + return ResponseEntity.ok(messageBuilder.build()); + } + + @DeleteMapping(path = "/{id}") + @ApiOperation(value = "删除告警定义", notes = "根据告警定义ID删除告警定义,告警定义不存在也是删除成功") + public ResponseEntity> deleteAlertDefine( + @ApiParam(value = "告警定义ID", example = "6565463543") @PathVariable("id") long id) { + // 删除告警定义不存在或删除成功都返回成功 + alertDefineService.deleteAlertDefine(id); + return ResponseEntity.ok(new Message<>("Delete success")); + } + + @PostMapping(path = "/{alertId}/monitors") + @ApiOperation(value = "应用告警定义与监控关联", notes = "应用指定告警定义与监控关联关系") + public ResponseEntity> applyAlertDefineMonitorsBind( + @ApiParam(value = "告警定义ID", example = "6565463543") @PathVariable("alertId") long alertId, + @RequestBody Map monitorMap) { + alertDefineService.applyBindAlertDefineMonitors(alertId, monitorMap); + return ResponseEntity.ok(new Message<>("Apply success")); + } + +} diff --git a/alerter/src/main/java/com/usthe/alert/dao/AlertDefineBindDao.java b/alerter/src/main/java/com/usthe/alert/dao/AlertDefineBindDao.java new file mode 100644 index 0000000..95c5df4 --- /dev/null +++ b/alerter/src/main/java/com/usthe/alert/dao/AlertDefineBindDao.java @@ -0,0 +1,19 @@ +package com.usthe.alert.dao; + +import com.usthe.alert.pojo.entity.AlertDefineBind; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +/** + * AlertDefineBind 数据库操作 + * @author tom + * @date 2021/12/9 10:03 + */ +public interface AlertDefineBindDao extends JpaRepository, JpaSpecificationExecutor { + + /** + * 根据告警定义ID删除告警定义与监控关联 + * @param alertDefineId 告警定义ID + */ + void deleteAlertDefineBindsByAlertDefineIdEquals(Long alertDefineId); +} diff --git a/alerter/src/main/java/com/usthe/alert/dao/AlertDefineDao.java b/alerter/src/main/java/com/usthe/alert/dao/AlertDefineDao.java new file mode 100644 index 0000000..9b20ff5 --- /dev/null +++ b/alerter/src/main/java/com/usthe/alert/dao/AlertDefineDao.java @@ -0,0 +1,21 @@ +package com.usthe.alert.dao; + +import com.usthe.alert.pojo.entity.AlertDefine; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +import java.util.Set; + +/** + * AlertDefine 数据库操作 + * @author tom + * @date 2021/12/9 10:03 + */ +public interface AlertDefineDao extends JpaRepository, JpaSpecificationExecutor { + + /** + * 根据ID列表删除告警定义 + * @param alertDefineIds 告警定义ID列表 + */ + void deleteAllByIdIn(Set alertDefineIds); +} diff --git a/alerter/src/main/java/com/usthe/alert/pojo/entity/AlertDefine.java b/alerter/src/main/java/com/usthe/alert/pojo/entity/AlertDefine.java new file mode 100644 index 0000000..8a6f3ac --- /dev/null +++ b/alerter/src/main/java/com/usthe/alert/pojo/entity/AlertDefine.java @@ -0,0 +1,111 @@ +package com.usthe.alert.pojo.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; + +import java.time.LocalDateTime; + +import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_ONLY; +import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_WRITE; + +/** + * 告警定义实体 + * @author tom + * @date 2021/12/8 20:41 + */ +@Entity +@Table(name = "alert_define") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(description = "告警定义实体") +public class AlertDefine { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @ApiModelProperty(value = "告警定义实体主键索引ID", example = "87584674384", accessMode = READ_ONLY, position = 0) + private Long id; + + @ApiModelProperty(value = "配置告警的监控类型", example = "linux", accessMode = READ_WRITE, position = 1) + @Length(max = 100) + private String app; + + @ApiModelProperty(value = "配置告警的指标集合", example = "cpu", accessMode = READ_WRITE, position = 2) + @Length(max = 100) + private String metric; + + @ApiModelProperty(value = "配置告警的指标", example = "usage", accessMode = READ_WRITE, position = 3) + @Length(max = 100) + private String field; + + @ApiModelProperty(value = "是否是默认预置告警", example = "false", accessMode = READ_WRITE, position = 4) + private boolean preset; + + @ApiModelProperty(value = "告警触发条件表达式", example = "usage>90", accessMode = READ_WRITE, position = 5) + @Length(max = 1024) + private String expr; + + @ApiModelProperty(value = "告警级别 0:高-emergency-紧急告警-红色 1:中-critical-严重告警-橙色 2:低-warning-警告告警-黄色", + example = "1", accessMode = READ_WRITE, position = 6) + @Min(0) + @Max(2) + private byte priority; + + @ApiModelProperty(value = "触发告警后持续时间,单位s", example = "60", accessMode = READ_WRITE, position = 7) + @Min(0) + private int duration; + + @ApiModelProperty(value = "告警触发后是否发送", example = "true", accessMode = READ_WRITE, position = 8) + private boolean enable = true; + + @ApiModelProperty(value = "告警延迟时间,即延迟多久再发送告警,单位s", example = "300", accessMode = READ_WRITE, position = 9) + @Min(0) + private int delay; + + @ApiModelProperty(value = "告警通知内容", example = "linux {monitor_name}: {monitor_id} cpu usage high", + accessMode = READ_WRITE, position = 10) + @Length(max = 1024) + private String content; + + /** + * 此条记录创建者 + */ + @ApiModelProperty(value = "此条记录创建者", example = "tom", accessMode = READ_ONLY, position = 11) + private String creator; + + /** + * 此条记录最新修改者 + */ + @ApiModelProperty(value = "此条记录最新修改者", example = "tom", accessMode = READ_ONLY, position = 12) + private String modifier; + + /** + * 记录创建时间 + */ + @ApiModelProperty(value = "记录创建时间(毫秒时间戳)", example = "1612198922000", accessMode = READ_ONLY, position = 13) + @Column(insertable = false, updatable = false) + private LocalDateTime gmtCreate; + + /** + * 记录最新修改时间 + */ + @ApiModelProperty(value = "记录最新修改时间(毫秒时间戳)", example = "1612198444000", accessMode = READ_ONLY, position = 14) + @Column(insertable = false, updatable = false) + private LocalDateTime gmtUpdate; + +} diff --git a/alerter/src/main/java/com/usthe/alert/pojo/entity/AlertDefineBind.java b/alerter/src/main/java/com/usthe/alert/pojo/entity/AlertDefineBind.java new file mode 100644 index 0000000..30c27bf --- /dev/null +++ b/alerter/src/main/java/com/usthe/alert/pojo/entity/AlertDefineBind.java @@ -0,0 +1,57 @@ +package com.usthe.alert.pojo.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.LocalDateTime; + +import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_ONLY; +import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_WRITE; + +/** + * 告警定义与监控关联实体 + * @author tom + * @date 2021/12/8 20:41 + */ +@Entity +@Table(name = "alert_define_monitor_bind") +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@ApiModel(description = "告警定义与监控关联实体") +public class AlertDefineBind { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @ApiModelProperty(value = "告警定义与监控关联主键索引ID", example = "74384", accessMode = READ_ONLY, position = 0) + private Long id; + + @ApiModelProperty(value = "告警定义ID", example = "87432674384", accessMode = READ_WRITE, position = 1) + private Long alertDefineId; + + @ApiModelProperty(value = "监控ID", example = "87432674336", accessMode = READ_WRITE, position = 2) + private Long monitorId; + + @ApiModelProperty(value = "监控名称", example = "Linux_192.123.23.1", accessMode = READ_WRITE, position = 3) + private String monitorName; + + @ApiModelProperty(value = "记录创建时间(毫秒时间戳)", example = "1612198922000", accessMode = READ_ONLY, position = 4) + @Column(insertable = false, updatable = false) + private LocalDateTime gmtCreate; + + @ApiModelProperty(value = "记录最新修改时间(毫秒时间戳)", example = "1612198444000", accessMode = READ_ONLY, position = 5) + @Column(insertable = false, updatable = false) + private LocalDateTime gmtUpdate; + +} diff --git a/alerter/src/main/java/com/usthe/alert/service/AlertDefineService.java b/alerter/src/main/java/com/usthe/alert/service/AlertDefineService.java new file mode 100644 index 0000000..0ac6fab --- /dev/null +++ b/alerter/src/main/java/com/usthe/alert/service/AlertDefineService.java @@ -0,0 +1,77 @@ +package com.usthe.alert.service; + +import com.usthe.alert.pojo.entity.AlertDefine; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.jpa.domain.Specification; + +import java.util.Map; +import java.util.Set; + +/** + * 告警定义管理接口 + * @author tom + * @date 2021/12/9 10:06 + */ +public interface AlertDefineService { + + /** + * 校验请求数据参数正确性 + * @param alertDefine alertDefine + * @param isModify 是否是修改配置 + * @throws IllegalArgumentException 校验参数错误抛出 + */ + void validate(AlertDefine alertDefine, boolean isModify) throws IllegalArgumentException; + + /** + * 新增告警定义 + * @param alertDefine 告警定义实体 + * @throws RuntimeException 新增过程异常抛出 + */ + void addAlertDefine(AlertDefine alertDefine) throws RuntimeException; + + /** + * 修改告警定义 + * @param alertDefine 告警定义实体 + * @throws RuntimeException 修改过程中异常抛出 + */ + void modifyAlertDefine(AlertDefine alertDefine) throws RuntimeException; + + /** + * 删除告警定义 + * @param alertId 告警定义ID + * @throws RuntimeException 删除过程中异常抛出 + */ + void deleteAlertDefine(long alertId) throws RuntimeException; + + /** + * 获取告警定义信息 + * @param alertId 监控ID + * @return AlertDefine + * @throws RuntimeException 查询过程中异常抛出 + */ + AlertDefine getAlertDefine(long alertId) throws RuntimeException; + + + /** + * 批量删除告警定义 + * @param alertIds 告警定义IDs + * @throws RuntimeException 删除过程中异常抛出 + */ + void deleteAlertDefines(Set alertIds) throws RuntimeException; + + /** + * 动态条件查询 + * @param specification 查询条件 + * @param pageRequest 分页参数 + * @return 查询结果 + */ + Page getAlertDefines(Specification specification, PageRequest pageRequest); + + /** + * 应用告警定于与监控关联关系 + * @param alertId 告警定义ID + * @param monitorMap 监控ID-名称 MAP + */ + void applyBindAlertDefineMonitors(Long alertId, Map monitorMap); +} diff --git a/alerter/src/main/java/com/usthe/alert/service/impl/AlertDefineServiceImpl.java b/alerter/src/main/java/com/usthe/alert/service/impl/AlertDefineServiceImpl.java new file mode 100644 index 0000000..20d4cce --- /dev/null +++ b/alerter/src/main/java/com/usthe/alert/service/impl/AlertDefineServiceImpl.java @@ -0,0 +1,87 @@ +package com.usthe.alert.service.impl; + +import com.usthe.alert.dao.AlertDefineBindDao; +import com.usthe.alert.dao.AlertDefineDao; +import com.usthe.alert.pojo.entity.AlertDefine; +import com.usthe.alert.pojo.entity.AlertDefineBind; +import com.usthe.alert.service.AlertDefineService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * 告警定义管理接口实现 + * @author tom + * @date 2021/12/9 10:17 + */ +@Service +@Transactional(rollbackFor = Exception.class) +@Slf4j +public class AlertDefineServiceImpl implements AlertDefineService { + + @Autowired + private AlertDefineDao alertDefineDao; + + @Autowired + private AlertDefineBindDao alertDefineBindDao; + + @Override + public void validate(AlertDefine alertDefine, boolean isModify) throws IllegalArgumentException { + // todo + } + + @Override + public void addAlertDefine(AlertDefine alertDefine) throws RuntimeException { + alertDefineDao.save(alertDefine); + } + + @Override + public void modifyAlertDefine(AlertDefine alertDefine) throws RuntimeException { + alertDefineDao.save(alertDefine); + } + + @Override + public void deleteAlertDefine(long alertId) throws RuntimeException { + alertDefineDao.deleteById(alertId); + } + + @Override + public AlertDefine getAlertDefine(long alertId) throws RuntimeException { + Optional optional = alertDefineDao.findById(alertId); + return optional.orElse(null); + } + + @Override + public void deleteAlertDefines(Set alertIds) throws RuntimeException { + alertDefineDao.deleteAllByIdIn(alertIds); + } + + @Override + public Page getAlertDefines(Specification specification, PageRequest pageRequest) { + return alertDefineDao.findAll(specification, pageRequest); + } + + @Override + public void applyBindAlertDefineMonitors(Long alertId, Map monitorMap) { + // todo 校验此告警定义和监控是否存在 + + // 先删除此告警的所有关联 + alertDefineBindDao.deleteAlertDefineBindsByAlertDefineIdEquals(alertId); + // 保存关联 + List alertDefineBinds = monitorMap.entrySet().stream().map(entry -> + AlertDefineBind.builder().alertDefineId(alertId).monitorId(entry.getKey()) + .monitorName(entry.getValue()).build()) + .collect(Collectors.toList()); + alertDefineBindDao.saveAll(alertDefineBinds); + } +} diff --git a/alerter/src/main/resources/META-INF/spring.factories b/alerter/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..750462c --- /dev/null +++ b/alerter/src/main/resources/META-INF/spring.factories @@ -0,0 +1,3 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +com.usthe.alert.service.impl.AlertDefineServiceImpl,\ +com.usthe.alert.controller.AlertDefineController \ No newline at end of file diff --git a/manager/pom.xml b/manager/pom.xml index 0a1024d..6578dc0 100644 --- a/manager/pom.xml +++ b/manager/pom.xml @@ -36,6 +36,12 @@ warehouse 1.0-SNAPSHOT + + + com.usthe.tancloud + alerter + 1.0-SNAPSHOT + org.springframework.boot diff --git a/manager/src/main/java/com/usthe/manager/Manager.java b/manager/src/main/java/com/usthe/manager/Manager.java index 79e9b91..76da45b 100644 --- a/manager/src/main/java/com/usthe/manager/Manager.java +++ b/manager/src/main/java/com/usthe/manager/Manager.java @@ -2,7 +2,9 @@ package com.usthe.manager; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; /** * @author tomsun28 @@ -11,6 +13,8 @@ import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableFeignClients(basePackages = {"com.usthe"}) +@EnableJpaRepositories(basePackages = {"com.usthe"}) +@EntityScan(basePackages = {"com.usthe"}) public class Manager { public static void main(String[] args) { diff --git a/manager/src/main/resources/db/schema.sql b/manager/src/main/resources/db/schema.sql index 232b715..4ce10f2 100644 --- a/manager/src/main/resources/db/schema.sql +++ b/manager/src/main/resources/db/schema.sql @@ -61,4 +61,48 @@ CREATE TABLE param_define gmt_update datetime default current_timestamp on update current_timestamp comment 'update time', primary key (id), unique key unique_param_define (app, field) -) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file +) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; + + +-- ---------------------------- +-- Table structure for alert_define +-- ---------------------------- +DROP TABLE IF EXISTS alert_define ; +CREATE TABLE alert_define +( + id bigint not null auto_increment comment '告警定义ID', + app varchar(100) not null comment '配置告警的监控类型:linux,mysql,jvm...', + metric varchar(100) not null comment '配置告警的指标集合:cpu,memory,info...', + field varchar(100) not null comment '配置告警的指标:usage,cores...', + preset boolean not null default false comment '是否是默认预置告警,是则新增监控默认关联此告警', + expr varchar(255) not null comment '告警触发条件表达式', + priority tinyint not null default 0 comment '告警级别 0:高-emergency-紧急告警-红色 1:中-critical-严重告警-橙色 2:低-warning-警告告警-黄色', + duration int not null comment '触发告警后持续时间,单位s', + enable boolean not null default true comment '告警触发后是否发送', + delay int not null comment '告警延迟时间,即延迟多久再发送告警,单位s', + content varchar(255) not null comment '告警通知内容', + creator varchar(100) comment '创建者', + modifier varchar(100) comment '最新修改者', + gmt_create timestamp default current_timestamp comment 'create time', + gmt_update datetime default current_timestamp on update current_timestamp comment 'update time', + primary key (id) +) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; + +-- ---------------------------- +-- Table structure for alert_define_monitor_bind +-- ---------------------------- +DROP TABLE IF EXISTS alert_define_monitor_bind ; +CREATE TABLE alert_define_monitor_bind +( + id bigint not null auto_increment comment '告警定义与监控关联ID', + alert_define_id bigint not null comment '告警定义ID', + monitor_id bigint not null comment '监控ID', + monitor_name varchar(100) not null comment '监控的名称(拢余字段方便展示)', + gmt_create timestamp default current_timestamp comment 'create time', + gmt_update datetime default current_timestamp on update current_timestamp comment 'update time', + primary key (id), + unique key unique_bind (alert_define_id, monitor_id) +) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; + + +COMMIT; \ No newline at end of file