Add operation log

This commit is contained in:
SwallowGG
2023-10-14 16:47:26 +08:00
parent 709fc8536f
commit ce0ccd15cf
12 changed files with 197 additions and 13 deletions

View File

@ -54,4 +54,31 @@ public class OperationLog {
* ddl内容 * ddl内容
*/ */
private String ddl; private String ddl;
/**
* 状态
*/
private String status;
/**
* 操作行数
*/
private Long operationRows;
/**
* 使用时长
*/
private Long useTime;
/**
* 扩展信息
*/
private String extendInfo;
/**
* schema名称
*/
private String schemaName;
} }

View File

@ -34,4 +34,30 @@ public class OperationLogCreateParam {
* ddl内容 * ddl内容
*/ */
private String ddl; private String ddl;
/**
* 状态
*/
private String status;
/**
* 操作行数
*/
private Long operationRows;
/**
* 使用时长
*/
private Long useTime;
/**
* 扩展信息
*/
private String extendInfo;
/**
* schema名称
*/
private String schemaName;
} }

View File

@ -21,4 +21,19 @@ public class OperationLogPageQueryParam extends PageQueryParam {
* 搜索关键词 * 搜索关键词
*/ */
private String searchKey; private String searchKey;
/**
* 数据源id
*/
private Long dataSourceId;
/**
* 数据库名称
*/
private String databaseName;
/**
* schema名称
*/
private String schemaName;
} }

View File

@ -8,7 +8,10 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import ai.chat2db.server.domain.api.param.*; import ai.chat2db.server.domain.api.param.*;
import ai.chat2db.server.domain.api.param.operation.OperationLogCreateParam;
import ai.chat2db.server.domain.api.service.OperationLogService;
import ai.chat2db.spi.MetaData; import ai.chat2db.spi.MetaData;
import ai.chat2db.spi.sql.ConnectInfo;
import com.alibaba.druid.DbType; import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.PagerUtils; import com.alibaba.druid.sql.PagerUtils;
import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.SQLUtils;
@ -35,6 +38,7 @@ import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/** /**
@ -46,15 +50,21 @@ import org.springframework.stereotype.Service;
@Service @Service
public class DlTemplateServiceImpl implements DlTemplateService { public class DlTemplateServiceImpl implements DlTemplateService {
@Autowired
private OperationLogService operationLogService;
@Override @Override
public ListResult<ExecuteResult> execute(DlExecuteParam param) { public ListResult<ExecuteResult> execute(DlExecuteParam param) {
if (StringUtils.isBlank(param.getSql())) { if (StringUtils.isBlank(param.getSql())) {
return ListResult.empty(); return ListResult.empty();
} }
// 解析sql // 解析sql
RemoveSpecialGO(param); String type = Chat2DBContext.getConnectInfo().getDbType();
DbType dbType = DbType dbType = JdbcUtils.parse2DruidDbType(type);
JdbcUtils.parse2DruidDbType(Chat2DBContext.getConnectInfo().getDbType()); if ("SQLSERVER".equalsIgnoreCase(type)) {
RemoveSpecialGO(param);
}
List<String> sqlList = SqlUtils.parse(param.getSql(), dbType); List<String> sqlList = SqlUtils.parse(param.getSql(), dbType);
@ -73,6 +83,7 @@ public class DlTemplateServiceImpl implements DlTemplateService {
listResult.errorCode(executeResult.getDescription()); listResult.errorCode(executeResult.getDescription());
listResult.setErrorMessage(executeResult.getMessage()); listResult.setErrorMessage(executeResult.getMessage());
} }
addOperationLog(executeResult);
} }
return listResult; return listResult;
} }
@ -90,11 +101,12 @@ public class DlTemplateServiceImpl implements DlTemplateService {
connection.setAutoCommit(false); connection.setAutoCommit(false);
for (String originalSql : sqlList) { for (String originalSql : sqlList) {
ExecuteResult executeResult = SQLExecutor.getInstance().executeUpdate(originalSql, connection, 1); ExecuteResult executeResult = SQLExecutor.getInstance().executeUpdate(originalSql, connection, 1);
dataResult.setData(executeResult); dataResult.setData(executeResult);
addOperationLog(executeResult);
} }
connection.commit(); connection.commit();
}catch (Exception e){ } catch (Exception e) {
log.error("executeUpdate error",e); log.error("executeUpdate error", e);
dataResult.setSuccess(false); dataResult.setSuccess(false);
dataResult.setErrorCode("connection error"); dataResult.setErrorCode("connection error");
dataResult.setErrorMessage(e.getMessage()); dataResult.setErrorMessage(e.getMessage());
@ -107,7 +119,7 @@ public class DlTemplateServiceImpl implements DlTemplateService {
if (StringUtils.isBlank(sql)) { if (StringUtils.isBlank(sql)) {
return; return;
} }
sql = sql.replaceAll("(?i)\\s*go\\s*", ";"); sql = sql.replaceAll("(?mi)^[ \\t]*go[ \\t]*$", ";");
param.setSql(sql); param.setSql(sql);
} }
@ -276,6 +288,9 @@ public class DlTemplateServiceImpl implements DlTemplateService {
} }
private String getInsertSql(UpdateSelectResultParam param, List<String> row, MetaData metaSchema) { private String getInsertSql(UpdateSelectResultParam param, List<String> row, MetaData metaSchema) {
if (CollectionUtils.isEmpty(row)) {
return "";
}
StringBuilder script = new StringBuilder(); StringBuilder script = new StringBuilder();
script.append("INSERT INTO ").append(metaSchema.getMetaDataName(param.getDatabaseName(), param.getSchemaName(), param.getTableName())) script.append("INSERT INTO ").append(metaSchema.getMetaDataName(param.getDatabaseName(), param.getSchemaName(), param.getTableName()))
.append(" ("); .append(" (");
@ -301,6 +316,9 @@ public class DlTemplateServiceImpl implements DlTemplateService {
private String getUpdateSql(UpdateSelectResultParam param, List<String> row, List<String> odlRow, MetaData metaSchema) { private String getUpdateSql(UpdateSelectResultParam param, List<String> row, List<String> odlRow, MetaData metaSchema) {
StringBuilder script = new StringBuilder(); StringBuilder script = new StringBuilder();
if (CollectionUtils.isEmpty(row) || CollectionUtils.isEmpty(odlRow)) {
return "";
}
script.append("UPDATE ").append(metaSchema.getMetaDataName(param.getDatabaseName(), param.getSchemaName(), param.getTableName())) script.append("UPDATE ").append(metaSchema.getMetaDataName(param.getDatabaseName(), param.getSchemaName(), param.getTableName()))
.append(" set "); .append(" set ");
for (int i = 1; i < row.size(); i++) { for (int i = 1; i < row.size(); i++) {
@ -336,4 +354,24 @@ public class DlTemplateServiceImpl implements DlTemplateService {
return executeResult; return executeResult;
} }
private void addOperationLog(ExecuteResult executeResult) {
if (executeResult == null) {
return;
}
try {
ConnectInfo connectInfo = Chat2DBContext.getConnectInfo();
OperationLogCreateParam createParam = new OperationLogCreateParam();
createParam.setDdl(executeResult.getSql());
createParam.setStatus(executeResult.getSuccess() ? "success" : "fail");
createParam.setDatabaseName(connectInfo.getDatabaseName());
createParam.setDataSourceId(connectInfo.getDataSourceId());
createParam.setSchemaName(connectInfo.getSchemaName());
createParam.setUseTime(executeResult.getDuration());
createParam.setType(connectInfo.getDbType());
createParam.setOperationRows(executeResult.getUpdateCount() != null ? Long.valueOf(executeResult.getUpdateCount()):null);
operationLogService.create(createParam);
} catch (Exception e) {
log.error("addOperationLog error:", e);
}
}
} }

View File

@ -58,7 +58,10 @@ public class OperationLogServiceImpl implements OperationLogService {
public PageResult<OperationLog> queryPage(OperationLogPageQueryParam param) { public PageResult<OperationLog> queryPage(OperationLogPageQueryParam param) {
EasyLambdaQueryWrapper<OperationLogDO> queryWrapper = new EasyLambdaQueryWrapper<>(); EasyLambdaQueryWrapper<OperationLogDO> queryWrapper = new EasyLambdaQueryWrapper<>();
queryWrapper.likeWhenPresent(OperationLogDO::getDdl, EasySqlUtils.buildLikeRightFuzzy(param.getSearchKey())) queryWrapper.likeWhenPresent(OperationLogDO::getDdl, EasySqlUtils.buildLikeRightFuzzy(param.getSearchKey()))
.eqWhenPresent(OperationLogDO::getUserId, param.getUserId()) .eqWhenPresent(OperationLogDO::getUserId, param.getUserId())
.eqWhenPresent(OperationLogDO::getDataSourceId, param.getDataSourceId())
.eqWhenPresent(OperationLogDO::getDatabaseName, param.getDatabaseName())
.eqWhenPresent(OperationLogDO::getSchemaName, param.getSchemaName())
; ;
Integer start = param.getPageNo(); Integer start = param.getPageNo();
Integer offset = param.getPageSize(); Integer offset = param.getPageSize();

View File

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Date;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@ -13,8 +14,8 @@ import lombok.Setter;
* 我的执行记录表 * 我的执行记录表
* </p> * </p>
* *
* @author ali-dbhub * @author chat2db
* @since 2022-12-28 * @since 2023-10-14
*/ */
@Getter @Getter
@Setter @Setter
@ -63,4 +64,29 @@ public class OperationLogDO implements Serializable {
* 用户id * 用户id
*/ */
private Long userId; private Long userId;
/**
* 状态
*/
private String status;
/**
* 操作行数
*/
private Long operationRows;
/**
* 使用时长
*/
private Long useTime;
/**
* 扩展信息
*/
private String extendInfo;
/**
* schema名称
*/
private String schemaName;
} }

View File

@ -8,8 +8,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
* 我的执行记录表 Mapper 接口 * 我的执行记录表 Mapper 接口
* </p> * </p>
* *
* @author ali-dbhub * @author chat2db
* @since 2022-12-28 * @since 2023-10-14
*/ */
public interface OperationLogMapper extends BaseMapper<OperationLogDO> { public interface OperationLogMapper extends BaseMapper<OperationLogDO> {

View File

@ -0,0 +1,3 @@
ALTER TABLE `operation_log`
ADD COLUMN `schema_name` varchar(256) COMMENT 'schema名称';
create INDEX idx_op_data_source_id on operation_log(data_source_id) ;

View File

@ -35,7 +35,7 @@ public class MybatisGeneratorTest extends BaseTest {
//doGenerator(Lists.newArrayList("operation_saved")); //doGenerator(Lists.newArrayList("operation_saved"));
//doGenerator(Lists.newArrayList("environment","data_source","team","team_dbhub_user","data_source_access", //doGenerator(Lists.newArrayList("environment","data_source","team","team_dbhub_user","data_source_access",
// "dbhub_user")); // "dbhub_user"));
doGenerator(Lists.newArrayList("table_cache")); doGenerator(Lists.newArrayList("operation_log"));
} }
private void doGenerator(List<String> tableList) { private void doGenerator(List<String> tableList) {

View File

@ -66,4 +66,5 @@ public class OperationLogController {
return operationLogService.create(param); return operationLogService.create(param);
} }
} }

View File

@ -16,4 +16,19 @@ public class OperationLogQueryRequest extends PageQueryRequest {
* 模糊词搜索 * 模糊词搜索
*/ */
private String searchKey; private String searchKey;
/**
* 数据源id
*/
private Long dataSourceId;
/**
* 数据库名称
*/
private String databaseName;
/**
* schema名称
*/
private String schemaName;
} }

View File

@ -45,4 +45,34 @@ public class OperationLogVO {
* ddl语言类型 * ddl语言类型
*/ */
private String type; private String type;
/**
* ddl内容
*/
private String ddl;
/**
* 状态
*/
private String status;
/**
* 操作行数
*/
private Long operationRows;
/**
* 使用时长
*/
private Long useTime;
/**
* 扩展信息
*/
private String extendInfo;
/**
* schema名称
*/
private String schemaName;
} }