refactor(接口测试): 优化大批量报告和队列入库慢问题

This commit is contained in:
fit2-zhao 2022-02-09 17:09:29 +08:00 committed by 刘瑞斌
parent 03f9b300b0
commit 4a5352430d
12 changed files with 211 additions and 81 deletions

View File

@ -42,6 +42,9 @@ public class MsAssertions extends MsTestElement {
if (!config.isOperating() && !this.isEnable()) {
return;
}
if (StringUtils.isEmpty(this.getName())) {
this.setName("Assertion");
}
addAssertions(tree);
}

View File

@ -1,34 +1,24 @@
package io.metersphere.api.service;
import io.metersphere.base.domain.ApiDefinitionExecResult;
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.Map;
@Service
public class ApiCaseResultService {
@Resource
private SqlSessionFactory sqlSessionFactory;
private ExtApiDefinitionExecResultMapper resultMapper;
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public void batchSave(Map<String, ApiDefinitionExecResult> executeQueue) {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiDefinitionExecResultMapper batchMapper = sqlSession.getMapper(ApiDefinitionExecResultMapper.class);
for (String testId : executeQueue.keySet()) {
ApiDefinitionExecResult report = executeQueue.get(testId);
batchMapper.insert(report);
}
sqlSession.flushStatements();
if (sqlSession != null && sqlSessionFactory != null) {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
if (!executeQueue.isEmpty()) {
resultMapper.sqlInsert(new LinkedList<>(executeQueue.values()));
}
}
}

View File

@ -28,10 +28,6 @@ import io.metersphere.utils.LoggerUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@ -45,8 +41,6 @@ public class ApiExecutionQueueService {
@Resource
private ApiExecutionQueueMapper queueMapper;
@Resource
private SqlSessionFactory sqlSessionFactory;
@Resource
private ApiExecutionQueueDetailMapper executionQueueDetailMapper;
@Resource
private ApiScenarioSerialService apiScenarioSerialService;
@ -79,9 +73,7 @@ public class ApiExecutionQueueService {
DBTestQueue resQueue = new DBTestQueue();
BeanUtils.copyBean(resQueue, executionQueue);
Map<String, String> detailMap = new HashMap<>();
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiExecutionQueueDetailMapper batchMapper = sqlSession.getMapper(ApiExecutionQueueDetailMapper.class);
List<ApiExecutionQueueDetail> queueDetails = new LinkedList<>();
if (StringUtils.equalsAnyIgnoreCase(type, ApiRunMode.DEFINITION.name(), ApiRunMode.API_PLAN.name())) {
final int[] sort = {0};
Map<String, ApiDefinitionExecResult> runMap = (Map<String, ApiDefinitionExecResult>) runObj;
@ -95,7 +87,7 @@ public class ApiExecutionQueueService {
resQueue.setQueue(queue);
}
sort[0]++;
batchMapper.insert(queue);
queueDetails.add(queue);
detailMap.put(k, queue.getId());
});
} else {
@ -108,13 +100,12 @@ public class ApiExecutionQueueService {
resQueue.setQueue(queue);
}
sort[0]++;
batchMapper.insert(queue);
queueDetails.add(queue);
detailMap.put(k, queue.getId());
});
}
sqlSession.flushStatements();
if (sqlSession != null && sqlSessionFactory != null) {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
if (CollectionUtils.isNotEmpty(queueDetails)) {
extApiExecutionQueueMapper.sqlInsert(queueDetails);
}
resQueue.setDetailMap(detailMap);
return resQueue;
@ -283,10 +274,10 @@ public class ApiExecutionQueueService {
public void timeOut() {
final int SECOND_MILLIS = 1000;
final int MINUTE_MILLIS = 60 * SECOND_MILLIS;
// 计算二十分钟前的超时报告
final long twentyMinutesAgo = System.currentTimeMillis() - (30 * MINUTE_MILLIS);
// 计算一小时前的超时报告
final long timeout = System.currentTimeMillis() - (60 * MINUTE_MILLIS);
ApiExecutionQueueDetailExample example = new ApiExecutionQueueDetailExample();
example.createCriteria().andCreateTimeLessThan(twentyMinutesAgo);
example.createCriteria().andCreateTimeLessThan(timeout);
List<ApiExecutionQueueDetail> queueDetails = executionQueueDetailMapper.selectByExample(example);
for (ApiExecutionQueueDetail item : queueDetails) {
@ -312,7 +303,7 @@ public class ApiExecutionQueueService {
ApiRunMode.JENKINS_SCENARIO_PLAN.name())) {
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(item.getReportId());
if (report != null && StringUtils.equalsAnyIgnoreCase(report.getStatus(), TestPlanReportStatus.RUNNING.name(), APITestStatus.Waiting.name())
&& report.getUpdateTime() < twentyMinutesAgo) {
&& report.getUpdateTime() < timeout) {
report.setStatus(ScenarioStatus.Timeout.name());
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
@ -344,13 +335,13 @@ public class ApiExecutionQueueService {
}
ApiExecutionQueueExample queueDetailExample = new ApiExecutionQueueExample();
queueDetailExample.createCriteria().andReportTypeEqualTo(RunModeConstants.SET_REPORT.toString()).andCreateTimeLessThan(twentyMinutesAgo);
queueDetailExample.createCriteria().andReportTypeEqualTo(RunModeConstants.SET_REPORT.toString()).andCreateTimeLessThan(timeout);
List<ApiExecutionQueue> executionQueues = queueMapper.selectByExample(queueDetailExample);
if (CollectionUtils.isNotEmpty(executionQueues)) {
executionQueues.forEach(item -> {
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(item.getReportId());
if (report != null && StringUtils.equalsAnyIgnoreCase(report.getStatus(), TestPlanReportStatus.RUNNING.name(), APITestStatus.Waiting.name())
&& (report.getUpdateTime() < twentyMinutesAgo)) {
&& (report.getUpdateTime() < timeout)) {
report.setStatus(ScenarioStatus.Timeout.name());
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
}

View File

@ -32,10 +32,7 @@ import io.metersphere.utils.LoggerUtil;
import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@ -743,19 +740,16 @@ public class ApiScenarioReportService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void batchSave(Map<String, RunModeDataDTO> executeQueue, String serialReportId, String runMode, List<MsExecResponseDTO> responseDTOS) {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiScenarioReportMapper batchMapper = sqlSession.getMapper(ApiScenarioReportMapper.class);
List<APIScenarioReportResult> list = new LinkedList<>();
if (StringUtils.isEmpty(serialReportId)) {
for (String reportId : executeQueue.keySet()) {
APIScenarioReportResult report = executeQueue.get(reportId).getReport();
batchMapper.insert(report);
list.add(report);
responseDTOS.add(new MsExecResponseDTO(executeQueue.get(reportId).getTestId(), reportId, runMode));
}
sqlSession.flushStatements();
if (sqlSession != null && sqlSessionFactory != null) {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
if (CollectionUtils.isNotEmpty(list)) {
extApiScenarioReportMapper.sqlInsert(list);
}
}
}
}

View File

@ -3,6 +3,7 @@ package io.metersphere.base.mapper.ext;
import io.metersphere.api.dto.datacount.ExecutedCaseInfoResult;
import io.metersphere.base.domain.ApiDefinitionExecResult;
import io.metersphere.track.dto.PlanReportCaseDTO;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
@ -35,4 +36,7 @@ public interface ExtApiDefinitionExecResultMapper {
void update(@Param("ids") List<String> ids);
@InsertProvider(type = ExtApiDefinitionExecResultProvider.class, method = "insertListSql")
void sqlInsert(List<ApiDefinitionExecResult> list);
}

View File

@ -0,0 +1,51 @@
package io.metersphere.base.mapper.ext;
import io.metersphere.base.domain.ApiDefinitionExecResult;
import java.util.List;
public class ExtApiDefinitionExecResultProvider {
public String insertListSql(List<ApiDefinitionExecResult> list) {
StringBuffer sqlList = new StringBuffer();
sqlList.append("insert into api_definition_exec_result (id, `name`, resource_id, `status`, user_id, start_time, end_time," +
" create_time, `type`, actuator, trigger_mode, version_id, error_code, content) values ");
for (int i = 0; i < list.size(); i++) {
ApiDefinitionExecResult result = list.get(i);
sqlList.append(" (")
.append("'")
.append(result.getId())
.append("','")
.append(result.getName())
.append("','")
.append(result.getResourceId())
.append("','")
.append(result.getStatus())
.append("','")
.append(result.getUserId())
.append("',")
.append(result.getStartTime())
.append(",")
.append(result.getEndTime())
.append(",")
.append(result.getCreateTime())
.append(",'")
.append(result.getType())
.append("','")
.append(result.getActuator())
.append("','")
.append(result.getTriggerMode())
.append("','")
.append(result.getVersionId())
.append("','")
.append(result.getErrorCode())
.append("','")
.append(result.getContent())
.append("'")
.append(")");
if (i < list.size() - 1) {
sqlList.append(",");
}
}
return sqlList.toString();
}
}

View File

@ -1,6 +1,8 @@
package io.metersphere.base.mapper.ext;
import io.metersphere.base.domain.ApiExecutionQueue;
import io.metersphere.base.domain.ApiExecutionQueueDetail;
import org.apache.ibatis.annotations.InsertProvider;
import java.util.List;
@ -10,4 +12,8 @@ public interface ExtApiExecutionQueueMapper {
List<ApiExecutionQueue> findTestPlanReportQueue();
List<String> findTestPlanRunningReport();
@InsertProvider(type = ExtApiExecutionQueueProvider.class, method = "insertListSql")
void sqlInsert(List<ApiExecutionQueueDetail> list);
}

View File

@ -0,0 +1,38 @@
package io.metersphere.base.mapper.ext;
import io.metersphere.base.domain.ApiExecutionQueueDetail;
import java.util.List;
public class ExtApiExecutionQueueProvider {
public String insertListSql(List<ApiExecutionQueueDetail> list) {
StringBuffer sqlList = new StringBuffer();
sqlList.append("insert into api_execution_queue_detail (id, queue_id, sort, report_id, test_id, `type`, create_time, evn_map) values ");
for (int i = 0; i < list.size(); i++) {
ApiExecutionQueueDetail result = list.get(i);
sqlList.append(" (")
.append("'")
.append(result.getId())
.append("','")
.append(result.getQueueId())
.append("',")
.append(result.getSort())
.append(",'")
.append(result.getReportId())
.append("','")
.append(result.getTestId())
.append("','")
.append(result.getType())
.append("',")
.append(result.getCreateTime())
.append(",'")
.append(result.getEvnMap())
.append("'")
.append(")");
if (i < list.size() - 1) {
sqlList.append(",");
}
}
return sqlList.toString();
}
}

View File

@ -6,6 +6,7 @@ import io.metersphere.api.dto.datacount.ApiDataCountResult;
import io.metersphere.base.domain.ApiScenarioReport;
import io.metersphere.dto.ApiReportCountDTO;
import io.metersphere.track.dto.PlanReportCaseDTO;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
@ -39,4 +40,8 @@ public interface ExtApiScenarioReportMapper {
List<PlanReportCaseDTO> selectForPlanReport(@Param("ids") List<String> reportIds);
void update(@Param("ids") List<String> ids);
@InsertProvider(type = ExtApiScenarioReportProvider.class, method = "insertListSql")
void sqlInsert(List<APIScenarioReportResult> list);
}

View File

@ -0,0 +1,57 @@
package io.metersphere.base.mapper.ext;
import io.metersphere.api.dto.automation.APIScenarioReportResult;
import java.util.List;
public class ExtApiScenarioReportProvider {
public String insertListSql(List<APIScenarioReportResult> list) {
StringBuffer sqlList = new StringBuffer();
sqlList.append("INSERT INTO api_scenario_report (id, project_id, `name`, create_time, update_time, `status`, user_id, trigger_mode," +
" execute_type, scenario_name, scenario_id, create_user, actuator, end_time, report_version, version_id, description) VALUES ");
for (int i = 0; i < list.size(); i++) {
APIScenarioReportResult result = list.get(i);
sqlList.append(" (")
.append("'")
.append(result.getId())
.append("','")
.append(result.getProjectId())
.append("','")
.append(result.getName())
.append("',")
.append(result.getCreateTime())
.append(",")
.append(result.getUpdateTime())
.append(",'")
.append(result.getStatus())
.append("','")
.append(result.getUserId())
.append("','")
.append(result.getTriggerMode())
.append("','")
.append(result.getExecuteType())
.append("','")
.append(result.getScenarioName())
.append("','")
.append(result.getScenarioId())
.append("','")
.append(result.getCreateUser())
.append("','")
.append(result.getActuator())
.append("',")
.append(result.getEndTime())
.append(",")
.append(2)
.append(",'")
.append(result.getVersionId())
.append("','")
.append(result.getDescription())
.append("'")
.append(")");
if (i < list.size() - 1) {
sqlList.append(",");
}
}
return sqlList.toString();
}
}

View File

@ -123,10 +123,10 @@ public class TestPlanReportService {
return list;
}
public void setTestPlanReportPassRate(List<TestPlanReportDTO> list){
for(TestPlanReportDTO testPlanReportDTO : list){
public void setTestPlanReportPassRate(List<TestPlanReportDTO> list) {
for (TestPlanReportDTO testPlanReportDTO : list) {
// 如果数据库查询成功率字段为空或 0 则重新计算一次
if(testPlanReportDTO.getPassRate() == null || testPlanReportDTO.getPassRate() == 0){
if (testPlanReportDTO.getPassRate() == null || testPlanReportDTO.getPassRate() == 0) {
TestPlanReportContentExample example = new TestPlanReportContentExample();
example.createCriteria().andTestPlanReportIdEqualTo(testPlanReportDTO.getId());
List<TestPlanReportContentWithBLOBs> testPlanReportContents = testPlanReportContentMapper.selectByExampleWithBLOBs(example);
@ -156,7 +156,7 @@ public class TestPlanReportService {
// 性能用例
planReportCaseDTOS = extTestPlanLoadCaseMapper.selectForPlanReport(planId);
TestPlanUtils.buildStatusResultMap(planReportCaseDTOS, statusResultMap, report, TestPlanLoadCaseStatus.success.name());
}else{
} else {
// 报告 ID 集合
List<String> reportIds = null;
if (MapUtils.isNotEmpty(testPlanExecuteReportDTO.getTestPlanApiCaseIdAndReportIdMap())) {
@ -513,7 +513,7 @@ public class TestPlanReportService {
public TestPlanReportContentWithBLOBs parseReportDaoToReportContent(TestPlanSimpleReportDTO reportDTO, TestPlanReportContentWithBLOBs testPlanReportContentWithBLOBs) {
String id = testPlanReportContentWithBLOBs.getId();
String testPlanReportId = testPlanReportContentWithBLOBs.getTestPlanReportId();
if(testPlanReportContentWithBLOBs.getEndTime() != null){
if (testPlanReportContentWithBLOBs.getEndTime() != null) {
reportDTO.setEndTime(testPlanReportContentWithBLOBs.getEndTime());
}
BeanUtils.copyBean(testPlanReportContentWithBLOBs, reportDTO);
@ -859,25 +859,20 @@ public class TestPlanReportService {
}
public void createTestPlanReportContentReportIds(String testPlanReportID, Map<String, String> apiCaseReportMap, Map<String, String> scenarioReportIdMap, Map<String, String> loadCaseReportIdMap) {
TestPlanReportContentExample example = new TestPlanReportContentExample();
example.createCriteria().andTestPlanReportIdEqualTo(testPlanReportID);
long dataCount = testPlanReportContentMapper.countByExample(example);
if (dataCount == 0) {
TestPlanReportContentWithBLOBs content = new TestPlanReportContentWithBLOBs();
content.setId(UUID.randomUUID().toString());
content.setTestPlanReportId(testPlanReportID);
TestPlanReportContentWithBLOBs content = new TestPlanReportContentWithBLOBs();
content.setId(UUID.randomUUID().toString());
content.setTestPlanReportId(testPlanReportID);
if (MapUtils.isNotEmpty(apiCaseReportMap)) {
content.setPlanApiCaseReportStruct(JSONObject.toJSONString(apiCaseReportMap));
}
if (MapUtils.isNotEmpty(scenarioReportIdMap)) {
content.setPlanScenarioReportStruct(JSONObject.toJSONString(scenarioReportIdMap));
}
if (MapUtils.isNotEmpty(loadCaseReportIdMap)) {
content.setPlanLoadCaseReportStruct(JSONObject.toJSONString(loadCaseReportIdMap));
}
testPlanReportContentMapper.insert(content);
if (MapUtils.isNotEmpty(apiCaseReportMap)) {
content.setPlanApiCaseReportStruct(JSONObject.toJSONString(apiCaseReportMap));
}
if (MapUtils.isNotEmpty(scenarioReportIdMap)) {
content.setPlanScenarioReportStruct(JSONObject.toJSONString(scenarioReportIdMap));
}
if (MapUtils.isNotEmpty(loadCaseReportIdMap)) {
content.setPlanLoadCaseReportStruct(JSONObject.toJSONString(loadCaseReportIdMap));
}
testPlanReportContentMapper.insert(content);
}
public TestPlanExecuteReportDTO genTestPlanExecuteReportDTOByTestPlanReportContent(TestPlanReportContentWithBLOBs testPlanReportContentWithBLOBs) {

View File

@ -4,9 +4,6 @@ package io.metersphere.track.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import io.metersphere.api.dto.APIReportResult;
import io.metersphere.api.dto.EnvironmentType;
@ -14,11 +11,6 @@ import io.metersphere.api.dto.automation.*;
import io.metersphere.api.dto.definition.ApiTestCaseRequest;
import io.metersphere.api.dto.definition.BatchRunDefinitionRequest;
import io.metersphere.api.dto.definition.TestPlanApiCaseDTO;
import io.metersphere.api.dto.definition.request.ElementUtil;
import io.metersphere.api.dto.definition.request.MsScenario;
import io.metersphere.api.dto.definition.request.MsTestPlan;
import io.metersphere.api.dto.definition.request.MsThreadGroup;
import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
import io.metersphere.api.service.ApiAutomationService;
import io.metersphere.api.service.ApiDefinitionService;
import io.metersphere.api.service.ApiScenarioReportService;
@ -43,7 +35,6 @@ import io.metersphere.performance.request.RunTestPlanRequest;
import io.metersphere.performance.service.MetricQueryService;
import io.metersphere.performance.service.PerformanceReportService;
import io.metersphere.performance.service.PerformanceTestService;
import io.metersphere.plugin.core.MsTestElement;
import io.metersphere.service.*;
import io.metersphere.track.Factory.ReportComponentFactory;
import io.metersphere.track.domain.ReportComponent;
@ -55,6 +46,7 @@ import io.metersphere.track.request.testplan.LoadCaseReportRequest;
import io.metersphere.track.request.testplan.LoadCaseRequest;
import io.metersphere.track.request.testplan.TestplanRunRequest;
import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest;
import io.metersphere.utils.LoggerUtil;
import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
@ -526,8 +518,8 @@ public class TestPlanService {
boolean isSelectAll = request.getRequest() != null && request.getRequest().isSelectAll();
if (isSelectAll) {
Map<String, TestCase> maintainerMap = extTestCaseMapper.getMaintainerMap(request.getRequest());
for (String k : maintainerMap.keySet()) {
userMap.put(k, maintainerMap.get(k).getMaintainer());
for (String k : maintainerMap.keySet()) {
userMap.put(k, maintainerMap.get(k).getMaintainer());
}
} else {
TestCaseExample testCaseExample = new TestCaseExample();
@ -1017,11 +1009,15 @@ public class TestPlanService {
//执行接口案例任务
LoggerUtil.info("开始执行测试计划接口用例 " + planReportId);
Map<String, String> apiCaseReportMap = this.executeApiTestCase(triggerMode, planReportId, userId, new ArrayList<>(reportInfoDTO.getApiTestCaseDataMap().keySet()), runModeConfig);
//执行场景执行任务
LoggerUtil.info("开始执行测试计划场景用例 " + planReportId);
Map<String, String> scenarioReportMap = this.executeScenarioCase(planReportId, testPlanID, projectID, runModeConfig, triggerMode, userId, reportInfoDTO.getPlanScenarioIdMap());
//执行性能测试任务
LoggerUtil.info("开始执行测试计划性能用例 " + planReportId);
Map<String, String> loadCaseReportMap = this.executeLoadCaseTask(runModeConfig, triggerMode, reportInfoDTO.getPerformanceIdMap());
LoggerUtil.info("开始生成测试计划报告 " + planReportId);
testPlanReportService.createTestPlanReportContentReportIds(planReportId, apiCaseReportMap, scenarioReportMap, loadCaseReportMap);
return planReportId;
}
@ -1040,9 +1036,9 @@ public class TestPlanService {
private Map<String, String> executeScenarioCase(String planReportId, String testPlanID, String projectID, RunModeConfigDTO runModeConfig, String triggerMode, String userId, Map<String, String> planScenarioIdMap) {
if (!planScenarioIdMap.isEmpty()) {
SchedulePlanScenarioExecuteRequest scenarioRequest = new SchedulePlanScenarioExecuteRequest();
String senarionReportID = UUID.randomUUID().toString();
scenarioRequest.setId(senarionReportID);
scenarioRequest.setReportId(senarionReportID);
String scenarioReportID = UUID.randomUUID().toString();
scenarioRequest.setId(scenarioReportID);
scenarioRequest.setReportId(scenarioReportID);
scenarioRequest.setProjectId(projectID);
if (StringUtils.equals(triggerMode, ReportTriggerMode.API.name())) {
scenarioRequest.setTriggerMode(ReportTriggerMode.API.name());