feat: add instance list

This commit is contained in:
Fine 2023-06-05 12:52:01 +08:00
parent a5fa298cd1
commit 8c6df4a3b4
12 changed files with 171 additions and 178 deletions

View File

@ -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
}
}`,
};

View File

@ -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}}`;

View File

@ -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;

View File

@ -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;

View File

@ -394,6 +394,6 @@ const msg = {
threshold: "阈值", threshold: "阈值",
uriRegex: "URI规则", uriRegex: "URI规则",
uriList: "URI列表", uriList: "URI列表",
process: "进程", processes: "进程",
}; };
export default msg; export default msg;

View File

@ -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: {

View File

@ -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;
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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);
} }

View File

@ -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" },
];