开发线程池历史数据存储以及监控功能, 拉去代码报错请查看 (https://github.com/acmenlt/dynamic-threadpool/issues/24)

pull/28/head
chen.ma 3 years ago
parent 4e2a03fad0
commit 51f93b1fbd

@ -2,6 +2,7 @@ package cn.hippo4j.auth.model.biz.user;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* User query page.
@ -10,6 +11,7 @@ import lombok.Data;
* @date 2021/10/30 21:47
*/
@Data
@Accessors(chain = true)
public class UserQueryPageReqDTO extends Page {
/**

@ -30,6 +30,11 @@
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
</dependencies>
<build>

@ -35,6 +35,11 @@ public class PoolRunStateInfo implements Serializable {
*/
private Integer coreSize;
/**
* activeCount
*/
private Integer activeCount;
/**
* maximumSize
*/
@ -105,4 +110,9 @@ public class PoolRunStateInfo implements Serializable {
*/
private String clientLastRefreshTime;
/**
* timestamp
*/
private Long timestamp;
}

@ -13,7 +13,7 @@ import java.util.List;
*/
@Data
@NoArgsConstructor
public abstract class AbstractMessage implements Message {
public abstract class AbstractMessage<T extends Message> implements Message {
/**
* groupKey: tenant + item + tpId + identify
@ -28,6 +28,6 @@ public abstract class AbstractMessage implements Message {
/**
* message
*/
private List<Message> messages;
private List<T> messages;
}

@ -9,7 +9,7 @@ import java.util.List;
* @author chen.ma
* @date 2021/12/6 20:16
*/
public interface Message extends Serializable {
public interface Message<T extends Message> extends Serializable {
/**
* Get groupKey.
@ -30,6 +30,6 @@ public interface Message extends Serializable {
*
* @return
*/
List<Message> getMessages();
List<T> getMessages();
}

@ -0,0 +1,35 @@
package cn.hippo4j.common.monitor;
import java.util.List;
import java.util.Map;
/**
* Message request.
*
* @author chen.ma
* @date 2021/12/10 21:17
*/
public interface MessageRequest<T extends Message> {
/**
* Get content params.
*
* @return
*/
List<Map<String, Object>> getContentParams();
/**
* Get response class.
*
* @return
*/
Class<T> getResponseClass();
/**
* Get message type.
*
* @return
*/
MessageTypeEnum getMessageType();
}

@ -9,8 +9,13 @@ package cn.hippo4j.common.monitor;
public enum MessageTypeEnum {
/**
*
* RUNTIME
*/
RUNTIME
RUNTIME,
/**
* DEFAULT
*/
DEFAULT
}

@ -4,7 +4,8 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* Message wrapper.
@ -15,11 +16,36 @@ import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MessageWrapper extends AbstractMessage implements Serializable {
public class MessageWrapper implements MessageRequest<Message> {
/**
* messageObj
* contentParams
*/
private Object messageObj;
private List<Map<String, Object>> contentParams;
/**
* responseClass
*/
private Class responseClass;
/**
* getMessageType
*/
private MessageTypeEnum messageType;
@Override
public List<Map<String, Object>> getContentParams() {
return contentParams;
}
@Override
public Class<Message> getResponseClass() {
return responseClass;
}
@Override
public MessageTypeEnum getMessageType() {
return messageType;
}
}

@ -33,6 +33,11 @@ public class RuntimeMessage extends AbstractMessage {
*/
private Integer largestPoolSize;
/**
* activeSize
*/
private String activeSize;
/**
* queueCapacity
*/
@ -43,6 +48,11 @@ public class RuntimeMessage extends AbstractMessage {
*/
private Integer queueSize;
/**
* queueRemainingCapacity
*/
private String queueRemainingCapacity;
/**
* completedTaskCount
*/
@ -53,4 +63,9 @@ public class RuntimeMessage extends AbstractMessage {
*/
private Integer rejectCount;
/**
* timestamp
*/
private Long timestamp;
}

@ -0,0 +1,59 @@
package cn.hippo4j.common.toolkit;
import cn.hippo4j.common.monitor.AbstractMessage;
import cn.hippo4j.common.monitor.Message;
import cn.hippo4j.common.monitor.MessageWrapper;
import cn.hutool.core.bean.BeanUtil;
import lombok.SneakyThrows;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Message convert.
*
* @author chen.ma
* @date 2021/12/10 21:27
*/
public class MessageConvert {
/**
* {@link Message} to {@link MessageWrapper}.
*
* @param message
* @return
*/
public static MessageWrapper convert(Message message) {
MessageWrapper wrapper = new MessageWrapper();
wrapper.setResponseClass(message.getClass());
wrapper.setMessageType(message.getMessageType());
List<Map<String, Object>> messageMapList = new ArrayList();
List<Message> messages = message.getMessages();
messages.forEach(each -> messageMapList.add(BeanUtil.beanToMap(each)));
wrapper.setContentParams(messageMapList);
return wrapper;
}
/**
* {@link MessageWrapper} to {@link Message}.
*
* @param messageWrapper
* @return
*/
@SneakyThrows
public static Message convert(MessageWrapper messageWrapper) {
AbstractMessage message = (AbstractMessage) messageWrapper.getResponseClass().newInstance();
List<Map<String, Object>> contentParams = messageWrapper.getContentParams();
List<Message> messages = new ArrayList();
contentParams.forEach(each -> messages.add(BeanUtil.toBean(each, messageWrapper.getResponseClass())));
message.setMessages(messages);
message.setMessageType(messageWrapper.getMessageType());
return message;
}
}

@ -10,12 +10,27 @@ public class UserContext {
private static String username;
private static String userRole;
public static void setUserName(String username) {
UserContext.username = username;
}
public static void setUserRole(String userRole) {
UserContext.userRole = userRole;
}
public static void setUserInfo(String username, String userRole) {
UserContext.username = username;
UserContext.userRole = userRole;
}
public static String getUserName() {
return username;
}
public static String getUserRole() {
return userRole;
}
}

@ -0,0 +1,14 @@
package cn.hippo4j.config.mapper;
import org.apache.ibatis.annotations.Mapper;
/**
* Dashboard mapper.
*
* @author chen.ma
* @date 2021/12/11 15:16
*/
@Mapper
public interface DashboardMapper {
}

@ -0,0 +1,61 @@
package cn.hippo4j.config.mapper;
import cn.hippo4j.config.model.HisRunDataInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import lombok.Data;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* His run data mapper.
*
* @author chen.ma
* @date 2021/12/10 21:33
*/
@Mapper
public interface HisRunDataMapper extends BaseMapper<HisRunDataInfo> {
/**
* Query thread pool task sum ranking.
*
* @param startTime
* @param endTime
* @return
*/
@Select("SELECT " +
"tenant_id, item_id, tp_id, max(completed_task_count) as max_completed_task_count " +
"FROM his_run_data " +
"where timestamp between #{startTime} and #{endTime} " +
"group by tenant_id, item_id, tp_id " +
"order by max_completed_task_count desc " +
"limit 8")
List<ThreadPoolTaskRanking> queryThreadPoolTaskSumRanking(@Param("startTime") Long startTime, @Param("endTime") Long endTime);
@Data
class ThreadPoolTaskRanking {
/**
* id
*/
private String tenantId;
/**
* id
*/
private String itemId;
/**
* 线id
*/
private String tpId;
/**
*
*/
private Long maxCompletedTaskCount;
}
}

@ -0,0 +1,106 @@
package cn.hippo4j.config.model;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.util.Date;
/**
* His run data info.
*
* @author chen.ma
* @date 2021/12/10 21:30
*/
@Data
@TableName("his_run_data")
public class HisRunDataInfo {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* id
*/
private String tenantId;
/**
* id
*/
private String itemId;
/**
* id
*/
private String instanceId;
/**
* 线id
*/
private String tpId;
/**
*
*/
private Long currentLoad;
/**
*
*/
private Long peakLoad;
/**
* 线
*/
private Long poolSize;
/**
* 线
*/
private Long activeSize;
/**
*
*/
private Long queueCapacity;
/**
*
*/
private Long queueSize;
/**
*
*/
private Long queueRemainingCapacity;
/**
*
*/
private Long completedTaskCount;
/**
*
*/
private Long rejectCount;
/**
*
*/
private Long timestamp;
/**
*
*/
@TableField(fill = FieldFill.INSERT)
private Date gmtCreate;
/**
*
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date gmtModified;
}

@ -0,0 +1,60 @@
package cn.hippo4j.config.model.biz.monitor;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* Monitor active resp dto.
*
* @author chen.ma
* @date 2021/12/12 17:18
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MonitorActiveRespDTO {
/**
* times
*/
private List<String> times;
/**
* poolSizeList
*/
List<Long> poolSizeList;
/**
* activeSizeList
*/
List<Long> activeSizeList;
/**
* queueSizeList
*/
List<Long> queueSizeList;
/**
* completedTaskCountList
*/
List<Long> completedTaskCountList;
/**
* rejectCountList
*/
List<Long> rejectCountList;
/**
* queueRemainingCapacityList
*/
List<Long> queueRemainingCapacityList;
/**
* currentLoadList
*/
List<Long> currentLoadList;
}

@ -0,0 +1,34 @@
package cn.hippo4j.config.model.biz.monitor;
import lombok.Data;
/**
* Monitor query req dto.
*
* @author chen.ma
* @date 2021/12/10 20:18
*/
@Data
public class MonitorQueryReqDTO {
/**
* id
*/
private String tenantId;
/**
* id
*/
private String itemId;
/**
* 线id
*/
private String tpId;
/**
* id
*/
private String instanceId;
}

@ -0,0 +1,79 @@
package cn.hippo4j.config.model.biz.monitor;
import lombok.Data;
/**
* Monitor resp dto.
*
* @author chen.ma
* @date 2021/12/10 20:23
*/
@Data
public class MonitorRespDTO {
/**
* id
*/
private String tenantId;
/**
* id
*/
private String itemId;
/**
* id
*/
private String instanceId;
/**
*
*/
private String completedTaskCount;
/**
* 线id
*/
private String tpId;
/**
*
*/
private String currentLoad;
/**
*
*/
private String peakLoad;
/**
* 线
*/
private String poolSize;
/**
* 线
*/
private String activeSize;
/**
*
*/
private String queueCapacity;
/**
*
*/
private String queueSize;
/**
*
*/
private String queueRemainingCapacity;
/**
*
*/
private String rejectCount;
}

@ -0,0 +1,27 @@
package cn.hippo4j.config.monitor;
import cn.hippo4j.common.monitor.Message;
/**
* Abstract monitor data execute strategy.
*
* @author chen.ma
* @date 2021/12/10 20:14
*/
public abstract class AbstractMonitorDataExecuteStrategy<T extends Message> {
/**
* Mark.
*
* @return
*/
public abstract String mark();
/**
* Execute.
*
* @param message
*/
public abstract void execute(T message);
}

@ -0,0 +1,28 @@
package cn.hippo4j.config.monitor;
import cn.hippo4j.common.monitor.Message;
import cn.hippo4j.common.monitor.MessageTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* Default monitor data resolver.
*
* @author chen.ma
* @date 2021/12/10 21:47
*/
@Slf4j
@Component
public class DefaultMonitorDataResolver extends AbstractMonitorDataExecuteStrategy<Message> {
@Override
public String mark() {
return MessageTypeEnum.DEFAULT.name();
}
@Override
public void execute(Message message) {
log.warn("There is no suitable monitoring data storage actuator.");
}
}

@ -0,0 +1,69 @@
package cn.hippo4j.config.monitor;
import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.monitor.Message;
import cn.hippo4j.common.monitor.MessageTypeEnum;
import com.google.common.collect.Maps;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* Query monitor execute choose.
*
* @author chen.ma
* @date 2021/12/10 20:12
*/
@Component
public class QueryMonitorExecuteChoose implements CommandLineRunner {
/**
* Storage monitoring data execution container.
*/
private Map<String, AbstractMonitorDataExecuteStrategy> monitorDataExecuteStrategyChooseMap = Maps.newHashMap();
/**
* Choose by {@link cn.hippo4j.common.monitor.MessageTypeEnum}.
*
* @param messageTypeEnum {@link cn.hippo4j.common.monitor.MessageTypeEnum}
* @return
*/
public AbstractMonitorDataExecuteStrategy choose(MessageTypeEnum messageTypeEnum) {
return choose(messageTypeEnum.name());
}
/**
* Choose by mark type.
*
* @param markType {@link cn.hippo4j.common.monitor.MessageTypeEnum#name()}
* @return
*/
public AbstractMonitorDataExecuteStrategy choose(String markType) {
AbstractMonitorDataExecuteStrategy executeStrategy = monitorDataExecuteStrategyChooseMap.get(markType);
if (executeStrategy == null) {
executeStrategy = monitorDataExecuteStrategyChooseMap.get(MessageTypeEnum.DEFAULT.name());
}
return executeStrategy;
}
/**
* Choose and execute.
*
* @param message {@link Message}
*/
public void chooseAndExecute(Message message) {
MessageTypeEnum messageType = message.getMessageType();
AbstractMonitorDataExecuteStrategy executeStrategy = choose(messageType);
executeStrategy.execute(message);
}
@Override
public void run(String... args) throws Exception {
Map<String, AbstractMonitorDataExecuteStrategy> monitorDataExecuteStrategyMap =
ApplicationContextHolder.getBeansOfType(AbstractMonitorDataExecuteStrategy.class);
monitorDataExecuteStrategyMap.values().forEach(each -> monitorDataExecuteStrategyChooseMap.put(each.mark(), each));
}
}

@ -0,0 +1,37 @@
package cn.hippo4j.config.monitor;
import cn.hippo4j.common.monitor.MessageTypeEnum;
import cn.hippo4j.common.monitor.RuntimeMessage;
import cn.hippo4j.config.service.biz.HisRunDataService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* Runtime data resolver.
*
* @author chen.ma
* @date 2021/12/10 20:18
*/
@Slf4j
@Component
@AllArgsConstructor
public class RuntimeDataResolver extends AbstractMonitorDataExecuteStrategy<RuntimeMessage> {
private final HisRunDataService hisRunDataService;
@Override
public String mark() {
return MessageTypeEnum.RUNTIME.name();
}
@Override
public void execute(RuntimeMessage message) {
log.info("[{}] Perform monitoring data persistence. content :: {}", this.getClass().getName(), JSON.toJSONString(message, SerializerFeature.PrettyFormat));
hisRunDataService.save(message);
}
}

@ -0,0 +1,43 @@
package cn.hippo4j.config.service.biz;
import cn.hippo4j.common.monitor.Message;
import cn.hippo4j.config.model.HisRunDataInfo;
import cn.hippo4j.config.model.biz.monitor.MonitorActiveRespDTO;
import cn.hippo4j.config.model.biz.monitor.MonitorQueryReqDTO;
import cn.hippo4j.config.model.biz.monitor.MonitorRespDTO;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* His run data service.
*
* @author chen.ma
* @date 2021/12/10 21:28
*/
public interface HisRunDataService extends IService<HisRunDataInfo> {
/**
* Query.
*
* @param reqDTO
* @return
*/
List<MonitorRespDTO> query(MonitorQueryReqDTO reqDTO);
/**
* Query active thread pool monitor.
*
* @param reqDTO
* @return
*/
MonitorActiveRespDTO queryInfoThreadPoolMonitor(MonitorQueryReqDTO reqDTO);
/**
* Save.
*
* @param message
*/
void save(Message message);
}

@ -0,0 +1,110 @@
package cn.hippo4j.config.service.biz.impl;
import cn.hippo4j.common.monitor.Message;
import cn.hippo4j.common.monitor.RuntimeMessage;
import cn.hippo4j.common.toolkit.GroupKey;
import cn.hippo4j.config.mapper.HisRunDataMapper;
import cn.hippo4j.config.model.HisRunDataInfo;
import cn.hippo4j.config.model.biz.monitor.MonitorActiveRespDTO;
import cn.hippo4j.config.model.biz.monitor.MonitorQueryReqDTO;
import cn.hippo4j.config.model.biz.monitor.MonitorRespDTO;
import cn.hippo4j.config.service.biz.HisRunDataService;
import cn.hippo4j.config.toolkit.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
import static cn.hutool.core.date.DatePattern.NORM_TIME_PATTERN;
/**
* His run data service impl.
*
* @author chen.ma
* @date 2021/12/10 21:28
*/
@Service
@AllArgsConstructor
public class HisRunDataServiceImpl extends ServiceImpl<HisRunDataMapper, HisRunDataInfo> implements HisRunDataService {
@Override
public List<MonitorRespDTO> query(MonitorQueryReqDTO reqDTO) {
Date currentDate = new Date();
DateTime dateTime = DateUtil.offsetMinute(currentDate, -30);
long startTime = dateTime.getTime();
List<HisRunDataInfo> hisRunDataInfos = this.lambdaQuery()
.eq(HisRunDataInfo::getTenantId, reqDTO.getTenantId())
.eq(HisRunDataInfo::getItemId, reqDTO.getItemId())
.eq(HisRunDataInfo::getTpId, reqDTO.getTpId())
.eq(HisRunDataInfo::getInstanceId, reqDTO.getInstanceId())
.between(HisRunDataInfo::getTimestamp, startTime, currentDate.getTime())
.list();
return BeanUtil.convert(hisRunDataInfos, MonitorRespDTO.class);
}
@Override
public MonitorActiveRespDTO queryInfoThreadPoolMonitor(MonitorQueryReqDTO reqDTO) {
Date currentDate = new Date();
DateTime dateTime = DateUtil.offsetMinute(currentDate, -60);
long startTime = dateTime.getTime();
List<HisRunDataInfo> hisRunDataInfos = this.lambdaQuery()
.eq(HisRunDataInfo::getTenantId, reqDTO.getTenantId())
.eq(HisRunDataInfo::getItemId, reqDTO.getItemId())
.eq(HisRunDataInfo::getTpId, reqDTO.getTpId())
.eq(HisRunDataInfo::getInstanceId, reqDTO.getInstanceId())
.between(HisRunDataInfo::getTimestamp, startTime, currentDate.getTime())
.list();
List<String> times = Lists.newArrayList();
List<Long> poolSizeList = Lists.newArrayList();
List<Long> activeSizeList = Lists.newArrayList();
List<Long> queueSizeList = Lists.newArrayList();
List<Long> completedTaskCountList = Lists.newArrayList();
List<Long> rejectCountList = Lists.newArrayList();
List<Long> queueRemainingCapacityList = Lists.newArrayList();
List<Long> currentLoadList = Lists.newArrayList();
hisRunDataInfos.forEach(each -> {
String time = DateUtil.format(new Date(each.getTimestamp()), NORM_TIME_PATTERN);
times.add(time);
poolSizeList.add(each.getPoolSize());
activeSizeList.add(each.getActiveSize());
queueSizeList.add(each.getQueueSize());
completedTaskCountList.add(each.getCompletedTaskCount());
rejectCountList.add(each.getRejectCount());
queueRemainingCapacityList.add(each.getQueueRemainingCapacity());
currentLoadList.add(each.getCurrentLoad());
});
return new MonitorActiveRespDTO(times, poolSizeList, activeSizeList, queueSizeList, completedTaskCountList, rejectCountList, queueRemainingCapacityList, currentLoadList);
}
@Override
public void save(Message message) {
List<RuntimeMessage> runtimeMessages = message.getMessages();
List<HisRunDataInfo> hisRunDataInfos = Lists.newArrayList();
runtimeMessages.forEach(each -> {
HisRunDataInfo hisRunDataInfo = BeanUtil.convert(each, HisRunDataInfo.class);
String[] parseKey = GroupKey.parseKey(each.getGroupKey());
hisRunDataInfo.setTpId(parseKey[0]);
hisRunDataInfo.setItemId(parseKey[1]);
hisRunDataInfo.setTenantId(parseKey[2]);
hisRunDataInfo.setInstanceId(parseKey[3]);
hisRunDataInfos.add(hisRunDataInfo);
});
this.saveBatch(hisRunDataInfos);
}
}

@ -3,7 +3,7 @@ package cn.hippo4j.console.controller;
import cn.hippo4j.common.constant.Constants;
import cn.hippo4j.common.web.base.Result;
import cn.hippo4j.common.web.base.Results;
import cn.hippo4j.console.model.ChartInfo;
import cn.hippo4j.console.model.*;
import cn.hippo4j.console.service.DashboardService;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
@ -28,4 +28,28 @@ public class DashboardController {
return Results.success(dashboardService.getChartInfo());
}
@GetMapping("/line/chart")
public Result<LineChartInfo> lineChart() {
LineChartInfo lineChatInfo = dashboardService.getLineChatInfo();
return Results.success(lineChatInfo);
}
@GetMapping("/tenant/chart")
public Result<TenantChart> tenantChart() {
TenantChart tenantChart = dashboardService.getTenantChart();
return Results.success(tenantChart);
}
@GetMapping("/pie/chart")
public Result<PieChartInfo> pieChart() {
PieChartInfo pieChartInfo = dashboardService.getPieChart();
return Results.success(pieChartInfo);
}
@GetMapping("/ranking")
public Result<RankingChart> rankingChart() {
RankingChart rankingChart = dashboardService.getRankingChart();
return Results.success(rankingChart);
}
}

@ -1,19 +1,21 @@
package cn.hippo4j.console.controller;
import cn.hippo4j.common.constant.Constants;
import cn.hippo4j.common.monitor.MessageTypeEnum;
import cn.hippo4j.common.monitor.Message;
import cn.hippo4j.common.monitor.MessageWrapper;
import cn.hippo4j.common.monitor.RuntimeMessage;
import cn.hippo4j.common.toolkit.MessageConvert;
import cn.hippo4j.common.web.base.Result;
import cn.hippo4j.common.web.base.Results;
import cn.hippo4j.config.toolkit.BeanUtil;
import com.alibaba.fastjson.JSON;
import cn.hippo4j.config.model.biz.monitor.MonitorActiveRespDTO;
import cn.hippo4j.config.model.biz.monitor.MonitorQueryReqDTO;
import cn.hippo4j.config.model.biz.monitor.MonitorRespDTO;
import cn.hippo4j.config.monitor.QueryMonitorExecuteChoose;
import cn.hippo4j.config.service.biz.HisRunDataService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* Monitor controller.
@ -27,12 +29,26 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping(Constants.BASE_PATH + "/monitor")
public class MonitorController {
private final HisRunDataService hisRunDataService;
private final QueryMonitorExecuteChoose queryMonitorExecuteChoose;
@GetMapping
public Result<List<MonitorRespDTO>> queryMonitor(MonitorQueryReqDTO reqDTO) {
List<MonitorRespDTO> monitorRespList = hisRunDataService.query(reqDTO);
return Results.success(monitorRespList);
}
@PostMapping("/info")
public Result<MonitorActiveRespDTO> querInfoThreadPoolMonitor(@RequestBody MonitorQueryReqDTO reqDTO) {
MonitorActiveRespDTO monitorRespList = hisRunDataService.queryInfoThreadPoolMonitor(reqDTO);
return Results.success(monitorRespList);
}
@PostMapping
public Result dataAcquisition(@RequestBody MessageWrapper messageWrapper) {
if (messageWrapper.getMessageType().name().equals(MessageTypeEnum.RUNTIME.name())) {
RuntimeMessage convert = BeanUtil.convert(messageWrapper.getMessageObj(), RuntimeMessage.class);
log.info("Receive runtime data uploaded by the client. message :: {}", JSON.toJSONString(convert));
}
public Result dataCollect(@RequestBody MessageWrapper messageWrapper) {
Message message = MessageConvert.convert(messageWrapper);
queryMonitorExecuteChoose.chooseAndExecute(message);
return Results.success();
}

@ -1,5 +1,6 @@
package cn.hippo4j.console.controller;
import cn.hippo4j.common.toolkit.UserContext;
import com.baomidou.mybatisplus.core.metadata.IPage;
import cn.hippo4j.auth.model.biz.user.UserQueryPageReqDTO;
import cn.hippo4j.auth.model.biz.user.UserReqDTO;
@ -32,6 +33,14 @@ public class UserController {
return Results.success(resultUserPage);
}
@GetMapping("/info")
public Result<UserRespDTO> userInfo() {
String userName = UserContext.getUserName();
IPage<UserRespDTO> listUser = userService.listUser(new UserQueryPageReqDTO().setUserName(userName));
UserRespDTO userRespDTO = listUser.getRecords().get(0);
return Results.success(userRespDTO);
}
@PostMapping("/add")
public Result<Void> addUser(@RequestBody UserReqDTO reqDTO) {
userService.addUser(reqDTO);

@ -0,0 +1,30 @@
package cn.hippo4j.console.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* Line chart info.
*
* @author chen.ma
* @date 2021/12/11 12:49
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LineChartInfo {
/**
* completedTaskCounts
*/
private List<Long> completedTaskCounts;
/**
* rejectCounts
*/
private List<Long> rejectCounts;
}

@ -0,0 +1,31 @@
package cn.hippo4j.console.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
/**
* Pie chart info.
*
* @author chen.ma
* @date 2021/12/11 14:27
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PieChartInfo {
/**
* itemIds
*/
private List<String> itemIds;
/**
* pieDataList
*/
private List<Map<String, Object>> pieDataList;
}

@ -0,0 +1,45 @@
package cn.hippo4j.console.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* Ranking chart.
*
* @author chen.ma
* @date 2021/12/11 19:39
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RankingChart {
/**
* rankingChartInfoList
*/
private List<RankingChartInfo> rankingChartInfoList;
@Data
public static class RankingChartInfo {
/**
* groupKey
*/
private String groupKey;
/**
* completedTaskCount
*/
private Long maxCompletedTaskCount;
/**
* inst
*/
private Integer inst;
}
}

@ -0,0 +1,26 @@
package cn.hippo4j.console.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
/**
* Tenant chart.
*
* @author chen.ma
* @date 2021/12/11 16:35
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TenantChart {
/**
* tenantCharts
*/
private List<Map<String, Object>> tenantCharts;
}

@ -1,6 +1,6 @@
package cn.hippo4j.console.service;
import cn.hippo4j.console.model.ChartInfo;
import cn.hippo4j.console.model.*;
/**
* Dashboard service.
@ -17,4 +17,32 @@ public interface DashboardService {
*/
ChartInfo getChartInfo();
/**
* Fet line chat info.
*
* @return
*/
LineChartInfo getLineChatInfo();
/**
* Get tenant chart.
*
* @return
*/
TenantChart getTenantChart();
/**
* Get pie chart.
*
* @return
*/
PieChartInfo getPieChart();
/**
* Get ranking chart.
*
* @return
*/
RankingChart getRankingChart();
}

@ -1,18 +1,36 @@
package cn.hippo4j.console.service.impl;
import cn.hippo4j.console.model.ChartInfo;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import cn.hippo4j.common.model.InstanceInfo;
import cn.hippo4j.common.toolkit.GroupKey;
import cn.hippo4j.config.enums.DelEnum;
import cn.hippo4j.config.mapper.ConfigInfoMapper;
import cn.hippo4j.config.mapper.HisRunDataMapper;
import cn.hippo4j.config.mapper.ItemInfoMapper;
import cn.hippo4j.config.mapper.TenantInfoMapper;
import cn.hippo4j.config.model.ConfigAllInfo;
import cn.hippo4j.config.model.ItemInfo;
import cn.hippo4j.config.model.TenantInfo;
import cn.hippo4j.config.model.*;
import cn.hippo4j.config.service.ConfigCacheService;
import cn.hippo4j.config.service.biz.HisRunDataService;
import cn.hippo4j.console.model.*;
import cn.hippo4j.console.service.DashboardService;
import cn.hippo4j.discovery.core.BaseInstanceRegistry;
import cn.hippo4j.discovery.core.Lease;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static cn.hippo4j.common.toolkit.ContentUtil.getGroupKey;
/**
* Dashboard service impl.
*
@ -29,6 +47,12 @@ public class DashboardServiceImpl implements DashboardService {
private final ConfigInfoMapper configInfoMapper;
private final HisRunDataService hisRunDataService;
private final HisRunDataMapper hisRunDataMapper;
private final BaseInstanceRegistry baseInstanceRegistry;
@Override
public ChartInfo getChartInfo() {
Integer tenantCount = tenantInfoMapper.selectCount(Wrappers.lambdaQuery(TenantInfo.class).eq(TenantInfo::getDelFlag, DelEnum.NORMAL));
@ -42,4 +66,105 @@ public class DashboardServiceImpl implements DashboardService {
return chartInfo;
}
@Override
public LineChartInfo getLineChatInfo() {
Date currentDate = new Date();
DateTime sixtyTime = DateUtil.offsetMinute(currentDate, -60);
List<Long> completedTaskCounts = Lists.newArrayList(2000L, 2345L, 5676L, 2357L, 1111L, 11193L);
List<Long> rejectCounts = Lists.newArrayList(1000L, 1345L, 2676L, 1357L, 111L, 11193L);
return new LineChartInfo(completedTaskCounts, rejectCounts);
}
@Override
public TenantChart getTenantChart() {
List<Map<String, Object>> tenantChartList = Lists.newArrayList();
List<TenantInfo> tenantInfos = tenantInfoMapper.selectList(Wrappers.lambdaQuery(TenantInfo.class).eq(TenantInfo::getDelFlag, DelEnum.NORMAL));
for (TenantInfo tenant : tenantInfos) {
int tenantThreadPoolNum = 0;
LambdaQueryWrapper<ItemInfo> itemQueryWrapper = Wrappers.lambdaQuery(ItemInfo.class).eq(ItemInfo::getTenantId, tenant.getTenantId()).eq(ItemInfo::getDelFlag, DelEnum.NORMAL).select(ItemInfo::getItemId);
List<ItemInfo> itemInfos = itemInfoMapper.selectList(itemQueryWrapper);
for (ItemInfo item : itemInfos) {
LambdaQueryWrapper<ConfigAllInfo> threadPoolQueryWrapper = Wrappers.lambdaQuery(ConfigAllInfo.class)
.eq(ConfigInfoBase::getItemId, item.getItemId())
.eq(ConfigAllInfo::getDelFlag, DelEnum.NORMAL);
Integer threadPoolCount = configInfoMapper.selectCount(threadPoolQueryWrapper);
tenantThreadPoolNum += threadPoolCount;
}
Dict dict = Dict.create().set("name", tenant.getTenantId()).set("value", tenantThreadPoolNum);
tenantChartList.add(dict);
}
List resultTenantChartList = tenantChartList.stream()
.sorted((one, two) -> (int) two.get("value") - (int) one.get("value"))
.limit(5)
.collect(Collectors.toList());
return new TenantChart(resultTenantChartList);
}
@Override
public PieChartInfo getPieChart() {
LambdaQueryWrapper<ItemInfo> itemQueryWrapper = Wrappers.lambdaQuery(ItemInfo.class).eq(ItemInfo::getDelFlag, DelEnum.NORMAL).select(ItemInfo::getItemId);
List<Object> itemNameList = itemInfoMapper.selectObjs(itemQueryWrapper);
List<Map<String, Object>> pieDataList = Lists.newArrayList();
for (Object each : itemNameList) {
LambdaQueryWrapper<ConfigAllInfo> threadPoolQueryWrapper = Wrappers.lambdaQuery(ConfigAllInfo.class)
.eq(ConfigInfoBase::getItemId, each)
.eq(ConfigAllInfo::getDelFlag, DelEnum.NORMAL);
Integer threadPoolCount = configInfoMapper.selectCount(threadPoolQueryWrapper);
if (threadPoolCount != null) {
Dict dict = Dict.create().set("name", each).set("value", threadPoolCount);
pieDataList.add(dict);
}
}
pieDataList.sort((one, two) -> (int) two.get("value") - (int) one.get("value"));
List<String> resultItemIds = Lists.newArrayList();
List<Map<String, Object>> resultPieDataList = pieDataList.stream()
.limit(5)
.map(each -> {
resultItemIds.add(each.get("name").toString());
return each;
})
.collect(Collectors.toList());
return new PieChartInfo(resultItemIds, resultPieDataList);
}
@Override
public RankingChart getRankingChart() {
Date currentDate = new Date();
DateTime tenTime = DateUtil.offsetMinute(currentDate, -10);
List<RankingChart.RankingChartInfo> resultList = Lists.newArrayList();
List<HisRunDataMapper.ThreadPoolTaskRanking> threadPoolTaskRankings = hisRunDataMapper.queryThreadPoolTaskSumRanking(tenTime.getTime(), currentDate.getTime());
threadPoolTaskRankings.forEach(each -> {
RankingChart.RankingChartInfo rankingChartInfo = new RankingChart.RankingChartInfo();
rankingChartInfo.setMaxCompletedTaskCount(each.getMaxCompletedTaskCount());
List<Lease<InstanceInfo>> leases = baseInstanceRegistry.listInstance(each.getItemId());
Lease<InstanceInfo> first = CollUtil.getFirst(leases);
if (first == null) {
rankingChartInfo.setInst(0);
}
InstanceInfo holder = first.getHolder();
String itemTenantKey = holder.getGroupKey();
String groupKey = getGroupKey(each.getTpId(), itemTenantKey);
Map<String, CacheItem> content = ConfigCacheService.getContent(groupKey);
rankingChartInfo.setInst(content.keySet().size());
String keyTenant = GroupKey.getKeyTenant(each.getTenantId(), each.getItemId(), each.getTpId());
rankingChartInfo.setGroupKey(keyTenant);
resultList.add(rankingChartInfo);
});
return new RankingChart(resultList);
}
}

@ -92,6 +92,34 @@ CREATE TABLE `inst_config` (
KEY `idx_instance` (`instance_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='线程池配置实例表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = his_run_data */
/******************************************/
DROP TABLE IF EXISTS `his_run_data`;
CREATE TABLE `his_run_data` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`tenant_id` varchar(128) DEFAULT NULL COMMENT '租户ID',
`item_id` varchar(256) DEFAULT NULL COMMENT '项目ID',
`tp_id` varchar(56) DEFAULT NULL COMMENT '线程池ID',
`instance_id` varchar(256) DEFAULT NULL COMMENT '实例ID',
`current_load` bigint(20) DEFAULT NULL COMMENT '当前负载',
`peak_load` bigint(20) DEFAULT NULL COMMENT '峰值负载',
`pool_size` bigint(20) DEFAULT NULL COMMENT '线程数',
`active_size` bigint(20) DEFAULT NULL COMMENT '活跃线程数',
`queue_capacity` bigint(20) DEFAULT NULL COMMENT '队列容量',
`queue_size` bigint(20) DEFAULT NULL COMMENT '队列元素',
`queue_remaining_capacity` bigint(20) DEFAULT NULL COMMENT '队列剩余容量',
`completed_task_count` bigint(20) DEFAULT NULL COMMENT '已完成任务计数',
`reject_count` bigint(20) DEFAULT NULL COMMENT '拒绝次数',
`timestamp` bigint(20) DEFAULT NULL COMMENT '时间戳',
`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
`gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
KEY `idx_group_key` (`tenant_id`,`item_id`,`tp_id`,`instance_id`) USING BTREE,
KEY `idx_timestamp` (`timestamp`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='历史运行数据表';
/******************************************/
/* 数据库全名 = hippo4j_manager */
/* 表名称 = log_record_info */

@ -50,9 +50,9 @@ public abstract class AbstractThreadPoolRuntime {
// 线程池中执行任务总数量 (有锁)
long completedTaskCount = pool.getCompletedTaskCount();
// 当前负载
String currentLoad = CalculateUtil.divide(activeCount, maximumPoolSize) + "%";
String currentLoad = CalculateUtil.divide(activeCount, maximumPoolSize) + "";
// 峰值负载
String peakLoad = CalculateUtil.divide(largestPoolSize, maximumPoolSize) + "%";
String peakLoad = CalculateUtil.divide(largestPoolSize, maximumPoolSize) + "";
BlockingQueue<Runnable> queue = pool.getQueue();
// 队列元素个数
@ -71,8 +71,8 @@ public abstract class AbstractThreadPoolRuntime {
stateInfo.setMaximumSize(maximumPoolSize);
stateInfo.setActiveSize(activeCount);
stateInfo.setCurrentLoad(currentLoad);
stateInfo.setQueueType(queueType);
stateInfo.setPeakLoad(peakLoad);
stateInfo.setQueueType(queueType);
stateInfo.setQueueSize(queueSize);
stateInfo.setQueueCapacity(queueCapacity);
stateInfo.setQueueRemainingCapacity(remainingCapacity);
@ -84,6 +84,7 @@ public abstract class AbstractThreadPoolRuntime {
: -1;
stateInfo.setRejectCount(rejectCount);
stateInfo.setClientLastRefreshTime(DateUtil.formatDateTime(new Date()));
stateInfo.setTimestamp(System.currentTimeMillis());
return supplement(stateInfo);
}

@ -39,6 +39,8 @@ public class ThreadPoolRunStateHandler extends AbstractThreadPoolRuntime {
ByteConvertUtil.getPrintSize(runtimeInfo.getMaxMemory())
).toString();
poolRunStateInfo.setCurrentLoad(poolRunStateInfo.getCurrentLoad() + "%");
poolRunStateInfo.setPeakLoad(poolRunStateInfo.getPeakLoad() + "%");
poolRunStateInfo.setHost(INET_ADDRESS.getHostAddress());
poolRunStateInfo.setMemoryProportion(memoryProportion);
poolRunStateInfo.setFreeMemory(ByteConvertUtil.getPrintSize(runtimeInfo.getFreeMemory()));

@ -2,6 +2,7 @@ package cn.hippo4j.starter.monitor;
import cn.hippo4j.common.monitor.Message;
import cn.hippo4j.common.monitor.MessageWrapper;
import cn.hippo4j.common.toolkit.MessageConvert;
import cn.hippo4j.starter.remote.HttpAgent;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -23,8 +24,7 @@ public class HttpMvcSender implements MessageSender {
@Override
public void send(Message message) {
try {
MessageWrapper messageWrapper = new MessageWrapper(message);
messageWrapper.setMessageType(message.getMessageType());
MessageWrapper messageWrapper = MessageConvert.convert(message);
httpAgent.httpPost(MONITOR_PATH, messageWrapper);
} catch (Throwable ex) {
log.error("Failed to push dynamic thread pool runtime data.", ex);

Loading…
Cancel
Save