feat: 添加自定监控
This commit is contained in:
parent
85facc5364
commit
5c69806d00
|
@ -18,6 +18,7 @@ import io.metersphere.dto.LogDetailDTO;
|
||||||
import io.metersphere.performance.base.*;
|
import io.metersphere.performance.base.*;
|
||||||
import io.metersphere.performance.dto.LoadTestExportJmx;
|
import io.metersphere.performance.dto.LoadTestExportJmx;
|
||||||
import io.metersphere.performance.dto.MetricData;
|
import io.metersphere.performance.dto.MetricData;
|
||||||
|
import io.metersphere.performance.dto.Monitor;
|
||||||
import io.metersphere.performance.service.MetricQueryService;
|
import io.metersphere.performance.service.MetricQueryService;
|
||||||
import io.metersphere.performance.service.PerformanceReportService;
|
import io.metersphere.performance.service.PerformanceReportService;
|
||||||
import io.metersphere.performance.service.PerformanceTestService;
|
import io.metersphere.performance.service.PerformanceTestService;
|
||||||
|
@ -239,7 +240,7 @@ public class ShareController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/metric/query/resource/{shareId}/{id}")
|
@GetMapping("/metric/query/resource/{shareId}/{id}")
|
||||||
public List<String> queryReportResource(@PathVariable String shareId, @PathVariable("id") String reportId) {
|
public List<Monitor> queryReportResource(@PathVariable String shareId, @PathVariable("id") String reportId) {
|
||||||
return metricService.queryReportResource(reportId);
|
return metricService.queryReportResource(reportId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.metersphere.performance.controller;
|
package io.metersphere.performance.controller;
|
||||||
|
|
||||||
import io.metersphere.performance.dto.MetricData;
|
import io.metersphere.performance.dto.MetricData;
|
||||||
|
import io.metersphere.performance.dto.Monitor;
|
||||||
import io.metersphere.performance.service.MetricQueryService;
|
import io.metersphere.performance.service.MetricQueryService;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ public class MetricQueryController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/query/resource/{id}")
|
@GetMapping("/query/resource/{id}")
|
||||||
public List<String> queryReportResource(@PathVariable("id") String reportId) {
|
public List<Monitor> queryReportResource(@PathVariable("id") String reportId) {
|
||||||
return metricService.queryReportResource(reportId);
|
return metricService.queryReportResource(reportId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,14 @@ package io.metersphere.performance.dto;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public class Monitor {
|
public class Monitor {
|
||||||
private String name;
|
private String name;
|
||||||
private String environmentId;
|
|
||||||
private String environmentName;
|
|
||||||
private String ip;
|
private String ip;
|
||||||
private Integer port;
|
private Integer port;
|
||||||
private String description;
|
private String description;
|
||||||
private String monitorStatus;
|
private List<MonitorItem> monitorConfig;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package io.metersphere.performance.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class MonitorItem {
|
||||||
|
private String value; // 表达式
|
||||||
|
private String name; // 监控项
|
||||||
|
}
|
|
@ -4,7 +4,6 @@ package io.metersphere.performance.service;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.alibaba.nacos.client.utils.StringUtils;
|
|
||||||
import io.metersphere.base.domain.LoadTestReportWithBLOBs;
|
import io.metersphere.base.domain.LoadTestReportWithBLOBs;
|
||||||
import io.metersphere.base.domain.TestResource;
|
import io.metersphere.base.domain.TestResource;
|
||||||
import io.metersphere.base.mapper.LoadTestReportMapper;
|
import io.metersphere.base.mapper.LoadTestReportMapper;
|
||||||
|
@ -21,9 +20,11 @@ import io.metersphere.performance.controller.request.MetricQuery;
|
||||||
import io.metersphere.performance.controller.request.MetricRequest;
|
import io.metersphere.performance.controller.request.MetricRequest;
|
||||||
import io.metersphere.performance.dto.MetricData;
|
import io.metersphere.performance.dto.MetricData;
|
||||||
import io.metersphere.performance.dto.Monitor;
|
import io.metersphere.performance.dto.Monitor;
|
||||||
|
import io.metersphere.performance.dto.MonitorItem;
|
||||||
import io.metersphere.service.SystemParameterService;
|
import io.metersphere.service.SystemParameterService;
|
||||||
import io.metersphere.service.TestResourceService;
|
import io.metersphere.service.TestResourceService;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
@ -156,7 +157,7 @@ public class MetricQueryService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MetricData> queryMetric(String reportId) {
|
public List<MetricData> queryMetric(String reportId) {
|
||||||
List<String> instances = new ArrayList<>();
|
List<Monitor> instances = new ArrayList<>();
|
||||||
LoadTestReportWithBLOBs report = loadTestReportMapper.selectByPrimaryKey(reportId);
|
LoadTestReportWithBLOBs report = loadTestReportMapper.selectByPrimaryKey(reportId);
|
||||||
String poolId = report.getTestResourcePoolId();
|
String poolId = report.getTestResourcePoolId();
|
||||||
List<TestResource> resourceList = testResourceService.getTestResourceList(poolId);
|
List<TestResource> resourceList = testResourceService.getTestResourceList(poolId);
|
||||||
|
@ -166,7 +167,10 @@ public class MetricQueryService {
|
||||||
NodeDTO dto = JSON.parseObject(resource.getConfiguration(), NodeDTO.class);
|
NodeDTO dto = JSON.parseObject(resource.getConfiguration(), NodeDTO.class);
|
||||||
if (StringUtils.isNotBlank(dto.getIp())) {
|
if (StringUtils.isNotBlank(dto.getIp())) {
|
||||||
int port = dto.getMonitorPort() == null ? 9100 : dto.getMonitorPort();
|
int port = dto.getMonitorPort() == null ? 9100 : dto.getMonitorPort();
|
||||||
instances.add(dto.getIp() + ":" + port);
|
Monitor e = new Monitor();
|
||||||
|
e.setIp(dto.getIp());
|
||||||
|
e.setPort(port);
|
||||||
|
instances.add(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -179,11 +183,14 @@ public class MetricQueryService {
|
||||||
List<MetricDataRequest> list = new ArrayList<>();
|
List<MetricDataRequest> list = new ArrayList<>();
|
||||||
// 加入高级设置中的监控配置
|
// 加入高级设置中的监控配置
|
||||||
for (int i = 0; i < monitorParams.size(); i++) {
|
for (int i = 0; i < monitorParams.size(); i++) {
|
||||||
Monitor monitor = monitorParams.getObject(i, Monitor.class);
|
JSONObject o = monitorParams.getJSONObject(i);
|
||||||
String instance = monitor.getIp() + ":" + monitor.getPort();
|
Monitor monitor = new Monitor();
|
||||||
if (!instances.contains(instance)) {
|
monitor.setIp(o.getString("ip"));
|
||||||
instances.add(instance);
|
monitor.setName(o.getString("name"));
|
||||||
}
|
monitor.setPort(o.getInteger("port"));
|
||||||
|
monitor.setDescription(o.getString("description"));
|
||||||
|
monitor.setMonitorConfig(JSONObject.parseArray(o.getString("monitorConfig"), MonitorItem.class));
|
||||||
|
instances.add(monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
instances.forEach(instance -> {
|
instances.forEach(instance -> {
|
||||||
|
@ -203,38 +210,55 @@ public class MetricQueryService {
|
||||||
return queryMetricData(metricRequest);
|
return queryMetricData(metricRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getRequest(String instance, List<MetricDataRequest> list) {
|
private void getRequest(Monitor monitor, List<MetricDataRequest> list) {
|
||||||
Map<String, String> map = MetricQuery.getMetricQueryMap();
|
if (CollectionUtils.isNotEmpty(monitor.getMonitorConfig())) {
|
||||||
Set<String> set = map.keySet();
|
monitor.getMonitorConfig().forEach(c -> {
|
||||||
set.forEach(s -> {
|
if (StringUtils.isBlank(c.getValue())) {
|
||||||
MetricDataRequest request = new MetricDataRequest();
|
return;
|
||||||
String promQL = map.get(s);
|
}
|
||||||
request.setPromQL(promQL);
|
MetricDataRequest request = new MetricDataRequest();
|
||||||
request.setSeriesName(s);
|
String promQL = c.getValue();
|
||||||
request.setInstance(instance);
|
request.setPromQL(promQL);
|
||||||
list.add(request);
|
request.setSeriesName(c.getName());
|
||||||
});
|
request.setInstance(monitor.getIp() + ":" + monitor.getPort());
|
||||||
|
list.add(request);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Map<String, String> map = MetricQuery.getMetricQueryMap();
|
||||||
|
Set<String> set = map.keySet();
|
||||||
|
set.forEach(s -> {
|
||||||
|
MetricDataRequest request = new MetricDataRequest();
|
||||||
|
String promQL = map.get(s);
|
||||||
|
request.setPromQL(promQL);
|
||||||
|
request.setSeriesName(s);
|
||||||
|
request.setInstance(monitor.getIp() + ":" + monitor.getPort());
|
||||||
|
list.add(request);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> queryReportResource(String reportId) {
|
public List<Monitor> queryReportResource(String reportId) {
|
||||||
List<String> result = new ArrayList<>();
|
List<Monitor> result = new ArrayList<>();
|
||||||
List<String> resourceIdAndIndexes = extLoadTestReportMapper.selectResourceId(reportId);
|
List<String> resourceIdAndIndexes = extLoadTestReportMapper.selectResourceId(reportId);
|
||||||
resourceIdAndIndexes.forEach(resourceIdAndIndex -> {
|
resourceIdAndIndexes.forEach(resourceIdAndIndex -> {
|
||||||
String[] split = org.apache.commons.lang3.StringUtils.split(resourceIdAndIndex, "_");
|
String[] split = StringUtils.split(resourceIdAndIndex, "_");
|
||||||
String resourceId = split[0];
|
String resourceId = split[0];
|
||||||
TestResource testResource = testResourceService.getTestResource(resourceId);
|
TestResource testResource = testResourceService.getTestResource(resourceId);
|
||||||
if (testResource == null) {
|
if (testResource == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String configuration = testResource.getConfiguration();
|
String configuration = testResource.getConfiguration();
|
||||||
if (org.apache.commons.lang3.StringUtils.isBlank(configuration)) {
|
if (StringUtils.isBlank(configuration)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
NodeDTO dto = JSON.parseObject(configuration, NodeDTO.class);
|
NodeDTO dto = JSON.parseObject(configuration, NodeDTO.class);
|
||||||
if (StringUtils.isNotBlank(dto.getIp())) {
|
if (StringUtils.isNotBlank(dto.getIp())) {
|
||||||
Integer monitorPort = dto.getMonitorPort();
|
Integer monitorPort = dto.getMonitorPort();
|
||||||
int port = monitorPort == null ? 9100 : monitorPort;
|
int port = monitorPort == null ? 9100 : monitorPort;
|
||||||
result.add(dto.getIp() + ":" + port);
|
Monitor monitor = new Monitor();
|
||||||
|
monitor.setIp(dto.getIp());
|
||||||
|
monitor.setPort(port);
|
||||||
|
result.add(monitor);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -247,11 +271,14 @@ public class MetricQueryService {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < monitorParams.size(); i++) {
|
for (int i = 0; i < monitorParams.size(); i++) {
|
||||||
Monitor monitor = monitorParams.getObject(i, Monitor.class);
|
JSONObject o = monitorParams.getJSONObject(i);
|
||||||
String instance = monitor.getIp() + ":" + monitor.getPort();
|
Monitor monitor = new Monitor();
|
||||||
if (!result.contains(instance)) {
|
monitor.setIp(o.getString("ip"));
|
||||||
result.add(instance);
|
monitor.setName(o.getString("name"));
|
||||||
}
|
monitor.setPort(o.getInteger("port"));
|
||||||
|
monitor.setDescription(o.getString("description"));
|
||||||
|
monitor.setMonitorConfig(JSONObject.parseArray(o.getString("monitorConfig"), MonitorItem.class));
|
||||||
|
result.add(monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import io.metersphere.dto.LogDetailDTO;
|
||||||
import io.metersphere.performance.base.*;
|
import io.metersphere.performance.base.*;
|
||||||
import io.metersphere.performance.dto.LoadTestExportJmx;
|
import io.metersphere.performance.dto.LoadTestExportJmx;
|
||||||
import io.metersphere.performance.dto.MetricData;
|
import io.metersphere.performance.dto.MetricData;
|
||||||
|
import io.metersphere.performance.dto.Monitor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ public class TestPlanLoadCaseDTO extends TestPlanLoadCase {
|
||||||
private List<Errors> reportErrors;
|
private List<Errors> reportErrors;
|
||||||
private List<ErrorsTop5> reportErrorsTop5;
|
private List<ErrorsTop5> reportErrorsTop5;
|
||||||
private List<LogDetailDTO> reportLogResource;
|
private List<LogDetailDTO> reportLogResource;
|
||||||
private List<String> reportResource;
|
private List<Monitor> reportResource;
|
||||||
private List<MetricData> metricData;
|
private List<MetricData> metricData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ import io.metersphere.notice.service.NoticeSendService;
|
||||||
import io.metersphere.performance.base.*;
|
import io.metersphere.performance.base.*;
|
||||||
import io.metersphere.performance.dto.LoadTestExportJmx;
|
import io.metersphere.performance.dto.LoadTestExportJmx;
|
||||||
import io.metersphere.performance.dto.MetricData;
|
import io.metersphere.performance.dto.MetricData;
|
||||||
|
import io.metersphere.performance.dto.Monitor;
|
||||||
import io.metersphere.performance.request.RunTestPlanRequest;
|
import io.metersphere.performance.request.RunTestPlanRequest;
|
||||||
import io.metersphere.performance.service.MetricQueryService;
|
import io.metersphere.performance.service.MetricQueryService;
|
||||||
import io.metersphere.performance.service.PerformanceReportService;
|
import io.metersphere.performance.service.PerformanceReportService;
|
||||||
|
@ -1573,7 +1574,7 @@ public class TestPlanService {
|
||||||
response.setReportLogResource(reportLogResource);
|
response.setReportLogResource(reportLogResource);
|
||||||
// performanceReportService.getReportLogs(reportId, resourceId);
|
// performanceReportService.getReportLogs(reportId, resourceId);
|
||||||
|
|
||||||
List<String> reportResource = metricQueryService.queryReportResource(reportId);
|
List<Monitor> reportResource = metricQueryService.queryReportResource(reportId);
|
||||||
response.setReportResource(reportResource);
|
response.setReportResource(reportResource);
|
||||||
List<MetricData> metricData = metricQueryService.queryMetric(reportId);
|
List<MetricData> metricData = metricQueryService.queryMetric(reportId);
|
||||||
response.setMetricData(metricData);
|
response.setMetricData(metricData);
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit a6a66f87a57346cdd7da22086bac5e82a7e47bdb
|
Subproject commit 6e2b1d3d7d79f985e6edf81eb593670b8da87465
|
|
@ -6,10 +6,10 @@
|
||||||
<el-select v-model="currentInstance" placeholder="" size="small" style="width: 100%"
|
<el-select v-model="currentInstance" placeholder="" size="small" style="width: 100%"
|
||||||
@change="handleChecked(currentInstance)">
|
@change="handleChecked(currentInstance)">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in instances"
|
v-for="item in instances"
|
||||||
:key="item"
|
:key="item.ip+item.port"
|
||||||
:label="item"
|
:value="item.ip+':'+item.port">
|
||||||
:value="item">
|
{{ item.ip }} {{ item.name }}
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -35,47 +35,47 @@
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :offset="2" :span="20">
|
<el-col :offset="2" :span="20">
|
||||||
<el-table
|
<el-table
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
stripe
|
stripe
|
||||||
border
|
border
|
||||||
style="width: 100%">
|
style="width: 100%">
|
||||||
<el-table-column label="Label" align="center">
|
<el-table-column label="Label" align="center">
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="label"
|
prop="label"
|
||||||
label="Label"
|
label="Label"
|
||||||
sortable>
|
sortable>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="Aggregate" align="center">
|
<el-table-column label="Aggregate" align="center">
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="avg"
|
prop="avg"
|
||||||
label="Avg."
|
label="Avg."
|
||||||
width="100"
|
width="100"
|
||||||
sortable
|
sortable
|
||||||
/>
|
/>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="min"
|
prop="min"
|
||||||
label="Min."
|
label="Min."
|
||||||
width="100"
|
width="100"
|
||||||
sortable
|
sortable
|
||||||
/>
|
/>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="max"
|
prop="max"
|
||||||
label="Max."
|
label="Max."
|
||||||
width="100"
|
width="100"
|
||||||
sortable
|
sortable
|
||||||
/>
|
/>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="Range" align="center">
|
<el-table-column label="Range" align="center">
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="startTime"
|
prop="startTime"
|
||||||
label="Start"
|
label="Start"
|
||||||
width="160"
|
width="160"
|
||||||
/>
|
/>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="endTime"
|
prop="endTime"
|
||||||
label="End"
|
label="End"
|
||||||
width="160"
|
width="160"
|
||||||
/>
|
/>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
@ -97,6 +97,14 @@ import {
|
||||||
} from "@/network/load-test";
|
} from "@/network/load-test";
|
||||||
|
|
||||||
const color = ['#60acfc', '#32d3eb', '#5bc49f', '#feb64d', '#ff7c7c', '#9287e7', '#ca8622', '#bda29a', '#6e7074', '#546570', '#c4ccd3'];
|
const color = ['#60acfc', '#32d3eb', '#5bc49f', '#feb64d', '#ff7c7c', '#9287e7', '#ca8622', '#bda29a', '#6e7074', '#546570', '#c4ccd3'];
|
||||||
|
const checkList = ['CPU', 'Memory', 'Disk', 'Network In', 'Network Out'];
|
||||||
|
const checkOptions = [
|
||||||
|
{key: 'cpu', label: 'CPU'},
|
||||||
|
{key: 'memory', label: 'Memory'},
|
||||||
|
{key: 'disk', label: 'Disk'},
|
||||||
|
{key: 'netIn', label: 'Network In'},
|
||||||
|
{key: 'netOut', label: 'Network Out'}
|
||||||
|
];
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MonitorCard",
|
name: "MonitorCard",
|
||||||
|
@ -113,14 +121,8 @@ export default {
|
||||||
instances: [],
|
instances: [],
|
||||||
data: [],
|
data: [],
|
||||||
tableData: [],
|
tableData: [],
|
||||||
checkList: ['CPU', 'Memory', 'Disk', 'Network In', 'Network Out'],
|
checkList: checkList,
|
||||||
checkOptions: [
|
checkOptions: checkOptions,
|
||||||
{key: 'cpu', label: 'CPU'},
|
|
||||||
{key: 'memory', label: 'Memory'},
|
|
||||||
{key: 'disk', label: 'Disk'},
|
|
||||||
{key: 'netIn', label: 'Network In'},
|
|
||||||
{key: 'netOut', label: 'Network Out'}
|
|
||||||
],
|
|
||||||
baseOption: {
|
baseOption: {
|
||||||
color: color,
|
color: color,
|
||||||
grid: {
|
grid: {
|
||||||
|
@ -175,14 +177,14 @@ export default {
|
||||||
// this.init = true;
|
// this.init = true;
|
||||||
if (this.planReportTemplate) {
|
if (this.planReportTemplate) {
|
||||||
this.instances = this.planReportTemplate.reportResource;
|
this.instances = this.planReportTemplate.reportResource;
|
||||||
this.currentInstance = this.instances[0];
|
this.currentInstance = this.instances[0].ip + ":" + this.instances[0].port;
|
||||||
this.data = this.planReportTemplate.metricData;
|
this.data = this.planReportTemplate.metricData;
|
||||||
this.totalOption = this.getOption(this.currentInstance);
|
this.totalOption = this.getOption(this.currentInstance);
|
||||||
} else if (this.isShare) {
|
} else if (this.isShare) {
|
||||||
getSharePerformanceMetricQueryResource(this.shareId, this.id).then(response => {
|
getSharePerformanceMetricQueryResource(this.shareId, this.id).then(response => {
|
||||||
this.instances = response.data.data;
|
this.instances = response.data.data;
|
||||||
if (!this.currentInstance) {
|
if (!this.currentInstance) {
|
||||||
this.currentInstance = this.instances[0];
|
this.currentInstance = this.instances[0].ip + ":" + this.instances[0].port;
|
||||||
}
|
}
|
||||||
getSharePerformanceMetricQuery(this.shareId, this.id).then(result => {
|
getSharePerformanceMetricQuery(this.shareId, this.id).then(result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
|
@ -196,7 +198,7 @@ export default {
|
||||||
getPerformanceMetricQueryResource(this.id).then(response => {
|
getPerformanceMetricQueryResource(this.id).then(response => {
|
||||||
this.instances = response.data.data;
|
this.instances = response.data.data;
|
||||||
if (!this.currentInstance) {
|
if (!this.currentInstance) {
|
||||||
this.currentInstance = this.instances[0];
|
this.currentInstance = this.instances[0].ip + ":" + this.instances[0].port;
|
||||||
}
|
}
|
||||||
getPerformanceMetricQuery(this.id).then(result => {
|
getPerformanceMetricQuery(this.id).then(result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
|
@ -211,6 +213,18 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleChecked(id) {
|
handleChecked(id) {
|
||||||
|
let curr = this.instances.filter(instance => id === instance.ip + ":" + instance.port)[0];
|
||||||
|
if (curr.monitorConfig) {
|
||||||
|
this.checkList = [];
|
||||||
|
this.checkOptions = curr.monitorConfig.filter(mc => mc.value && mc.name)
|
||||||
|
.map(mc => {
|
||||||
|
this.checkList.push(mc.name);
|
||||||
|
return {key: mc.name, label: mc.name,};
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.checkOptions = checkOptions;
|
||||||
|
this.checkList = checkList;
|
||||||
|
}
|
||||||
this.totalOption = {};
|
this.totalOption = {};
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.totalOption = this.getOption(id);
|
this.totalOption = this.getOption(id);
|
||||||
|
|
|
@ -8,27 +8,36 @@
|
||||||
:destroy-on-close="true"
|
:destroy-on-close="true"
|
||||||
v-loading="result.loading"
|
v-loading="result.loading"
|
||||||
>
|
>
|
||||||
<el-form :model="form" label-position="right" label-width="80px" size="small" :rules="rule" ref="monitorForm">
|
<div style="height: 50vh;overflow-y: auto;">
|
||||||
<el-form-item :label="$t('commons.name')" prop="name">
|
<el-form :model="form" label-position="right" label-width="80px" size="small" :rules="rule" ref="monitorForm">
|
||||||
<el-input v-model="form.name" autocomplete="off"/>
|
<el-form-item :label="$t('commons.name')" prop="name">
|
||||||
</el-form-item>
|
<el-input v-model="form.name" autocomplete="off"/>
|
||||||
<h4 style="margin-left: 80px;">监控配置</h4>
|
</el-form-item>
|
||||||
<el-row>
|
<h4 style="margin-left: 80px;">监控配置</h4>
|
||||||
<el-col :span="12">
|
<el-row>
|
||||||
<el-form-item label="IP" prop="ip">
|
<el-col :span="12">
|
||||||
<el-input v-model="form.ip" autocomplete="off"/>
|
<el-form-item label="IP" prop="ip">
|
||||||
</el-form-item>
|
<el-input v-model="form.ip" autocomplete="off"/>
|
||||||
</el-col>
|
</el-form-item>
|
||||||
<el-col :span="12">
|
</el-col>
|
||||||
<el-form-item label="Port" prop="port">
|
<el-col :span="12">
|
||||||
<el-input-number v-model="form.port" :min="1" :max="65535"/>
|
<el-form-item label="Port" prop="port">
|
||||||
</el-form-item>
|
<el-input-number v-model="form.port" :min="1" :max="65535"/>
|
||||||
</el-col>
|
</el-form-item>
|
||||||
</el-row>
|
</el-col>
|
||||||
<el-form-item label="描述" prop="description">
|
</el-row>
|
||||||
<el-input v-model="form.description" autocomplete="off"/>
|
<el-form-item label="描述" prop="description">
|
||||||
</el-form-item>
|
<el-input v-model="form.description" autocomplete="off"/>
|
||||||
</el-form>
|
</el-form-item>
|
||||||
|
<h4 style="margin-left: 80px;">监控项</h4>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="20" :offset="2">
|
||||||
|
<monitor-key-value key-placeholder="Label" value-placeholder="promQL" :items="monitorList"
|
||||||
|
:suggestions="metricSuggestions"/>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<ms-dialog-footer
|
<ms-dialog-footer
|
||||||
|
@ -47,11 +56,11 @@
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import MsDialogFooter from "@/business/components/common/components/MsDialogFooter";
|
import MsDialogFooter from "@/business/components/common/components/MsDialogFooter";
|
||||||
import {CONFIG_TYPE} from "@/common/js/constants";
|
import MonitorKeyValue from "@/business/components/performance/test/components/MonitorKeyValue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "EditMonitor",
|
name: "EditMonitor",
|
||||||
components: {MsDialogFooter},
|
components: {MonitorKeyValue, MsDialogFooter},
|
||||||
props: {
|
props: {
|
||||||
testId: String,
|
testId: String,
|
||||||
list: Array,
|
list: Array,
|
||||||
|
@ -67,6 +76,8 @@ export default {
|
||||||
port: {required: true, message: "port必填", trigger: 'blur'},
|
port: {required: true, message: "port必填", trigger: 'blur'},
|
||||||
},
|
},
|
||||||
index: '',
|
index: '',
|
||||||
|
monitorList: [],
|
||||||
|
metricSuggestions: [{value: 'cpu'}, {value: 'memory'}, {value: 'disk'}, {value: 'netIn'}, {value: 'netOut'}]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -75,6 +86,9 @@ export default {
|
||||||
this.dialogVisible = true;
|
this.dialogVisible = true;
|
||||||
if (data) {
|
if (data) {
|
||||||
const copy = JSON.parse(JSON.stringify(data));
|
const copy = JSON.parse(JSON.stringify(data));
|
||||||
|
if (copy.monitorConfig) {
|
||||||
|
this.monitorList = JSON.parse(copy.monitorConfig);
|
||||||
|
}
|
||||||
this.form = copy;
|
this.form = copy;
|
||||||
}
|
}
|
||||||
if (index !== '' && index !== undefined) {
|
if (index !== '' && index !== undefined) {
|
||||||
|
@ -88,6 +102,7 @@ export default {
|
||||||
update() {
|
update() {
|
||||||
this.$refs.monitorForm.validate(valid => {
|
this.$refs.monitorForm.validate(valid => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
this.form.monitorConfig = JSON.stringify(this.monitorList);
|
||||||
this.list.splice(this.index, 1, this.form);
|
this.list.splice(this.index, 1, this.form);
|
||||||
this.$emit("update:list", this.list);
|
this.$emit("update:list", this.list);
|
||||||
this.dialogVisible = false;
|
this.dialogVisible = false;
|
||||||
|
@ -99,6 +114,7 @@ export default {
|
||||||
create() {
|
create() {
|
||||||
this.$refs.monitorForm.validate(valid => {
|
this.$refs.monitorForm.validate(valid => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
this.form.monitorConfig = JSON.stringify(this.monitorList);
|
||||||
// this.form.monitorStatus = CONFIG_TYPE.NOT;
|
// this.form.monitorStatus = CONFIG_TYPE.NOT;
|
||||||
this.list.push(this.form);
|
this.list.push(this.form);
|
||||||
this.$emit("update:list", this.list);
|
this.$emit("update:list", this.list);
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<span class="kv-description" v-if="description">
|
||||||
|
{{ description }}
|
||||||
|
</span>
|
||||||
|
<div class="kv-row" v-for="(item, index) in items" :key="index">
|
||||||
|
<el-row type="flex" :gutter="20" justify="space-between" align="middle">
|
||||||
|
<el-col>
|
||||||
|
<el-input v-if="!suggestions" :disabled="isReadOnly" v-model="item.name" size="small" maxlength="200"
|
||||||
|
@change="changeKey(item)"
|
||||||
|
:placeholder="keyText" show-word-limit/>
|
||||||
|
<el-autocomplete :disabled="isReadOnly" :maxlength="200" v-if="suggestions" v-model="item.name" size="small"
|
||||||
|
:fetch-suggestions="querySearch" :placeholder="keyText"
|
||||||
|
@select="changeKey(item)"
|
||||||
|
show-word-limit/>
|
||||||
|
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col>
|
||||||
|
<el-input :disabled="isReadOnly" v-model="item.value" size="small" @change="change"
|
||||||
|
:placeholder="valueText" show-word-limit/>
|
||||||
|
</el-col>
|
||||||
|
<el-col class="kv-delete">
|
||||||
|
<el-button size="mini" class="el-icon-delete-solid" circle @click="remove(index)"
|
||||||
|
:disabled="isDisable(index) || isReadOnly"/>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
const CPU_QL = "100 - (avg by (instance) (irate(node_cpu_seconds_total{instance='%1$s', mode='idle'}[1m])) * 100)";
|
||||||
|
const MEMORY_QL = "(node_memory_MemTotal_bytes{instance='%1$s'} - node_memory_MemAvailable_bytes{instance='%1$s'}) / node_memory_MemTotal_bytes{instance='%1$s'} * 100";
|
||||||
|
const DISK_QL = "100 - node_filesystem_free_bytes{instance='%1$s'} / node_filesystem_size_bytes{instance='%1$s'} * 100";
|
||||||
|
const NET_IN_QL = "sum by (instance) (irate(node_network_receive_bytes_total{instance='%1$s',device!~'bond.*?|lo'}[1m])/1024)";
|
||||||
|
const NET_OUT_QL = "sum by (instance) (irate(node_network_transmit_bytes_total{instance='%1$s',device!~'bond.*?|lo'}[1m])/1024)";
|
||||||
|
|
||||||
|
import {KeyValue} from "@/business/components/api/test/model/ScenarioModel";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "MonitorKeyValue",
|
||||||
|
|
||||||
|
props: {
|
||||||
|
keyPlaceholder: String,
|
||||||
|
valuePlaceholder: String,
|
||||||
|
description: String,
|
||||||
|
items: Array,
|
||||||
|
isReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
suggestions: Array
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
keyText() {
|
||||||
|
return this.keyPlaceholder || this.$t("api_test.key");
|
||||||
|
},
|
||||||
|
valueText() {
|
||||||
|
return this.valuePlaceholder || this.$t("api_test.value");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
remove: function (index) {
|
||||||
|
// 移除整行输入控件及内容
|
||||||
|
this.items.splice(index, 1);
|
||||||
|
this.$emit('change', this.items);
|
||||||
|
},
|
||||||
|
change: function () {
|
||||||
|
let isNeedCreate = true;
|
||||||
|
let removeIndex = -1;
|
||||||
|
this.items.forEach((item, index) => {
|
||||||
|
if (!item.name && !item.value) {
|
||||||
|
// 多余的空行
|
||||||
|
if (index !== this.items.length - 1) {
|
||||||
|
removeIndex = index;
|
||||||
|
}
|
||||||
|
// 没有空行,需要创建空行
|
||||||
|
isNeedCreate = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (isNeedCreate) {
|
||||||
|
this.items.push(new KeyValue({enable: true}));
|
||||||
|
}
|
||||||
|
this.$emit('change', this.items);
|
||||||
|
// TODO 检查key重复
|
||||||
|
},
|
||||||
|
changeKey: function (curr) {
|
||||||
|
// 填充值
|
||||||
|
if (curr.name === 'cpu') {
|
||||||
|
curr.value = CPU_QL;
|
||||||
|
}
|
||||||
|
if (curr.name === 'memory') {
|
||||||
|
curr.value = MEMORY_QL;
|
||||||
|
}
|
||||||
|
if (curr.name === 'disk') {
|
||||||
|
curr.value = DISK_QL;
|
||||||
|
}
|
||||||
|
if (curr.name === 'netIn') {
|
||||||
|
curr.value = NET_IN_QL;
|
||||||
|
}
|
||||||
|
if (curr.name === 'netOut') {
|
||||||
|
curr.value = NET_OUT_QL;
|
||||||
|
}
|
||||||
|
this.change();
|
||||||
|
},
|
||||||
|
isDisable: function (index) {
|
||||||
|
return this.items.length - 1 === index;
|
||||||
|
},
|
||||||
|
querySearch(queryString, cb) {
|
||||||
|
let suggestions = this.suggestions;
|
||||||
|
let results = queryString ? suggestions.filter(this.createFilter(queryString)) : suggestions;
|
||||||
|
cb(results);
|
||||||
|
},
|
||||||
|
createFilter(queryString) {
|
||||||
|
return (restaurant) => {
|
||||||
|
return (restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (this.items.length === 0 || this.items[this.items.length - 1].name) {
|
||||||
|
this.items.push(new KeyValue({enable: true}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.kv-description {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-row {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-checkbox {
|
||||||
|
width: 20px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kv-delete {
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-autocomplete {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue