diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/RdbDmlController.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/RdbDmlController.java index c0b46bf7..d7a6f18f 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/RdbDmlController.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/RdbDmlController.java @@ -2,22 +2,33 @@ package ai.chat2db.server.web.api.controller.rdb; import java.sql.Connection; import java.util.List; +import java.util.Objects; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import ai.chat2db.server.domain.api.model.Config; import ai.chat2db.server.domain.api.param.DlExecuteParam; import ai.chat2db.server.domain.api.param.UpdateSelectResultParam; +import ai.chat2db.server.domain.api.service.ConfigService; import ai.chat2db.server.domain.api.service.DlTemplateService; import ai.chat2db.server.tools.base.enums.DataSourceTypeEnum; import ai.chat2db.server.tools.base.wrapper.result.DataResult; import ai.chat2db.server.tools.base.wrapper.result.ListResult; import ai.chat2db.server.web.api.aspect.ConnectionInfoAspect; +import ai.chat2db.server.web.api.controller.ai.chat2db.client.Chat2dbAIClient; import ai.chat2db.server.web.api.controller.rdb.converter.RdbWebConverter; import ai.chat2db.server.web.api.controller.rdb.request.DdlCountRequest; import ai.chat2db.server.web.api.controller.rdb.request.DmlRequest; import ai.chat2db.server.web.api.controller.rdb.request.DmlTableRequest; import ai.chat2db.server.web.api.controller.rdb.request.SelectResultUpdateRequest; import ai.chat2db.server.web.api.controller.rdb.vo.ExecuteResultVO; +import ai.chat2db.server.web.api.http.GatewayClientService; +import ai.chat2db.server.web.api.http.request.SqlExecuteHistoryCreateRequest; +import ai.chat2db.server.web.api.util.ApplicationContextUtil; import ai.chat2db.spi.model.ExecuteResult; import ai.chat2db.spi.sql.Chat2DBContext; +import com.google.common.collect.Lists; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.RequestBody; @@ -43,6 +54,11 @@ public class RdbDmlController { @Autowired private DlTemplateService dlTemplateService; + @Autowired + private GatewayClientService gatewayClientService; + + public static ExecutorService executorService = Executors.newFixedThreadPool(10); + /** * 增删改查等数据运维 * @@ -54,9 +70,48 @@ public class RdbDmlController { DlExecuteParam param = rdbWebConverter.request2param(request); ListResult resultDTOListResult = dlTemplateService.execute(param); List resultVOS = rdbWebConverter.dto2vo(resultDTOListResult.getData()); + String type = Chat2DBContext.getConnectInfo().getDbType(); + String clientId = getApiKey(); + String sqlContent = request.getSql(); + executorService.submit(() -> { + try { + addOperationLog(clientId, type, sqlContent, resultDTOListResult.getErrorMessage(), resultDTOListResult.getSuccess(), resultVOS); + } catch (Exception e) { + // do nothing + } + }); return ListResult.of(resultVOS); } + private void addOperationLog(String clientId, String sqlType, String sqlContent, String errorMessage, Boolean isSuccess, List executeResultVOS) { + SqlExecuteHistoryCreateRequest createRequest = new SqlExecuteHistoryCreateRequest(); + createRequest.setClientId(clientId); + createRequest.setErrorMessage(errorMessage); + createRequest.setDatabaseType(sqlType); + createRequest.setSqlContent(sqlContent); + createRequest.setExecuteStatus(isSuccess ? "success" : "fail"); + executeResultVOS.forEach(executeResultVO -> { + createRequest.setSqlType(executeResultVO.getSqlType()); + createRequest.setDuration(executeResultVO.getDuration()); + createRequest.setTableName(executeResultVO.getTableName()); + gatewayClientService.addOperationLog(createRequest); + }); + } + + /** + * query chat2db apikey + * + * @return + */ + private String getApiKey() { + ConfigService configService = ApplicationContextUtil.getBean(ConfigService.class); + Config keyConfig = configService.find(Chat2dbAIClient.CHAT2DB_OPENAI_KEY).getData(); + if (Objects.isNull(keyConfig) || StringUtils.isBlank(keyConfig.getContent())) { + return null; + } + return keyConfig.getContent(); + } + /** * 查询表结构信息 * @@ -90,7 +145,18 @@ public class RdbDmlController { if (!result.success()) { return DataResult.error(result.getErrorCode(), result.getErrorMessage()); } - return DataResult.of(rdbWebConverter.dto2vo(result.getData())); + ExecuteResultVO executeResultVO = rdbWebConverter.dto2vo(result.getData()); + String type = Chat2DBContext.getConnectInfo().getDbType(); + String sqlContent = request.getSql(); + String clientId = getApiKey(); + executorService.submit(() -> { + try { + addOperationLog(clientId, type, sqlContent, result.getErrorMessage(), result.getSuccess(), Lists.newArrayList(executeResultVO)); + } catch (Exception e) { + // do nothing + } + }); + return DataResult.of(executeResultVO); } diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/http/GatewayClientService.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/http/GatewayClientService.java index b2fab090..54b73e8c 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/http/GatewayClientService.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/http/GatewayClientService.java @@ -3,10 +3,7 @@ package ai.chat2db.server.web.api.http; import ai.chat2db.server.tools.base.wrapper.result.ActionResult; import ai.chat2db.server.tools.base.wrapper.result.DataResult; import ai.chat2db.server.tools.common.config.Chat2dbProperties; -import ai.chat2db.server.web.api.http.request.EsTableSchemaRequest; -import ai.chat2db.server.web.api.http.request.KnowledgeRequest; -import ai.chat2db.server.web.api.http.request.TableSchemaRequest; -import ai.chat2db.server.web.api.http.request.WhiteListRequest; +import ai.chat2db.server.web.api.http.request.*; import ai.chat2db.server.web.api.http.response.*; import com.dtflys.forest.Forest; import com.dtflys.forest.utils.TypeReference; @@ -216,4 +213,14 @@ public class GatewayClientService { return result; } + public ActionResult addOperationLog(SqlExecuteHistoryCreateRequest request) { + ActionResult result = Forest.post(chat2dbProperties.getGateway().getBaseUrl() + "/api/client/sql/execute/history") + .connectTimeout(Duration.ofMillis(5000)) + .readTimeout(Duration.ofMillis(10000)) + .contentType("application/json") + .addBody(request) + .execute(new TypeReference<>() { + }); + return result; + } } diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/http/request/SqlExecuteHistoryCreateRequest.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/http/request/SqlExecuteHistoryCreateRequest.java new file mode 100644 index 00000000..777bd70f --- /dev/null +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/http/request/SqlExecuteHistoryCreateRequest.java @@ -0,0 +1,66 @@ +package ai.chat2db.server.web.api.http.request; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.io.Serializable; + +/** + *

+ * sql执行历史 + *

+ * + * @author chat2db + * @since 2023-12-25 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class SqlExecuteHistoryCreateRequest implements Serializable { + + private static final long serialVersionUID = 1L; + + + /** + * 数据库类型 + */ + private String databaseType; + + /** + * 执行SQL + */ + private String sqlContent; + + /** + * 客户端ID + */ + private String clientId; + + /** + * 状态 + */ + private String executeStatus; + + /** + * 错误消息 + */ + private String errorMessage; + + /** + * sql 类型 + */ + private String sqlType; + + /** + * 执行持续时间 + */ + private Long duration; + + /** + * 表名 + */ + private String tableName; +}