[alerter] 工程初始化与告警定义相关接口

This commit is contained in:
tomsun28
2021-12-09 11:56:20 +08:00
parent 08bd342001
commit 29b3e23d02
12 changed files with 599 additions and 1 deletions

View File

@@ -15,4 +15,82 @@
</properties>
<dependencies>
<!-- common -->
<dependency>
<groupId>com.usthe.tancloud</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- spring -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- data jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<scope>provided</scope>
</dependency>
<!-- validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<scope>provided</scope>
</dependency>
<!-- influxdb -->
<dependency>
<groupId>com.influxdb</groupId>
<artifactId>influxdb-client-java</artifactId>
<version>3.4.0</version>
</dependency>
<!-- kafka -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>3.0.0</version>
</dependency>
<!--redis-->
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<scope>provided</scope>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<scope>provided</scope>
</dependency>
<!-- 表达式计算 -->
<dependency>
<groupId>com.googlecode.aviator</groupId>
<artifactId>aviator</artifactId>
<version>5.2.7</version>
</dependency>
<!-- feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.0.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -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<Message<Void>> 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<Message<Void>> 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<Message<AlertDefine>> getAlertDefine(
@ApiParam(value = "告警定义ID", example = "6565463543") @PathVariable("id") long id) {
// 获取监控信息
AlertDefine alertDefine = alertDefineService.getAlertDefine(id);
Message.MessageBuilder<AlertDefine> 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<Message<Void>> 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<Message<Void>> applyAlertDefineMonitorsBind(
@ApiParam(value = "告警定义ID", example = "6565463543") @PathVariable("alertId") long alertId,
@RequestBody Map<Long, String> monitorMap) {
alertDefineService.applyBindAlertDefineMonitors(alertId, monitorMap);
return ResponseEntity.ok(new Message<>("Apply success"));
}
}

View File

@@ -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<AlertDefineBind, Long>, JpaSpecificationExecutor<AlertDefineBind> {
/**
* 根据告警定义ID删除告警定义与监控关联
* @param alertDefineId 告警定义ID
*/
void deleteAlertDefineBindsByAlertDefineIdEquals(Long alertDefineId);
}

View File

@@ -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<AlertDefine, Long>, JpaSpecificationExecutor<AlertDefine> {
/**
* 根据ID列表删除告警定义
* @param alertDefineIds 告警定义ID列表
*/
void deleteAllByIdIn(Set<Long> alertDefineIds);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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<Long> alertIds) throws RuntimeException;
/**
* 动态条件查询
* @param specification 查询条件
* @param pageRequest 分页参数
* @return 查询结果
*/
Page<AlertDefine> getAlertDefines(Specification<AlertDefine> specification, PageRequest pageRequest);
/**
* 应用告警定于与监控关联关系
* @param alertId 告警定义ID
* @param monitorMap 监控ID-名称 MAP
*/
void applyBindAlertDefineMonitors(Long alertId, Map<Long, String> monitorMap);
}

View File

@@ -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<AlertDefine> optional = alertDefineDao.findById(alertId);
return optional.orElse(null);
}
@Override
public void deleteAlertDefines(Set<Long> alertIds) throws RuntimeException {
alertDefineDao.deleteAllByIdIn(alertIds);
}
@Override
public Page<AlertDefine> getAlertDefines(Specification<AlertDefine> specification, PageRequest pageRequest) {
return alertDefineDao.findAll(specification, pageRequest);
}
@Override
public void applyBindAlertDefineMonitors(Long alertId, Map<Long, String> monitorMap) {
// todo 校验此告警定义和监控是否存在
// 先删除此告警的所有关联
alertDefineBindDao.deleteAlertDefineBindsByAlertDefineIdEquals(alertId);
// 保存关联
List<AlertDefineBind> alertDefineBinds = monitorMap.entrySet().stream().map(entry ->
AlertDefineBind.builder().alertDefineId(alertId).monitorId(entry.getKey())
.monitorName(entry.getValue()).build())
.collect(Collectors.toList());
alertDefineBindDao.saveAll(alertDefineBinds);
}
}

View File

@@ -0,0 +1,3 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.usthe.alert.service.impl.AlertDefineServiceImpl,\
com.usthe.alert.controller.AlertDefineController

View File

@@ -36,6 +36,12 @@
<artifactId>warehouse</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- alerter -->
<dependency>
<groupId>com.usthe.tancloud</groupId>
<artifactId>alerter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- spring -->
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -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) {

View File

@@ -62,3 +62,47 @@ CREATE TABLE param_define
primary key (id),
unique key unique_param_define (app, field)
) 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;