feat: 添加自定监控

This commit is contained in:
Captain.B 2021-09-16 17:15:10 +08:00 committed by 刘瑞斌
parent 85facc5364
commit 5c69806d00
11 changed files with 327 additions and 100 deletions

View File

@ -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);
} }

View File

@ -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);
} }
} }

View File

@ -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;
} }

View File

@ -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; // 监控项
}

View File

@ -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;

View File

@ -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;
} }
} }

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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>