refactor(接口测试): 调试结果优化

Signed-off-by: fit2-zhao <yong.zhao@fit2cloud.com>
This commit is contained in:
fit2-zhao 2023-03-09 16:04:51 +08:00 committed by wxg0103
parent 78bdc78ef6
commit 5b220beb65
5 changed files with 20 additions and 344 deletions

View File

@ -56,6 +56,8 @@ public class MsDebugListener extends AbstractListenerElement implements SampleLi
private String runMode;
private ApiDefinitionEnvService apiDefinitionEnvService;
@Override
public Object clone() {
MsDebugListener clone = (MsDebugListener) super.clone();
@ -119,6 +121,9 @@ public class MsDebugListener extends AbstractListenerElement implements SampleLi
@Override
public void testStarted(String host) {
LogUtil.debug("TestStarted " + this.getName());
if (apiDefinitionEnvService == null) {
apiDefinitionEnvService = CommonBeanFactory.getBean(ApiDefinitionEnvService.class);
}
}
@Override
@ -163,33 +168,30 @@ public class MsDebugListener extends AbstractListenerElement implements SampleLi
dto.setRunMode(runMode);
String console = FixedCapacityUtil.getJmeterLogger(this.getName(), false);
ApiDefinitionEnvService apiDefinitionEnvService = CommonBeanFactory.getBean(ApiDefinitionEnvService.class);
if (StringUtils.isNotEmpty(requestResult.getName()) && requestResult.getName().startsWith("Transaction=")) {
requestResult.getSubRequestResults().forEach(transactionResult -> {
transactionResult.getResponseResult().setConsole(console);
//对响应内容进行进一步解析和处理
RequestResultExpandDTO expandDTO = ResponseUtil.parseByRequestResult(transactionResult);
if (StringUtils.equalsAnyIgnoreCase(dto.getRunMode(), ApiRunMode.DEFINITION.name(), ApiRunMode.API_PLAN.name())) {
apiDefinitionEnvService.setEnvAndPoolName(transactionResult, expandDTO);
}
dto.setContent("result_" + JSON.toJSONString(expandDTO));
WebSocketUtil.sendMessageSingle(dto);
this.sendResult(transactionResult, console, dto);
});
} else {
requestResult.getResponseResult().setConsole(console);
//对响应内容进行进一步解析和处理
RequestResultExpandDTO expandDTO = ResponseUtil.parseByRequestResult(requestResult);
if (StringUtils.equalsAnyIgnoreCase(dto.getRunMode(), ApiRunMode.DEFINITION.name(), ApiRunMode.API_PLAN.name())) {
apiDefinitionEnvService.setEnvAndPoolName(requestResult, expandDTO);
}
dto.setContent("result_" + JSON.toJSONString(expandDTO));
WebSocketUtil.sendMessageSingle(dto);
this.sendResult(requestResult, console, dto);
}
LoggerUtil.debug("send. " + this.getName());
}
}
}
private void sendResult(RequestResult requestResult, String console, MsgDTO dto) {
requestResult.getResponseResult().setConsole(console);
//对响应内容进行进一步解析和处理
RequestResultExpandDTO expandDTO = ResponseUtil.parseByRequestResult(requestResult);
if (StringUtils.equalsAnyIgnoreCase(dto.getRunMode(), ApiRunMode.DEFINITION.name(), ApiRunMode.API_PLAN.name())) {
apiDefinitionEnvService.setEnvAndPoolName(requestResult, expandDTO);
}
dto.setContent("result_" + JSON.toJSONString(expandDTO));
WebSocketUtil.sendMessageSingle(dto);
}
private void setVars(SampleResult result) {
if (StringUtils.isNotEmpty(result.getSampleLabel()) && result.getSampleLabel().startsWith("Transaction=")) {
for (int i = 0; i < result.getSubResults().length; i++) {

View File

@ -101,23 +101,4 @@ public class MsKafkaListener {
LoggerUtil.error("KAFKA消费失败", e);
}
}
public void outKafkaPoolLogger() {
StringBuffer buffer = new StringBuffer()
.append(StringUtils.LF)
.append("KAFKA Consume 线程池详情:")
.append(StringUtils.LF)
.append(" KAFKA Consume 核心线程数:" + threadPool.getCorePoolSize())
.append(StringUtils.LF)
.append(" KAFKA Consume 活动线程数:" + threadPool.getActiveCount())
.append(StringUtils.LF)
.append(" KAFKA Consume 最大线程数:" + threadPool.getMaximumPoolSize())
.append(StringUtils.LF)
.append(" KAFKA Consume 最大队列数:" + (threadPool.getQueue().size() + threadPool.getQueue().remainingCapacity()))
.append(StringUtils.LF)
.append(" KAFKA Consume 当前排队线程数:" + (threadPool.getQueue().size()))
.append(StringUtils.LF);
LoggerUtil.info(buffer.toString());
}
}

View File

@ -6,17 +6,11 @@ import io.metersphere.base.domain.TestResourcePool;
import io.metersphere.base.domain.TestResourcePoolExample;
import io.metersphere.base.mapper.TestResourceMapper;
import io.metersphere.base.mapper.TestResourcePoolMapper;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.JSON;
import io.metersphere.dto.JvmInfoDTO;
import io.metersphere.dto.NodeDTO;
import io.metersphere.dto.TestResourceDTO;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@ -28,18 +22,6 @@ public class ResourcePoolCalculation {
TestResourcePoolMapper testResourcePoolMapper;
@Resource
TestResourceMapper testResourceMapper;
@Resource
private RestTemplate restTemplate;
private static final String BASE_URL = "http://%s:%d";
private JvmInfoDTO getNodeJvmInfo(String uri) {
try {
return restTemplate.getForObject(uri, JvmInfoDTO.class);
} catch (Exception e) {
return null;
}
}
public List<TestResource> getResourcePools(String resourcePoolId) {
TestResourcePoolExample example = new TestResourcePoolExample();
@ -55,26 +37,4 @@ public class ResourcePoolCalculation {
}
return new ArrayList<>();
}
public List<JvmInfoDTO> getPools(String resourcePoolId) {
// 按照NODE节点的可用内存空间大小排序
List<JvmInfoDTO> availableNodes = new ArrayList<>();
List<TestResource> testResources = getResourcePools(resourcePoolId);
for (TestResource testResource : testResources) {
String configuration = testResource.getConfiguration();
NodeDTO node = JSON.parseObject(configuration, NodeDTO.class);
String nodeIp = node.getIp();
Integer port = node.getPort();
String uri = String.format(BASE_URL + "/jmeter/get-jvm-info", nodeIp, port);
JvmInfoDTO nodeJvm = this.getNodeJvmInfo(uri);
if (nodeJvm == null) {
continue;
}
TestResourceDTO dto = new TestResourceDTO();
BeanUtils.copyBean(dto, testResource);
nodeJvm.setTestResource(dto);
availableNodes.add(nodeJvm);
}
return availableNodes;
}
}

View File

@ -1,51 +0,0 @@
package io.metersphere.api.jmeter;
import io.metersphere.dto.RequestResult;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class ScenarioResult {
private Integer id;
private String name;
private long responseTime;
private int error = 0;
private int success = 0;
private int totalAssertions = 0;
private int passAssertions = 0;
private List<RequestResult> requestResults = new ArrayList<>();
public void addResponseTime(long time) {
this.responseTime += time;
}
public void addError(int count) {
this.error += count;
}
public void addSuccess() {
this.success++;
}
public void addTotalAssertions(int count) {
this.totalAssertions += count;
}
public void addPassAssertions(int count) {
this.passAssertions += count;
}
public int getTotal() {
return error + success;
}
}

View File

@ -1,216 +0,0 @@
package io.metersphere.api.jmeter;
import io.metersphere.commons.constants.DelimiterConstants;
import io.metersphere.commons.utils.JSON;
import io.metersphere.dto.RequestResult;
import lombok.Data;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
@Data
public class TestResult {
private String testId;
private String setReportId;
private int scenarioTotal;
private int scenarioSuccess;
private int scenarioError;
private String userId;
private boolean isDebug;
private boolean end;
private String runMode;
private int success = 0;
private int error = 0;
private int total = 0;
private int totalAssertions = 0;
private int passAssertions = 0;
private String console;
private String runningDebugSampler;
private List<ScenarioResult> scenarios = new ArrayList<>();
private Map<String, Boolean> margeScenarioMap = new HashMap<>();
private Map<String, Boolean> scenarioStepMap = new HashMap<>();
private int scenarioStepSuccess = 0;
private int scenarioStepError = 0;
private int scenarioStepTotal = 0;
public void addError(int count) {
this.error += count;
}
public void addSuccess() {
this.success++;
}
public void addTotalAssertions(int count) {
this.totalAssertions += count;
}
public void addPassAssertions(int count) {
this.passAssertions += count;
}
private static final String SEPARATOR = DelimiterConstants.SEPARATOR.toString();
private void setStatus(List<String> id_names, boolean status) {
if (CollectionUtils.isNotEmpty(id_names)) {
id_names.forEach(item -> {
if (!margeScenarioMap.containsKey(item) || status) {
margeScenarioMap.put(item, status);
}
});
}
}
private void setStatus(String id_names, boolean status) {
if (!margeScenarioMap.containsKey(id_names) || status) {
margeScenarioMap.put(id_names, status);
}
}
private void setStepStatus(String step_names, boolean status) {
if (!scenarioStepMap.containsKey(step_names) || status) {
scenarioStepMap.put(step_names, status);
}
}
public void addScenario(ScenarioResult result) {
/**
* 1.10.2统计逻辑修改
* 不统计所有的请求改为统计场景和场景步骤
* 场景里的第一层视为步骤不考虑深层情况
*/
if (result != null && CollectionUtils.isNotEmpty(result.getRequestResults())) {
//如果有全局前后置脚本会出现前后置的测试步骤影响统计此处略过不处理
// 同时jmeter会将前后置脚本步骤作为一个请求来计算当检测到有前后置脚本步骤执行时请求数也要做处理
List<RequestResult> formattedResult = new ArrayList<>();
int successStep = 0;
int errorStep = 0;
for (RequestResult item : result.getRequestResults()) {
if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) {
formattedResult.add(item);
} else {
if (StringUtils.equalsAnyIgnoreCase(item.getName(), "PRE_PROCESSOR_ENV_false", "POST_PROCESSOR_ENV_false")) {
if (item.isSuccess()) {
successStep++;
} else {
errorStep++;
}
}
}
}
result.setSuccess(result.getSuccess() - successStep);
result.setError(result.getError() - errorStep);
this.success = this.success - successStep;
this.error = this.error - errorStep;
this.total = this.total - successStep - errorStep;
result.setRequestResults(formattedResult);
result.getRequestResults().forEach(item -> {
String itemAndScenarioName = StringUtils.EMPTY;
if (StringUtils.isNotEmpty(item.getScenario())) {
//第1个当前场景 第all_id_names个最后一层场景
List<String> all_id_names = JSON.parseObject(item.getScenario(), List.class);
if (all_id_names.size() > 1) {
StringBuffer scenarioNames = new StringBuffer();
//因为要进行步骤统计第一层级下的场景算作步骤所以统计视角只按照第一级别场景来计算
scenarioNames.append(all_id_names.get(all_id_names.size() - 1) + all_id_names.get(all_id_names.size() - 2));
this.setStatus(scenarioNames.toString(), item.getError() > 0);
itemAndScenarioName = scenarioNames.toString();
} else {
//不存在多场景时需要补上步骤名字做唯一判断 添加UUID进行处理
itemAndScenarioName = item.getName() + ":" + JSON.toJSONString(all_id_names.get(0)) + UUID.randomUUID().toString();
this.setStatus(all_id_names, item.getError() > 0);
}
}
if (StringUtils.isNotEmpty(item.getName()) && item.getName().indexOf(SEPARATOR) != -1) {
String array[] = item.getName().split(SEPARATOR);
item.setName(array[1] + array[0]);
// item.getSubRequestResults().forEach(subItem -> {
// subItem.setName(array[0]);
// });
} else {
this.genScenarioInSubRequestResult(item);
}
this.setStepStatus(itemAndScenarioName, item.getError() > 0);
});
scenarios.add(result);
}
/**
* 1.10.2 场景成功/失败统计不再按照请求为纬度按照场景为纬度
*/
for (String key : scenarioStepMap.keySet()) {
if (scenarioStepMap.get(key)) {
this.scenarioStepError++;
} else {
this.scenarioStepSuccess++;
}
}
boolean hasError = false;
for (String key : margeScenarioMap.keySet()) {
if (margeScenarioMap.get(key)) {
hasError = true;
break;
}
}
if (!margeScenarioMap.isEmpty()) {
if (hasError) {
this.scenarioError++;
} else {
this.scenarioSuccess++;
}
this.scenarioTotal++;
}
this.setScenarioStepTotal(this.scenarioStepMap.size());
}
//一般多层的事务控制器会出现这种情况
private String genScenarioInSubRequestResult(RequestResult item) {
if (StringUtils.isNotEmpty(item.getName()) && item.getName().indexOf(SEPARATOR) != -1) {
String array[] = item.getName().split(SEPARATOR);
item.setName(array[0]);
}
if (StringUtils.isNotEmpty(item.getScenario())) {
List<String> id_names = JSON.parseObject(item.getScenario(), List.class);
this.setStatus(id_names, item.getError() > 0);
return item.getScenario();
} else {
if (CollectionUtils.isNotEmpty(item.getSubRequestResults())) {
for (RequestResult requestResult : item.getSubRequestResults()) {
this.genScenarioInSubRequestResult(requestResult);
}
}
return null;
}
}
}