mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-07-18 14:45:25 +00:00
add filters
This commit is contained in:
parent
70aec8f345
commit
20f49e6e21
@ -58,7 +58,7 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
size: { type: null, default: "default" },
|
size: { type: null, default: "default" },
|
||||||
placeholder: {
|
placeholder: {
|
||||||
type: [String, Number] as PropType<string | number>,
|
type: [String, undefined] as PropType<string>,
|
||||||
default: "Select a option",
|
default: "Select a option",
|
||||||
},
|
},
|
||||||
borderRadius: { type: Number, default: 3 },
|
borderRadius: { type: Number, default: 3 },
|
||||||
|
2
src/types/ebpf.d.ts
vendored
2
src/types/ebpf.d.ts
vendored
@ -43,7 +43,7 @@ export interface EBPFProfilingSchedule {
|
|||||||
startTime: number;
|
startTime: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Process = {
|
export type Process = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
serviceId: string;
|
serviceId: string;
|
||||||
|
@ -15,7 +15,7 @@ limitations under the License. -->
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex-h content">
|
<div class="flex-h content">
|
||||||
<TaskList />
|
<TaskList />
|
||||||
<div class="vis-graph">
|
<div class="vis-graph ml-5">
|
||||||
<EBPFSchedules />
|
<EBPFSchedules />
|
||||||
<EBPFTree />
|
<EBPFTree />
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,7 +15,7 @@ limitations under the License. -->
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex-h header">
|
<div class="flex-h header">
|
||||||
<div>eBPF Profile</div>
|
<div>eBPF Profile</div>
|
||||||
<el-button class="new-btn" size="small" @click="createTask">
|
<el-button type="primary" size="small" @click="createTask">
|
||||||
{{ t("newTask") }}
|
{{ t("newTask") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
@ -83,9 +83,10 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.header {
|
.header {
|
||||||
padding: 10px;
|
padding: 5px 20px 5px 10px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
border-bottom: 1px solid #dcdfe6;
|
border-bottom: 1px solid #dcdfe6;
|
||||||
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
|
@ -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
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<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>
|
<div ref="timeline" class="schedules"></div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import dayjs from "dayjs";
|
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 { useEbpfStore } from "@/store/modules/ebpf";
|
||||||
import { EBPFProfilingSchedule } from "@/types/ebpf";
|
import { EBPFProfilingSchedule, Process } from "@/types/ebpf";
|
||||||
import { DataSet, Timeline } from "vis-timeline/standalone";
|
import { DataSet, Timeline } from "vis-timeline/standalone";
|
||||||
import "vis-timeline/styles/vis-timeline-graph2d.css";
|
import "vis-timeline/styles/vis-timeline-graph2d.css";
|
||||||
|
import type { ElTable } from "element-plus";
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
const ebpfStore = useEbpfStore();
|
const ebpfStore = useEbpfStore();
|
||||||
/*global Nullable */
|
/*global Nullable */
|
||||||
|
const multipleTableRef = ref<InstanceType<typeof ElTable>>();
|
||||||
|
const selectedProcesses = ref<string[]>([]);
|
||||||
const timeline = ref<Nullable<HTMLDivElement>>(null);
|
const timeline = ref<Nullable<HTMLDivElement>>(null);
|
||||||
const visGraph = ref<Nullable<any>>(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") =>
|
const dateFormat = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") =>
|
||||||
dayjs(date).format(pattern);
|
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() {
|
function visTimeline() {
|
||||||
if (visGraph.value) {
|
if (visGraph.value) {
|
||||||
visGraph.value.destroy();
|
visGraph.value.destroy();
|
||||||
}
|
}
|
||||||
|
labels.value = [{ label: "All", value: "0" }];
|
||||||
|
processes.value = [];
|
||||||
const schedules = ebpfStore.eBPFSchedules.map(
|
const schedules = ebpfStore.eBPFSchedules.map(
|
||||||
(d: EBPFProfilingSchedule, index: number) => {
|
(d: EBPFProfilingSchedule, index: number) => {
|
||||||
|
for (const l of d.process.labels) {
|
||||||
|
labels.value.push({ label: l, value: l });
|
||||||
|
}
|
||||||
|
processes.value.push(d.process);
|
||||||
return {
|
return {
|
||||||
id: index + 1,
|
id: index + 1,
|
||||||
content: "schedule" + index,
|
content: d.process.name,
|
||||||
start: dateFormat(d.startTime),
|
start: dateFormat(d.startTime),
|
||||||
end: dateFormat(d.endTime),
|
end: dateFormat(d.endTime),
|
||||||
};
|
};
|
||||||
@ -46,8 +159,7 @@ function visTimeline() {
|
|||||||
);
|
);
|
||||||
const items: any = new DataSet(schedules);
|
const items: any = new DataSet(schedules);
|
||||||
const options = {
|
const options = {
|
||||||
editable: true,
|
height: 250,
|
||||||
selectable: true,
|
|
||||||
};
|
};
|
||||||
if (!timeline.value) {
|
if (!timeline.value) {
|
||||||
return;
|
return;
|
||||||
@ -63,8 +175,16 @@ watch(
|
|||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.filters {
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
.schedules {
|
.schedules {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 400px;
|
margin: 0 5px 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputs {
|
||||||
|
width: 300px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -45,3 +45,7 @@ export const InitTaskField = {
|
|||||||
{ value: "15", label: "15 min" },
|
{ value: "15", label: "15 min" },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
export const TableHeader = [
|
||||||
|
{ property: "name", label: "Name" },
|
||||||
|
{ property: "instanceName", label: "Instance Name" },
|
||||||
|
];
|
||||||
|
Loading…
Reference in New Issue
Block a user