mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
重构路由监控
This commit is contained in:
@@ -21,11 +21,6 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-bridge-nacos</artifactId>
|
||||
<version>4.0.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- easyopen starter -->
|
||||
<dependency>
|
||||
@@ -64,6 +59,11 @@
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- optional-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
|
@@ -0,0 +1,79 @@
|
||||
package com.gitee.sop.adminserver.api.service;
|
||||
|
||||
import com.gitee.easyopen.annotation.Api;
|
||||
import com.gitee.easyopen.annotation.ApiService;
|
||||
import com.gitee.fastmybatis.core.query.Query;
|
||||
import com.gitee.fastmybatis.core.query.Sort;
|
||||
import com.gitee.fastmybatis.core.support.PageEasyui;
|
||||
import com.gitee.fastmybatis.core.util.MapperUtil;
|
||||
import com.gitee.sop.adminserver.api.service.param.InstanceMonitorSearchParam;
|
||||
import com.gitee.sop.adminserver.api.service.param.MonitorErrorMsgParam;
|
||||
import com.gitee.sop.adminserver.api.service.param.MonitorInfoErrorSolveParam;
|
||||
import com.gitee.sop.adminserver.api.service.param.MonitorSearchParam;
|
||||
import com.gitee.sop.adminserver.bean.RouteErrorCount;
|
||||
import com.gitee.sop.adminserver.entity.MonitorInfoError;
|
||||
import com.gitee.sop.adminserver.entity.MonitorSummary;
|
||||
import com.gitee.sop.adminserver.mapper.MonitorInfoErrorMapper;
|
||||
import com.gitee.sop.adminserver.mapper.MonitorInfoMapper;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@ApiService
|
||||
public class MonitorNewApi {
|
||||
|
||||
@Autowired
|
||||
private MonitorInfoMapper monitorInfoMapper;
|
||||
|
||||
@Autowired
|
||||
private MonitorInfoErrorMapper monitorInfoErrorMapper;
|
||||
|
||||
@Api(name = "monitornew.data.page")
|
||||
PageInfo<Object> listMonitor(MonitorSearchParam param) {
|
||||
Query query = Query.build(param);
|
||||
query.orderby("errorCount", Sort.DESC)
|
||||
.orderby("avgTime", Sort.DESC);
|
||||
return PageHelper.offsetPage(query.getStart(), query.getLimit())
|
||||
.doSelectPage(() -> monitorInfoMapper.listMonitorSummary(query))
|
||||
.toPageInfo();
|
||||
}
|
||||
|
||||
@Api(name = "monitornew.routeid.data.get")
|
||||
List<MonitorSummary> listInstanceMonitor(InstanceMonitorSearchParam param) {
|
||||
Query query = Query.build(param);
|
||||
query.orderby("errorCount", Sort.DESC)
|
||||
.orderby("avgTime", Sort.DESC);
|
||||
return monitorInfoMapper.listInstanceMonitorInfo(query);
|
||||
}
|
||||
|
||||
private Map<String, Integer> getRouteErrorCount() {
|
||||
List<RouteErrorCount> routeErrorCounts = monitorInfoErrorMapper.listRouteErrorCount();
|
||||
return routeErrorCounts.stream()
|
||||
.collect(Collectors.toMap(RouteErrorCount::getRouteId, RouteErrorCount::getCount));
|
||||
}
|
||||
|
||||
@Api(name = "monitornew.error.page")
|
||||
PageEasyui<MonitorInfoError> listError(MonitorErrorMsgParam param) {
|
||||
Query query = param.toQuery()
|
||||
.orderby("gmt_modified", Sort.DESC);
|
||||
return MapperUtil.queryForEasyuiDatagrid(monitorInfoErrorMapper, query);
|
||||
}
|
||||
|
||||
@Api(name = "monitornew.error.solve")
|
||||
void solve(MonitorInfoErrorSolveParam param) {
|
||||
Query query = Query.build(param);
|
||||
Map<String, Object> set = new HashMap<>(4);
|
||||
set.put("is_deleted", 1);
|
||||
set.put("count", 0);
|
||||
monitorInfoErrorMapper.updateByMap(set, query);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
package com.gitee.sop.adminserver.api.service.param;
|
||||
|
||||
import com.gitee.fastmybatis.core.query.annotation.Condition;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class InstanceMonitorSearchParam {
|
||||
@Condition(column = "t.route_id")
|
||||
private String routeId;
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package com.gitee.sop.adminserver.api.service.param;
|
||||
|
||||
import com.gitee.fastmybatis.core.query.annotation.Condition;
|
||||
import com.gitee.fastmybatis.core.query.param.PageParam;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class MonitorErrorMsgParam extends PageParam {
|
||||
@NotBlank(message = "routeId不能为空")
|
||||
private String routeId;
|
||||
|
||||
@Condition(ignoreEmptyString = true)
|
||||
private String instanceId;
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package com.gitee.sop.adminserver.api.service.param;
|
||||
|
||||
import com.gitee.fastmybatis.core.query.annotation.Condition;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class MonitorInfoErrorSolveParam {
|
||||
/** 错误id,md5(error_msg), 数据库字段:error_id */
|
||||
@NotBlank
|
||||
@Condition(index = 1)
|
||||
private String errorId;
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package com.gitee.sop.adminserver.api.service.param;
|
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import com.gitee.fastmybatis.core.query.Operator;
|
||||
import com.gitee.fastmybatis.core.query.annotation.Condition;
|
||||
import com.gitee.fastmybatis.core.query.param.PageParam;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class MonitorSearchParam extends PageParam {
|
||||
@ApiDocField(description = "服务名serviceId")
|
||||
@Condition(column = "service_id", operator = Operator.like, ignoreEmptyString = true)
|
||||
private String serviceId;
|
||||
|
||||
@ApiDocField(description = "路由id")
|
||||
@Condition(column = "route_id", operator = Operator.like, ignoreEmptyString = true)
|
||||
private String routeId;
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package com.gitee.sop.adminserver.api.service.result;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class MonitorInfoErrorMsgResult {
|
||||
|
||||
private String routeId;
|
||||
|
||||
private String errorId;
|
||||
|
||||
/** 错误信息, 数据库字段:error_msg */
|
||||
private String errorMsg;
|
||||
|
||||
private Integer errorStatus;
|
||||
|
||||
private Integer count;
|
||||
|
||||
/** 数据库字段:gmt_modified */
|
||||
private Date gmtModified;
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package com.gitee.sop.adminserver.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class RouteErrorCount {
|
||||
|
||||
private String routeId;
|
||||
private Integer count;
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
package com.gitee.sop.adminserver.common;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Slf4j
|
||||
public class CopyUtil {
|
||||
|
||||
public static void copyProperties(Object from, Object to) {
|
||||
BeanUtils.copyProperties(from, to);
|
||||
}
|
||||
|
||||
public static <T> T copyBean(Object from, Supplier<T> supplier) {
|
||||
Objects.requireNonNull(from);
|
||||
T to = supplier.get();
|
||||
BeanUtils.copyProperties(from, to);
|
||||
return to;
|
||||
}
|
||||
|
||||
public static <T> T copyBeanNullable(Object from, Supplier<T> supplier) {
|
||||
if (from == null) {
|
||||
return supplier.get();
|
||||
}
|
||||
T to = supplier.get();
|
||||
BeanUtils.copyProperties(from, to);
|
||||
return to;
|
||||
}
|
||||
|
||||
public static <T> T copyBean(Object from, Supplier<T> supplier, Consumer<T> after) {
|
||||
if (from == null) {
|
||||
return null;
|
||||
}
|
||||
T to = supplier.get();
|
||||
BeanUtils.copyProperties(from, to);
|
||||
after.accept(to);
|
||||
return to;
|
||||
}
|
||||
|
||||
public static <T> List<T> copyList(List<?> fromList, Supplier<T> toElement) {
|
||||
if (fromList == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return fromList.stream()
|
||||
.map(source -> {
|
||||
T target = toElement.get();
|
||||
BeanUtils.copyProperties(source, target);
|
||||
return target;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static <T> List<T> copyList(List<?> fromList, Supplier<T> toElement, Consumer<T> after) {
|
||||
if (fromList == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return fromList.stream()
|
||||
.map(source -> {
|
||||
T target = toElement.get();
|
||||
BeanUtils.copyProperties(source, target);
|
||||
after.accept(target);
|
||||
return target;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
package com.gitee.sop.adminserver.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 表名:monitor_info
|
||||
* 备注:接口监控信息
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Table(name = "monitor_info")
|
||||
@Data
|
||||
public class MonitorInfo {
|
||||
/** 数据库字段:id */
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
/** 路由id, 数据库字段:route_id */
|
||||
private String routeId;
|
||||
|
||||
/** 接口名, 数据库字段:name */
|
||||
private String name;
|
||||
|
||||
/** 版本号, 数据库字段:version */
|
||||
private String version;
|
||||
|
||||
/** 数据库字段:service_id */
|
||||
private String serviceId;
|
||||
|
||||
/** 数据库字段:instance_id */
|
||||
private String instanceId;
|
||||
|
||||
/** 请求耗时最长时间, 数据库字段:max_time */
|
||||
private Integer maxTime;
|
||||
|
||||
/** 请求耗时最小时间, 数据库字段:min_time */
|
||||
private Integer minTime;
|
||||
|
||||
/** 总时长,毫秒, 数据库字段:total_time */
|
||||
private Long totalTime;
|
||||
|
||||
/** 总调用次数, 数据库字段:total_request_count */
|
||||
private Long totalRequestCount;
|
||||
|
||||
/** 成功次数, 数据库字段:success_count */
|
||||
private Long successCount;
|
||||
|
||||
/** 失败次数(业务主动抛出的异常算作成功,如参数校验,未知的错误算失败), 数据库字段:error_count */
|
||||
private Long errorCount;
|
||||
|
||||
/** 数据库字段:gmt_create */
|
||||
private Date gmtCreate;
|
||||
|
||||
/** 数据库字段:gmt_modified */
|
||||
private Date gmtModified;
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
package com.gitee.sop.adminserver.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 表名:monitor_info_error
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Table(name = "monitor_info_error")
|
||||
@Data
|
||||
public class MonitorInfoError {
|
||||
/** 数据库字段:id */
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
/** 错误id,md5Hex(instanceId + routeId + errorMsg), 数据库字段:error_id */
|
||||
private String errorId;
|
||||
|
||||
/** 实例id, 数据库字段:instance_id */
|
||||
private String instanceId;
|
||||
|
||||
/** 数据库字段:route_id */
|
||||
private String routeId;
|
||||
|
||||
/** 数据库字段:error_msg */
|
||||
private String errorMsg;
|
||||
|
||||
/** http status,非200错误, 数据库字段:error_status */
|
||||
private Integer errorStatus;
|
||||
|
||||
/** 错误次数, 数据库字段:count */
|
||||
private Integer count;
|
||||
|
||||
/** 数据库字段:is_deleted */
|
||||
@com.gitee.fastmybatis.core.annotation.LogicDelete
|
||||
private Byte isDeleted;
|
||||
|
||||
/** 数据库字段:gmt_create */
|
||||
private Date gmtCreate;
|
||||
|
||||
/** 数据库字段:gmt_modified */
|
||||
private Date gmtModified;
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
package com.gitee.sop.adminserver.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class MonitorSummary {
|
||||
|
||||
private static final AtomicInteger i = new AtomicInteger();
|
||||
|
||||
private Integer id = i.incrementAndGet();
|
||||
|
||||
private String routeId;
|
||||
|
||||
private String name;
|
||||
private String version;
|
||||
|
||||
/** 数据库字段:service_id */
|
||||
private String serviceId;
|
||||
|
||||
/** 数据库字段:instance_id */
|
||||
private String instanceId;
|
||||
|
||||
/** 请求耗时最长时间, 数据库字段:max_time */
|
||||
private Integer maxTime;
|
||||
|
||||
/** 请求耗时最小时间, 数据库字段:min_time */
|
||||
private Integer minTime;
|
||||
|
||||
/** 总时长,毫秒, 数据库字段:total_time */
|
||||
private Long totalTime;
|
||||
|
||||
/** 总调用次数, 数据库字段:total_request_count */
|
||||
private Long totalRequestCount;
|
||||
|
||||
/** 成功次数, 数据库字段:success_count */
|
||||
private Long successCount;
|
||||
|
||||
/** 失败次数(业务主动抛出的异常算作成功,如参数校验,未知的错误算失败), 数据库字段:error_count */
|
||||
private Long errorCount;
|
||||
|
||||
/** 未解决的错误数量 */
|
||||
private Long unsolvedErrorCount;
|
||||
|
||||
private Float avgTime;
|
||||
|
||||
private Boolean hasChildren;
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package com.gitee.sop.adminserver.mapper;
|
||||
|
||||
import com.gitee.fastmybatis.core.mapper.CrudMapper;
|
||||
import com.gitee.sop.adminserver.bean.RouteErrorCount;
|
||||
import com.gitee.sop.adminserver.entity.MonitorInfoError;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface MonitorInfoErrorMapper extends CrudMapper<MonitorInfoError, Long> {
|
||||
|
||||
|
||||
@Select("SELECT route_id routeId, count(*) `count` FROM monitor_info_error \n" +
|
||||
"WHERE is_deleted=0 \n" +
|
||||
"GROUP BY route_id")
|
||||
List<RouteErrorCount> listRouteErrorCount();
|
||||
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package com.gitee.sop.adminserver.mapper;
|
||||
|
||||
import com.gitee.fastmybatis.core.mapper.CrudMapper;
|
||||
import com.gitee.fastmybatis.core.query.Query;
|
||||
import com.gitee.sop.adminserver.entity.MonitorInfo;
|
||||
import com.gitee.sop.adminserver.entity.MonitorSummary;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface MonitorInfoMapper extends CrudMapper<MonitorInfo, Long> {
|
||||
List<MonitorSummary> listMonitorSummary(@Param("query") Query query);
|
||||
|
||||
List<MonitorSummary> listInstanceMonitorInfo(@Param("query") Query query);
|
||||
}
|
@@ -30,6 +30,7 @@ spring.datasource.hikari.pool-name=HikariCP
|
||||
spring.datasource.hikari.max-lifetime=500000
|
||||
|
||||
# 固定不用改
|
||||
mybatis.config-location=classpath:mybatis/mybatisConfig.xml
|
||||
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
|
||||
easyopen.show-doc=false
|
||||
easyopen.ignore-validate=true
|
||||
|
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<!-- 注意:文件名必须跟Dao类名字一致,因为是根据文件名做关联。 -->
|
||||
<mapper namespace="com.gitee.sop.adminserver.mapper.MonitorInfoMapper">
|
||||
|
||||
|
||||
<select id="listMonitorSummary" resultType="com.gitee.sop.adminserver.entity.MonitorSummary">
|
||||
SELECT t.*, IFNULL(t2.unsolvedErrorCount, 0) unsolvedErrorCount
|
||||
FROM (
|
||||
SELECT
|
||||
t.`service_id` serviceId,
|
||||
CONCAT(t.name, t.version) routeId,
|
||||
t.`name` name,
|
||||
t.`version` version,
|
||||
SUM(t.`max_time`) maxTime,
|
||||
SUM(t.`min_time`) minTime,
|
||||
SUM(t.`total_time`) totalTime,
|
||||
SUM(t.`total_request_count`) totalRequestCount,
|
||||
SUM(t.`success_count`) successCount,
|
||||
SUM(t.`error_count`) errorCount,
|
||||
SUM(t.`total_time`)/SUM(t.`total_request_count`) avgTime,
|
||||
1 hasChildren
|
||||
FROM
|
||||
`monitor_info` t
|
||||
<include refid="common.where"/>
|
||||
GROUP BY t.service_id, t.name, t.version
|
||||
<include refid="common.orderBy"/>
|
||||
) t
|
||||
LEFT JOIN
|
||||
(
|
||||
SELECT route_id, count(*) unsolvedErrorCount
|
||||
FROM monitor_info_error WHERE is_deleted=0 GROUP BY route_id
|
||||
) t2 on t.routeId = t2.route_id
|
||||
</select>
|
||||
|
||||
<select id="listInstanceMonitorInfo" resultType="com.gitee.sop.adminserver.entity.MonitorSummary">
|
||||
SELECT
|
||||
t.`service_id` serviceId,
|
||||
t.`instance_id` instanceId,
|
||||
t.route_id routeId,
|
||||
t.`name` name,
|
||||
t.`version` version,
|
||||
t.`max_time` maxTime,
|
||||
t.`min_time` minTime,
|
||||
t.`total_time` totalTime,
|
||||
t.`total_request_count` totalRequestCount,
|
||||
t.`success_count` successCount,
|
||||
t.`error_count` errorCount,
|
||||
IFNULL(t2.unsolvedErrorCount, 0) unsolvedErrorCount,
|
||||
t.`total_time`/t.`total_request_count` avgTime,
|
||||
0 hasChildren
|
||||
FROM
|
||||
`monitor_info` t
|
||||
LEFT JOIN
|
||||
(
|
||||
SELECT instance_id, route_id, count(*) unsolvedErrorCount
|
||||
FROM monitor_info_error WHERE is_deleted=0 GROUP BY instance_id, route_id
|
||||
) t2 on t.route_id = t2.route_id AND t.instance_id = t2.instance_id
|
||||
<include refid="common.where" />
|
||||
<include refid="common.orderBy" />
|
||||
</select>
|
||||
|
||||
</mapper>
|
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
|
||||
<configuration>
|
||||
|
||||
<plugins>
|
||||
<!-- com.github.pagehelper为PageHelper类所在包名 -->
|
||||
<plugin interceptor="com.github.pagehelper.PageInterceptor" />
|
||||
</plugins>
|
||||
|
||||
</configuration>
|
@@ -76,7 +76,7 @@ export const constantRoutes = [
|
||||
{
|
||||
path: 'monitor',
|
||||
name: 'Monitor',
|
||||
component: () => import('@/views/service/monitor'),
|
||||
component: () => import('@/views/service/monitorNew'),
|
||||
meta: { title: '路由监控' }
|
||||
},
|
||||
{
|
||||
|
273
sop-admin/sop-admin-vue/src/views/service/monitorNew.vue
Normal file
273
sop-admin/sop-admin-vue/src/views/service/monitorNew.vue
Normal file
@@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :inline="true" :model="searchFormData" class="demo-form-inline" size="mini" @submit.native.prevent>
|
||||
<el-form-item label="接口名">
|
||||
<el-input v-model="searchFormData.routeId" :clearable="true" style="width: 250px;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="serviceId">
|
||||
<el-input v-model="searchFormData.serviceId" :clearable="true" style="width: 250px;" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" native-type="submit" @click="loadTable">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table
|
||||
:data="pageInfo.list"
|
||||
row-key="id"
|
||||
lazy
|
||||
empty-text="无数据"
|
||||
:load="loadInstanceMonitorInfo"
|
||||
>
|
||||
<el-table-column
|
||||
fixed
|
||||
prop="instanceId"
|
||||
label="网关实例"
|
||||
width="200"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-if="!scope.row.children">{{ scope.row.instanceId }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
fixed
|
||||
prop="name"
|
||||
label="接口名 (版本号)"
|
||||
width="200"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.name + (scope.row.version ? ' (' + scope.row.version + ')' : '') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="serviceId"
|
||||
label="serviceId"
|
||||
width="150"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="maxTime"
|
||||
label="最大耗时(ms)"
|
||||
>
|
||||
<template slot="header">
|
||||
最大耗时(ms)
|
||||
<el-tooltip content="耗时计算:签名验证成功后开始,应用返回结果后结束" placement="top">
|
||||
<i class="el-icon-question" style="cursor: pointer"></i>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="minTime"
|
||||
label="最小耗时(ms)"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="avgTime"
|
||||
label="平均耗时(ms)"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.avgTime.toFixed(1) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="totalRequestCount"
|
||||
label="总调用次数"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="successCount"
|
||||
label="成功次数"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="errorCount"
|
||||
label="失败次数"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="unsolvedErrorCount"
|
||||
label="未解决错误"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-link
|
||||
v-if="scope.row.unsolvedErrorCount > 0"
|
||||
:underline="false"
|
||||
type="danger"
|
||||
style="text-decoration: underline;"
|
||||
@click="onShowErrorDetail(scope.row)"
|
||||
>
|
||||
{{ scope.row.unsolvedErrorCount }}
|
||||
</el-link>
|
||||
<span v-if="scope.row.unsolvedErrorCount === 0">0</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
background
|
||||
style="margin-top: 5px"
|
||||
:current-page="searchFormData.pageIndex"
|
||||
:page-size="searchFormData.pageSize"
|
||||
:page-sizes="[5, 10, 20, 40]"
|
||||
:total="pageInfo.total"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onPageIndexChange"
|
||||
/>
|
||||
<!-- dialog -->
|
||||
<el-dialog
|
||||
:title="errorMsgData.title"
|
||||
:visible.sync="logDetailVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="70%"
|
||||
@close="onCloseErrorDlg"
|
||||
>
|
||||
<el-alert
|
||||
title="修复错误后请标记解决"
|
||||
:closable="false"
|
||||
class="el-alert-tip"
|
||||
/>
|
||||
<el-table
|
||||
:data="errorMsgData.pageInfo.rows"
|
||||
empty-text="无错误日志"
|
||||
>
|
||||
<el-table-column
|
||||
type="expand"
|
||||
>
|
||||
<template slot-scope="props">
|
||||
<el-input v-model="props.row.errorMsg" type="textarea" :rows="8" readonly />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="errorMsg"
|
||||
label="错误内容"
|
||||
>
|
||||
<template slot-scope="props">
|
||||
<span v-if="props.row.errorMsg.length > 50">{{ props.row.errorMsg.substring(0, 50) }}...</span>
|
||||
<span v-else>{{ props.row.errorMsg }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="instanceId"
|
||||
label="实例ID"
|
||||
width="150px"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="count"
|
||||
label="报错次数"
|
||||
width="80px"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="gmtModified"
|
||||
label="报错时间"
|
||||
width="160px"
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
width="120"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-link type="primary" @click="onSolve(scope.row)">标记解决</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
background
|
||||
style="margin-top: 5px"
|
||||
:current-page="errorMsgFormData.pageIndex"
|
||||
:page-size="errorMsgFormData.pageSize"
|
||||
:page-sizes="[5, 10, 20, 40]"
|
||||
:total="errorMsgData.pageInfo.total"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
@size-change="onSizeChange"
|
||||
@current-change="onPageIndexChange"
|
||||
/>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="logDetailVisible = false">关 闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
searchFormData: {
|
||||
routeId: '',
|
||||
serviceId: '',
|
||||
pageIndex: 1,
|
||||
pageSize: 20
|
||||
},
|
||||
pageInfo: {
|
||||
list: [],
|
||||
total: 0
|
||||
},
|
||||
logDetailVisible: false,
|
||||
errorMsgFormData: {
|
||||
routeId: '',
|
||||
instanceId: '',
|
||||
pageIndex: 1,
|
||||
pageSize: 5
|
||||
},
|
||||
errorMsgData: {
|
||||
title: '',
|
||||
name: '',
|
||||
version: '',
|
||||
pageInfo: {
|
||||
rows: [],
|
||||
total: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadTable()
|
||||
},
|
||||
methods: {
|
||||
loadTable: function() {
|
||||
this.post('monitornew.data.page', this.searchFormData, function(resp) {
|
||||
this.pageInfo = resp.data
|
||||
})
|
||||
},
|
||||
loadErrorData: function() {
|
||||
this.post('monitornew.error.page', this.errorMsgFormData, function(resp) {
|
||||
this.errorMsgData.pageInfo = resp.data
|
||||
this.logDetailVisible = true
|
||||
})
|
||||
},
|
||||
loadInstanceMonitorInfo(row, treeNode, resolve) {
|
||||
this.post('monitornew.routeid.data.get', { routeId: row.routeId }, resp => {
|
||||
const children = resp.data
|
||||
row.children = children
|
||||
resolve(children)
|
||||
})
|
||||
},
|
||||
onShowErrorDetail: function(row) {
|
||||
this.errorMsgData.title = `错误日志 ${row.name}(${row.version})`
|
||||
this.errorMsgData.name = row.name
|
||||
this.errorMsgData.version = row.version
|
||||
this.errorMsgFormData.routeId = row.routeId
|
||||
this.errorMsgFormData.instanceId = row.instanceId
|
||||
this.loadErrorData()
|
||||
},
|
||||
onSolve: function(row) {
|
||||
this.confirm('确认标记为已解决吗?', function(done) {
|
||||
this.post('monitornew.error.solve', { routeId: row.routeId, errorId: row.errorId }, function(resp) {
|
||||
done()
|
||||
this.loadErrorData()
|
||||
})
|
||||
})
|
||||
},
|
||||
onCloseErrorDlg: function() {
|
||||
this.loadTable()
|
||||
},
|
||||
onSizeChange: function(size) {
|
||||
this.searchFormData.pageSize = size
|
||||
this.loadTable()
|
||||
},
|
||||
onAdd: function() {
|
||||
this.dialogTitle = '新增IP'
|
||||
this.dialogVisible = true
|
||||
this.dialogFormData.id = 0
|
||||
},
|
||||
onPageIndexChange: function(pageIndex) {
|
||||
this.searchFormData.pageIndex = pageIndex
|
||||
this.loadTable()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
Reference in New Issue
Block a user