mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-05-12 15:52:57 +00:00
add task list
This commit is contained in:
parent
ede8f1cd82
commit
f3894d2bff
@ -149,3 +149,38 @@ export const EditStrategy = {
|
||||
}
|
||||
`,
|
||||
};
|
||||
|
||||
export const GetAsyncTaskList = {
|
||||
variable: "$request: AsyncProfilerTaskListRequest!",
|
||||
query: `
|
||||
asyncTaskList: queryAsyncProfilerTaskList(request: $request) {
|
||||
errorReason
|
||||
tasks {
|
||||
id
|
||||
serviceId
|
||||
serviceInstanceIds
|
||||
createTime
|
||||
events
|
||||
duration
|
||||
execArgs
|
||||
}
|
||||
}
|
||||
`,
|
||||
};
|
||||
|
||||
export const GetAsyncProfileTaskProcess = {
|
||||
variable: "$taskID: String",
|
||||
query: `
|
||||
taskLogs: queryAsyncProfilerTaskProgress(taskID: $taskID) {
|
||||
logs {
|
||||
id
|
||||
instanceId
|
||||
instanceName
|
||||
operationType
|
||||
operationTime
|
||||
}
|
||||
errorInstanceIds
|
||||
successInstanceIds
|
||||
}
|
||||
`,
|
||||
};
|
||||
|
@ -23,6 +23,8 @@ import {
|
||||
GetProfileTaskLogs,
|
||||
GetStrategyList,
|
||||
EditStrategy,
|
||||
GetAsyncTaskList,
|
||||
GetAsyncProfileTaskProcess,
|
||||
} from "../fragments/profile";
|
||||
|
||||
export const saveProfileTask = `mutation createProfileTask(${CreateProfileTask.variable}) {${CreateProfileTask.query}}`;
|
||||
@ -40,3 +42,7 @@ export const getProfileTaskLogs = `query profileTaskLogs(${GetProfileTaskLogs.va
|
||||
export const getStrategyList = `query getStrategyList(${GetStrategyList.variable}) {${GetStrategyList.query}}`;
|
||||
|
||||
export const editStrategy = `mutation editStrategy(${EditStrategy.variable}) {${EditStrategy.query}}`;
|
||||
|
||||
export const getAsyncTaskList = `query getAsyncTaskList(${GetAsyncTaskList.variable}) {${GetAsyncTaskList.query}}`;
|
||||
|
||||
export const getAsyncProfileTaskProcess = `query getAsyncProfileTaskProcess(${GetAsyncProfileTaskProcess.variable}) {${GetAsyncProfileTaskProcess.query}}`;
|
||||
|
75
src/store/modules/async-profiling.ts
Normal file
75
src/store/modules/async-profiling.ts
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
import { defineStore } from "pinia";
|
||||
import type { Option } from "@/types/app";
|
||||
import type { AsyncProfilingTaskList } from "@/types/async-profiling";
|
||||
import { store } from "@/store";
|
||||
import graphql from "@/graphql";
|
||||
import type { AxiosResponse } from "axios";
|
||||
|
||||
interface AsyncProfilingState {
|
||||
taskList: Array<Recordable<AsyncProfilingTaskList>>;
|
||||
labels: Option[];
|
||||
asyncProfilingTips: string;
|
||||
selectedTask: Recordable<AsyncProfilingTaskList>;
|
||||
}
|
||||
|
||||
export const asyncProfilingStore = defineStore({
|
||||
id: "asyncProfiling",
|
||||
state: (): AsyncProfilingState => ({
|
||||
taskList: [],
|
||||
labels: [{ value: "", label: "" }],
|
||||
asyncProfilingTips: "",
|
||||
selectedTask: {},
|
||||
}),
|
||||
actions: {
|
||||
setSelectedTask(task: Recordable<AsyncProfilingTaskList>) {
|
||||
this.selectedTask = task || {};
|
||||
},
|
||||
async getTaskList(params: { serviceId: string; targets: string[] }) {
|
||||
if (!params.serviceId) {
|
||||
return new Promise((resolve) => resolve({}));
|
||||
}
|
||||
const res: AxiosResponse = await graphql.query("getAsyncTaskList").params(params);
|
||||
|
||||
this.asyncProfilingTips = "";
|
||||
if (res.data.errors) {
|
||||
return res.data;
|
||||
}
|
||||
this.taskList = res.data.data.asyncTaskList || [];
|
||||
this.selectedTask = this.taskList[0] || {};
|
||||
this.setSelectedTask(this.selectedTask);
|
||||
if (!this.taskList.length) {
|
||||
return res.data;
|
||||
}
|
||||
return res.data;
|
||||
},
|
||||
async getTaskLogs(param: { taskID: string }) {
|
||||
const res: AxiosResponse = await graphql.query("getAsyncProfileTaskProcess").params(param);
|
||||
|
||||
if (res.data.errors) {
|
||||
return res.data;
|
||||
}
|
||||
this.taskLogs = res.data.data.taskLogs;
|
||||
return res.data;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export function useAsyncProfilingStore(): Recordable {
|
||||
return asyncProfilingStore(store);
|
||||
}
|
26
src/types/async-profiling.ts
Normal file
26
src/types/async-profiling.ts
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export type AsyncProfilingTaskList = {
|
||||
id: string;
|
||||
serviceId: string;
|
||||
serviceInstanceIds: string[];
|
||||
createTime: number;
|
||||
events: string;
|
||||
duration: number;
|
||||
execArgs: string;
|
||||
};
|
@ -0,0 +1,177 @@
|
||||
<!-- 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="profile-task-list flex-v">
|
||||
<div class="profile-task-wrapper flex-v">
|
||||
<div class="profile-t-tool flex-h">{{ t("taskList") }}</div>
|
||||
<div class="profile-t-wrapper">
|
||||
<div class="no-data" v-show="!asyncProfilingStore.taskList.length">
|
||||
{{ t("noData") }}
|
||||
</div>
|
||||
<table class="profile-t">
|
||||
<tr
|
||||
class="profile-tr cp"
|
||||
v-for="(i, index) in asyncProfilingStore.taskList"
|
||||
@click="changeTask(i)"
|
||||
:key="index"
|
||||
>
|
||||
<td
|
||||
class="profile-td"
|
||||
:class="{
|
||||
selected: asyncProfilingStore.currentTask && asyncProfilingStore.currentTask.id === i.id,
|
||||
}"
|
||||
>
|
||||
<div class="ell">
|
||||
<span>{{ i.endpointName }}</span>
|
||||
<a class="profile-btn r" @click="viewTask($event, i)">
|
||||
<Icon iconName="view" size="middle" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="grey ell sm">
|
||||
<span class="mr-10 sm">
|
||||
{{ dateFormat(i.startTime) }}
|
||||
</span>
|
||||
<span class="mr-10 sm">
|
||||
{{ dateFormat(i.startTime + i.duration * 60 * 1000) }}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useSelectorStore } from "@/store/modules/selectors";
|
||||
import { useAsyncProfilingStore } from "@/store/modules/async-profiling";
|
||||
import type { TaskLog, TaskListItem } from "@/types/profile";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { dateFormat } from "@/utils/dateFormat";
|
||||
|
||||
const { t } = useI18n();
|
||||
const asyncProfilingStore = useAsyncProfilingStore();
|
||||
const selectorStore = useSelectorStore();
|
||||
const viewDetail = ref<boolean>(false);
|
||||
const service = ref<string>("");
|
||||
// const selectedTask = ref<TaskListItem | Record<string, never>>({});
|
||||
const instanceLogs = ref<TaskLog | any>({});
|
||||
|
||||
async function changeTask(item: TaskListItem) {
|
||||
asyncProfilingStore.setCurrentSegment({});
|
||||
asyncProfilingStore.setCurrentTask(item);
|
||||
const res = await asyncProfilingStore.getSegmentList({ taskID: item.id });
|
||||
if (res.errors) {
|
||||
ElMessage.error(res.errors);
|
||||
}
|
||||
}
|
||||
|
||||
async function viewTask(e: Event, item: TaskListItem) {
|
||||
e.stopPropagation();
|
||||
viewDetail.value = true;
|
||||
asyncProfilingStore.setCurrentTask(item);
|
||||
service.value = (selectorStore.services.filter((s: any) => s.id === item.serviceId)[0] || {}).label;
|
||||
const res = await asyncProfilingStore.getTaskLogs({ taskID: item.id });
|
||||
|
||||
if (res.errors) {
|
||||
ElMessage.error(res.errors);
|
||||
return;
|
||||
}
|
||||
item.logs = asyncProfilingStore.taskLogs;
|
||||
instanceLogs.value = {};
|
||||
for (const d of item.logs) {
|
||||
if (instanceLogs.value[d.instanceName]) {
|
||||
instanceLogs.value[d.instanceName].push({
|
||||
operationType: d.operationType,
|
||||
operationTime: d.operationTime,
|
||||
});
|
||||
} else {
|
||||
instanceLogs.value[d.instanceName] = [{ operationType: d.operationType, operationTime: d.operationTime }];
|
||||
}
|
||||
}
|
||||
asyncProfilingStore.setCurrentTask(item);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.profile-task-list {
|
||||
width: 300px;
|
||||
height: calc((100% - 60px) / 2);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.item span {
|
||||
height: 21px;
|
||||
}
|
||||
|
||||
.profile-td {
|
||||
padding: 5px 10px;
|
||||
border-bottom: 1px solid var(--sw-trace-list-border);
|
||||
|
||||
&.selected {
|
||||
background-color: var(--sw-list-selected);
|
||||
}
|
||||
}
|
||||
|
||||
.no-data {
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.profile-t-wrapper {
|
||||
overflow: auto;
|
||||
flex-grow: 1;
|
||||
border-right: 1px solid var(--sw-trace-list-border);
|
||||
}
|
||||
|
||||
.profile-t {
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
table-layout: fixed;
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.profile-tr {
|
||||
&:hover {
|
||||
background-color: var(--sw-list-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.profile-segment {
|
||||
border-top: 1px solid var(--sw-trace-list-border);
|
||||
}
|
||||
|
||||
.profile-t-tool {
|
||||
padding: 5px 10px;
|
||||
font-weight: bold;
|
||||
border-right: 1px solid var(--sw-trace-list-border);
|
||||
border-bottom: 1px solid var(--sw-trace-list-border);
|
||||
background-color: var(--sw-table-header);
|
||||
}
|
||||
|
||||
.log-item {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.profile-btn {
|
||||
color: $font-color;
|
||||
padding: 1px 3px;
|
||||
border-radius: 2px;
|
||||
font-size: $font-size-smaller;
|
||||
float: right;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user