mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-05-13 00:08:56 +00:00
feat: add ebpf
This commit is contained in:
parent
34ff6d9e9c
commit
cb62b19eb6
@ -16,15 +16,13 @@
|
|||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
|
import { useNetworkProfilingStore } from "@/store/modules/network-profiling";
|
||||||
import type { StrategyItem, CheckItems } from "@/types/continous-profiling";
|
import type { StrategyItem, CheckItems } from "@/types/continous-profiling";
|
||||||
import type { ProcessNode, EBPFTaskList } from "@/types/ebpf";
|
import type { EBPFTaskList, EBPFProfilingSchedule, AnalyzationTrees } from "@/types/ebpf";
|
||||||
import type { Instance, Process } from "@/types/selector";
|
import type { Instance, Process } from "@/types/selector";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import type { AxiosResponse } from "axios";
|
import type { AxiosResponse } from "axios";
|
||||||
import type { Call } from "@/types/topology";
|
|
||||||
import type { LayoutConfig } from "@/types/dashboard";
|
|
||||||
import type { DurationTime } from "@/types/app";
|
|
||||||
import { EBPFProfilingTriggerType } from "../data";
|
import { EBPFProfilingTriggerType } from "../data";
|
||||||
|
|
||||||
interface ContinousProfilingState {
|
interface ContinousProfilingState {
|
||||||
@ -36,15 +34,11 @@ interface ContinousProfilingState {
|
|||||||
errorReason: string;
|
errorReason: string;
|
||||||
processes: Process[];
|
processes: Process[];
|
||||||
instances: Instance[];
|
instances: Instance[];
|
||||||
nodes: ProcessNode[];
|
eBPFSchedules: EBPFProfilingSchedule[];
|
||||||
calls: Call[];
|
currentSchedule: EBPFProfilingSchedule | Record<string, never>;
|
||||||
node: Nullable<ProcessNode>;
|
analyzeTrees: AnalyzationTrees[];
|
||||||
call: Nullable<Call>;
|
ebpfTips: string;
|
||||||
metricsLayout: LayoutConfig[];
|
aggregateType: string;
|
||||||
selectedMetric: Nullable<LayoutConfig>;
|
|
||||||
activeMetricIndex: string;
|
|
||||||
aliveNetwork: boolean;
|
|
||||||
loadNodes: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const continousProfilingStore = defineStore({
|
export const continousProfilingStore = defineStore({
|
||||||
@ -56,17 +50,13 @@ export const continousProfilingStore = defineStore({
|
|||||||
selectedContinousTask: {},
|
selectedContinousTask: {},
|
||||||
errorReason: "",
|
errorReason: "",
|
||||||
errorTip: "",
|
errorTip: "",
|
||||||
|
ebpfTips: "",
|
||||||
processes: [],
|
processes: [],
|
||||||
instances: [],
|
instances: [],
|
||||||
nodes: [],
|
eBPFSchedules: [],
|
||||||
calls: [],
|
currentSchedule: {},
|
||||||
node: null,
|
analyzeTrees: [],
|
||||||
call: null,
|
aggregateType: "COUNT",
|
||||||
metricsLayout: [],
|
|
||||||
selectedMetric: null,
|
|
||||||
activeMetricIndex: "",
|
|
||||||
aliveNetwork: false,
|
|
||||||
loadNodes: false,
|
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
setSelectedStrategy(task: Recordable<StrategyItem>) {
|
setSelectedStrategy(task: Recordable<StrategyItem>) {
|
||||||
@ -75,57 +65,11 @@ export const continousProfilingStore = defineStore({
|
|||||||
setSelectedContinousTask(task: Recordable<EBPFTaskList>) {
|
setSelectedContinousTask(task: Recordable<EBPFTaskList>) {
|
||||||
this.selectedContinousTask = task || {};
|
this.selectedContinousTask = task || {};
|
||||||
},
|
},
|
||||||
setNode(node: Nullable<ProcessNode>) {
|
setCurrentSchedule(s: EBPFProfilingSchedule) {
|
||||||
this.node = node;
|
this.currentSchedule = s;
|
||||||
},
|
},
|
||||||
setLink(link: Call) {
|
setAnalyzeTrees(tree: AnalyzationTrees[]) {
|
||||||
this.call = link;
|
this.analyzeTrees = tree;
|
||||||
},
|
|
||||||
setMetricsLayout(layout: LayoutConfig[]) {
|
|
||||||
this.metricsLayout = layout;
|
|
||||||
},
|
|
||||||
setSelectedMetric(item: LayoutConfig) {
|
|
||||||
this.selectedMetric = item;
|
|
||||||
},
|
|
||||||
setActiveItem(index: string) {
|
|
||||||
this.activeMetricIndex = index;
|
|
||||||
},
|
|
||||||
setTopology(data: { nodes: ProcessNode[]; calls: Call[] }) {
|
|
||||||
const obj = {} as Recordable;
|
|
||||||
let calls = (data.calls || []).reduce((prev: Call[], next: Call) => {
|
|
||||||
if (!obj[next.id]) {
|
|
||||||
obj[next.id] = true;
|
|
||||||
next.value = next.value || 1;
|
|
||||||
for (const node of data.nodes) {
|
|
||||||
if (next.source === node.id) {
|
|
||||||
next.sourceObj = node;
|
|
||||||
}
|
|
||||||
if (next.target === node.id) {
|
|
||||||
next.targetObj = node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
next.value = next.value || 1;
|
|
||||||
prev.push(next);
|
|
||||||
}
|
|
||||||
return prev;
|
|
||||||
}, []);
|
|
||||||
const param = {} as Recordable;
|
|
||||||
calls = data.calls.reduce((prev: (Call & Recordable)[], next: Call & Recordable) => {
|
|
||||||
if (param[next.targetId + next.sourceId]) {
|
|
||||||
next.lowerArc = true;
|
|
||||||
}
|
|
||||||
param[next.sourceId + next.targetId] = true;
|
|
||||||
next.sourceId = next.source;
|
|
||||||
next.targetId = next.target;
|
|
||||||
next.source = next.sourceObj;
|
|
||||||
next.target = next.targetObj;
|
|
||||||
delete next.sourceObj;
|
|
||||||
delete next.targetObj;
|
|
||||||
prev.push(next);
|
|
||||||
return prev;
|
|
||||||
}, []);
|
|
||||||
this.calls = calls;
|
|
||||||
this.nodes = data.nodes;
|
|
||||||
},
|
},
|
||||||
async setContinuousProfilingPolicy(
|
async setContinuousProfilingPolicy(
|
||||||
serviceId: string,
|
serviceId: string,
|
||||||
@ -193,8 +137,11 @@ export const continousProfilingStore = defineStore({
|
|||||||
this.selectedContinousTask = this.taskList[0] || {};
|
this.selectedContinousTask = this.taskList[0] || {};
|
||||||
this.setSelectedContinousTask(this.selectedContinousTask);
|
this.setSelectedContinousTask(this.selectedContinousTask);
|
||||||
if (!this.taskList.length) {
|
if (!this.taskList.length) {
|
||||||
this.nodes = [];
|
const networkProfilingStore = useNetworkProfilingStore();
|
||||||
this.calls = [];
|
networkProfilingStore.seNodes([]);
|
||||||
|
networkProfilingStore.setLinks([]);
|
||||||
|
this.eBPFSchedules = [];
|
||||||
|
this.analyzeTrees = [];
|
||||||
}
|
}
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
@ -224,18 +171,55 @@ export const continousProfilingStore = defineStore({
|
|||||||
}
|
}
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getProcessTopology(params: { duration: DurationTime; serviceInstanceId: string }) {
|
async getEBPFSchedules(params: { taskId: string }) {
|
||||||
this.loadNodes = true;
|
if (!params.taskId) {
|
||||||
const res: AxiosResponse = await graphql.query("getProcessTopology").params(params);
|
return new Promise((resolve) => resolve({}));
|
||||||
this.loadNodes = false;
|
}
|
||||||
|
const res: AxiosResponse = await graphql.query("getEBPFSchedules").params({ ...params });
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
this.nodes = [];
|
this.eBPFSchedules = [];
|
||||||
this.calls = [];
|
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
const { topology } = res.data.data;
|
this.ebpftTips = "";
|
||||||
|
const { eBPFSchedules } = res.data.data;
|
||||||
|
|
||||||
this.setTopology(topology);
|
this.eBPFSchedules = eBPFSchedules;
|
||||||
|
if (!eBPFSchedules.length) {
|
||||||
|
this.eBPFSchedules = [];
|
||||||
|
this.analyzeTrees = [];
|
||||||
|
}
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
|
async getEBPFAnalyze(params: {
|
||||||
|
scheduleIdList: string[];
|
||||||
|
timeRanges: Array<{ start: number; end: number }>;
|
||||||
|
aggregateType: string;
|
||||||
|
}) {
|
||||||
|
this.aggregateType = params.aggregateType;
|
||||||
|
if (!params.scheduleIdList.length) {
|
||||||
|
return new Promise((resolve) => resolve({}));
|
||||||
|
}
|
||||||
|
if (!params.timeRanges.length) {
|
||||||
|
return new Promise((resolve) => resolve({}));
|
||||||
|
}
|
||||||
|
const res: AxiosResponse = await graphql.query("getEBPFResult").params(params);
|
||||||
|
|
||||||
|
if (res.data.errors) {
|
||||||
|
this.analyzeTrees = [];
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
const { analysisEBPFResult } = res.data.data;
|
||||||
|
this.ebpftTips = analysisEBPFResult.tip;
|
||||||
|
if (!analysisEBPFResult) {
|
||||||
|
this.analyzeTrees = [];
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
if (analysisEBPFResult.tip) {
|
||||||
|
this.analyzeTrees = [];
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
this.analyzeTrees = analysisEBPFResult.trees;
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -28,7 +28,7 @@ interface EbpfState {
|
|||||||
analyzeTrees: AnalyzationTrees[];
|
analyzeTrees: AnalyzationTrees[];
|
||||||
labels: Option[];
|
labels: Option[];
|
||||||
couldProfiling: boolean;
|
couldProfiling: boolean;
|
||||||
tip: string;
|
ebpfTips: string;
|
||||||
selectedTask: Recordable<EBPFTaskList>;
|
selectedTask: Recordable<EBPFTaskList>;
|
||||||
aggregateType: string;
|
aggregateType: string;
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ export const ebpfStore = defineStore({
|
|||||||
analyzeTrees: [],
|
analyzeTrees: [],
|
||||||
labels: [{ value: "", label: "" }],
|
labels: [{ value: "", label: "" }],
|
||||||
couldProfiling: false,
|
couldProfiling: false,
|
||||||
tip: "",
|
ebpfTips: "",
|
||||||
selectedTask: {},
|
selectedTask: {},
|
||||||
aggregateType: "COUNT",
|
aggregateType: "COUNT",
|
||||||
}),
|
}),
|
||||||
@ -88,7 +88,7 @@ export const ebpfStore = defineStore({
|
|||||||
}
|
}
|
||||||
const res: AxiosResponse = await graphql.query("getEBPFTasks").params(params);
|
const res: AxiosResponse = await graphql.query("getEBPFTasks").params(params);
|
||||||
|
|
||||||
this.tip = "";
|
this.ebpfTips = "";
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
@ -111,7 +111,7 @@ export const ebpfStore = defineStore({
|
|||||||
this.eBPFSchedules = [];
|
this.eBPFSchedules = [];
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.tip = "";
|
this.ebpfTips = "";
|
||||||
const { eBPFSchedules } = res.data.data;
|
const { eBPFSchedules } = res.data.data;
|
||||||
|
|
||||||
this.eBPFSchedules = eBPFSchedules;
|
this.eBPFSchedules = eBPFSchedules;
|
||||||
@ -140,7 +140,7 @@ export const ebpfStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
const { analysisEBPFResult } = res.data.data;
|
const { analysisEBPFResult } = res.data.data;
|
||||||
this.tip = analysisEBPFResult.tip;
|
this.ebpfTips = analysisEBPFResult.tip;
|
||||||
if (!analysisEBPFResult) {
|
if (!analysisEBPFResult) {
|
||||||
this.analyzeTrees = [];
|
this.analyzeTrees = [];
|
||||||
return res.data;
|
return res.data;
|
||||||
|
@ -65,6 +65,12 @@ export const networkProfilingStore = defineStore({
|
|||||||
setLink(link: Call) {
|
setLink(link: Call) {
|
||||||
this.call = link;
|
this.call = link;
|
||||||
},
|
},
|
||||||
|
seNodes(nodes: Node[]) {
|
||||||
|
this.nodes = nodes;
|
||||||
|
},
|
||||||
|
setLinks(links: Call[]) {
|
||||||
|
this.calls = links;
|
||||||
|
},
|
||||||
setMetricsLayout(layout: LayoutConfig[]) {
|
setMetricsLayout(layout: LayoutConfig[]) {
|
||||||
this.metricsLayout = layout;
|
this.metricsLayout = layout;
|
||||||
},
|
},
|
||||||
|
@ -39,7 +39,7 @@ limitations under the License. -->
|
|||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="vis-graph ml-5"
|
class="vis-graph-topology ml-5"
|
||||||
v-loading="networkProfilingStore.loadNodes"
|
v-loading="networkProfilingStore.loadNodes"
|
||||||
v-if="continousProfilingStore.selectedContinousTask.type === TargetTypes[2].value"
|
v-if="continousProfilingStore.selectedContinousTask.type === TargetTypes[2].value"
|
||||||
>
|
>
|
||||||
@ -48,7 +48,14 @@ limitations under the License. -->
|
|||||||
{{ t("noData") }}
|
{{ t("noData") }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="vis-graph ml-5"> ebpf </div>
|
<div class="vis-graph ml-5" v-else>
|
||||||
|
<div class="schedules">
|
||||||
|
<EBPFSchedules :type="ComponentType" />
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<EBPFStack :type="ComponentType" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -61,7 +68,9 @@ limitations under the License. -->
|
|||||||
import { useNetworkProfilingStore } from "@/store/modules/network-profiling";
|
import { useNetworkProfilingStore } from "@/store/modules/network-profiling";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import ProcessTopology from "@/views/dashboard/related/network-profiling/components/ProcessTopology.vue";
|
import ProcessTopology from "@/views/dashboard/related/network-profiling/components/ProcessTopology.vue";
|
||||||
import { TargetTypes } from "../data";
|
import EBPFSchedules from "@/views/dashboard/related/ebpf/components/EBPFSchedules.vue";
|
||||||
|
import EBPFStack from "@/views/dashboard/related/ebpf/components/EBPFStack.vue";
|
||||||
|
import { TargetTypes, ComponentType } from "../data";
|
||||||
import dateFormatStep from "@/utils/dateFormat";
|
import dateFormatStep from "@/utils/dateFormat";
|
||||||
import getLocalTime from "@/utils/localtime";
|
import getLocalTime from "@/utils/localtime";
|
||||||
|
|
||||||
@ -95,6 +104,12 @@ limitations under the License. -->
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const res = await continousProfilingStore.getEBPFSchedules({
|
||||||
|
taskId: continousProfilingStore.selectedContinousTask.taskId,
|
||||||
|
});
|
||||||
|
if (res.errors) {
|
||||||
|
ElMessage.error(res.errors);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getTopology() {
|
async function getTopology() {
|
||||||
@ -148,4 +163,20 @@ limitations under the License. -->
|
|||||||
.selector {
|
.selector {
|
||||||
width: 220px;
|
width: 220px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vis-graph {
|
||||||
|
height: 100%;
|
||||||
|
flex-grow: 2;
|
||||||
|
min-width: 700px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vis-graph-topology {
|
||||||
|
height: 100%;
|
||||||
|
flex-grow: 2;
|
||||||
|
min-width: 700px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
width: calc(100% - 330px);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -28,3 +28,5 @@ export const TargetTypes = [
|
|||||||
{ label: "OFF_CPU", value: "OFF_CPU" },
|
{ label: "OFF_CPU", value: "OFF_CPU" },
|
||||||
{ label: "NETWORK", value: "NETWORK" },
|
{ label: "NETWORK", value: "NETWORK" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const ComponentType = "CONTINOUS_PROFILING";
|
||||||
|
@ -98,12 +98,21 @@ limitations under the License. -->
|
|||||||
import type { Option } from "@/types/app";
|
import type { Option } from "@/types/app";
|
||||||
import { TableHeader, AggregateTypes } from "./data";
|
import { TableHeader, AggregateTypes } from "./data";
|
||||||
import { useEbpfStore } from "@/store/modules/ebpf";
|
import { useEbpfStore } from "@/store/modules/ebpf";
|
||||||
|
import { useContinousProfilingStore } from "@/store/modules/continous-profiling";
|
||||||
import type { EBPFProfilingSchedule, Process } from "@/types/ebpf";
|
import type { EBPFProfilingSchedule, Process } from "@/types/ebpf";
|
||||||
import { ElMessage, ElTable } from "element-plus";
|
import { ElMessage, ElTable } from "element-plus";
|
||||||
import { dateFormat } from "@/utils/dateFormat";
|
import { dateFormat } from "@/utils/dateFormat";
|
||||||
|
import { ComponentType } from "@/views/dashboard/related/continuous-profiling/data";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const ebpfStore = useEbpfStore();
|
/*global defineProps*/
|
||||||
|
const props = defineProps({
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const ebpfStore = props.type === ComponentType ? useContinousProfilingStore() : useEbpfStore();
|
||||||
const pageSize = 5;
|
const pageSize = 5;
|
||||||
const multipleTableRef = ref<InstanceType<typeof ElTable>>();
|
const multipleTableRef = ref<InstanceType<typeof ElTable>>();
|
||||||
const selectedProcesses = ref<string[]>([]);
|
const selectedProcesses = ref<string[]>([]);
|
||||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div id="graph-stack" ref="graph">
|
<div id="graph-stack" ref="graph">
|
||||||
<span class="tip" v-show="ebpfStore.tip">{{ ebpfStore.tip }}</span>
|
<span class="tip" v-show="ebpfStore.ebpfTips">{{ ebpfStore.ebpfTips }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -23,12 +23,20 @@ limitations under the License. -->
|
|||||||
import d3tip from "d3-tip";
|
import d3tip from "d3-tip";
|
||||||
import { flamegraph } from "d3-flame-graph";
|
import { flamegraph } from "d3-flame-graph";
|
||||||
import { useEbpfStore } from "@/store/modules/ebpf";
|
import { useEbpfStore } from "@/store/modules/ebpf";
|
||||||
|
import { useContinousProfilingStore } from "@/store/modules/continous-profiling";
|
||||||
|
import { ComponentType } from "@/views/dashboard/related/continuous-profiling/data";
|
||||||
import type { StackElement } from "@/types/ebpf";
|
import type { StackElement } from "@/types/ebpf";
|
||||||
import { AggregateTypes } from "./data";
|
import { AggregateTypes } from "./data";
|
||||||
import "d3-flame-graph/dist/d3-flamegraph.css";
|
import "d3-flame-graph/dist/d3-flamegraph.css";
|
||||||
|
|
||||||
/*global Nullable*/
|
/*global Nullable, defineProps*/
|
||||||
const ebpfStore = useEbpfStore();
|
const props = defineProps({
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const ebpfStore = props.type === ComponentType ? useContinousProfilingStore() : useEbpfStore();
|
||||||
const stackTree = ref<Nullable<StackElement>>(null);
|
const stackTree = ref<Nullable<StackElement>>(null);
|
||||||
const selectStack = ref<Nullable<StackElement>>(null);
|
const selectStack = ref<Nullable<StackElement>>(null);
|
||||||
const graph = ref<Nullable<HTMLDivElement>>(null);
|
const graph = ref<Nullable<HTMLDivElement>>(null);
|
||||||
|
Loading…
Reference in New Issue
Block a user