feat(项目定时报告): 项目定时报告开发

基于docker-selenium的项目定时报告开发
This commit is contained in:
song-tianyang 2021-12-18 13:22:35 +08:00 committed by song-tianyang
parent 40ddddc44a
commit 0d59e3494e
13 changed files with 72 additions and 34 deletions

View File

@ -88,7 +88,7 @@ public interface ParamConstants {
} }
} }
enum MAIL implements ParamConstants{ enum MAIL implements ParamConstants {
SERVER("smtp.host"), SERVER("smtp.host"),
PORT("smtp.port"), PORT("smtp.port"),
ACCOUNT("smtp.account"), ACCOUNT("smtp.account"),
@ -112,7 +112,8 @@ public interface ParamConstants {
enum BASE implements ParamConstants { enum BASE implements ParamConstants {
URL("base.url"), URL("base.url"),
CONCURRENCY("base.concurrency"), CONCURRENCY("base.concurrency"),
PROMETHEUS_HOST("base.prometheus.host"); PROMETHEUS_HOST("base.prometheus.host"),
SELENIUM_DOCKER_URL("base.selenium.docker.url");
private String value; private String value;

View File

@ -9,4 +9,5 @@ public class BaseSystemConfigDTO {
private String url; private String url;
private String concurrency; private String concurrency;
private String prometheusHost; private String prometheusHost;
private String seleniumDockerUrl;
} }

View File

@ -2,10 +2,15 @@ package io.metersphere.reportstatistics.dto;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
@Getter @Getter
@Setter @Setter
public class HeadlessRequest { public class HeadlessRequest {
public String url; private String url;
public String driverPath; private String remoteDriverUrl;
public boolean isEmpty() {
return StringUtils.isEmpty(this.url) || StringUtils.isEmpty(this.remoteDriverUrl);
}
} }

View File

@ -251,18 +251,19 @@ public class ReportStatisticsService {
} }
public String getImageContentById(ReportStatisticsWithBLOBs reportRecordId) { public String getImageContentById(ReportStatisticsWithBLOBs reportRecordId) {
ChromeUtils chromeUtils = new ChromeUtils(); ChromeUtils chromeUtils = ChromeUtils.getInstance();
HeadlessRequest headlessRequest = new HeadlessRequest(); HeadlessRequest headlessRequest = new HeadlessRequest();
BaseSystemConfigDTO baseInfo = CommonBeanFactory.getBean(SystemParameterService.class).getBaseInfo(); BaseSystemConfigDTO baseInfo = CommonBeanFactory.getBean(SystemParameterService.class).getBaseInfo();
// 占位符 // 占位符
String platformUrl = "http://localhost:8081"; String platformUrl = "http://localhost:8081";
String remoteDriverUrl = "http://localhost:4444";
if (baseInfo != null) { if (baseInfo != null) {
platformUrl = baseInfo.getUrl(); platformUrl = baseInfo.getUrl();
remoteDriverUrl = baseInfo.getSeleniumDockerUrl();
} }
platformUrl += "/echartPic?shareId=" + reportRecordId.getId(); platformUrl += "/echartPic?shareId=" + reportRecordId.getId();
headlessRequest.setUrl(platformUrl); headlessRequest.setUrl(platformUrl);
headlessRequest.setRemoteDriverUrl(remoteDriverUrl);
String imageData = chromeUtils.getImageInfo(headlessRequest); String imageData = chromeUtils.getImageInfo(headlessRequest);
return imageData; return imageData;
} }

View File

@ -1,21 +1,30 @@
package io.metersphere.reportstatistics.utils; package io.metersphere.reportstatistics.utils;
import com.alibaba.fastjson.JSON;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import io.metersphere.reportstatistics.dto.HeadlessRequest; import io.metersphere.reportstatistics.dto.HeadlessRequest;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeDriverService;
import org.openqa.selenium.chrome.ChromeOptions; import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
import java.net.URL;
public class ChromeUtils { public class ChromeUtils {
private static final String DEFAULT_DRIVERPATH = "/Users/handsomesong/chromeDriver/chromedriver_mac64_m1/chromedriver"; private static ChromeUtils chromeUtils = new ChromeUtils();
private WebDriver genWebDriver(HeadlessRequest headlessRequest) { private ChromeUtils() {
String driverPath = headlessRequest.driverPath; }
if (StringUtils.isEmpty(driverPath)) {
driverPath = DEFAULT_DRIVERPATH; public static ChromeUtils getInstance() {
return chromeUtils;
}
private synchronized WebDriver genWebDriver(HeadlessRequest headlessRequest) {
if (headlessRequest.isEmpty()) {
LogUtil.error("Headless request is null! " + JSON.toJSONString(headlessRequest));
return null;
} }
//初始化一个chrome浏览器实例driver //初始化一个chrome浏览器实例driver
ChromeOptions options = new ChromeOptions(); ChromeOptions options = new ChromeOptions();
@ -30,14 +39,14 @@ public class ChromeUtils {
options.addArguments("no-proxy-server"); options.addArguments("no-proxy-server");
options.addArguments("disable-dev-shm-usage"); options.addArguments("disable-dev-shm-usage");
options.addArguments("lang=zh_CN.UTF-8"); options.addArguments("lang=zh_CN.UTF-8");
WebDriver driver = null; WebDriver driver = null;
try { try {
System.setProperty(ChromeDriverService.CHROME_DRIVER_EXE_PROPERTY, driverPath); driver = new RemoteWebDriver(new URL(headlessRequest.getRemoteDriverUrl()), options);
driver = new ChromeDriver(options); driver.get(headlessRequest.getUrl());
driver.get(headlessRequest.url);
driver.manage().window().fullscreen(); driver.manage().window().fullscreen();
}catch (Exception e){ } catch (Exception e) {
if(driver != null){ if (driver != null) {
driver.quit(); driver.quit();
driver = null; driver = null;
} }
@ -46,29 +55,30 @@ public class ChromeUtils {
return driver; return driver;
} }
public String getImageInfo(HeadlessRequest request){ public synchronized String getImageInfo(HeadlessRequest request) {
WebDriver driver = this.genWebDriver(request); WebDriver driver = this.genWebDriver(request);
String files = null; String files = null;
if(driver != null){ if (driver != null) {
try { try {
//预留echart动画的加载时间 //预留echart动画的加载时间
Thread.sleep(3 * 1000); Thread.sleep(3 * 1000);
String js = "var chartsCanvas = document.getElementById('picChart').getElementsByTagName('canvas')[0];" + String js = "var chartsCanvas = document.getElementById('picChart').getElementsByTagName('canvas')[0];" +
"var imageUrl = null;" + "var imageUrl = null;" +
"if (chartsCanvas!= null) {" + "if (chartsCanvas!= null) {" +
" imageUrl = chartsCanvas && chartsCanvas.toDataURL('image/png');"+ " imageUrl = chartsCanvas && chartsCanvas.toDataURL('image/png');" +
"return imageUrl;" + "return imageUrl;" +
"}"; "}";
files = ((JavascriptExecutor)driver).executeScript(js).toString(); files = ((JavascriptExecutor) driver).executeScript(js).toString();
}catch (Exception e){ } catch (Exception e) {
LogUtil.error(e); LogUtil.error(e);
}finally { } finally {
driver.quit(); driver.quit();
} }
} }
if(StringUtils.isNotEmpty(files)){ if (StringUtils.isNotEmpty(files)) {
return files; return files;
}else { } else {
LogUtil.error("获取报表图片失败!参数:" + JSON.toJSONString(request));
return null; return null;
} }
} }

View File

@ -253,6 +253,9 @@ public class SystemParameterService {
if (StringUtils.equals(param.getParamKey(), ParamConstants.BASE.PROMETHEUS_HOST.getValue())) { if (StringUtils.equals(param.getParamKey(), ParamConstants.BASE.PROMETHEUS_HOST.getValue())) {
baseSystemConfigDTO.setPrometheusHost(param.getParamValue()); baseSystemConfigDTO.setPrometheusHost(param.getParamValue());
} }
if (StringUtils.equals(param.getParamKey(), ParamConstants.BASE.SELENIUM_DOCKER_URL.getValue())) {
baseSystemConfigDTO.setSeleniumDockerUrl(param.getParamValue());
}
} }
} }
return baseSystemConfigDTO; return baseSystemConfigDTO;

@ -1 +1 @@
Subproject commit 2165b7cc0b0358b0b792bc06ff25570dbb230a5c Subproject commit b0c13798836a8bfbc1d415bc5a9610c56df61833

View File

@ -113,7 +113,7 @@ test_case_remark=Remark
test_case_step_desc=Step description test_case_step_desc=Step description
test_case_step_result=Step result test_case_step_result=Step result
test_case_module=Module test_case_module=Module
test_case=Test case test_case=Case
user=User user=User
user_import_template_name=User import templates user_import_template_name=User import templates
user_import_template_sheet=templates user_import_template_sheet=templates
@ -276,9 +276,9 @@ test_case_status_success=Success
test_case_status_trash=Trash test_case_status_trash=Trash
test_case_status_saved=Saved test_case_status_saved=Saved
# track home # track home
api_case=API api_case=Api test
performance_case=PERFORMANCE performance_case=Performance test
scenario_case=SCENARIO scenario_case=Scenario test
create_user=Create user create_user=Create user
test_case_status=Case status test_case_status=Case status
id_not_rightful=ID is not rightful id_not_rightful=ID is not rightful

View File

@ -15,6 +15,10 @@
<el-input v-model="formInline.prometheusHost" :placeholder="$t('system_config.prometheus.host_tip')"/> <el-input v-model="formInline.prometheusHost" :placeholder="$t('system_config.prometheus.host_tip')"/>
<i>({{ $t('commons.examples') }}:http://ms-prometheus:9090)</i> <i>({{ $t('commons.examples') }}:http://ms-prometheus:9090)</i>
</el-form-item> </el-form-item>
<el-form-item :label="$t('system_config.selenium_docker_url')" prop="seleniumDockerUrl">
<el-input v-model="formInline.seleniumDockerUrl" :placeholder="$t('system_config.selenium_docker.url_tip')"/>
<i>({{ $t('commons.examples') }}:http://localhost:4444)</i>
</el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
@ -91,6 +95,7 @@ export default {
{paramKey: "base.url", paramValue: this.formInline.url, type: "text", sort: 1}, {paramKey: "base.url", paramValue: this.formInline.url, type: "text", sort: 1},
{paramKey: "base.concurrency", paramValue: this.formInline.concurrency, type: "text", sort: 2}, {paramKey: "base.concurrency", paramValue: this.formInline.concurrency, type: "text", sort: 2},
{paramKey: "base.prometheus.host", paramValue: this.formInline.prometheusHost, type: "text", sort: 1}, {paramKey: "base.prometheus.host", paramValue: this.formInline.prometheusHost, type: "text", sort: 1},
{paramKey: "base.selenium.docker.url", paramValue: this.formInline.seleniumDockerUrl, type: "text", sort: 1},
]; ];
this.$refs[formInline].validate(valid => { this.$refs[formInline].validate(valid => {

@ -1 +1 @@
Subproject commit 77076b0e650fe18119b434c86c724ad61d43ce21 Subproject commit 11750dbae3a23590a8e58c7b42f5838be51677af

View File

@ -449,6 +449,10 @@ export default {
host: 'Prometheus Host', host: 'Prometheus Host',
host_tip: 'example: http://ms-prometheus:9090', host_tip: 'example: http://ms-prometheus:9090',
host_is_null: 'Prometheus Host cannot be empty' host_is_null: 'Prometheus Host cannot be empty'
},
selenium_docker_url: 'selenium-docker URL',
selenium_docker: {
url_tip: 'example: http://localhost:4444',
} }
}, },
custom_field: { custom_field: {

View File

@ -451,6 +451,10 @@ export default {
host: 'Prometheus地址', host: 'Prometheus地址',
host_tip: '例如:http://ms-prometheus:9090', host_tip: '例如:http://ms-prometheus:9090',
host_is_null: 'Prometheus地址不能为空' host_is_null: 'Prometheus地址不能为空'
},
selenium_docker_url: 'selenium-docker 地址',
selenium_docker: {
url_tip: '例如:http://localhost:4444',
} }
}, },
custom_field: { custom_field: {

View File

@ -451,6 +451,10 @@ export default {
host: 'Prometheus地址', host: 'Prometheus地址',
host_tip: '例如:http://ms-prometheus:9090', host_tip: '例如:http://ms-prometheus:9090',
host_is_null: 'Prometheus地址不能為空' host_is_null: 'Prometheus地址不能為空'
},
selenium_docker_url: 'selenium-docker 地址',
selenium_docker: {
url_tip: '例如:http://localhost:4444',
} }
}, },
custom_field: { custom_field: {