完善统计

This commit is contained in:
WenG 2021-05-16 23:57:16 +08:00
parent 8799ea2078
commit 5aacf09cb2
6 changed files with 149 additions and 15 deletions

View File

@ -35,6 +35,10 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId> <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

View File

@ -14,6 +14,7 @@ public interface ISystemConst {
String UUID = "uuid"; String UUID = "uuid";
String COUNT = "count"; String COUNT = "count";
String SESSION_USER = "SESSION_USER"; String SESSION_USER = "SESSION_USER";
String USER_ADMIN_USERNAME = "admin"; String USER_ADMIN_USERNAME = "admin";
String USER_ADMIN_PASSWORD = "aaa111!!!"; String USER_ADMIN_PASSWORD = "aaa111!!!";
@ -22,4 +23,7 @@ public interface ISystemConst {
String ROUTE_PREFIX = "/gw"; String ROUTE_PREFIX = "/gw";
String ROOT_PATH_PREFIX = "/*"; String ROOT_PATH_PREFIX = "/*";
String DATE_YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
String DATE_YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
} }

View File

@ -1,17 +1,24 @@
package ink.wgink.gateway.handler.count; package ink.wgink.gateway.handler.count;
import ink.wgink.gateway.consts.ISystemConst;
import ink.wgink.gateway.dao.log.IRequestLogDao; import ink.wgink.gateway.dao.log.IRequestLogDao;
import ink.wgink.gateway.dao.route.IRouteDao; import ink.wgink.gateway.dao.route.IRouteDao;
import ink.wgink.gateway.dao.routetype.IRouteTypeDao; import ink.wgink.gateway.dao.routetype.IRouteTypeDao;
import ink.wgink.gateway.handler.BaseHandler; import ink.wgink.gateway.handler.BaseHandler;
import ink.wgink.gateway.pojo.count.HomeCount; import ink.wgink.gateway.pojo.count.HomeCount;
import ink.wgink.gateway.pojo.count.RequestLogCount; import ink.wgink.gateway.pojo.count.RequestLogLineChat;
import ink.wgink.gateway.pojo.log.RequestLog; import ink.wgink.gateway.pojo.log.RequestLog;
import ink.wgink.gateway.pojo.result.SuccessResult;
import ink.wgink.gateway.pojo.result.SuccessResultData; import ink.wgink.gateway.pojo.result.SuccessResultData;
import ink.wgink.gateway.util.DateUtil; import ink.wgink.gateway.util.DateUtil;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.data.domain.Example; import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher; import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerRequest;
@ -37,11 +44,13 @@ public class CountHandler extends BaseHandler {
private IRouteTypeDao routeTypeDao; private IRouteTypeDao routeTypeDao;
private IRouteDao routeDao; private IRouteDao routeDao;
private IRequestLogDao requestLogDao; private IRequestLogDao requestLogDao;
private MongoTemplate mongoTemplate;
public CountHandler(IRouteTypeDao routeTypeDao, IRouteDao routeDao, IRequestLogDao requestLogDao) { public CountHandler(IRouteTypeDao routeTypeDao, IRouteDao routeDao, IRequestLogDao requestLogDao, MongoTemplate mongoTemplate) {
this.routeTypeDao = routeTypeDao; this.routeTypeDao = routeTypeDao;
this.routeDao = routeDao; this.routeDao = routeDao;
this.requestLogDao = requestLogDao; this.requestLogDao = requestLogDao;
this.mongoTemplate = mongoTemplate;
} }
/** /**
@ -83,16 +92,30 @@ public class CountHandler extends BaseHandler {
/** /**
* 最新请求数量列表 * 最新请求数量列表
* 按分钟统计访问次数
* *
* @param serverRequest * @param serverRequest
* @return * @return
*/ */
// 每分钟跟新依次统计数据
public Mono<ServerResponse> listLastCount(ServerRequest serverRequest) { public Mono<ServerResponse> listLastCount(ServerRequest serverRequest) {
return ServerResponse.ok().contentType(MediaType.TEXT_EVENT_STREAM).body(requestLogDao.count().flatMap(count -> { return ServerResponse.ok().contentType(MediaType.TEXT_EVENT_STREAM).body(
RequestLogCount requestLogCount = new RequestLogCount(); Flux.interval(Duration.ofMinutes(0), Duration.ofSeconds(15)).flatMap(second ->
return Mono.just(requestLogCount); requestLogDao.count().flatMap(count -> {
}), RequestLogCount.class); DateTime nowDateTime = DateTime.now();
DateTime startDateTime = nowDateTime.minusMinutes(60);
String now = nowDateTime.toString(DateTimeFormat.forPattern(ISystemConst.DATE_YYYY_MM_DD_HH_MM));
String start = startDateTime.toString(DateTimeFormat.forPattern(ISystemConst.DATE_YYYY_MM_DD_HH_MM));
// 这个条件类似
// SELECT gmtCreate, count(gmtCreate) FROM log_request WHERE LEFT('gmtCreate', 16) >= '' and LEFT('gmtCreate', 16) <= '' GROUP BY gmtCreate
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.project().andExpression("{substr(gmtCreate,0,16)}").as("gmtMinute"),
Aggregation.match(Criteria.where("gmtMinute").gte(start).lte(now)),
Aggregation.group("gmtMinute").count().as("count"),
Aggregation.sort(Sort.by("_id").ascending())
);
AggregationResults<RequestLogLineChat> aggregate = mongoTemplate.aggregate(aggregation, IRequestLogDao.COLLECTION_NAME, RequestLogLineChat.class);
return Mono.just(new SuccessResultData(aggregate.getMappedResults()));
})), SuccessResultData.class);
} }
} }

View File

@ -1,9 +1,9 @@
package ink.wgink.gateway.pojo.count; package ink.wgink.gateway.pojo.count;
import ink.wgink.gateway.dao.log.IRequestLogDao; import ink.wgink.gateway.dao.log.IRequestLogDao;
import ink.wgink.gateway.pojo.BasePOJO;
import lombok.Data; import lombok.Data;
import lombok.ToString; import lombok.ToString;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable; import java.io.Serializable;
@ -21,10 +21,11 @@ import java.io.Serializable;
@Data @Data
@ToString @ToString
@Document(collection = IRequestLogDao.COLLECTION_NAME) @Document(collection = IRequestLogDao.COLLECTION_NAME)
public class RequestLogCount implements Serializable { public class RequestLogLineChat implements Serializable {
private static final long serialVersionUID = 289254213770448241L; private static final long serialVersionUID = 289254213770448241L;
private String gmtCreate; @Id
private String gmtMinute;
private Long count; private Long count;
} }

View File

@ -10,7 +10,7 @@
<link rel="stylesheet" href="assets/layui/css/admin.css"/> <link rel="stylesheet" href="assets/layui/css/admin.css"/>
<link rel="stylesheet" href="assets/layui/css/admin.css"/> <link rel="stylesheet" href="assets/layui/css/admin.css"/>
<style> <style>
#app {padding: 15px 0;} #app {padding-top: 15px; overflow-x: hidden;}
.layuiadmin-badge {float: right; height: 42px; line-height: 42px;} .layuiadmin-badge {float: right; height: 42px; line-height: 42px;}
.layuiadmin-card-list {padding: 15px;line-height: 38px !important; text-align: right;} .layuiadmin-card-list {padding: 15px;line-height: 38px !important; text-align: right;}
.layuiadmin-card-list .layuiadmin-big-font {font-size: 38px;} .layuiadmin-card-list .layuiadmin-big-font {font-size: 38px;}
@ -65,11 +65,11 @@
</div> </div>
</div> </div>
<div class="layui-row layui-col-space15"> <div class="layui-row layui-col-space15">
<div class="layui-col-sm12 layui-col-md6"> <div class="layui-col-sm12 layui-col-md12">
<div class="layui-col-sm12"> <div class="layui-col-sm12">
<div class="layui-card"> <div class="layui-card">
<div class="layui-card-body"> <div class="layui-card-body">
<div id="loginEChart" style="width: 100%; height: 267px;"></div> <div id="lastRequestLogLineChat" style="width: 100%;"></div>
</div> </div>
</div> </div>
</div> </div>
@ -84,13 +84,19 @@
base: 'assets/layui/modules/' base: 'assets/layui/modules/'
}).extend({}).use(['layer', 'animate-numbers'], function () { }).extend({}).use(['layer', 'animate-numbers'], function () {
var $ = layui.$; var $ = layui.$;
var $win = $(window);
new Vue({ new Vue({
el: '#app', el: '#app',
data: { data: {
requestCount: 0, requestCount: 0,
requestTodayCount: 0, requestTodayCount: 0,
routeTypeCount: 0, routeTypeCount: 0,
routeCount: 0 routeCount: 0,
lastRequestLog: {
list: [],
lastRequestLogLineChat: null
},
resizeTimeout: null
}, },
watch: { watch: {
'requestCount': function(value, old) { 'requestCount': function(value, old) {
@ -105,6 +111,12 @@
'routeCount': function(value, old) { 'routeCount': function(value, old) {
$('#routeCount').animateNumbers(value); $('#routeCount').animateNumbers(value);
}, },
'lastRequestLogArray': function(value, old) {
},
'lastRequestLogLineChat': function() {
}
}, },
methods: { methods: {
sseCountHome: function() { sseCountHome: function() {
@ -131,18 +143,108 @@
} }
}, false); }, false);
}, },
initRequestLogLineChat: function(data) {
var self = this;
if(self.lastRequestLogLineChat) {
self.lastRequestLogLineChat.resize();
return;
}
var legendData = [];
var xAxisData = [];
var seriesData = [];
for(var i = 0, item; item = data.data[i++];) {
legendData.push(item.gmtMinute);
xAxisData.push(item.gmtMinute.split(' ')[1]);
seriesData.push(item.count);
}
var option = {
title: {
text: '最近一小时内接口网关调用次数'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: legendData
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: xAxisData
},
yAxis: {
type: 'value'
},
series: [
{
name: '访问次数',
type: 'line',
stack: '总量',
data: seriesData
}
]
};
if(!self.lastRequestLogLineChat) {
self.lastRequestLogLineChat = echarts.init(document.getElementById('lastRequestLogLineChat'));
self.lastRequestLogLineChat.setOption(option);
return;
}
self.lastRequestLogLineChat.setOption(option);
},
sseRequestLogLineChat: function() {
var self = this;
var source = new EventSource(top.restAjax.path('api/count/list-last-count', []));
source.addEventListener('message', function(e) {
var data = JSON.parse(e.data);
self.initRequestLogLineChat(data);
});
source.addEventListener('open', function(e) {}, false);
// 响应finish事件主动关闭EventSource
source.addEventListener('finish', function(e) {
source.close();
}, false);
// 异常
source.addEventListener('error', function(e) {
if (e.readyState == EventSource.CLOSED) {
console.log("连接关闭");
} else {
console.log(e);
}
}, false);
},
countHome: function() { countHome: function() {
var self = this; var self = this;
if (window.EventSource) { if (window.EventSource) {
self.sseCountHome(); self.sseCountHome();
self.sseRequestLogLineChat();
} else { } else {
console.log('浏览器不支持sse'); console.log('浏览器不支持sse');
} }
},
resize: function() {
$('#lastRequestLogLineChat').height($win.height() - 170 +'px');
} }
}, },
mounted: function() { mounted: function() {
var self = this; var self = this;
self.resize();
self.countHome(); self.countHome();
$win.on('resize', function() {
if(self.resizeTimeout) {
return;
}
self.resizeTimeout = setTimeout(function() {
self.resize();
self.initRequestLogLineChat();
self.resizeTimeout = null;
}, 500);
});
} }
}) })
}); });