提交 8a95da21 authored 作者: Matrix's avatar Matrix

feat(历史数据): 优化了历史数据和队列的日志记录部分

上级 f20d5cc3
......@@ -17,6 +17,7 @@ import org.matrix.database.entity.TestCaseBTO;
import org.matrix.database.service.ITestDataService;
import org.matrix.database.service.impl.ActionServiceImpl;
import org.matrix.enums.ActionType;
import org.matrix.enums.ModuleType;
import org.matrix.exception.GlobalException;
import org.matrix.socket.queue.LogQueueRuntime;
import org.matrix.util.BeanFlattener;
......@@ -29,6 +30,8 @@ import java.util.stream.Collectors;
import static org.matrix.actuators.move.MoveStrategy.*;
import static org.matrix.enums.ActionType.*;
import static org.matrix.enums.ModuleType.MOVE_ACTUATOR;
import static org.matrix.enums.ModuleType.SYNTAX_PARSE;
/**
* MoveActuator. 行为执行器
......@@ -133,8 +136,7 @@ public class MoveActuator implements Actuator {
if (pathResolution) {
finalValue = expressionUtil.completeJsonPathExpression(jsonPath, finalValue);
}
log.info("[行为语法解析] 初始语法 = {} ,解析结果 = {}",dynamicString,finalValue);
LogQueueRuntime.addNewLog(String.format("[行为语法解析] 初始语法 = %s ,解析结果 = %s",dynamicString,finalValue));
LogQueueRuntime.addNewLog(this.getClass(),SYNTAX_PARSE, String.format("初始语法 = %s ,解析结果 = %s",dynamicString,finalValue));
return finalValue;
}
......@@ -154,7 +156,7 @@ public class MoveActuator implements Actuator {
public void runMove(Long moveId, Long envId, Long projectId, String caseResultData, MoveStrategy strategy) {
Action action = actionService.findByMoveAndEnv(moveId, envId)
.orElseThrow(() -> new GlobalException(String.format("没有找到指定的action动作对象,提供查询的moveId = %d,envId = %d", moveId, envId)));
LogQueueRuntime.addNewLog(String.format("准备执行行为动作,动作策略: %s,行为Id =%d ,动作id = %d", strategy, moveId, action.getId()));
LogQueueRuntime.addNewLog(this.getClass(), MOVE_ACTUATOR, String.format("准备执行行为动作,动作策略: %s,行为Id =%d ,动作id = %d", strategy, moveId, action.getId()));
// 如果是 mid 或者 aft 动作,则需要进行结果集的语法替换 与 空值判断
if (strategy != PRE_MOVE) {
......@@ -175,8 +177,7 @@ public class MoveActuator implements Actuator {
Map<String, List<Map<String, Object>>> res = resSet.get();
// 分类处理 + 结果集处理(如果不存在则put数据,如果存在则替换数据)
log.info("[动作执行器] 正在执行动作 actionId = {},动作类型 = {},动作策略 = {},动作参数 = {}", action.getId(), action, strategy, runtimeDetail);
LogQueueRuntime.addNewLog(String.format("[动作执行器] 正在执行动作 actionId = %d,动作类型 = %sΩ,动作策略 = %s,动作参数 = %s", action.getId(), action, strategy, runtimeDetail));
LogQueueRuntime.addNewLog(this.getClass(),MOVE_ACTUATOR, String.format("正在执行动作 actionId = %d,动作类型 = %sΩ,动作策略 = %s,动作参数 = %s", action.getId(), action, strategy, runtimeDetail));
if (actionType == SQL_ACTION) {
List<Map<String, Object>> resultMap = sqlActionHandler(envId, projectId, runtimeDetail);
res.put(key, resultMap);
......@@ -239,7 +240,7 @@ public class MoveActuator implements Actuator {
throw new GlobalException("[行为执行器]行为语法里定位部分的语法没有提供合适的actionId!例如需要提供pre1,pre2,您提供的部分是: " + col);
}
String key = strategy + "_" + actionId;
LogQueueRuntime.addNewLog("行为执行器] KEY值拼接完成,KEY值 = " + key);
LogQueueRuntime.addNewLog(this.getClass(),MOVE_ACTUATOR, "KEY值拼接完成,KEY值 = " + key);
return new MoveRegularObject(key, colArray[1]);
}
......
......@@ -28,6 +28,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.matrix.enums.DynamicVarType.*;
import static org.matrix.enums.ModuleType.SQL_ACTUATOR;
import static org.springframework.util.CollectionUtils.isEmpty;
/**
......@@ -112,7 +113,7 @@ public class SqlExpActuator implements Actuator {
* @return 变量递归解析后的值
*/
public String parseVarByName(String varNameString, Long envId, Long projectId) {
LogQueueRuntime.addNewLog(String.format("初始化即系变量,变量名=%s,环境id=%d,项目id=%d", varNameString, envId, projectId));
LogQueueRuntime.addNewLog(this.getClass(), SQL_ACTUATOR, String.format("初始化即系变量,变量名=%s,环境id=%d,项目id=%d", varNameString, envId, projectId));
List<SqlRegularObject> varList = findDynamicVarList(varNameString);
if (varList.size() == 1) {
SqlRegularObject sqlReg = varList.get(0);
......@@ -153,8 +154,7 @@ public class SqlExpActuator implements Actuator {
*/
private String parseVar(Long envId, Integer takenIndex, Long projectId, DynamicVariable dynamicVar) {
DynamicVarType varType = dynamicVar.getType();
log.info("[变量解析器] 当前解析的动态变量是: {}", JSON.toJSONString(dynamicVar));
LogQueueRuntime.addNewLog("[变量解析器] 当前解析的动态变量是: " + JSON.toJSONString(dynamicVar));
LogQueueRuntime.addNewLog(this.getClass(), SQL_ACTUATOR, "当前解析的动态变量是: " + JSON.toJSONString(dynamicVar));
// 依据变量类型的不同调用不同的Handler
if (varType == CONSTANT_VARIABLE) {
return dynamicVar.getDetail();
......@@ -222,8 +222,7 @@ public class SqlExpActuator implements Actuator {
.orElseThrow(() -> new GlobalException(
String.format("没有找到项目id = %d 下,name = %s的变量", projectId, sqlRegular.getVarName())));
String calculatedValue = parseVar(envId, sqlRegular.getIndex(), projectId, recVar);
log.info("[SQL执行器] 正在进行SQL变量计算 变量名: {} 计算后的替换值: {}", sqlRegular.getVarName(), calculatedValue);
LogQueueRuntime.addNewLog(String.format("[SQL执行器] 正在进行SQL变量计算 变量名: %s 计算后的替换值: %s", sqlRegular.getVarName(), calculatedValue));
LogQueueRuntime.addNewLog(this.getClass(), SQL_ACTUATOR, String.format("正在进行SQL变量计算 变量名: %s 计算后的替换值: %s", sqlRegular.getVarName(), calculatedValue));
sqlExp = sqlExp.replaceAll(String.format(REPLACE_VAR_EXP, sqlRegular.getVarName()), calculatedValue);
dynamicVar.getSqlExpDetail().setSqlExp(sqlExp);
}
......@@ -272,7 +271,7 @@ public class SqlExpActuator implements Actuator {
// 校验dynamicVar里的detail是否是可以直接执行的SQL
if (dynamicVar.getType() == SQL_VARIABLE && findDynamicVarList(sqlExp).size() == 0) {
// 切换数据源,执行SQL,获取数值
LogQueueRuntime.addNewLog(String.format("当前执行的SQL语句: %s, 使用的数据源: %s", sqlExp, dataSourceDTO));
LogQueueRuntime.addNewLog(this.getClass(),SQL_ACTUATOR, String.format("当前执行的SQL语句: %s, 使用的数据源: %s", sqlExp, dataSourceDTO));
Set<String> dataSources = dataSourceService.switchDataSource(dataSourceDTO);
log.info("当前存在的数据源 {}", dataSources);
List<Map<String, Object>> resultMap = jdbcTemplate.queryForList(sqlExp);
......
......@@ -18,6 +18,7 @@ import org.matrix.actuators.httpclient.HttpRequestDetail;
import org.matrix.actuators.httpclient.HttpResponseDetail;
import org.matrix.database.service.IExecutionHistoryService;
import org.matrix.enums.ExecutionHistoryStatus;
import org.matrix.enums.ModuleType;
import org.matrix.exception.GlobalException;
import org.matrix.socket.ExecutionStatusMonitorSocketHandler;
import org.matrix.socket.pool.TestCaseExecuteSocketPool;
......@@ -25,7 +26,6 @@ import org.matrix.socket.queue.LogQueueRuntime;
import org.matrix.socket.vo.CaseExecuteVo;
import org.matrix.socket.vo.TestExecuteLog;
import org.matrix.util.SpringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
......@@ -34,6 +34,8 @@ import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import static org.matrix.enums.ModuleType.CASE_ACTUATOR;
/**
* 测试用例执行器
* @author huangxiahao
......@@ -66,8 +68,8 @@ public class CaseActuator implements Actuator {
*/
public TestCaseExecuteResult executeTestCase(TestCaseBTO testCaseBto, Long envId, Long projectId) {
try {
LogQueueRuntime.addNewLog("[用例执行器] 开始执行用例!!");
LogQueueRuntime.addNewLog(String.format("[用例执行器] 当前正在执行用例ID: %s 用例名: %s", testCaseBto.getTestCase().getId(), testCaseBto.getTestCase().getName()));
LogQueueRuntime.addNewLog(this.getClass(), CASE_ACTUATOR, "开始执行用例!!");
LogQueueRuntime.addNewLog(this.getClass(),CASE_ACTUATOR, String.format("当前正在执行用例ID: %s 用例名: %s", testCaseBto.getTestCase().getId(), testCaseBto.getTestCase().getName()));
//执行前置动作
executeMove(testCaseBto.getTestCase().getMoveAfterCase()
, envId, projectId, null, MoveStrategy.PRE_MOVE);
......@@ -96,7 +98,7 @@ public class CaseActuator implements Actuator {
testCaseBto.getTestData().getId(),
baseTestCaseResponseDetail,
checkPointResult);
LogQueueRuntime.addNewLog(JSON.toJSONString(testCaseExecuteResult));
LogQueueRuntime.addNewLog(this.getClass(),CASE_ACTUATOR, JSON.toJSONString(testCaseExecuteResult));
//将线程中正在执行的DataId清除
LogQueueRuntime.clearTestData();
return testCaseExecuteResult;
......@@ -110,26 +112,26 @@ public class CaseActuator implements Actuator {
* 执行一条测试用例的多条测试数据
*/
public List<TestCaseExecuteResult> executeTestCases(TestCaseListDataBto testCaseBto, Long envId, Long projectId) {
LogQueueRuntime.addNewLog("[用例执行器] 开始执行用例!!" );
LogQueueRuntime.addNewLog(this.getClass(),CASE_ACTUATOR, "开始执行用例!!");
try {
LogQueueRuntime.addNewLog(String.format("[用例执行器] 当前正在执行用例ID: %s 用例名: %s", testCaseBto.getTestCase().getId(), testCaseBto.getTestCase().getName()));
LogQueueRuntime.addNewLog(this.getClass(),CASE_ACTUATOR, String.format("当前正在执行用例ID: %s 用例名: %s", testCaseBto.getTestCase().getId(), testCaseBto.getTestCase().getName()));
//执行前置动作
executeMove(testCaseBto.getTestCase().getMoveAfterCase()
, envId, projectId, null, MoveStrategy.PRE_MOVE);
LogQueueRuntime.addNewLog("[用例执行器] 开始执行前置动作!!");
LogQueueRuntime.addNewLog(this.getClass(),CASE_ACTUATOR, "开始执行前置动作!!");
//执行测试用例的本体内容
List<TestCaseExecuteResult> resultList = new ArrayList<>();
for (TestData testData : testCaseBto.getTestDataList()) {
//向线程中设置当前正在执行的DataId
LogQueueRuntime.setTestData(testData.getId());
changeExecutionHistoryStatus(ExecutionHistoryStatus.RUN);
LogQueueRuntime.addNewLog("[用例执行器] 开始执行数据组ID:" + testData.getId());
LogQueueRuntime.addNewLog(this.getClass(),CASE_ACTUATOR, "开始执行数据组ID:" + testData.getId());
HttpResponseDetail baseTestCaseResponseDetail = getHttpResponseDetail(
envId,
projectId,
testCaseBto.getTestCase(),
testData);
LogQueueRuntime.addNewLog("[用例执行器] 即将开始执行中置动作");
LogQueueRuntime.addNewLog(this.getClass(),CASE_ACTUATOR, "即将开始执行中置动作333");
//执行中置动作
executeMove(testCaseBto.getTestCase().getMoveAfterTest()
, envId, projectId, baseTestCaseResponseDetail.getResponseBody(), MoveStrategy.MID_MOVE);
......@@ -145,7 +147,7 @@ public class CaseActuator implements Actuator {
checkPointResult
);
resultList.add(testCaseExecuteResult);
LogQueueRuntime.addNewLog("用例执行结果:" + JSON.toJSONString(testCaseExecuteResult));
LogQueueRuntime.addNewLog(this.getClass(),CASE_ACTUATOR, "用例执行结果:" + JSON.toJSONString(testCaseExecuteResult));
//执行后置动作
executeMove(testCaseBto.getTestCase().getMoveAfterTest()
, envId, projectId, baseTestCaseResponseDetail.getResponseBody(), MoveStrategy.AFT_MOVE);
......@@ -265,7 +267,7 @@ public class CaseActuator implements Actuator {
if (session != null && session.isOpen()) {
TestExecuteLog currentTestExecute = LogQueueRuntime.getCurrentTestExecute(ThreadUtil.currentThreadId());
if (currentTestExecute!=null){
LogQueueRuntime.addNewLog(e.getMessage());
LogQueueRuntime.addNewLog(this.getClass(),CASE_ACTUATOR, e.getMessage());
}else {
//这里加-1.-1.-1是用来表明这里发出去的数据是不属于任何执行中的用例的
session.sendMessage(new TextMessage(String.format("-1.-1.-1.%s", e.getMessage())));
......
package org.matrix.enums;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor;
/**
* ModuleType. 模块类型的枚举类 用于例如日志等模块
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2022/3/17 at 10:46 AM
* Suffering is the most powerful teacher of life.
*/
@AllArgsConstructor
public enum ModuleType {
/**
* SQL执行器
*/
SQL_ACTUATOR("SQL执行器"),
/**
* HTTP执行器
*/
HTTP_ACTUATOR("HTTP执行器"),
/**
* 用例执行器
*/
CASE_ACTUATOR("用例执行器"),
/**
* 动作执行器
*/
MOVE_ACTUATOR("动作执行器"),
/**
* 变量解析器
*/
VAR_PARSE("变量解析器"),
/**
* 语法解析器
*/
SYNTAX_PARSE("语法解析器");
/**
* 模块名
*/
private final String name;
@JsonValue
public String getName() {
return name;
}
}
package org.matrix.socket.queue;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.matrix.enums.ModuleType;
import java.time.LocalDateTime;
/**
* LogMessage. 日志的消息对象 封装了一些通用属性和消息
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2022/3/17 at 11:02 AM
* Suffering is the most powerful teacher of life.
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LogMessage {
private LocalDateTime logTime;
@JSONField(serialize = false)
private ModuleType moduleType;
private String msg;
public String toLogString() {
return String.format("[%s] %s", moduleType.getName(), msg);
}
@JSONField(name = "module")
public String getModuleType() {
return moduleType.getName();
}
}
......@@ -3,19 +3,22 @@ package org.matrix.socket.queue;
import cn.hutool.log.LogFactory;
import cn.hutool.log.level.Level;
import com.alibaba.fastjson.JSONObject;
import org.matrix.actuators.httpclient.HttpClientActuator;
import org.matrix.actuators.sql.SqlExpActuator;
import org.matrix.actuators.util.ThreadUtil;
import org.matrix.database.service.IExecutionRecordService;
import org.matrix.enums.ModuleType;
import org.matrix.exception.GlobalException;
import org.matrix.socket.ExecutionSocketHandler;
import org.matrix.socket.vo.TestExecuteLog;
import org.matrix.socket.enums.TestExecuteType;
import org.matrix.socket.pool.MonitorSocketPool;
import org.matrix.socket.pool.TestCaseExecuteSocketPool;
import org.matrix.util.SpringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
......@@ -60,13 +63,16 @@ public class LogQueueRuntime {
LOG_MAP.get(currentThreadId).setTestDataId(-1L);
}
public static void addNewLog(String log) {
public static void addNewLog(Class<?> clazz, ModuleType type, String logString) {
Logger classLog = LoggerFactory.getLogger(clazz);
LogMessage logMsg = new LogMessage(LocalDateTime.now(), type, logString);
classLog.info(logMsg.toLogString());
Long currentThreadId = ThreadUtil.currentThreadId();
TestExecuteLog testExecuteLog = LOG_MAP.get(currentThreadId);
if (testExecuteLog !=null){
testExecuteLog.addLog(log);
sendMessage(currentThreadId,testExecuteLog.getUniqueKey(),log);
addExecutionRecord(testExecuteLog,log);
testExecuteLog.addLog(logMsg);
sendMessage(currentThreadId,testExecuteLog.getUniqueKey(),logMsg);
addExecutionRecord(testExecuteLog,logString);
}else {
throw new GlobalException("该线程中的TestCaseLog对象未初始化,请先调用put方法初始化对象");
}
......
......@@ -2,6 +2,7 @@ package org.matrix.socket.vo;
import lombok.Data;
import org.matrix.socket.enums.TestExecuteType;
import org.matrix.socket.queue.LogMessage;
import java.util.ArrayList;
import java.util.List;
......@@ -29,15 +30,16 @@ public class TestExecuteLog {
private Long testDataId = -1L;
private List<String> log = new ArrayList<>();
private List<LogMessage> log = new ArrayList<>();
/**
* 前置条件:每个用例下的数据组是单线程执行的
* 由于arrayList是有序的,所以只需要向下新增就好了
* @param logMsg
*/
public void addLog(String log){
this.log.add(log);
public void addLog(LogMessage logMsg){
this.log.add(logMsg);
}
@Override
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论