mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-05-13 00:08:56 +00:00
feat: add instance list
This commit is contained in:
parent
a5fa298cd1
commit
8c6df4a3b4
@ -112,3 +112,26 @@ export const keepNetworkProfiling = {
|
|||||||
errorReason
|
errorReason
|
||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const monitoringInstances = {
|
||||||
|
variable: "$serviceId: ID!, $target: ContinuousProfilingTargetType!",
|
||||||
|
query: `
|
||||||
|
instances: queryContinuousProfilingMonitoringInstances(serviceId: $serviceId, target: $target) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
value
|
||||||
|
}
|
||||||
|
triggeredCount
|
||||||
|
lastTriggerTimestamp
|
||||||
|
processes {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
detectType
|
||||||
|
labels
|
||||||
|
lastTriggerTimestamp
|
||||||
|
triggeredCount
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
};
|
||||||
|
@ -23,6 +23,7 @@ import {
|
|||||||
analysisEBPFResult,
|
analysisEBPFResult,
|
||||||
createNetworkProfiling,
|
createNetworkProfiling,
|
||||||
keepNetworkProfiling,
|
keepNetworkProfiling,
|
||||||
|
monitoringInstances,
|
||||||
} from "../fragments/ebpf";
|
} from "../fragments/ebpf";
|
||||||
|
|
||||||
export const getCreateTaskData = `query queryCreateTaskData(${queryCreateTaskData.variable}) {${queryCreateTaskData.query}}`;
|
export const getCreateTaskData = `query queryCreateTaskData(${queryCreateTaskData.variable}) {${queryCreateTaskData.query}}`;
|
||||||
@ -38,3 +39,5 @@ export const getEBPFResult = `query analysisEBPFResult(${analysisEBPFResult.vari
|
|||||||
export const newNetworkProfiling = `mutation createNetworkProfiling(${createNetworkProfiling.variable}) {${createNetworkProfiling.query}}`;
|
export const newNetworkProfiling = `mutation createNetworkProfiling(${createNetworkProfiling.variable}) {${createNetworkProfiling.query}}`;
|
||||||
|
|
||||||
export const aliveNetworkProfiling = `mutation keepNetworkProfiling(${keepNetworkProfiling.variable}) {${keepNetworkProfiling.query}}`;
|
export const aliveNetworkProfiling = `mutation keepNetworkProfiling(${keepNetworkProfiling.variable}) {${keepNetworkProfiling.query}}`;
|
||||||
|
|
||||||
|
export const getMonitoringInstances = `query continuousProfilingMonitoringInstances(${monitoringInstances.variable}) {${monitoringInstances.query}}`;
|
||||||
|
@ -323,6 +323,7 @@ const msg = {
|
|||||||
keywordsOfContentLogTips: "Current storage of SkyWalking OAP server does not support this.",
|
keywordsOfContentLogTips: "Current storage of SkyWalking OAP server does not support this.",
|
||||||
setEvent: "Set Event",
|
setEvent: "Set Event",
|
||||||
viewAttributes: "View",
|
viewAttributes: "View",
|
||||||
|
attributes: "Attributes",
|
||||||
serviceEvents: "Service Events",
|
serviceEvents: "Service Events",
|
||||||
select: "Select",
|
select: "Select",
|
||||||
eventID: "Event ID",
|
eventID: "Event ID",
|
||||||
@ -397,6 +398,6 @@ const msg = {
|
|||||||
threshold: "Threshold",
|
threshold: "Threshold",
|
||||||
uriRegex: "URI Regex",
|
uriRegex: "URI Regex",
|
||||||
uriList: "URI List",
|
uriList: "URI List",
|
||||||
process: "Process",
|
processes: "Processes",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
@ -396,6 +396,6 @@ const msg = {
|
|||||||
threshold: "Umbral",
|
threshold: "Umbral",
|
||||||
uriRegex: "Lista URI",
|
uriRegex: "Lista URI",
|
||||||
uriList: "Lista URI",
|
uriList: "Lista URI",
|
||||||
process: "Proceso",
|
processes: "Proceso",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
@ -394,6 +394,6 @@ const msg = {
|
|||||||
threshold: "阈值",
|
threshold: "阈值",
|
||||||
uriRegex: "URI规则",
|
uriRegex: "URI规则",
|
||||||
uriList: "URI列表",
|
uriList: "URI列表",
|
||||||
process: "进程",
|
processes: "进程",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
@ -123,11 +123,21 @@ export const continousProfilingStore = defineStore({
|
|||||||
if (!this.selectedStrategy.type) {
|
if (!this.selectedStrategy.type) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.getContinousTaskList({
|
this.getMonitoringInstances(params.serviceId);
|
||||||
serviceId: params.serviceId,
|
return res.data;
|
||||||
targets: [this.selectedStrategy.type],
|
},
|
||||||
triggerType: EBPFProfilingTriggerType.CONTINUOUS_PROFILING,
|
async getMonitoringInstances(serviceId: string): Promise<Nullable<AxiosResponse>> {
|
||||||
|
if (!serviceId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const res: AxiosResponse = await graphql.query("getMonitoringInstances").params({
|
||||||
|
serviceId,
|
||||||
|
target: this.selectedStrategy.type,
|
||||||
});
|
});
|
||||||
|
if (!res.data.errors) {
|
||||||
|
this.instances = res.data.data.instances || [];
|
||||||
|
this.instance = this.instances[0] || null;
|
||||||
|
}
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getContinousTaskList(params: {
|
async getContinousTaskList(params: {
|
||||||
|
17
src/types/continous-profiling.d.ts
vendored
17
src/types/continous-profiling.d.ts
vendored
@ -1,3 +1,4 @@
|
|||||||
|
import { MonitorType } from "./../views/dashboard/related/continuous-profiling/data";
|
||||||
/**
|
/**
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
@ -27,3 +28,19 @@ export type CheckItems = {
|
|||||||
uriList?: string[];
|
uriList?: string[];
|
||||||
uriRegex?: string;
|
uriRegex?: string;
|
||||||
};
|
};
|
||||||
|
export interface MonitorInstance {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
attributes: { name: string; value: string }[];
|
||||||
|
triggeredCount: number;
|
||||||
|
lastTriggerTimestamp: number;
|
||||||
|
processes: MonitorProcess[];
|
||||||
|
}
|
||||||
|
interface MonitorProcess {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
detectType: string;
|
||||||
|
labels: string[];
|
||||||
|
lastTriggerTimestamp: number;
|
||||||
|
triggeredCount: number;
|
||||||
|
}
|
||||||
|
@ -14,18 +14,16 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div class="flex-h content">
|
<div class="flex-h content">
|
||||||
<div class="list flex-v">
|
<policy-list />
|
||||||
<PolicyList />
|
<div class="instance-list">
|
||||||
<TaskList />
|
<instance-list />
|
||||||
</div>
|
</div>
|
||||||
<Panel :config="config" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import PolicyList from "./components/PolicyList.vue";
|
import PolicyList from "./components/PolicyList.vue";
|
||||||
import TaskList from "./components/TaskList.vue";
|
import InstanceList from "./components/InstanceList.vue";
|
||||||
import Panel from "./components/Panel.vue";
|
|
||||||
|
|
||||||
/*global defineProps */
|
/*global defineProps */
|
||||||
defineProps({
|
defineProps({
|
||||||
@ -40,4 +38,11 @@ limitations under the License. -->
|
|||||||
height: calc(100% - 30px);
|
height: calc(100% - 30px);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.instance-list {
|
||||||
|
height: 100%;
|
||||||
|
flex-grow: 2;
|
||||||
|
min-width: 600px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -0,0 +1,83 @@
|
|||||||
|
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
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>
|
||||||
|
<el-table :data="tableData" style="width: 100%">
|
||||||
|
<el-table-column type="expand">
|
||||||
|
<template #default="props">
|
||||||
|
<div class="child">
|
||||||
|
<div class="title">Attributes</div>
|
||||||
|
<div v-for="(attr, index) in props.row.attributes" :key="index">
|
||||||
|
{{ `${attr.name}: ${attr.value}` }}
|
||||||
|
</div>
|
||||||
|
<div class="title mt-20">Processes</div>
|
||||||
|
<el-table :data="props.row.processes" size="small">
|
||||||
|
<el-table-column
|
||||||
|
v-for="item in HeaderChildLabels"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:prop="item.value"
|
||||||
|
/>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
v-for="item in HeaderLabels"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:prop="item.value"
|
||||||
|
:width="item.width"
|
||||||
|
/>
|
||||||
|
</el-table>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed } from "vue";
|
||||||
|
import type { EBPFTaskList } from "@/types/ebpf";
|
||||||
|
import { useContinousProfilingStore } from "@/store/modules/continous-profiling";
|
||||||
|
import type { MonitorInstance, MonitorProcess } from "@/types/continous-profiling";
|
||||||
|
import { HeaderLabels, HeaderChildLabels } from "../data";
|
||||||
|
import { dateFormat } from "@/utils/dateFormat";
|
||||||
|
|
||||||
|
const continousProfilingStore = useContinousProfilingStore();
|
||||||
|
|
||||||
|
const tableData = computed(() => {
|
||||||
|
return continousProfilingStore.instances.map((d: MonitorInstance) => {
|
||||||
|
const processes = (d.processes || []).map((p: MonitorProcess) => {
|
||||||
|
return {
|
||||||
|
...p,
|
||||||
|
lastTriggerTime: d.lastTriggerTimestamp ? dateFormat(d.lastTriggerTimestamp) : "",
|
||||||
|
labels: p.labels.join("; "),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return { ...d, processes, lastTriggerTime: d.lastTriggerTimestamp ? dateFormat(d.lastTriggerTimestamp) : "" };
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
async function changeTask(item: EBPFTaskList) {
|
||||||
|
continousProfilingStore.setselectedTask(item);
|
||||||
|
continousProfilingStore.getGraphData();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.title {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.child {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,158 +0,0 @@
|
|||||||
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
contributor license agreements. See the NOTICE file distributed with
|
|
||||||
this work for additional information regarding copyright ownership.
|
|
||||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
(the "License"); you may not use this file except in compliance with
|
|
||||||
the License. You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
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="policy-graph flex-v">
|
|
||||||
<div class="header">
|
|
||||||
<span class="label mr-5">{{ t("instance") }}</span>
|
|
||||||
<Selector
|
|
||||||
class="selector mr-10"
|
|
||||||
size="small"
|
|
||||||
:value="instance.label"
|
|
||||||
:options="continousProfilingStore.instances"
|
|
||||||
placeholder="Select a instance"
|
|
||||||
@change="changeInstance"
|
|
||||||
/>
|
|
||||||
<span class="label mr-5">{{ t("process") }}</span>
|
|
||||||
<Selector
|
|
||||||
class="selector mr-10"
|
|
||||||
size="small"
|
|
||||||
:value="process.label"
|
|
||||||
:options="continousProfilingStore.processes"
|
|
||||||
placeholder="Select a process"
|
|
||||||
@change="changeProcess"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div v-if="continousProfilingStore.selectedTask.taskId" class="vis-graph">
|
|
||||||
<div
|
|
||||||
class="graph-topology ml-5"
|
|
||||||
v-loading="networkProfilingStore.loadNodes"
|
|
||||||
v-if="continousProfilingStore.selectedStrategy.type === TargetTypes[2].value"
|
|
||||||
>
|
|
||||||
<process-topology v-if="networkProfilingStore.nodes.length" :config="config" />
|
|
||||||
<div class="text" v-else>
|
|
||||||
{{ t("noData") }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="graph-flame ml-5" v-else>
|
|
||||||
<div class="schedules">
|
|
||||||
<EBPFSchedules :type="ComponentType" />
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<EBPFStack :type="ComponentType" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- <div v-else> dashboard </div> -->
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, watch } from "vue";
|
|
||||||
import type { PropType } from "vue";
|
|
||||||
import { useI18n } from "vue-i18n";
|
|
||||||
import { useSelectorStore } from "@/store/modules/selectors";
|
|
||||||
import { useContinousProfilingStore } from "@/store/modules/continous-profiling";
|
|
||||||
import { useNetworkProfilingStore } from "@/store/modules/network-profiling";
|
|
||||||
import ProcessTopology from "@/views/dashboard/related/network-profiling/components/ProcessTopology.vue";
|
|
||||||
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 type { Instance, Process } from "@/types/selector";
|
|
||||||
|
|
||||||
/*global defineProps, Recordable */
|
|
||||||
defineProps({
|
|
||||||
config: {
|
|
||||||
type: Object as PropType<any>,
|
|
||||||
default: () => ({ graph: {} }),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const continousProfilingStore = useContinousProfilingStore();
|
|
||||||
const networkProfilingStore = useNetworkProfilingStore();
|
|
||||||
const selectorStore = useSelectorStore();
|
|
||||||
const { t } = useI18n();
|
|
||||||
const process = ref<Recordable<Process>>({});
|
|
||||||
const instance = ref<Recordable<Instance>>({});
|
|
||||||
|
|
||||||
function changeInstance(opt: Recordable<Instance>[]) {
|
|
||||||
instance.value = opt[0];
|
|
||||||
continousProfilingStore.setCurrentInstance(instance.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeProcess(opt: Recordable<Process>[]) {
|
|
||||||
process.value = opt[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getSelectors() {
|
|
||||||
const serviceId = (selectorStore.currentService && selectorStore.currentService.id) || "";
|
|
||||||
|
|
||||||
await continousProfilingStore.getServiceInstances(serviceId);
|
|
||||||
instance.value = continousProfilingStore.instances[0] || {};
|
|
||||||
await continousProfilingStore.getProcesses(instance.value.id);
|
|
||||||
process.value = continousProfilingStore.processes[0] || {};
|
|
||||||
}
|
|
||||||
getSelectors();
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => selectorStore.currentService,
|
|
||||||
() => {
|
|
||||||
getSelectors();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.header {
|
|
||||||
margin: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.selector {
|
|
||||||
width: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vis-graph {
|
|
||||||
height: calc(100% - 20px);
|
|
||||||
flex-grow: 2;
|
|
||||||
min-width: 700px;
|
|
||||||
overflow: auto;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.graph-topology,
|
|
||||||
.graph-flame {
|
|
||||||
height: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
width: calc(100% - 5px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.graph-flame {
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.policy-graph {
|
|
||||||
height: 100%;
|
|
||||||
flex-grow: 2;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text {
|
|
||||||
height: 100%;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 100px;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -72,7 +72,6 @@ limitations under the License. -->
|
|||||||
import type { StrategyItem, CheckItems } from "@/types/continous-profiling";
|
import type { StrategyItem, CheckItems } from "@/types/continous-profiling";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import EditPolicy from "./EditPolicy.vue";
|
import EditPolicy from "./EditPolicy.vue";
|
||||||
import { EBPFProfilingTriggerType } from "@/store/data";
|
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const selectorStore = useSelectorStore();
|
const selectorStore = useSelectorStore();
|
||||||
@ -85,11 +84,7 @@ limitations under the License. -->
|
|||||||
async function changePolicy(item: StrategyItem) {
|
async function changePolicy(item: StrategyItem) {
|
||||||
continousProfilingStore.setSelectedStrategy(item);
|
continousProfilingStore.setSelectedStrategy(item);
|
||||||
const serviceId = (selectorStore.currentService && selectorStore.currentService.id) || "";
|
const serviceId = (selectorStore.currentService && selectorStore.currentService.id) || "";
|
||||||
await continousProfilingStore.getContinousTaskList({
|
await continousProfilingStore.getMonitoringInstances(serviceId);
|
||||||
serviceId,
|
|
||||||
targets: [item.type],
|
|
||||||
triggerType: EBPFProfilingTriggerType.CONTINUOUS_PROFILING,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setStrategies() {
|
function setStrategies() {
|
||||||
@ -144,7 +139,7 @@ limitations under the License. -->
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.profile-task-list {
|
.profile-task-list {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 48%;
|
height: 98%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
border-right: 1px solid rgba(0, 0, 0, 0.1);
|
border-right: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
@ -30,3 +30,17 @@ export const TargetTypes = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const ComponentType = "CONTINOUS_PROFILING";
|
export const ComponentType = "CONTINOUS_PROFILING";
|
||||||
|
|
||||||
|
export const HeaderLabels = [
|
||||||
|
{ value: "name", label: "Name", width: 400 },
|
||||||
|
{ value: "triggeredCount", label: "Triggered Count", width: 150 },
|
||||||
|
{ value: "lastTriggerTime", label: "Last Trigger Time", width: 150 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const HeaderChildLabels = [
|
||||||
|
{ value: "name", label: "Name" },
|
||||||
|
{ value: "detectType", label: "Detect Type" },
|
||||||
|
{ value: "triggeredCount", label: "Triggered Count" },
|
||||||
|
{ value: "labels", label: "Labels" },
|
||||||
|
{ value: "lastTriggerTime", label: "Last Trigger Time" },
|
||||||
|
];
|
||||||
|
Loading…
Reference in New Issue
Block a user