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
|
||||
}`,
|
||||
};
|
||||
|
||||
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,
|
||||
createNetworkProfiling,
|
||||
keepNetworkProfiling,
|
||||
monitoringInstances,
|
||||
} from "../fragments/ebpf";
|
||||
|
||||
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 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.",
|
||||
setEvent: "Set Event",
|
||||
viewAttributes: "View",
|
||||
attributes: "Attributes",
|
||||
serviceEvents: "Service Events",
|
||||
select: "Select",
|
||||
eventID: "Event ID",
|
||||
@ -397,6 +398,6 @@ const msg = {
|
||||
threshold: "Threshold",
|
||||
uriRegex: "URI Regex",
|
||||
uriList: "URI List",
|
||||
process: "Process",
|
||||
processes: "Processes",
|
||||
};
|
||||
export default msg;
|
||||
|
@ -396,6 +396,6 @@ const msg = {
|
||||
threshold: "Umbral",
|
||||
uriRegex: "Lista URI",
|
||||
uriList: "Lista URI",
|
||||
process: "Proceso",
|
||||
processes: "Proceso",
|
||||
};
|
||||
export default msg;
|
||||
|
@ -394,6 +394,6 @@ const msg = {
|
||||
threshold: "阈值",
|
||||
uriRegex: "URI规则",
|
||||
uriList: "URI列表",
|
||||
process: "进程",
|
||||
processes: "进程",
|
||||
};
|
||||
export default msg;
|
||||
|
@ -123,11 +123,21 @@ export const continousProfilingStore = defineStore({
|
||||
if (!this.selectedStrategy.type) {
|
||||
return res.data;
|
||||
}
|
||||
this.getContinousTaskList({
|
||||
serviceId: params.serviceId,
|
||||
targets: [this.selectedStrategy.type],
|
||||
triggerType: EBPFProfilingTriggerType.CONTINUOUS_PROFILING,
|
||||
this.getMonitoringInstances(params.serviceId);
|
||||
return res.data;
|
||||
},
|
||||
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;
|
||||
},
|
||||
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
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
@ -27,3 +28,19 @@ export type CheckItems = {
|
||||
uriList?: 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. -->
|
||||
<template>
|
||||
<div class="flex-h content">
|
||||
<div class="list flex-v">
|
||||
<PolicyList />
|
||||
<TaskList />
|
||||
<policy-list />
|
||||
<div class="instance-list">
|
||||
<instance-list />
|
||||
</div>
|
||||
<Panel :config="config" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from "vue";
|
||||
import PolicyList from "./components/PolicyList.vue";
|
||||
import TaskList from "./components/TaskList.vue";
|
||||
import Panel from "./components/Panel.vue";
|
||||
import InstanceList from "./components/InstanceList.vue";
|
||||
|
||||
/*global defineProps */
|
||||
defineProps({
|
||||
@ -40,4 +38,11 @@ limitations under the License. -->
|
||||
height: calc(100% - 30px);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.instance-list {
|
||||
height: 100%;
|
||||
flex-grow: 2;
|
||||
min-width: 600px;
|
||||
overflow: auto;
|
||||
}
|
||||
</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 { ElMessage } from "element-plus";
|
||||
import EditPolicy from "./EditPolicy.vue";
|
||||
import { EBPFProfilingTriggerType } from "@/store/data";
|
||||
|
||||
const { t } = useI18n();
|
||||
const selectorStore = useSelectorStore();
|
||||
@ -85,11 +84,7 @@ limitations under the License. -->
|
||||
async function changePolicy(item: StrategyItem) {
|
||||
continousProfilingStore.setSelectedStrategy(item);
|
||||
const serviceId = (selectorStore.currentService && selectorStore.currentService.id) || "";
|
||||
await continousProfilingStore.getContinousTaskList({
|
||||
serviceId,
|
||||
targets: [item.type],
|
||||
triggerType: EBPFProfilingTriggerType.CONTINUOUS_PROFILING,
|
||||
});
|
||||
await continousProfilingStore.getMonitoringInstances(serviceId);
|
||||
}
|
||||
|
||||
function setStrategies() {
|
||||
@ -144,7 +139,7 @@ limitations under the License. -->
|
||||
<style lang="scss" scoped>
|
||||
.profile-task-list {
|
||||
width: 300px;
|
||||
height: 48%;
|
||||
height: 98%;
|
||||
overflow: auto;
|
||||
border-right: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
@ -30,3 +30,17 @@ export const TargetTypes = [
|
||||
];
|
||||
|
||||
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