diff --git a/src/main/java/neatlogic/framework/asynchronization/threadlocal/RequestContext.java b/src/main/java/neatlogic/framework/asynchronization/threadlocal/RequestContext.java index 84907aa3cbfbdeade0bdc5ffafef305a21d287ea..3618f8b7fa32ce5b6ffbba4c2bf98b1ac57ba2f2 100644 --- a/src/main/java/neatlogic/framework/asynchronization/threadlocal/RequestContext.java +++ b/src/main/java/neatlogic/framework/asynchronization/threadlocal/RequestContext.java @@ -16,6 +16,7 @@ along with this program. If not, see .*/ package neatlogic.framework.asynchronization.threadlocal; import neatlogic.framework.common.util.IpUtil; +import neatlogic.framework.dto.healthcheck.RequestSqlAuditVo; import neatlogic.framework.dto.healthcheck.SqlAuditVo; import neatlogic.framework.restful.constvalue.RejectSource; import org.apache.commons.lang3.StringUtils; @@ -46,7 +47,9 @@ public class RequestContext implements Serializable { //语言 Locale locale; //收集该请求执行的sql语句 - private List sqlAuditList = Collections.synchronizedList(new ArrayList<>()); +// private List sqlAuditList = Collections.synchronizedList(new ArrayList<>()); + + private RequestSqlAuditVo requestSqlAuditVo; public String getUrl() { return url; @@ -112,16 +115,28 @@ public class RequestContext implements Serializable { this.locale = locale; } - public List getSqlAuditList() { - return sqlAuditList; +// public List getSqlAuditList() { +// return sqlAuditList; +// } +// +// public void setSqlAuditList(List sqlAuditList) { +// this.sqlAuditList = sqlAuditList; +// } + + public void addSqlAudit(SqlAuditVo sqlAuditVo) { +// sqlAuditList.add(sqlAuditVo); + if (requestSqlAuditVo == null) { + requestSqlAuditVo = new RequestSqlAuditVo(); + } + requestSqlAuditVo.addSqlAudit(sqlAuditVo); } - public void setSqlAuditList(List sqlAuditList) { - this.sqlAuditList = sqlAuditList; + public RequestSqlAuditVo getRequestSqlAuditVo() { + return requestSqlAuditVo; } - public void addSqlAudit(SqlAuditVo sqlAuditVo) { - sqlAuditList.add(sqlAuditVo); + public void setRequestSqlAuditVo(RequestSqlAuditVo requestSqlAuditVo) { + this.requestSqlAuditVo = requestSqlAuditVo; } public static RequestContext init(RequestContext _requestContext) { @@ -129,7 +144,8 @@ public class RequestContext implements Serializable { if (_requestContext != null) { context.setUrl(_requestContext.getUrl()); context.setLocale(_requestContext.getLocale()); - context.setSqlAuditList(_requestContext.getSqlAuditList()); +// context.setSqlAuditList(_requestContext.getSqlAuditList()); + context.setRequestSqlAuditVo(_requestContext.getRequestSqlAuditVo()); context.setRemoteAddr(_requestContext.getRemoteAddr()); String tempUrl = _requestContext.getUrl(); if (tempUrl == null) { diff --git a/src/main/java/neatlogic/framework/dao/plugin/SqlCostInterceptor.java b/src/main/java/neatlogic/framework/dao/plugin/SqlCostInterceptor.java index 7052d0e40dfaedfe1d58ba3053c8a9ece6490580..5865548ffe6bc59c62cfe4e0e69f03c0caf1b7ee 100644 --- a/src/main/java/neatlogic/framework/dao/plugin/SqlCostInterceptor.java +++ b/src/main/java/neatlogic/framework/dao/plugin/SqlCostInterceptor.java @@ -80,6 +80,16 @@ public class SqlCostInterceptor implements Interceptor { if (sqlSet.contains(id)) { return true; } + // 支持接口token作为监控目标 + RequestContext requestContext = RequestContext.get(); + if (requestContext != null && StringUtils.isNotBlank(requestContext.getUrl())) { + // 这里requestContext.getUrl()值为/neatlogic/api/rest/xxx/yyy/zzz + for (String element : sqlSet) { + if (requestContext.getUrl().endsWith(element)) { + return true; + } + } + } if (id.contains(".")) { id = id.substring(id.lastIndexOf(".") + 1); } diff --git a/src/main/java/neatlogic/framework/dto/healthcheck/RequestSqlAuditVo.java b/src/main/java/neatlogic/framework/dto/healthcheck/RequestSqlAuditVo.java new file mode 100644 index 0000000000000000000000000000000000000000..9c3350df374fdb3a803cd62a0c82b144cb390e7b --- /dev/null +++ b/src/main/java/neatlogic/framework/dto/healthcheck/RequestSqlAuditVo.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2025 深圳极向量科技有限公司 All Rights Reserved. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package neatlogic.framework.dto.healthcheck; + +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +public class RequestSqlAuditVo { + // 没有使用缓存的总耗时 + private long notUseCacheTotalTimeCost = 0; + // 总耗时 + private long totalTimeCost = 0; + // 相同IDSql审计列表 + private final List sameIdSqlAuditList = Collections.synchronizedList(new ArrayList<>()); + + public long getNotUseCacheTotalTimeCost() { + return this.notUseCacheTotalTimeCost; + } + + public long getTotalTimeCost() { + return this.totalTimeCost; + } + + public List getSameIdSqlAuditList() { + return this.sameIdSqlAuditList; + } + + public void addSqlAudit(SqlAuditVo sqlAuditVo) { + if (sqlAuditVo != null) { + int notUseCacheCount = 0; + long notUseCacheTimeCost = 0; + long timeCost = sqlAuditVo.getTimeCost(); + this.totalTimeCost += timeCost; + if (StringUtils.isBlank(sqlAuditVo.getUseCacheLevel())) { + notUseCacheCount = 1; + notUseCacheTimeCost = timeCost; + this.notUseCacheTotalTimeCost += timeCost; + } + SameIdSqlAuditVo sameIdSqlAuditVo = null; + for (SameIdSqlAuditVo sameIdSqlAudit : this.sameIdSqlAuditList) { + if (Objects.equals(sameIdSqlAudit.getId(), sqlAuditVo.getId())) { + sameIdSqlAuditVo = sameIdSqlAudit; + } + } + if (sameIdSqlAuditVo == null) { + sameIdSqlAuditVo = new SameIdSqlAuditVo(sqlAuditVo.getId());//, timeCost, notUseCacheTimeCost, notUseCacheCount, sqlAuditVo.getUseCacheLevel(), sqlAuditVo.getSql() + this.sameIdSqlAuditList.add(sameIdSqlAuditVo); + } + sameIdSqlAuditVo.setTotalTimeCost(sameIdSqlAuditVo.getTotalTimeCost() + timeCost); + sameIdSqlAuditVo.setNotUseCacheTotalTimeCost(sameIdSqlAuditVo.getNotUseCacheTotalTimeCost() + notUseCacheTimeCost); + sameIdSqlAuditVo.setNotUseCacheCount(sameIdSqlAuditVo.getNotUseCacheCount() + notUseCacheCount); + sameIdSqlAuditVo.getTimeCostList().add(timeCost); + sameIdSqlAuditVo.getUseCacheLevelList().add(sqlAuditVo.getUseCacheLevel()); + sameIdSqlAuditVo.getSqlList().add(sqlAuditVo.getSql()); + } + } + + public static class SameIdSqlAuditVo { + // sqlID + private final String id; + // 耗时列表 + private final List timeCostList = Collections.synchronizedList(new ArrayList<>()); + // 总耗时 + private long totalTimeCost = 0; + // 没有使用缓存的总耗时 + private long notUseCacheTotalTimeCost = 0; + // 没有使用缓存的次数 + private int notUseCacheCount = 0; + // 是否使用缓存列表 + private final List useCacheLevelList = Collections.synchronizedList(new ArrayList<>()); + // sql语句列表 + private final List sqlList = Collections.synchronizedList(new ArrayList<>()); + + public SameIdSqlAuditVo(String id) { + this.id = id; + } + + public String getId() { + return id; + } + + public List getTimeCostList() { + return timeCostList; + } + + public long getTotalTimeCost() { + return totalTimeCost; + } + + public void setTotalTimeCost(long totalTimeCost) { + this.totalTimeCost = totalTimeCost; + } + + public long getNotUseCacheTotalTimeCost() { + return notUseCacheTotalTimeCost; + } + + public void setNotUseCacheTotalTimeCost(long notUseCacheTotalTimeCost) { + this.notUseCacheTotalTimeCost = notUseCacheTotalTimeCost; + } + + public int getNotUseCacheCount() { + return notUseCacheCount; + } + + public void setNotUseCacheCount(int notUseCacheCount) { + this.notUseCacheCount = notUseCacheCount; + } + + public List getUseCacheLevelList() { + return useCacheLevelList; + } + + public List getSqlList() { + return sqlList; + } + } +} diff --git a/src/main/java/neatlogic/module/framework/restful/dispatch/handler/AnonymousApiDispatcher.java b/src/main/java/neatlogic/module/framework/restful/dispatch/handler/AnonymousApiDispatcher.java index 7fc34b9011a5b14c22015474627d75e9b4c6eac0..b96fe0f87d00f753f3f0cb424d8f4075eaaafba7 100644 --- a/src/main/java/neatlogic/module/framework/restful/dispatch/handler/AnonymousApiDispatcher.java +++ b/src/main/java/neatlogic/module/framework/restful/dispatch/handler/AnonymousApiDispatcher.java @@ -48,7 +48,6 @@ import neatlogic.framework.restful.ratelimiter.RateLimiterTokenBucket; import neatlogic.framework.util.$; import neatlogic.framework.util.AnonymousApiTokenUtil; import neatlogic.module.framework.restful.counter.ApiAccessCountService; -import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; @@ -163,7 +162,8 @@ public class AnonymousApiDispatcher { returnObj.put("TimeCost", endTime - startTime); returnObj.put("Return", returnV); returnObj.put("Status", "OK"); - returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); +// returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); + returnObj.put("requestSqlAudit", RequestContext.get().getRequestSqlAuditVo()); } else { returnObj.putAll(JSON.parseObject(JSON.toJSONString(returnV))); } @@ -190,7 +190,8 @@ public class AnonymousApiDispatcher { returnObj.put("TimeCost", endtime - starttime); returnObj.put("Return", returnV); returnObj.put("Status", "OK"); - returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); +// returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); + returnObj.put("requestSqlAudit", RequestContext.get().getRequestSqlAuditVo()); } else { returnObj.putAll(JSON.parseObject(JSON.toJSONString(returnV))); } @@ -217,7 +218,8 @@ public class AnonymousApiDispatcher { returnObj.put("TimeCost", endtime - starttime); returnObj.put("Return", returnV); returnObj.put("Status", "OK"); - returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); +// returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); + returnObj.put("requestSqlAudit", RequestContext.get().getRequestSqlAuditVo()); } else { returnObj.putAll(JSON.parseObject(JSON.toJSONString(returnV))); } @@ -244,7 +246,8 @@ public class AnonymousApiDispatcher { returnObj.put("TimeCost", endtime - starttime); returnObj.put("Return", returnV); returnObj.put("Status", "OK"); - returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); +// returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); + returnObj.put("requestSqlAudit", RequestContext.get().getRequestSqlAuditVo()); if (restComponent.disableReturnCircularReferenceDetect()) { returnObj.put("_disableDetect", true); } diff --git a/src/main/java/neatlogic/module/framework/restful/dispatch/handler/ApiDispatcher.java b/src/main/java/neatlogic/module/framework/restful/dispatch/handler/ApiDispatcher.java index d4cd2550e7ad8be6f018714bf1968858d0cdb7b9..a09a0aa0b640e5acde430ccd43b91fde01efce33 100644 --- a/src/main/java/neatlogic/module/framework/restful/dispatch/handler/ApiDispatcher.java +++ b/src/main/java/neatlogic/module/framework/restful/dispatch/handler/ApiDispatcher.java @@ -45,7 +45,6 @@ import neatlogic.framework.util.$; import neatlogic.framework.util.HttpRequestUtil; import neatlogic.framework.util.mongodb.IJsonSerializer; import neatlogic.module.framework.restful.counter.ApiAccessCountService; -import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.reflections.Reflections; @@ -182,7 +181,8 @@ public class ApiDispatcher { returnObj.put("TimeCost", endtime - starttime); returnObj.put("Return", returnV); returnObj.put("Status", "OK"); - returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); +// returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); + returnObj.put("requestSqlAudit", RequestContext.get().getRequestSqlAuditVo()); if (restComponent.disableReturnCircularReferenceDetect()) { returnObj.put("_disableDetect", true); } @@ -212,7 +212,8 @@ public class ApiDispatcher { returnObj.put("TimeCost", endtime - starttime); returnObj.put("Return", returnV); returnObj.put("Status", "OK"); - returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); +// returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); + returnObj.put("requestSqlAudit", RequestContext.get().getRequestSqlAuditVo()); if (restComponent.disableReturnCircularReferenceDetect()) { returnObj.put("_disableDetect", true); } @@ -238,7 +239,8 @@ public class ApiDispatcher { returnObj.put("TimeCost", endtime - starttime); returnObj.put("Return", returnV); returnObj.put("Status", "OK"); - returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); +// returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); + returnObj.put("requestSqlAudit", RequestContext.get().getRequestSqlAuditVo()); if (restComponent.disableReturnCircularReferenceDetect()) { returnObj.put("_disableDetect", true); } @@ -264,7 +266,8 @@ public class ApiDispatcher { returnObj.put("TimeCost", endtime - starttime); returnObj.put("Return", returnV); returnObj.put("Status", "OK"); - returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); +// returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); + returnObj.put("requestSqlAudit", RequestContext.get().getRequestSqlAuditVo()); if (restComponent.disableReturnCircularReferenceDetect()) { returnObj.put("_disableDetect", true); } diff --git a/src/main/java/neatlogic/module/framework/restful/dispatch/handler/PublicApiDispatcher.java b/src/main/java/neatlogic/module/framework/restful/dispatch/handler/PublicApiDispatcher.java index aaba524026d03febf562a1cfca2262067e9739bc..306a37714435c8c20fbf205b2acbaa366a14c1aa 100644 --- a/src/main/java/neatlogic/module/framework/restful/dispatch/handler/PublicApiDispatcher.java +++ b/src/main/java/neatlogic/module/framework/restful/dispatch/handler/PublicApiDispatcher.java @@ -194,7 +194,8 @@ public class PublicApiDispatcher { returnObj.put("TimeCost", endtime - starttime); returnObj.put("Return", returnV); returnObj.put("Status", "OK"); - returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); +// returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); + returnObj.put("requestSqlAudit", RequestContext.get().getRequestSqlAuditVo()); } else { returnObj.putAll(JSONObject.parseObject(JSONObject.toJSONString(returnV))); } @@ -217,7 +218,8 @@ public class PublicApiDispatcher { returnObj.put("TimeCost", endtime - starttime); returnObj.put("Return", returnV); returnObj.put("Status", "OK"); - returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); +// returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); + returnObj.put("requestSqlAudit", RequestContext.get().getRequestSqlAuditVo()); } else { returnObj.putAll(JSONObject.parseObject(JSONObject.toJSONString(returnV))); } @@ -240,7 +242,8 @@ public class PublicApiDispatcher { returnObj.put("TimeCost", endtime - starttime); returnObj.put("Return", returnV); returnObj.put("Status", "OK"); - returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); +// returnObj.put("sqlList", CollectionUtils.isEmpty(RequestContext.get().getSqlAuditList()) ? null : RequestContext.get().getSqlAuditList()); + returnObj.put("requestSqlAudit", RequestContext.get().getRequestSqlAuditVo()); } else { returnObj.putAll(JSONObject.parseObject(JSONObject.toJSONString(returnV))); }