mirror of https://github.com/alibaba/arthas.git
update web ui (#2318)
* fix(web ui): profiler * chore(web ui):perf proxy config * perf(web ui):update style * chore(web ui):update deps * perf(web ui):fix monitor category * fix(web ui):fix style of table and monitor rt chart * refactor(web ui):refactor config * feat(web ui):support debug http api with consolepull/2325/head
parent
f6fe8b9134
commit
aa2526075b
@ -0,0 +1,2 @@
|
|||||||
|
# NODE_ENV=production
|
||||||
|
VITE_AGENT=true
|
@ -0,0 +1,2 @@
|
|||||||
|
# NODE_ENV=production
|
||||||
|
VITE_AGENT=false
|
@ -1,57 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { computed, reactive, ref } from 'vue';
|
|
||||||
import { PuzzleIcon, TerminalIcon, ViewGridIcon } from "@heroicons/vue/outline"
|
|
||||||
import { DesktopComputerIcon } from "@heroicons/vue/solid"
|
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
|
||||||
const tabs = [
|
|
||||||
{
|
|
||||||
name: 'dashboard',
|
|
||||||
url: "/dashboard",
|
|
||||||
icon: DesktopComputerIcon
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'immediacy',
|
|
||||||
url: '/synchronize',
|
|
||||||
icon: ViewGridIcon
|
|
||||||
}, {
|
|
||||||
name: "real time",
|
|
||||||
url: '/asynchronize',
|
|
||||||
icon: ViewGridIcon
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'option',
|
|
||||||
url: '/config',
|
|
||||||
icon: PuzzleIcon
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// name: 'console',
|
|
||||||
// url: '/console',
|
|
||||||
// icon: TerminalIcon
|
|
||||||
// },
|
|
||||||
|
|
||||||
]
|
|
||||||
const router = useRouter()
|
|
||||||
const routePath = computed(() => useRoute().path)
|
|
||||||
const toNext = (url: string) => {
|
|
||||||
router.push(url)
|
|
||||||
}
|
|
||||||
const a: StatusResult = { type: "status", message: "", statusCode: 0 }
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<ul class="menu bg-base-200 w-[10vw] menu-compact">
|
|
||||||
<li v-for="(tab, idx) in tabs" :key="idx"
|
|
||||||
@click="toNext(tab.url)" class="pl-2" >
|
|
||||||
<a class="break-all" :class="{ 'bg-primary text-primary-content': routePath.includes(tab.url), }">
|
|
||||||
<component :is="tab.icon" class="w-4 h-4" />
|
|
||||||
{{
|
|
||||||
tab.name
|
|
||||||
}}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
@ -0,0 +1,102 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import permachine from '@/machines/perRequestMachine';
|
||||||
|
import { fetchStore } from '@/stores/fetch';
|
||||||
|
import { publicStore } from '@/stores/public';
|
||||||
|
import { onBeforeMount, reactive, ref, Ref } from 'vue';
|
||||||
|
import { interpret } from 'xstate';
|
||||||
|
const fetchS = fetchStore();
|
||||||
|
const publicS = publicStore()
|
||||||
|
type ResultType = MergeObj<Omit<GlobalOptions, "value">, {
|
||||||
|
value: Ref<string>, changeValue: null | (() => void)
|
||||||
|
}>
|
||||||
|
|
||||||
|
const tableResultList: ResultType[] = reactive([])
|
||||||
|
const keyList: (keyof GlobalOptions)[] = [
|
||||||
|
"level",
|
||||||
|
"name",
|
||||||
|
"type",
|
||||||
|
"value",
|
||||||
|
"summary",
|
||||||
|
"description",
|
||||||
|
]
|
||||||
|
const setVmoption = (key: string, value: string) => fetchS.baseSubmit(interpret(permachine), {
|
||||||
|
action: "exec",
|
||||||
|
command: `options ${key} ${value}`
|
||||||
|
})
|
||||||
|
|
||||||
|
const getVmoption = () => fetchS.baseSubmit(interpret(permachine), {
|
||||||
|
action: "exec",
|
||||||
|
command: "options",
|
||||||
|
}).then(res => {
|
||||||
|
let result = (res as CommonRes).body.results[0]
|
||||||
|
if (result.type == "options") {
|
||||||
|
tableResultList.length = 0;
|
||||||
|
result.options.forEach((option) => {
|
||||||
|
let rows: ResultType[] = []
|
||||||
|
// 用来绑定读写
|
||||||
|
|
||||||
|
let _raw = ref(option.value)
|
||||||
|
let changeValue = null
|
||||||
|
changeValue = publicS.inputDialogFactory(_raw,
|
||||||
|
(raw) => {
|
||||||
|
setVmoption(option.name, raw.trim())
|
||||||
|
.then(res =>{
|
||||||
|
let result = (res as CommonRes).body.results[0]
|
||||||
|
if(result.type === "options") _raw.value = (result.changeResult.afterValue as string).toString()
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
// 失败就回退
|
||||||
|
_raw.value = option.value
|
||||||
|
})
|
||||||
|
return raw.trim()
|
||||||
|
},
|
||||||
|
(input) => input.value)
|
||||||
|
rows.push({
|
||||||
|
...option,
|
||||||
|
value: _raw,
|
||||||
|
changeValue,
|
||||||
|
})
|
||||||
|
tableResultList.push(...rows)
|
||||||
|
})
|
||||||
|
tableResultList.sort((a, b) => {
|
||||||
|
if(a.level != b.level) return a.level - b.level
|
||||||
|
else {
|
||||||
|
return a.name > b.name ? 1 :-1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onBeforeMount(() => {
|
||||||
|
getVmoption()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<table class="table w-full table-compact">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<th></th>
|
||||||
|
<th v-for="(k, i) in keyList" :key="i">{{ k }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(map, i) in tableResultList" :key="i" class="hover">
|
||||||
|
<th>
|
||||||
|
<button class="btn btn-outline btn-xs btn-primary" @click.prevent="map.changeValue"
|
||||||
|
v-if="map.changeValue !== null">edit</button>
|
||||||
|
</th>
|
||||||
|
<template v-for="(k, j) in keyList" :key="j">
|
||||||
|
<th v-if="k === 'name' || k === 'level'">{{ map[k] }}</th>
|
||||||
|
<td v-else class="break-words"> {{ map[k] }}</td>
|
||||||
|
</template>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th v-for="(k, i) in keyList" :key="i">{{ k }}</th>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</template>
|
@ -0,0 +1,69 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import permachine from '@/machines/perRequestMachine';
|
||||||
|
import { fetchStore } from '@/stores/fetch';
|
||||||
|
import { onBeforeMount, reactive } from 'vue';
|
||||||
|
import { interpret } from 'xstate';
|
||||||
|
const fetchS = fetchStore();
|
||||||
|
type ResultType = MergeObj<Perfcounter,{rowspan:number}>
|
||||||
|
const perfcounterList: ResultType[] = reactive([])
|
||||||
|
let keyList: (keyof Perfcounter)[] = [
|
||||||
|
"name",
|
||||||
|
"units",
|
||||||
|
"variability",
|
||||||
|
"value",
|
||||||
|
]
|
||||||
|
const getPerCounter = () => fetchS.baseSubmit(interpret(permachine), { action: "exec", command: "perfcounter -d" }).then(res => {
|
||||||
|
const result = (res as CommonRes).body.results[0]
|
||||||
|
if (result.type === "perfcounter") {
|
||||||
|
const perfcounters = result.perfCounters
|
||||||
|
perfcounterList.length = 0;
|
||||||
|
perfcounters.forEach(perfcouter => {
|
||||||
|
let result = {...perfcouter,rowspan:1}
|
||||||
|
result.value = result.value.toString()
|
||||||
|
perfcounterList.push(result)
|
||||||
|
})
|
||||||
|
perfcounterList.sort((a, b) => a.name > b.name ? 1 : -1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
getPerCounter()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<table class="table w-full table-compact">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th v-for="(v,i) in keyList" :key="i">{{v}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="">
|
||||||
|
<tr v-for="(map, i) in perfcounterList" :key="i" class="hover">
|
||||||
|
<template v-for="(key,j) in keyList" :key="j">
|
||||||
|
<!-- 展示合并的单元格且定住name -->
|
||||||
|
<th v-if="key == 'name' && map.rowspan > 0" :rowspan="map.rowspan">
|
||||||
|
{{map[key]}}
|
||||||
|
</th>
|
||||||
|
<!-- 只有value才会裂变 -->
|
||||||
|
<td v-else-if="key === 'value'" >
|
||||||
|
<div class="break-all">{{map[key]}}</div>
|
||||||
|
</td>
|
||||||
|
<!-- 展示合并的单元格 -->
|
||||||
|
<td v-else-if="map.rowspan > 0" :rowspan="map.rowspan">
|
||||||
|
{{map[key]}}
|
||||||
|
</td>
|
||||||
|
</template>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<th v-for="(v,i) in keyList" :key="i" class="break-words">{{v}}</th>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,52 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import permachine from '@/machines/perRequestMachine';
|
||||||
|
import { fetchStore } from '@/stores/fetch';
|
||||||
|
import { onBeforeMount, reactive } from 'vue';
|
||||||
|
import { interpret } from 'xstate';
|
||||||
|
const fetchS = fetchStore();
|
||||||
|
type ResultType = { "key": string, "value": string, rowspan: number };
|
||||||
|
const tableResultList: ResultType[] = reactive([])
|
||||||
|
const getSysenv = () => fetchS.baseSubmit(interpret(permachine), {
|
||||||
|
action: "exec",
|
||||||
|
command: "sysenv",
|
||||||
|
}).then(res => {
|
||||||
|
tableResultList.length = 0
|
||||||
|
let result = (res as CommonRes).body.results[0]
|
||||||
|
if (result.type == "sysenv") {
|
||||||
|
Object.entries(result.env).forEach(([key, value]) => {
|
||||||
|
let rows: ResultType[] = []
|
||||||
|
rows.push({
|
||||||
|
key, value, rowspan: 1
|
||||||
|
})
|
||||||
|
tableResultList.push(...rows)
|
||||||
|
})
|
||||||
|
tableResultList.sort((a, b) => a.key > b.key ? 1 : -1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onBeforeMount(() => {
|
||||||
|
getSysenv()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<table class="table w-full table-compact">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>key</th>
|
||||||
|
<th>value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(map, i) in tableResultList" :key="i" class="hover">
|
||||||
|
<th v-if="map.rowspan > 0" :rowspan="map.rowspan">{{map.key}}</th>
|
||||||
|
<td>{{map.value}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<th>key</th>
|
||||||
|
<th>value</th>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</template>
|
@ -0,0 +1,78 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import permachine from '@/machines/perRequestMachine';
|
||||||
|
import { fetchStore } from '@/stores/fetch';
|
||||||
|
import { publicStore } from '@/stores/public';
|
||||||
|
import { onBeforeMount, reactive, ref, Ref } from 'vue';
|
||||||
|
import { interpret } from 'xstate';
|
||||||
|
const fetchS = fetchStore();
|
||||||
|
const publicS = publicStore()
|
||||||
|
type ResultType = { "key": string, "value": Ref<string>, rowspan: number, changeValue:()=>void};
|
||||||
|
const tableResultList: ResultType[] = reactive([])
|
||||||
|
|
||||||
|
const setSysprop = (key:string,value:string) => fetchS.baseSubmit(interpret(permachine),{
|
||||||
|
action: "exec",
|
||||||
|
command:`sysprop ${key} ${value}`
|
||||||
|
})
|
||||||
|
|
||||||
|
const getSysprop = () => fetchS.baseSubmit(interpret(permachine), {
|
||||||
|
action: "exec",
|
||||||
|
command: "sysprop",
|
||||||
|
}).then(res => {
|
||||||
|
let result = (res as CommonRes).body.results[0]
|
||||||
|
if (result.type == "sysprop") {
|
||||||
|
tableResultList.length = 0;
|
||||||
|
Object.entries(result.props).forEach(([key, value]) => {
|
||||||
|
let rows: ResultType[] = []
|
||||||
|
// 用来绑定读写
|
||||||
|
let _raw = ref(value)
|
||||||
|
const changeValue = publicS.inputDialogFactory(_raw,
|
||||||
|
(raw) => {
|
||||||
|
setSysprop(key, raw.trim()).then(res=>{
|
||||||
|
},err=>{
|
||||||
|
// 失败就回退
|
||||||
|
_raw.value = value
|
||||||
|
})
|
||||||
|
return raw.trim()
|
||||||
|
},
|
||||||
|
(input) => input.value)
|
||||||
|
rows.push({
|
||||||
|
key, value:_raw, rowspan: 1, changeValue
|
||||||
|
})
|
||||||
|
tableResultList.push(...rows)
|
||||||
|
})
|
||||||
|
tableResultList.sort((a, b) => a.key > b.key ? 1 : -1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onBeforeMount(() => {
|
||||||
|
getSysprop()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<table class="table w-full table-compact">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<th></th>
|
||||||
|
<th>key</th>
|
||||||
|
<th>value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(map, i) in tableResultList" :key="i" class="hover">
|
||||||
|
<th v-if="map.rowspan > 0" :rowspan="map.rowspan">
|
||||||
|
<button class="btn btn-outline btn-xs btn-primary" @click.prevent="map.changeValue">edit</button>
|
||||||
|
</th>
|
||||||
|
<th v-if="map.rowspan > 0" :rowspan="map.rowspan">{{map.key}}</th>
|
||||||
|
<td>{{map.value}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th>key</th>
|
||||||
|
<th>value</th>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</template>
|
@ -0,0 +1,92 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import permachine from '@/machines/perRequestMachine';
|
||||||
|
import { fetchStore } from '@/stores/fetch';
|
||||||
|
import { publicStore } from '@/stores/public';
|
||||||
|
import { onBeforeMount, reactive, ref, Ref } from 'vue';
|
||||||
|
import { interpret } from 'xstate';
|
||||||
|
const fetchS = fetchStore();
|
||||||
|
const publicS = publicStore()
|
||||||
|
type ResultType = { name: string, origin: string, value: Ref<string>, writeable: string, changeValue: null|(() => void)
|
||||||
|
};
|
||||||
|
const tableResultList: ResultType[] = reactive([])
|
||||||
|
const keyList: (keyof VmOption)[] = [
|
||||||
|
"name",
|
||||||
|
"origin",
|
||||||
|
"writeable",
|
||||||
|
"value",
|
||||||
|
]
|
||||||
|
const setVmoption = (key: string, value: string) => fetchS.baseSubmit(interpret(permachine), {
|
||||||
|
action: "exec",
|
||||||
|
command: `vmoption ${key} ${value}`
|
||||||
|
})
|
||||||
|
|
||||||
|
const getVmoption = () => fetchS.baseSubmit(interpret(permachine), {
|
||||||
|
action: "exec",
|
||||||
|
command: "vmoption",
|
||||||
|
}).then(res => {
|
||||||
|
let result = (res as CommonRes).body.results[0]
|
||||||
|
if (result.type == "vmoption") {
|
||||||
|
tableResultList.length = 0;
|
||||||
|
result.vmOptions.forEach((vmoption) => {
|
||||||
|
let rows: ResultType[] = []
|
||||||
|
// 用来绑定读写
|
||||||
|
|
||||||
|
let _raw = ref(vmoption.value)
|
||||||
|
let changeValue = null
|
||||||
|
if(vmoption.writeable===true) {
|
||||||
|
changeValue = publicS.inputDialogFactory(_raw,
|
||||||
|
(raw) => {
|
||||||
|
setVmoption(vmoption.name, raw.trim()).then(res => {
|
||||||
|
}, err => {
|
||||||
|
// 失败就回退
|
||||||
|
_raw.value = vmoption.value
|
||||||
|
})
|
||||||
|
return raw.trim()
|
||||||
|
},
|
||||||
|
(input) => input.value)
|
||||||
|
}
|
||||||
|
rows.push({
|
||||||
|
name: vmoption.name,
|
||||||
|
value: _raw,
|
||||||
|
changeValue,
|
||||||
|
writeable: vmoption.writeable.toString(),
|
||||||
|
origin: vmoption.origin
|
||||||
|
})
|
||||||
|
tableResultList.push(...rows)
|
||||||
|
})
|
||||||
|
tableResultList.sort((a, b) => a.name > b.name ? 1 : -1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
onBeforeMount(() => {
|
||||||
|
getVmoption()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<table class="table w-full table-compact">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<th></th>
|
||||||
|
<th v-for="(k, i) in keyList" :key="i">{{k}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(map, i) in tableResultList" :key="i" class="hover">
|
||||||
|
<th >
|
||||||
|
<button class="btn btn-outline btn-xs btn-primary" @click.prevent="map.changeValue" v-if="map.changeValue !== null">edit</button>
|
||||||
|
</th>
|
||||||
|
<template v-for="(k,j) in keyList" :key="j">
|
||||||
|
<th v-if="k==='name'">{{map[k]}}</th>
|
||||||
|
<td v-else class="break-words"> {{map[k]}}</td>
|
||||||
|
</template>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th v-for="(k, i) in keyList" :key="i">{{k}}</th>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</template>
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue