feat:Email&Database Status Monitor

This commit is contained in:
nieziyan 2023-11-22 18:26:57 +08:00
parent 0de89da6f6
commit 3377c6ba7b
21 changed files with 400 additions and 202 deletions

View File

@ -1,9 +0,0 @@
package org.jeecg.common.constant;
/**
* 邮件服务常量
*/
public class EmailConstant {
public static final String EMAIL_STATUS_PREFIX = "email_status";
}

View File

@ -26,4 +26,10 @@ public interface RedisConstant {
String CONSUMER_ANALYSIS = "Consumer_Analysis";
String NUCLIDE_LINES_LIB = "Nuclide_Lines_Lib:";
String PREFIX_STATUS = "Status:";
String DATABASE_STATUS = "Database_Status";
String EMAIL_STATUS = "Email_Status";
}

View File

@ -0,0 +1,22 @@
package org.jeecg.common.util;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
@Slf4j
public class EmailUtil {
public static boolean isConnection(String address, Integer port){
try(Socket socket = new Socket()){
InetSocketAddress socketAddress = new InetSocketAddress(address, port);
socket.connect(socketAddress,5000);
return true;
}catch (IOException e){
log.error("EmailUtil.isConnection():邮箱服务[{}]连接失败: {}", address, e.getMessage());
return false;
}
}
}

View File

@ -1,16 +1,13 @@
package org.jeecg.common.util;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.base.entity.postgre.SysDatabase;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
import java.io.FileReader;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.sql.*;
import java.util.Properties;
@Slf4j
public class JDBCUtil {
@ -24,7 +21,7 @@ public class JDBCUtil {
return new JdbcTemplate(dataSource);
}
public static boolean testConnection(String url, String driver, String user, String pass){
public static boolean isConnection(String url, String driver, String user, String pass){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(url);
dataSource.setDriverClassName(driver);
@ -34,16 +31,8 @@ public class JDBCUtil {
try (Connection connection = dataSource.getConnection()) {
return true;
} catch (SQLException e) {
log.error("JDBCUtil.testConnection(): 数据源["+ url +"]连接异常,原因: {}",e.getMessage());
log.error("JDBCUtil.isConnection():数据源["+ url +"]连接失败: {}", e.getMessage());
return false;
}
}
public static boolean testConnection(SysDatabase database){
String dbUrl = database.getDbUrl();
String dbDriver = database.getDbDriver();
String dbUsername = database.getDbUsername();
String dbPassword = database.getDbPassword();
return testConnection(dbUrl, dbDriver, dbUsername, dbPassword);
}
}

View File

@ -161,11 +161,7 @@ public class RedisStreamUtil {
return redisTemplate.opsForStream().delete(streamKey, recordIds);
}
/**
* 根据记录id删除n个消息记录
*
* @param streamKey
*/
public boolean del(String streamKey){
return redisTemplate.delete(streamKey);
}

View File

@ -28,6 +28,5 @@ public class ItemDto implements Serializable{
this.itemId = alarmItemDe.getId();
this.name = alarmItemDe.getName();
this.units = alarmItemDe.getUnits();
this.valueType = alarmItemDe.getValueType();
}
}

View File

@ -30,9 +30,6 @@ public class AlarmItemDe {
@TableField("source_type")
private String sourceType;
@TableField("value_type")
private String valueType;
/**
* 创建人
*/

View File

@ -27,12 +27,6 @@ public class SysDatabase implements Serializable {
@TableField(value = "name")
private String name;
/**
* 状态0-断开连接1-连接成功
*/
@TableField(value = "status")
private Integer status;
/**
* 用户名称
*/
@ -87,5 +81,4 @@ public class SysDatabase implements Serializable {
*/
@TableField(value = "update_by")
private String updateBy;
}

View File

@ -0,0 +1,56 @@
package org.jeecg.modules;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.RedisConstant;
import org.jeecg.common.util.JDBCUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.modules.base.entity.postgre.SysDatabase;
import org.jeecg.modules.service.ISysDatabaseService;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Component
@Slf4j
public class DatabaseStatusManager {
public void start() {
DbStatusThread dbStatusThread = new DbStatusThread();
dbStatusThread.start();
}
private static class DbStatusThread extends Thread{
private long sleepTime;
private RedisUtil redisUtil;
private ISysDatabaseService databaseService;
private DbStatusThread(){
init();
}
@Override
public void run() {
while (true){
try {
databaseService.status2Redis();
TimeUnit.MILLISECONDS.sleep(sleepTime);
} catch (Exception e) {
log.error("DatabaseStatusManager.run()异常: {}", e.getMessage());
}
}
}
private void init(){
sleepTime = 30 * 60 * 1000; // 睡眠时间30min
redisUtil = SpringContextUtils.getBean(RedisUtil.class);
databaseService = SpringContextUtils.getBean(ISysDatabaseService.class);
}
}
}

View File

@ -0,0 +1,56 @@
package org.jeecg.modules;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.RedisConstant;
import org.jeecg.common.util.EmailUtil;
import org.jeecg.common.util.JDBCUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.modules.base.entity.postgre.SysDatabase;
import org.jeecg.modules.base.entity.postgre.SysEmail;
import org.jeecg.modules.service.ISysDatabaseService;
import org.jeecg.modules.service.ISysEmailService;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Component
@Slf4j
public class EmailStatusManager {
public void start() {
EmailStatusThread emailStatusThread = new EmailStatusThread();
emailStatusThread.start();
}
private static class EmailStatusThread extends Thread{
private long sleepTime;
private ISysEmailService emailService;
private EmailStatusThread(){
init();
}
@Override
public void run() {
while (true){
try {
emailService.status2Redis();
TimeUnit.MILLISECONDS.sleep(sleepTime);
} catch (Exception e) {
log.error("EmailStatusManager.run()异常: {}", e.getMessage());
}
}
}
private void init(){
sleepTime = 30 * 60 * 1000; // 睡眠时间30min
emailService = SpringContextUtils.getBean(ISysEmailService.class);
}
}
}

View File

@ -1,14 +1,11 @@
package org.jeecg.modules.controller;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.EmailConstant;
import org.jeecg.common.constant.RedisConstant;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.qiyeEmail.base.RParam;
import org.jeecg.modules.qiyeEmail.base.dto.AccountInfo;
import org.jeecg.modules.qiyeEmail.service.Account;
import org.jeecg.modules.service.ISysEmailLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@ -23,18 +20,21 @@ import java.util.Map;
@RequestMapping("sysEmailLog")
@Api(value = "邮箱日志服务", tags = "邮箱日志服务")
public class SysEmailLogController {
@Autowired
private ISysEmailLogService sysEmailLogService;
@Autowired
private RedisUtil redisUtil;
@Autowired
private ISysEmailLogService sysEmailLogService;
@GetMapping("status")
@ApiOperation("邮箱服务器状态")
public Result<?> status(@RequestParam("emailId") String emailId){
String key = EmailConstant.EMAIL_STATUS_PREFIX;
Boolean emailSatus = (Boolean) redisUtil.hget(key, emailId);
return Result.OK(emailSatus == null ? false : emailSatus);
String prefixStatus = RedisConstant.PREFIX_STATUS;
String emailStatus = RedisConstant.EMAIL_STATUS;
String statusKey = prefixStatus + emailStatus;
Boolean emailSatus = (Boolean) redisUtil.hget(statusKey, emailId);
return Result.OK(ObjectUtil.isNotNull(emailSatus) && emailSatus);
}
@GetMapping("space")

View File

@ -15,20 +15,4 @@ public interface SysDatabaseMapper extends BaseMapper<SysDatabase> {
List<AlarmHistory> findAlarmHistory(Map<String,Object> params);
List<DatabaseDto> findPage(Map<String,Object> params);
List<String> dbNamesPG();
List<String> dbNamesMY();
List<String> dbNamesOR();
List<DBInfo> dbInfoOR(@Param("owner") String dataBase);
List<DBInfo> dbIndexOR(@Param("owner") String dataBase);
List<DBInfo> dbInfoPG();
List<DBInfo> dbRowNumPG();
List<DBInfo> dbInfoMY(@Param("owner") String dataBase);
}

View File

@ -13,17 +13,17 @@ import java.util.List;
public interface ISysDatabaseService extends IService<SysDatabase> {
Result findPage(QueryRequest query);
Result<?> findPage(QueryRequest query);
Result<?> findInfo(String id);
Result create(SysDatabase sysDatabase);
Result<?> create(SysDatabase sysDatabase);
Result update(SysDatabase sysDatabase);
Result<?> update(SysDatabase sysDatabase);
Result deleteById(String id);
Result<?> deleteById(String id);
Result findAlarmHistory(SourceVo sourceVo);
Result<?> findAlarmHistory(SourceVo sourceVo);
List<SourceDto> listAll();
@ -32,4 +32,6 @@ public interface ISysDatabaseService extends IService<SysDatabase> {
List<DBInfo> dbInfo(String id, String dbName);
List<SpaceInfo> spaceInfo(String id);
void status2Redis();
}

View File

@ -13,17 +13,19 @@ public interface ISysEmailService extends IService<SysEmail> {
Result<?> findPage(QueryRequest query);
Result findInfo(String id);
Result<?> findInfo(String id);
Result create(SysEmail sysEmail);
Result<?> create(SysEmail sysEmail);
Result update(SysEmail sysEmail);
Result<?> update(SysEmail sysEmail);
Result deleteById(String id);
Result<?> deleteById(String id);
Result findAlarmHistory(SourceVo sourceVo);
Result<?> findAlarmHistory(SourceVo sourceVo);
Result<SysEmail> getSender();
List<SourceDto> listAll();
void status2Redis();
}

View File

@ -1,6 +1,8 @@
package org.jeecg.modules.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -27,10 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import static org.jeecg.modules.base.enums.SourceType.*;
@ -156,6 +155,12 @@ public class AlarmRuleServiceImpl extends ServiceImpl<AlarmRuleMapper, AlarmRule
public void rule2Redis(){
String colon = SymbolConstant.COLON;
String prefixRule = RedisConstant.PREFIX_RULE;
// 收集所有待删除的key
List<String> keys = new ArrayList<>();
keys.addAll(redisStreamUtil.keys(prefixRule + DATABASE.getType()));
keys.addAll(redisStreamUtil.keys(prefixRule + EMAIL.getType()));
keys.addAll(redisStreamUtil.keys(prefixRule + SERVER.getType()));
LambdaQueryWrapper<AlarmRule> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(AlarmRule::getEnabled,1);
List<AlarmRule> alarmRules = this.list(wrapper);
@ -166,6 +171,9 @@ public class AlarmRuleServiceImpl extends ServiceImpl<AlarmRuleMapper, AlarmRule
String ruleKey = prefixRule + sourceType + colon + ruleId;
ruleMap.put(ruleKey,alarmRule);
}
// 删除旧规则
redisUtil.del(ArrayUtil.toArray(keys, String.class));
// 添加修改后的规则
redisStreamUtil.setRules(ruleMap);
}
}

View File

@ -15,6 +15,7 @@ import org.jeecg.common.constant.*;
import org.jeecg.common.constant.enums.DbType;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.util.JDBCUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.config.mybatis.DSSwitcher;
import org.jeecg.modules.base.dto.DBInfo;
import org.jeecg.modules.base.dto.DatabaseDto;
@ -44,11 +45,14 @@ import static org.jeecg.common.constant.enums.DbType.*;
@Service("sysDatabaseService")
public class SysDatabaseServiceImpl extends ServiceImpl<SysDatabaseMapper, SysDatabase> implements ISysDatabaseService {
@Autowired
private RedisUtil redisUtil;
@Autowired
private SystemClient systemClient;
@Override
public Result findPage(QueryRequest query) {
public Result<?> findPage(QueryRequest query) {
Integer pageNo = query.getPageNo();
Integer pageSize = query.getPageSize();
Integer pageStart = (pageNo - 1) * pageSize;
@ -64,13 +68,22 @@ public class SysDatabaseServiceImpl extends ServiceImpl<SysDatabaseMapper, SysDa
params.put("endDate",endDate);
List<DatabaseDto> databaseDtos = baseMapper.findPage(params);
List<DictModel> items = systemClient.getItems(DictConstant.DATASOURCE_TYPE);
// 数据库类型Map key:类型值 value:类型名称
Map<String, String> dataSourceMap = items.stream().collect(Collectors
.toMap(DictModel::getValue, DictModel::getText, (oldValue, newValue) -> newValue));
// 数据库连接状态Map key:id value:状态值(true|false)
String prefixStatus = RedisConstant.PREFIX_STATUS;
String databaseStatus = RedisConstant.DATABASE_STATUS;
String statusKey = prefixStatus + databaseStatus;
Map<Object, Object> statusMap = redisUtil.hmget(statusKey);
for (DatabaseDto databaseDto : databaseDtos) {
String id = databaseDto.getId();
String type = databaseDto.getType();
Boolean online = (Boolean) statusMap.get(id);
if (ObjectUtil.isNull(online)) online = false;
String dataBaseType = dataSourceMap.get(type);
databaseDto.setDataBaseType(dataBaseType)
.setOnline(true).setSlowQuery("328/s")
.setOnline(online).setSlowQuery("328/s")
.setAlarmRed(true).setCpuUutilzation("35.8%")
.setMemoryUsage("55.8%").setDiskUsage("35.68%");
}
@ -83,17 +96,10 @@ public class SysDatabaseServiceImpl extends ServiceImpl<SysDatabaseMapper, SysDa
@Override
public Result<?> findInfo(String id) {
Result result = new Result();
LambdaQueryWrapper<SysDatabase> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysDatabase::getId, id);
SysDatabase database = this.baseMapper.selectOne(queryWrapper);
if (Objects.isNull(database)){
result.error500("当前数据不存在");
return result;
}
result.setSuccess(true);
result.setResult(database);
return result;
SysDatabase sysDatabase = getById(id);
if (ObjectUtil.isNull(sysDatabase))
return Result.error(Prompt.DATA_NOT_EXITS);
return Result.OK(sysDatabase);
}
@Override
@ -103,50 +109,40 @@ public class SysDatabaseServiceImpl extends ServiceImpl<SysDatabaseMapper, SysDa
LambdaQueryWrapper<SysDatabase> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SysDatabase::getName,name);
if (CollUtil.isNotEmpty(list(wrapper)))
return Result.error("Name"+Prompt.NOT_REPEAT);
return Result.error("Name" + Prompt.NOT_REPEAT);
// 截取dbName并保存
String dbType = sysDatabase.getDbType();
String dbUrl = sysDatabase.getDbUrl();
DbType dbTypeE = typeOf(dbType);
switch (dbTypeE){
case POSTGRESQL:
sysDatabase.setDbName(bias(dbUrl));
break;
case ORACLE:
sysDatabase.setDbName(colon(dbUrl));
break;
case MYSQL55:
sysDatabase.setDbName(bias(dbUrl));
break;
case MYSQL57:
sysDatabase.setDbName(bias(dbUrl));
break;
default:
break;
if (ObjectUtil.isNotNull(dbTypeE)){
switch (dbTypeE){
case POSTGRESQL:
sysDatabase.setDbName(bias(dbUrl));
break;
case ORACLE:
sysDatabase.setDbName(colon(dbUrl));
break;
case MYSQL55:
sysDatabase.setDbName(bias(dbUrl));
break;
case MYSQL57:
sysDatabase.setDbName(bias(dbUrl));
break;
default:
break;
}
}
int count = baseMapper.insert(sysDatabase);
if (count == 1)
boolean success = save(sysDatabase);
if (success){
status2Redis();
return Result.OK(Prompt.ADD_SUCC);
}
return Result.error(Prompt.ADD_ERR);
}
private String colon(String url){
if (StrUtil.isBlank(url))
return null;
String regex = ".*:(.*)";
return ReUtil.getGroup1(regex, url);
}
private String bias(String url){
if (StrUtil.isBlank(url))
return null;
String regex = "/([^/?]+)\\?";
return ReUtil.getGroup1(regex, url);
}
@Override
@Transactional
public Result update(SysDatabase sysDatabase) {
public Result<?> update(SysDatabase sysDatabase) {
SysDatabase database = getById(sysDatabase.getId());
if (ObjectUtil.isNull(database))
return Result.error(Prompt.DATA_NOT_EXITS);
@ -161,40 +157,45 @@ public class SysDatabaseServiceImpl extends ServiceImpl<SysDatabaseMapper, SysDa
String dbType = sysDatabase.getDbType();
String dbUrl = sysDatabase.getDbUrl();
DbType dbTypeE = typeOf(dbType);
switch (dbTypeE){
case POSTGRESQL:
sysDatabase.setDbName(bias(dbUrl));
break;
case ORACLE:
sysDatabase.setDbName(colon(dbUrl));
break;
case MYSQL55:
sysDatabase.setDbName(bias(dbUrl));
break;
case MYSQL57:
sysDatabase.setDbName(bias(dbUrl));
break;
default:
break;
if (ObjectUtil.isNotNull(dbTypeE)){
switch (dbTypeE){
case POSTGRESQL:
sysDatabase.setDbName(bias(dbUrl));
break;
case ORACLE:
sysDatabase.setDbName(colon(dbUrl));
break;
case MYSQL55:
sysDatabase.setDbName(bias(dbUrl));
break;
case MYSQL57:
sysDatabase.setDbName(bias(dbUrl));
break;
default:
break;
}
}
int count = baseMapper.updateById(sysDatabase);
if (count == 1)
boolean success = updateById(sysDatabase);
if (success) {
status2Redis();
return Result.OK(Prompt.UPDATE_SUCC);
}
return Result.error(Prompt.UPDATE_ERR);
}
@Override
@Transactional
public Result deleteById(String id) {
int count = baseMapper.deleteById(id);
if(count == 1)
public Result<?> deleteById(String id) {
boolean success = removeById(id);
if(success) {
statusDel(id);
return Result.OK(Prompt.DELETE_SUCC);
}
return Result.error(Prompt.DELETE_ERR);
}
@Override
public Result findAlarmHistory(SourceVo sourceVo) {
public Result<?> findAlarmHistory(SourceVo sourceVo) {
String startDate = sourceVo.getStartDate();
String endDate = sourceVo.getEndDate();
if (StrUtil.isNotBlank(startDate))
@ -209,7 +210,7 @@ public class SysDatabaseServiceImpl extends ServiceImpl<SysDatabaseMapper, SysDa
List<AlarmHistory> alarmHistories = baseMapper.findAlarmHistory(params);
// 获取数据总条数(经过查询条件过滤后的)
params.put("pageFlag","noPage");
Integer total = baseMapper.findAlarmHistory(params).size();
int total = baseMapper.findAlarmHistory(params).size();
Page<AlarmHistory> page = new Page<>(pageNo,pageSize,total);
// 当前页数据
page.setRecords(alarmHistories);
@ -219,7 +220,6 @@ public class SysDatabaseServiceImpl extends ServiceImpl<SysDatabaseMapper, SysDa
@Override
public List<SourceDto> listAll() {
LambdaQueryWrapper<SysDatabase> wrapper = new LambdaQueryWrapper<>();
wrapper.orderByDesc(SysDatabase::getStatus);
wrapper.orderByAsc(SysDatabase::getName);
List<SourceDto> sourceDtos = new ArrayList<>();
for (SysDatabase sysDatabase : list(wrapper)) {
@ -319,6 +319,27 @@ public class SysDatabaseServiceImpl extends ServiceImpl<SysDatabaseMapper, SysDa
return spaceInfos;
}
@Override
public void status2Redis() {
// 获取所有配置的数据源
List<SysDatabase> databases = list();
Map<String, Object> statusMap = new HashMap<>();
for (SysDatabase database : databases) {
String id = database.getId();
String dbUrl = database.getDbUrl();
String dbDriver = database.getDbDriver();
String dbUsername = database.getDbUsername();
String dbPassword = database.getDbPassword();
boolean isConn = JDBCUtil.isConnection(dbUrl, dbDriver, dbUsername, dbPassword);
statusMap.put(id, isConn);
}
// 将数据源连接状态更新到reids
String prefixStatus = RedisConstant.PREFIX_STATUS;
String databaseStatus = RedisConstant.DATABASE_STATUS;
String statusKey = prefixStatus + databaseStatus;
redisUtil.hmset(statusKey, statusMap);
}
private List<DBInfo> dbInfoPG(SysDatabase sysDatabase, String dbName, RowMapper<DBInfo> mapper){
String dbUrl = sysDatabase.getDbUrl();
String dbDriver = sysDatabase.getDbDriver();
@ -361,4 +382,28 @@ public class SysDatabaseServiceImpl extends ServiceImpl<SysDatabaseMapper, SysDa
String dbInfoSQL = String.format(DBSQL.DBINFO_MY, dbName);
return template.query(dbInfoSQL, mapper);
}
private String colon(String url){
if (StrUtil.isBlank(url))
return null;
String regex = ".*:(.*)";
return ReUtil.getGroup1(regex, url);
}
private String bias(String url){
if (StrUtil.isBlank(url))
return null;
String regex = "/([^/?]+)\\?";
return ReUtil.getGroup1(regex, url);
}
/*
* 删除指定id的数据源的状态值
* */
private void statusDel(String id){
String prefixStatus = RedisConstant.PREFIX_STATUS;
String databaseStatus = RedisConstant.DATABASE_STATUS;
String statusKey = prefixStatus + databaseStatus;
redisUtil.hdel(statusKey, id);
}
}

View File

@ -16,7 +16,10 @@ import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.DateConstant;
import org.jeecg.common.constant.Prompt;
import org.jeecg.common.constant.RedisConstant;
import org.jeecg.common.email.emuns.SysMailType;
import org.jeecg.common.util.EmailUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.base.dto.EmailDto;
import org.jeecg.modules.base.dto.IdCount;
import org.jeecg.modules.base.dto.SourceDto;
@ -25,10 +28,12 @@ import org.jeecg.modules.base.bizVo.SourceVo;
import org.jeecg.modules.entity.AlarmHistory;
import org.jeecg.modules.mapper.SysEmailMapper;
import org.jeecg.modules.service.ISysEmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.mail.*;
import java.security.Key;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
@ -37,6 +42,9 @@ import java.util.stream.Collectors;
@Service("sysEmailService")
public class SysEmailServiceImpl extends ServiceImpl<SysEmailMapper, SysEmail> implements ISysEmailService {
@Autowired
private RedisUtil redisUtil;
@Override
public Result<?> findPage(QueryRequest query) {
Integer pageNo = query.getPageNo();
@ -71,9 +79,16 @@ public class SysEmailServiceImpl extends ServiceImpl<SysEmailMapper, SysEmail> i
.stream().collect(Collectors.toMap(IdCount::getId, IdCount::getCount));
Map<String, Integer> weekMap = baseMapper.counts(emailIds, weekStart, todayEnd)
.stream().collect(Collectors.toMap(IdCount::getId, IdCount::getCount));
// 邮箱状态Map key:id value:状态(true|false)
String prefixStatus = RedisConstant.PREFIX_STATUS;
String emailStatus = RedisConstant.EMAIL_STATUS;
String statusKey = prefixStatus + emailStatus;
Map<Object, Object> statusMap = redisUtil.hmget(statusKey);
for (EmailDto emailDto : emailDtos) {
String id = emailDto.getId();
emailDto.setOnline(true).setStoerCapacity("100%").setStoerRed(true)
Boolean online = (Boolean) statusMap.get(id);
if (ObjectUtil.isNull(online)) online = false;
emailDto.setOnline(online).setStoerCapacity("100%").setStoerRed(true)
.setToday(todayMap.getOrDefault(id, 0))
.setYesterday(yestMap.getOrDefault(id, 0))
.setWeekly(weekMap.getOrDefault(id, 0));
@ -87,39 +102,35 @@ public class SysEmailServiceImpl extends ServiceImpl<SysEmailMapper, SysEmail> i
}
@Override
public Result findInfo(String id) {
Result result = new Result();
//根据id查询对应的邮箱配置信息
LambdaQueryWrapper<SysEmail> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysEmail::getId, id);
SysEmail sysEmail = this.baseMapper.selectOne(queryWrapper);
if (Objects.isNull(sysEmail)){
result.error500("查询数据不存在");
return result;
public Result<?> findInfo(String id) {
SysEmail sysEmail = getById(id);
if (ObjectUtil.isNull(sysEmail)){
return Result.error(Prompt.DATA_NOT_EXITS);
}
result.setSuccess(true);
result.setResult(sysEmail);
return result;
return Result.OK(sysEmail);
}
@Override
@Transactional
public Result create(SysEmail sysEmail) {
public Result<?> create(SysEmail sysEmail) {
String name = sysEmail.getName();
LambdaQueryWrapper<SysEmail> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SysEmail::getName,name);
if (CollUtil.isNotEmpty(list(wrapper)))
return Result.error("Name"+Prompt.NOT_REPEAT);
int count = baseMapper.insert(sysEmail);
if (count == 1)
boolean success = save(sysEmail);
if (success) {
// 更新邮箱连接状态到redis
status2Redis();
return Result.OK(Prompt.ADD_SUCC);
}
return Result.error(Prompt.ADD_ERR);
}
@Override
@Transactional
public Result update(SysEmail sysEmail) {
public Result<?> update(SysEmail sysEmail) {
SysEmail email = getById(sysEmail.getId());
if (ObjectUtil.isNull(email))
return Result.error(Prompt.DATA_NOT_EXITS);
@ -131,23 +142,28 @@ public class SysEmailServiceImpl extends ServiceImpl<SysEmailMapper, SysEmail> i
return Result.error("Name" + Prompt.NOT_REPEAT);
wrapper.clear();
}
int count = baseMapper.updateById(sysEmail);
if (count == 1)
boolean success = updateById(sysEmail);
if (success) {
// 更新邮箱连接状态到redis
status2Redis();
return Result.OK(Prompt.UPDATE_SUCC);
}
return Result.error(Prompt.UPDATE_ERR);
}
@Override
@Transactional
public Result deleteById(String id) {
int count = baseMapper.deleteById(id);
if(count == 1)
public Result<?> deleteById(String id) {
boolean success = this.removeById(id);
if (success){
statusDel(id);
return Result.OK(Prompt.DELETE_SUCC);
}
return Result.error(Prompt.DELETE_ERR);
}
@Override
public Result findAlarmHistory(SourceVo sourceVo) {
public Result<?> findAlarmHistory(SourceVo sourceVo) {
String startDate = sourceVo.getStartDate();
String endDate = sourceVo.getEndDate();
if (StrUtil.isNotBlank(startDate))
@ -162,7 +178,7 @@ public class SysEmailServiceImpl extends ServiceImpl<SysEmailMapper, SysEmail> i
List<AlarmHistory> alarmHistories = baseMapper.findAlarmHistory(params);
// 获取数据总条数(经过查询条件过滤后的)
params.put("pageFlag","noPage");
Integer total = baseMapper.findAlarmHistory(params).size();
int total = baseMapper.findAlarmHistory(params).size();
Page<AlarmHistory> page = new Page<>(pageNo,pageSize,total);
// 当前页数据
page.setRecords(alarmHistories);
@ -196,4 +212,37 @@ public class SysEmailServiceImpl extends ServiceImpl<SysEmailMapper, SysEmail> i
}
return sourceDtos;
}
/*
* 调用场景
* 1.应用启动 2.修改邮箱信息 3.新增邮箱信息
* */
@Override
public void status2Redis() {
// 获取所有配置的邮箱服务器
List<SysEmail> emails = list();
Map<String, Object> statusMap = new HashMap<>();
for (SysEmail email : emails) {
String id = email.getId();
String address = email.getEmailServerAddress();
Integer port = email.getPort();
boolean isConn = EmailUtil.isConnection(address, port);
statusMap.put(id, isConn);
}
// 将邮箱服务器连接状态更新到reids
String prefixStatus = RedisConstant.PREFIX_STATUS;
String emailStatus = RedisConstant.EMAIL_STATUS;
String statusKey = prefixStatus + emailStatus;
redisUtil.hmset(statusKey, statusMap);
}
/*
* 删除指定id的邮箱服务器的状态值
* */
private void statusDel(String id){
String prefixStatus = RedisConstant.PREFIX_STATUS;
String emailStatus = RedisConstant.EMAIL_STATUS;
String statusKey = prefixStatus + emailStatus;
redisUtil.hdel(statusKey, id);
}
}

View File

@ -2,17 +2,17 @@ package org.jeecg.modules;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.EmailConstant;
import org.jeecg.common.email.EmailServiceManager;
import org.jeecg.common.properties.TaskProperties;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.base.enums.SysMailEnableType;
import org.jeecg.modules.email.EmailProperties;
import org.jeecg.common.properties.TaskProperties;
import org.jeecg.modules.service.ISysMailService;
import org.jeecg.modules.spectrum.EmailCounter;
import org.jeecg.modules.spectrum.SpectrumServiceQuotes;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.concurrent.TimeUnit;
@ -129,7 +129,7 @@ public class AutoProcessManager{
final EmailServiceManager emailServiceManager = EmailServiceManager.getInstance();
emailServiceManager.init(email);
boolean testFlag = emailServiceManager.testConnectEmailServer();
redisUtil.hset(EmailConstant.EMAIL_STATUS_PREFIX,email.getId(),testFlag);
// redisUtil.hset(EmailConstant.EMAIL_STATUS_PREFIX,email.getId(),testFlag);
if(testFlag && !emailExecThreadMap.containsKey(email.getId())){
email.setNewEmailFlag(true);
}

View File

@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
import lombok.Getter;
import org.jeecg.common.config.mqtoken.UserTokenContext;
import org.jeecg.common.util.RedisStreamUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.modules.feignclient.AbnormalAlarmClient;
import org.jeecg.modules.feignclient.MonitorSystem;
@ -13,6 +14,8 @@ import static org.jeecg.common.util.TokenUtils.getTempToken;
@Getter
public abstract class Monitor {
private RedisUtil redisUtil;
private SendMessage sendMessage;
private MonitorSystem monitorSystem;
@ -32,6 +35,7 @@ public abstract class Monitor {
protected void init(){
// start:生成临时Token到线程中
UserTokenContext.setToken(getTempToken());
redisUtil = SpringContextUtils.getBean(RedisUtil.class);
sendMessage = SpringContextUtils.getBean(SendMessage.class);
redisStreamUtil = SpringContextUtils.getBean(RedisStreamUtil.class);
alarmClient = SpringContextUtils.getBean(AbnormalAlarmClient.class);

View File

@ -80,7 +80,7 @@ public class DatabaseJob extends Monitor implements Job{
Number current = null;
switch (item){
case DATABASE_CONN: // 监控项-2: 测试数据源是否可以连接成功
current = isConnection(database);
current = isConnection(sourceId);
break;
// 追加的监控项...
default:
@ -115,9 +115,9 @@ public class DatabaseJob extends Monitor implements Job{
getSendMessage().send(message, groupId, notific);
}
} catch (JsonProcessingException e) {
log.error("Database预警规则:{}解析失败,失败原因:{}!", operator, e.getMessage());
log.error("Database预警规则{}解析失败: {}", operator, e.getMessage());
}catch (RuntimeException e){
log.error("Database监控异常:{}",e.getMessage());
log.error("Database监控异常: {}",e.getMessage());
}
}
destroy();
@ -126,26 +126,13 @@ public class DatabaseJob extends Monitor implements Job{
/*
* 监控项-2: 测试数据源是否可以连接成功 (0:失败 1:成功)
* */
private Integer isConnection(SysDatabase database){
int res = 0;
try {
boolean conn = JDBCUtil.testConnection(database);
res = conn ? 1 : res;
// 如果数据源连接状态发生变化则进行更新
Integer status = database.getStatus();
if (ObjectUtil.isNotNull(status)){
if (res != status){
database.setStatus(res);
getAlarmClient().updateDatabase(database);
}
}else {
database.setStatus(res);
getAlarmClient().updateDatabase(database);
}
return res;
}catch (Exception e){
log.error("Database监控-更新数据源状态异常:{}", e.getMessage());
return res;
}
private Integer isConnection(String databaseId){
int res = 1;
String prefixStatus = RedisConstant.PREFIX_STATUS;
String databaseStatus = RedisConstant.DATABASE_STATUS;
String statusKey = prefixStatus + databaseStatus;
Boolean status = (Boolean)getRedisUtil().hget(statusKey, databaseId);
if (ObjectUtil.isNull(status) || !status) res = 0;
return res;
}
}

View File

@ -1,7 +1,10 @@
package org.jeecg;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.DatabaseStatusManager;
import org.jeecg.modules.EmailStatusManager;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@ -19,7 +22,13 @@ import java.net.UnknownHostException;
@SpringBootApplication
@EnableFeignClients(basePackages = {"org.jeecg"})
@EnableScheduling
@RequiredArgsConstructor
public class JeecgAbnormalAlarmApplication extends SpringBootServletInitializer implements CommandLineRunner {
private final EmailStatusManager emailStatusManager;
private final DatabaseStatusManager databaseStatusManager;
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(JeecgAbnormalAlarmApplication.class);
@ -41,7 +50,10 @@ public class JeecgAbnormalAlarmApplication extends SpringBootServletInitializer
@Override
public void run(String... args) throws Exception {
// 启动监测数据库连接状态的线程
databaseStatusManager.start();
// 启动监测邮箱服务器连接状态的线程
emailStatusManager.start();
}
}