analyze profiling

This commit is contained in:
Fine 2024-11-25 19:05:33 +08:00
parent 0e047d091a
commit 5f8af6df38
4 changed files with 82 additions and 4 deletions

View File

@ -64,7 +64,7 @@ export const CreateAsyncProfileTask = {
export const GetAsyncProfileAnalyze = { export const GetAsyncProfileAnalyze = {
variable: "$request: AsyncProfilerAnalyzationRequest!", variable: "$request: AsyncProfilerAnalyzationRequest!",
query: ` query: `
analyze: queryAsyncProfilerAnalyze(request: $request) { analysisResult: queryAsyncProfilerAnalyze(request: $request) {
trees { trees {
type type
elements { elements {

View File

@ -16,7 +16,12 @@
*/ */
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import type { Option } from "@/types/app"; import type { Option } from "@/types/app";
import type { AsyncProfilingTaskList, AsyncProfileTaskCreationRequest } from "@/types/async-profiling"; import type {
AsyncProfilingTaskList,
AsyncProfileTaskCreationRequest,
AsyncProfilerStackElement,
AsyncProfilerTaskProgress,
} from "@/types/async-profiling";
import { store } from "@/store"; import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
@ -28,8 +33,9 @@ interface AsyncProfilingState {
labels: Option[]; labels: Option[];
asyncProfilingTips: string; asyncProfilingTips: string;
selectedTask: Recordable<AsyncProfilingTaskList>; selectedTask: Recordable<AsyncProfilingTaskList>;
taskProgress: Recordable<any>; taskProgress: Recordable<AsyncProfilerTaskProgress>;
instances: Instance[]; instances: Instance[];
analyzeTrees: AsyncProfilerStackElement[];
} }
export const asyncProfilingStore = defineStore({ export const asyncProfilingStore = defineStore({
@ -41,6 +47,7 @@ export const asyncProfilingStore = defineStore({
selectedTask: {}, selectedTask: {},
taskProgress: {}, taskProgress: {},
instances: [], instances: [],
analyzeTrees: [],
}), }),
actions: { actions: {
setSelectedTask(task: Recordable<AsyncProfilingTaskList>) { setSelectedTask(task: Recordable<AsyncProfilingTaskList>) {
@ -98,6 +105,28 @@ export const asyncProfilingStore = defineStore({
this.getTaskList(); this.getTaskList();
return res.data; return res.data;
}, },
async getAsyncProfilingAnalyze(params: { taskId: string; instanceIds: Array<string>; eventType: string }) {
if (!params.instanceIds.length) {
return new Promise((resolve) => resolve({}));
}
const res: AxiosResponse = await graphql.query("GetAsyncProfileAnalyze").params(params);
if (res.data.errors) {
this.analyzeTrees = [];
return res.data;
}
const { analysisResult } = res.data.data;
if (!analysisResult) {
this.analyzeTrees = [];
return res.data;
}
if (analysisResult.tip) {
this.analyzeTrees = [];
return res.data;
}
this.analyzeTrees = analysisResult.elements;
return res.data;
},
}, },
}); });

View File

@ -32,3 +32,25 @@ export type AsyncProfileTaskCreationRequest = {
events: string[]; events: string[];
execArgs: string; execArgs: string;
}; };
export type AsyncProfilerStackElement = {
id: string;
parentId: string;
codeSignature: string;
total: number;
self: number;
};
export type AsyncProfilerTaskProgress = {
errorInstanceIds: string[];
successInstanceIds: string[];
logs: AsyncProfilerTaskLog[];
};
type AsyncProfilerTaskLog = {
id: string;
instanceId: string;
instanceName: string;
operationType: string;
operationTime: number;
};

View File

@ -23,6 +23,14 @@ limitations under the License. -->
placeholder="Select instances" placeholder="Select instances"
@change="changeInstances" @change="changeInstances"
/> />
<Selector
class="profile-input"
:value="selectedEventType"
size="small"
:options="eventTypes"
placeholder="Select a event"
@change="changeEventType"
/>
<el-button type="primary" size="small" @click="analyzeProfiling"> <el-button type="primary" size="small" @click="analyzeProfiling">
{{ t("analyze") }} {{ t("analyze") }}
</el-button> </el-button>
@ -31,6 +39,7 @@ limitations under the License. -->
<script lang="ts" setup> <script lang="ts" setup>
import { computed, ref } from "vue"; import { computed, ref } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { ElMessage } from "element-plus";
import { useAsyncProfilingStore } from "@/store/modules/async-profiling"; import { useAsyncProfilingStore } from "@/store/modules/async-profiling";
import type { Instance } from "@/types/selector"; import type { Instance } from "@/types/selector";
import type { Option } from "@/types/app"; import type { Option } from "@/types/app";
@ -38,6 +47,10 @@ limitations under the License. -->
const { t } = useI18n(); const { t } = useI18n();
const asyncProfilingStore = useAsyncProfilingStore(); const asyncProfilingStore = useAsyncProfilingStore();
const serviceInstanceIds = ref<string[]>([]); const serviceInstanceIds = ref<string[]>([]);
const selectedEventType = ref<string>("");
const eventTypes = computed(() =>
asyncProfilingStore.selectedTask.eventTypes((d: string) => ({ label: d, value: d })),
);
const instances = computed(() => const instances = computed(() =>
asyncProfilingStore.instances.filter((d: Instance) => asyncProfilingStore.instances.filter((d: Instance) =>
asyncProfilingStore.selectedTask.serviceInstanceIds.includes(d.id), asyncProfilingStore.selectedTask.serviceInstanceIds.includes(d.id),
@ -48,7 +61,21 @@ limitations under the License. -->
serviceInstanceIds.value = options.map((d: Option) => d.value); serviceInstanceIds.value = options.map((d: Option) => d.value);
} }
function analyzeProfiling() {} function changeEventType(options: Option[]) {
selectedEventType.value = options[0].value;
}
async function analyzeProfiling() {
const res = await asyncProfilingStore.getAsyncProfilingAnalyze({
instanceIds: serviceInstanceIds.value,
taskId: asyncProfilingStore.selectedTask.id,
eventType: selectedEventType.value,
});
if (res.data && res.data.errors) {
ElMessage.error(res.data.errors);
return;
}
}
</script> </script>
<style> <style>
.profile-input { .profile-input {