diff --git a/src/main/java/neatlogic/module/tenant/api/healthcheck/ClearExecutingSQLApi.java b/src/main/java/neatlogic/module/tenant/api/healthcheck/ClearExecutingSQLApi.java new file mode 100644 index 0000000000000000000000000000000000000000..93b4821143018287f24de31e0b8dc2951f9e997a --- /dev/null +++ b/src/main/java/neatlogic/module/tenant/api/healthcheck/ClearExecutingSQLApi.java @@ -0,0 +1,44 @@ +/* + * + * Copyright (C) 2025 TechSure Co., Ltd. All Rights Reserved. + * This file is part of the NeatLogic software. + * Licensed under the NeatLogic Sustainable Use License (NSUL), Version 4.x – 2025. + * You may use this file only in compliance with the License. + * See the LICENSE file distributed with this work for the full license text. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +package neatlogic.module.tenant.api.healthcheck; + +import com.alibaba.fastjson.JSONObject; +import neatlogic.framework.auth.core.AuthAction; +import neatlogic.framework.auth.label.ADMIN; +import neatlogic.framework.dao.plugin.ExecutingSQLInterceptor; +import neatlogic.framework.restful.annotation.OperationType; +import neatlogic.framework.restful.constvalue.OperationTypeEnum; +import neatlogic.framework.restful.core.privateapi.PrivateApiComponentBase; +import org.springframework.stereotype.Service; + +@Service +@AuthAction(action = ADMIN.class) +@OperationType(type = OperationTypeEnum.OPERATE) +public class ClearExecutingSQLApi extends PrivateApiComponentBase { + + @Override + public String getName() { + return "清空正在执行的sql"; + } + + @Override + public Object myDoService(JSONObject paramObj) throws Exception { + ExecutingSQLInterceptor.clearThread2ExecutingSQLMap(); + return null; + } + + @Override + public String getToken() { + return "/healthcheck/executingsql/clear"; + } +} diff --git a/src/main/java/neatlogic/module/tenant/api/healthcheck/GetExecutingSQLApi.java b/src/main/java/neatlogic/module/tenant/api/healthcheck/GetExecutingSQLApi.java new file mode 100644 index 0000000000000000000000000000000000000000..826289c7336321ecc41f48f46db9da75b2a8cbd1 --- /dev/null +++ b/src/main/java/neatlogic/module/tenant/api/healthcheck/GetExecutingSQLApi.java @@ -0,0 +1,61 @@ +/* + * + * Copyright (C) 2025 TechSure Co., Ltd. All Rights Reserved. + * This file is part of the NeatLogic software. + * Licensed under the NeatLogic Sustainable Use License (NSUL), Version 4.x – 2025. + * You may use this file only in compliance with the License. + * See the LICENSE file distributed with this work for the full license text. + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +package neatlogic.module.tenant.api.healthcheck; + +import com.alibaba.fastjson.JSONObject; +import neatlogic.framework.auth.core.AuthAction; +import neatlogic.framework.auth.label.ADMIN; +import neatlogic.framework.dao.plugin.ExecutingSQLInterceptor; +import neatlogic.framework.dto.healthcheck.DataSourceInfoVo; +import neatlogic.framework.restful.annotation.OperationType; +import neatlogic.framework.restful.constvalue.OperationTypeEnum; +import neatlogic.framework.restful.core.privateapi.PrivateApiComponentBase; +import neatlogic.framework.store.mysql.DatasourceManager; +import neatlogic.framework.store.mysql.NeatLogicBasicDataSource; +import org.springframework.stereotype.Service; + +import java.util.Map; + +@Service +@AuthAction(action = ADMIN.class) +@OperationType(type = OperationTypeEnum.OPERATE) +public class GetExecutingSQLApi extends PrivateApiComponentBase { + + @Override + public String getName() { + return "查看正在执行的sql"; + } + + @Override + public Object myDoService(JSONObject paramObj) throws Exception { + JSONObject resultObj = new JSONObject(); + Map thread2ExecutingSQLMap = ExecutingSQLInterceptor.getThread2ExecutingSQLMap(); + resultObj.put("executingSQLMap", thread2ExecutingSQLMap); + NeatLogicBasicDataSource datasource = DatasourceManager.getDatasource(); + DataSourceInfoVo dataSourceInfoVo = new DataSourceInfoVo(); + dataSourceInfoVo.setPoolName(datasource.getPoolName()); + if (datasource.getHikariPoolMXBean() != null) { + dataSourceInfoVo.setIdleConnections(datasource.getHikariPoolMXBean().getIdleConnections()); + dataSourceInfoVo.setActiveConnections(datasource.getHikariPoolMXBean().getActiveConnections()); + dataSourceInfoVo.setThreadsAwaitingConnection(datasource.getHikariPoolMXBean().getThreadsAwaitingConnection()); + dataSourceInfoVo.setTotalConnections(datasource.getHikariPoolMXBean().getTotalConnections()); + } + resultObj.put("dataSourceInfoVo", dataSourceInfoVo); + return resultObj; + } + + @Override + public String getToken() { + return "/healthcheck/executingsql/get"; + } +} diff --git a/src/main/java/neatlogic/module/tenant/api/healthcheck/ThreadDumpApi.java b/src/main/java/neatlogic/module/tenant/api/healthcheck/ThreadDumpApi.java index 2e27798b05f6fe00cc99e02d861d5fd0221ab643..213f780940bf45b622cc831ee5d75188edd1b969 100644 --- a/src/main/java/neatlogic/module/tenant/api/healthcheck/ThreadDumpApi.java +++ b/src/main/java/neatlogic/module/tenant/api/healthcheck/ThreadDumpApi.java @@ -21,18 +21,10 @@ import neatlogic.framework.restful.annotation.Description; import neatlogic.framework.restful.annotation.OperationType; import neatlogic.framework.restful.constvalue.OperationTypeEnum; import neatlogic.framework.restful.core.privateapi.PrivateApiComponentBase; +import neatlogic.framework.util.ThreadUtil; import org.springframework.stereotype.Service; -import java.io.IOException; import java.io.StringWriter; -import java.io.Writer; -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadInfo; -import java.lang.management.ThreadMXBean; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; @Service @AuthAction(action = ADMIN.class) @@ -54,41 +46,11 @@ public class ThreadDumpApi extends PrivateApiComponentBase { return null; } - private static void dumpTraces(ThreadMXBean mxBean, Map threadInfoMap, Writer writer) throws IOException { - Map stacks = Thread.getAllStackTraces(); - long now = System.currentTimeMillis(); - writer.write("=================" + stacks.size() + " thread of " + RequestContext.get().getRequest().getLocalAddr() + " at " + new SimpleDateFormat("yyyy/MM/dd HH:mm:ss z").format(new Date(now)) + " start.serverId is " + Config.SCHEDULE_SERVER_ID + "=================\n\n"); - for (Map.Entry entry : stacks.entrySet()) { - Thread thread = entry.getKey(); - writer.write("\"" + thread.getName() + "\" prio=" + thread.getPriority() + " tid=" + thread.getId() + " " + thread.getState() + " " + (thread.isDaemon() ? "deamon" : "worker")); - ThreadInfo threadInfo = threadInfoMap.get(thread.getId()); - if (threadInfo != null) { - writer.write(" native=" + threadInfo.isInNative() + ", suspended=" + threadInfo.isSuspended() + ", block=" + threadInfo.getBlockedCount() + ", wait=" + threadInfo.getWaitedCount()); - writer.write(" lock=" + threadInfo.getLockName() + " owned by " + threadInfo.getLockOwnerName() + " (" + threadInfo.getLockOwnerId() + "), cpu=" + (mxBean.getThreadCpuTime(threadInfo.getThreadId()) / 1000000L) + ", user=" + (mxBean.getThreadUserTime(threadInfo.getThreadId()) / 1000000L) + "\n"); - } - for (StackTraceElement element : entry.getValue()) { - writer.write("\t\t"); - writer.write(element.toString()); - writer.write("\n"); - } - writer.write("\n"); - } - writer.write("=================" + stacks.size() + " thread of " + RequestContext.get().getUrl() + " at " + new SimpleDateFormat("yyyy/MM/dd HH:mm:ss z").format(new Date(now)) + " end.=================\n\n"); - - } - @Description(desc = "打印线程快照接口") @Override public Object myDoService(JSONObject paramObj) throws Exception { - ThreadMXBean mxBean = ManagementFactory.getThreadMXBean(); - ThreadInfo[] threadInfos = mxBean.getThreadInfo(mxBean.getAllThreadIds(), 0); - Map threadInfoMap = new HashMap<>(); - for (ThreadInfo threadInfo : threadInfos) { - threadInfoMap.put(threadInfo.getThreadId(), threadInfo); - } - StringWriter writer = new StringWriter(); - dumpTraces(mxBean, threadInfoMap, writer); + ThreadUtil.dumpTraces(writer); return writer.toString(); } }