add filters

This commit is contained in:
Qiuxia Fan 2022-04-20 17:48:55 +08:00
parent 70aec8f345
commit 20f49e6e21
6 changed files with 135 additions and 10 deletions

View File

@ -58,7 +58,7 @@ const props = defineProps({
},
size: { type: null, default: "default" },
placeholder: {
type: [String, Number] as PropType<string | number>,
type: [String, undefined] as PropType<string>,
default: "Select a option",
},
borderRadius: { type: Number, default: 3 },

2
src/types/ebpf.d.ts vendored
View File

@ -43,7 +43,7 @@ export interface EBPFProfilingSchedule {
startTime: number;
}
type Process = {
export type Process = {
id: string;
name: string;
serviceId: string;

View File

@ -15,7 +15,7 @@ limitations under the License. -->
<template>
<div class="flex-h content">
<TaskList />
<div class="vis-graph">
<div class="vis-graph ml-5">
<EBPFSchedules />
<EBPFTree />
</div>

View File

@ -15,7 +15,7 @@ limitations under the License. -->
<template>
<div class="flex-h header">
<div>eBPF Profile</div>
<el-button class="new-btn" size="small" @click="createTask">
<el-button type="primary" size="small" @click="createTask">
{{ t("newTask") }}
</el-button>
</div>
@ -83,9 +83,10 @@ watch(
</script>
<style lang="scss" scoped>
.header {
padding: 10px;
padding: 5px 20px 5px 10px;
font-size: 12px;
border-bottom: 1px solid #dcdfe6;
justify-content: space-between;
}
.name {

View File

@ -13,32 +13,145 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->
<template>
<div class="filters">
<Selector
:value="selectedLabels"
:options="labels"
size="small"
placeholder="Please select labels"
@change="changeLabels"
class="inputs mr-10"
:multiple="true"
/>
<el-popover placement="bottom" :width="680" trigger="click">
<template #reference>
<el-button type="primary" size="small">
Click to select processes
</el-button>
</template>
<el-table
:data="processes"
ref="multipleTableRef"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" />
<el-table-column
v-for="(h, index) of TableHeader"
:property="h.property"
:label="h.label"
:key="index"
width="150"
/>
<el-table-column width="300" label="Attributes">
<template #default="scope">
{{ scope.row.attributes.map((d: any) => `${d.name}=${d.value}`).join("; ") }}
</template>
</el-table-column>
</el-table>
</el-popover>
<el-button type="primary" size="small" @click="analyzeEBPF">
{{ t("analyze") }}
</el-button>
</div>
<div ref="timeline" class="schedules"></div>
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
import dayjs from "dayjs";
import { useI18n } from "vue-i18n";
import { Option } from "@/types/app";
import { TableHeader } from "./data";
import { useEbpfStore } from "@/store/modules/ebpf";
import { EBPFProfilingSchedule } from "@/types/ebpf";
import { EBPFProfilingSchedule, Process } from "@/types/ebpf";
import { DataSet, Timeline } from "vis-timeline/standalone";
import "vis-timeline/styles/vis-timeline-graph2d.css";
import type { ElTable } from "element-plus";
const { t } = useI18n();
const ebpfStore = useEbpfStore();
/*global Nullable */
const multipleTableRef = ref<InstanceType<typeof ElTable>>();
const selectedProcesses = ref<string[]>([]);
const timeline = ref<Nullable<HTMLDivElement>>(null);
const visGraph = ref<Nullable<any>>(null);
const labels = ref<Option[]>([{ label: "All", value: "0" }]);
const processes = ref<Process[]>([]);
const selectedLabels = ref<string[]>(["0"]);
const dateFormat = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") =>
dayjs(date).format(pattern);
function changeLabels(opt: any[]) {
const arr = opt.map((d) => d.value);
// if (arr.includes("0")) {
// selectedLabels.value = labels.value.map((d: Option) => d.value);
// return;
// }
// selectedLabels.value = Array.from(new Set(arr));
selectedLabels.value = arr;
}
const handleSelectionChange = (arr: Process[]) => {
selectedProcesses.value = arr.map((d: Process) => d.id);
};
async function analyzeEBPF() {
let arr: string[] = [];
if (selectedLabels.value.includes("0")) {
arr = labels.value.map((d: Option) => d.value);
arr.pop();
}
console.log(arr);
const ranges: { start: number; end: number }[] = [];
const scheduleIdList = ebpfStore.eBPFSchedules.flatMap(
(d: EBPFProfilingSchedule) => {
const l = d.process.labels.find((d: string) => arr.includes(d));
const i = selectedLabels.value.includes(d.process.id);
if (l || i) {
ranges.push({
start: d.startTime,
end: d.endTime,
});
return d.scheduleId;
}
}
);
let timeRanges: { start: number; end: number }[] = [];
for (const r of ranges) {
if (timeRanges.length) {
for (const t of timeRanges) {
if (r.start > t.start && r.start < t.end) {
if (r.end > t.end) {
t.end = r.end;
}
}
}
} else {
timeRanges.push(r);
}
}
const res = await ebpfStore.getEBPFAnalyze({
scheduleIdList,
timeRanges,
});
}
function visTimeline() {
if (visGraph.value) {
visGraph.value.destroy();
}
labels.value = [{ label: "All", value: "0" }];
processes.value = [];
const schedules = ebpfStore.eBPFSchedules.map(
(d: EBPFProfilingSchedule, index: number) => {
for (const l of d.process.labels) {
labels.value.push({ label: l, value: l });
}
processes.value.push(d.process);
return {
id: index + 1,
content: "schedule" + index,
content: d.process.name,
start: dateFormat(d.startTime),
end: dateFormat(d.endTime),
};
@ -46,8 +159,7 @@ function visTimeline() {
);
const items: any = new DataSet(schedules);
const options = {
editable: true,
selectable: true,
height: 250,
};
if (!timeline.value) {
return;
@ -63,8 +175,16 @@ watch(
);
</script>
<style lang="scss" scoped>
.filters {
margin: 5px 0;
}
.schedules {
width: 100%;
height: 400px;
margin: 0 5px 5px 0;
}
.inputs {
width: 300px;
}
</style>

View File

@ -45,3 +45,7 @@ export const InitTaskField = {
{ value: "15", label: "15 min" },
],
};
export const TableHeader = [
{ property: "name", label: "Name" },
{ property: "instanceName", label: "Instance Name" },
];