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 console
pull/2325/head
xudaotutou 2 years ago committed by GitHub
parent f6fe8b9134
commit aa2526075b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,2 @@
# NODE_ENV=production
VITE_AGENT=true

@ -0,0 +1,2 @@
# NODE_ENV=production
VITE_AGENT=false

@ -3,8 +3,10 @@
"private": false, "private": false,
"version": "0.1.4", "version": "0.1.4",
"scripts": { "scripts": {
"dev": "vite --port 8000", "dev": "vite --port 8000 --mode ui",
"build": "vue-tsc --noEmit && vite build", "dev:tunnel": "vite --port 8000 --mode tunnel",
"build": "vue-tsc --noEmit && vite build --mode ui",
"build:tunnel": "vue-tsc --noEmit && vite build --mode tunnel",
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
@ -31,6 +33,6 @@
"tailwindcss": "^3.1.4", "tailwindcss": "^3.1.4",
"typescript": "^4.7.4", "typescript": "^4.7.4",
"vite": "^2.9.9", "vite": "^2.9.9",
"vue-tsc": "^0.34.7" "vue-tsc": "1.0.8"
} }
} }

@ -2,7 +2,7 @@
import { onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
import { Terminal } from "xterm" import { Terminal } from "xterm"
import { FitAddon } from 'xterm-addon-fit'; import { FitAddon } from 'xterm-addon-fit';
import {WebglAddon} from "xterm-addon-webgl" import { WebglAddon } from "xterm-addon-webgl"
let ws: WebSocket | undefined; let ws: WebSocket | undefined;
@ -14,9 +14,11 @@ const ip = ref("")
const port = ref('') const port = ref('')
const iframe = ref(true) const iframe = ref(true)
const fullSc = ref(true) const fullSc = ref(true)
const agentID = ref('')
const isTunnel = import.meta.env.VITE_AGENT === 'true'
const fitAddon = new FitAddon(); const fitAddon = new FitAddon();
const webglAddon = new WebglAddon(); const webglAddon = new WebglAddon();
let xterm = new Terminal({allowProposedApi: true}) let xterm = new Terminal({ allowProposedApi: true })
onMounted(() => { onMounted(() => {
ip.value = getUrlParam('ip') ?? window.location.hostname; ip.value = getUrlParam('ip') ?? window.location.hostname;
@ -27,7 +29,7 @@ onMounted(() => {
startConnect(true); startConnect(true);
window.addEventListener('resize', function () { window.addEventListener('resize', function () {
if (ws !== undefined && ws !== null) { if (ws !== undefined && ws !== null) {
const {cols, rows} = fitAddon.proposeDimensions()! const { cols, rows } = fitAddon.proposeDimensions()!
ws.send(JSON.stringify({ action: 'resize', cols, rows: rows })); ws.send(JSON.stringify({ action: 'resize', cols, rows: rows }));
fitAddon.fit(); fitAddon.fit();
} }
@ -56,7 +58,7 @@ function initWs(silent: boolean) {
let scrollback = getUrlParam('scrollback') ?? '0'; let scrollback = getUrlParam('scrollback') ?? '0';
const {cols, rows} = initXterm(scrollback) const { cols, rows } = initXterm(scrollback)
xterm.onData(function (data) { xterm.onData(function (data) {
ws?.send(JSON.stringify({ action: 'read', data: data })) ws?.send(JSON.stringify({ action: 'read', data: data }))
}); });
@ -136,8 +138,8 @@ function disconnect() {
function xtermFullScreen() { function xtermFullScreen() {
var ele = document.getElementById('terminal-card')!; var ele = document.getElementById('terminal-card')!;
requestFullScreen(ele); requestFullScreen(ele);
ele.onfullscreenchange = (e:Event)=>{ ele.onfullscreenchange = (e: Event) => {
fitAddon.fit() fitAddon.fit()
} }
} }
@ -162,8 +164,8 @@ function requestFullScreen(element: HTMLElement) {
<div class="flex flex-col h-[100vh] resize-none"> <div class="flex flex-col h-[100vh] resize-none">
<nav v-if="iframe" class="navbar bg-base-100 flex-row"> <nav v-if="iframe" class="navbar bg-base-100 flex-row">
<div class="flex-1"> <div class="flex-1">
<a href="https://github.com/alibaba/arthas" target="_blank" title="" class="mr-2 w-20"><img <a href="https://github.com/alibaba/arthas" target="_blank" title="" class="mr-2 w-20"><img src="/arthas.png"
src="/arthas.png" alt="Arthas" title="Welcome to Arthas web console" class=""></a> alt="Arthas" title="Welcome to Arthas web console" class=""></a>
<ul class="menu menu-horizontal p-0"> <ul class="menu menu-horizontal p-0">
<li> <li>
<a class="hover:text-sky-500 dark:hover:text-sky-400 text-sm" href="https://arthas.aliyun.com/doc" <a class="hover:text-sky-500 dark:hover:text-sky-400 text-sm" href="https://arthas.aliyun.com/doc"
@ -200,7 +202,7 @@ function requestFullScreen(element: HTMLElement) {
<button <button
class="btn btn-sm bg-secondary hover:bg-secondary-focus border-none text-secondary-content focus:bg-secondary-focus normal-case" class="btn btn-sm bg-secondary hover:bg-secondary-focus border-none text-secondary-content focus:bg-secondary-focus normal-case"
@click.prevent="disconnect">Disconnect</button> @click.prevent="disconnect">Disconnect</button>
<a class="btn btn-sm bg-secondary hover:bg-secondary-focus border-none text-secondary-content focus:bg-secondary-focus normal-case" <a v-if="!isTunnel" class="btn btn-sm bg-secondary hover:bg-secondary-focus border-none text-secondary-content focus:bg-secondary-focus normal-case"
href="arthas-output/" target="_blank">Arthas Output</a> href="arthas-output/" target="_blank">Arthas Output</a>
</div> </div>
</form> </form>

@ -5,3 +5,10 @@ declare module '*.vue' {
const component: DefineComponent<{}, {}, any> const component: DefineComponent<{}, {}, any>
export default component export default component
} }
interface ImportMetaEnv {
readonly VITE_AGENT:string
}
interface ImportMeta {
readonly env: ImportMetaEnv
}

@ -1,11 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import NavAside from "@/components/routeTo/NavAside.vue"; // import NavAside from "@/components/routeTo/NavAside.vue";
import NavHeader from "@/components/NavHeader.vue"; import NavHeader from "@/components/NavHeader.vue";
import ErrDialog from "@/components/dialog/ErrDialog.vue"; import ErrDialog from "@/components/dialog/ErrDialog.vue";
import SuccessDialog from "@/components/dialog/SuccessDialog.vue"; import SuccessDialog from "@/components/dialog/SuccessDialog.vue";
import { onBeforeUnmount } from "vue"; import { onBeforeUnmount } from "vue";
import machine from "./machines/consoleMachine";
import { interpret } from "xstate";
import { fetchStore } from "./stores/fetch"; import { fetchStore } from "./stores/fetch";
import InputDialog from "./components/dialog/InputDialog.vue"; import InputDialog from "./components/dialog/InputDialog.vue";
import { publicStore } from "./stores/public"; import { publicStore } from "./stores/public";
@ -13,24 +11,16 @@ import WarnDialog from "./components/dialog/WarnDialog.vue";
const fetchS = fetchStore() const fetchS = fetchStore()
const publicS = publicStore() const publicS = publicStore()
onBeforeUnmount(() => { onBeforeUnmount(() => {
const actor = interpret(machine) fetchS.interruptJob()
actor.start()
actor.send("INIT")
actor.send({
type: "SUBMIT",
value: {
action: "interrupt_job",
} as AsyncReq
})
}) })
</script> </script>
<!-- dialog用v-if方便触发hooks -->
<template> <template>
<div class=" h-screen flex flex-col"> <div class=" h-screen flex flex-col">
<nav-header class="h-[10vh]"></nav-header> <nav-header class="h-[10vh]"></nav-header>
<div class=" flex-auto h-[90vh] overflow-auto"> <div class=" flex-auto h-[90vh] overflow-auto">
<div class="flex flex-row h-full"> <div class="flex flex-row h-full">
<nav-aside ></nav-aside> <!-- <nav-aside ></nav-aside> -->
<div class="flex-auto overflow-auto h-[90vh] w-[90vw]"> <div class="flex-auto overflow-auto h-[90vh] w-[90vw]">
<router-view> <router-view>
</router-view> </router-view>

@ -1,4 +1,3 @@
type SessionAction = type SessionAction =
| "join_session" | "join_session"
| "init_session" | "init_session"
@ -68,7 +67,7 @@ type AsyncReq = SessionId<
} | { } | {
command: StringInclude<"stack", 3>; command: StringInclude<"stack", 3>;
} | { } | {
command: `monitor -c ${number} ${string} ${string}`; command: `monitor ${string} ${string} ${string} ${string}`;
} | { } | {
command: `trace ${string} ${string}`; command: `trace ${string} ${string}`;
} | { } | {
@ -88,6 +87,7 @@ type CommandReq = CommonAction<
| "sysenv" | "sysenv"
| "version" | "version"
| "sysprop" | "sysprop"
| `sysprop ${string} ${string}`
| "pwd" | "pwd"
| "jvm" | "jvm"
| "memory" | "memory"
@ -114,6 +114,8 @@ type CommandReq = CommonAction<
| `profiler ${"list" | "status" | "stop" | "resume" | "getSamples"}` | `profiler ${"list" | "status" | "stop" | "resume" | "getSamples"}`
| `profiler ${string}` | `profiler ${string}`
| `stop` | `stop`
| `options`
| `options ${string} ${string}`
| `ognl ${string}`; | `ognl ${string}`;
} | { } | {
command: StringInclude<"vmoption" | "thread", 2>; command: StringInclude<"vmoption" | "thread", 2>;
@ -362,6 +364,12 @@ type TimeFragment = {
"throwExp": string; "throwExp": string;
"timestamp": string; "timestamp": string;
}; };
type Perfcounter = {
name: string;
units: string;
value: string | number;
variability: string;
};
type MonitorData = { type MonitorData = {
className: string; className: string;
cost: number; cost: number;
@ -369,6 +377,15 @@ type MonitorData = {
methodName: number; methodName: number;
success: number; success: number;
total: number; total: number;
timestamp: string;
};
type GlobalOptions = {
"description": string;
"level": number;
"name": string;
"summary": string;
"type": string;
"value": string;
}; };
type CommandResult = { type CommandResult = {
type: "command"; type: "command";
@ -402,6 +419,14 @@ type CommandResult = {
threadStats: never; threadStats: never;
busyThreads: never; busyThreads: never;
type: "thread"; type: "thread";
} | {
options: GlobalOptions[];
changeResult: {
"afterValue": unknown,
"beforeValue": unknown,
"name": string
};
type: "options";
} | { } | {
all: boolean; all: boolean;
threadStateCount: never; threadStateCount: never;
@ -416,43 +441,23 @@ type CommandResult = {
memoryInfo: MemoryInfo; memoryInfo: MemoryInfo;
type: "memory"; type: "memory";
} | { } | {
perfCounters: { perfCounters: Perfcounter[];
name: string;
units: string;
value: string | number;
variability: string;
}[];
type: "perfcounter"; type: "perfcounter";
} | {
"classLoaderStats": Record<string,Record<"loadedCount"|"numberOfInstance",number>>
urlStats: never;
urls:never;
tree:never;
type: "classloader";
} | { } | {
type: "classloader"; "classLoaderStats": Record<
string,
Record<"loadedCount" | "numberOfInstance", number>
>;
urlStats: { urlStats: {
[x: `{hash":${string},"name:${string}}`]: { [x: `{hash":${string},"name:${string}}`]: {
unUsedUrls: string[]; unUsedUrls: string[];
usedUrls: string[]; usedUrls: string[];
}; };
}; };
"classLoaderStats":never; urls: string[];
urls: never;
tree: never;
} | {
type: "classloader";
urls: never;
"classLoaderStats";
urlStats:never;
classLoaders: ClassLoaderNode[]; classLoaders: ClassLoaderNode[];
tree: boolean; tree: boolean;
} | {
type: "classloader"; type: "classloader";
urls: string[];
urlStats:never;
"classLoaderStats":never;
tree: never;
} | { } | {
classInfo: ClassInfo; classInfo: ClassInfo;
detailed: true; detailed: true;

@ -1,12 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { useMachine } from '@xstate/vue'; import { useMachine } from '@xstate/vue';
import { onBeforeMount, Ref, ref, watchEffect } from 'vue'; import { computed, onBeforeMount, Ref, ref, watchEffect } from 'vue';
import { RefreshIcon, LogoutIcon, LoginIcon, MenuIcon, XCircleIcon } from '@heroicons/vue/outline'; import { RefreshIcon, LogoutIcon, LoginIcon, MenuIcon, XCircleIcon } from '@heroicons/vue/outline';
import { fetchStore } from '@/stores/fetch'; import { fetchStore } from '@/stores/fetch';
import machine from "@/machines/consoleMachine" import machine from "@/machines/consoleMachine"
import { publicStore } from '@/stores/public'; import { publicStore } from '@/stores/public';
import { interpret } from 'xstate'; import { interpret } from 'xstate';
import { Menu, MenuButton, MenuItems, MenuItem } from '@headlessui/vue' import { PuzzleIcon, TerminalIcon, ViewGridIcon } from "@heroicons/vue/outline"
import { DesktopComputerIcon } from "@heroicons/vue/solid"
import { useRoute, useRouter } from 'vue-router';
import permachine from '@/machines/perRequestMachine'; import permachine from '@/machines/perRequestMachine';
const fetchM = useMachine(machine) const fetchM = useMachine(machine)
const publicS = publicStore() const publicS = publicStore()
@ -22,8 +24,9 @@ const vCmd: CommandReq = {
const restBtnclass: Ref<'animate-spin-rev-pause' | 'animate-spin-rev-running'> = ref('animate-spin-rev-pause') const restBtnclass: Ref<'animate-spin-rev-pause' | 'animate-spin-rev-running'> = ref('animate-spin-rev-pause')
publicS.getCommonResEffect(fetchM, body => { publicS.getCommonResEffect(fetchM, body => {
const result = body.results[0] const result = body.results[0]
if (result.type === "version") version.value = result.version if (result.type === "version") {
}) version.value = result.version
}})
watchEffect(() => { watchEffect(() => {
if (!fetchS.wait) restBtnclass.value = "animate-spin-rev-pause" if (!fetchS.wait) restBtnclass.value = "animate-spin-rev-pause"
@ -36,6 +39,7 @@ onBeforeMount(() => {
value: vCmd value: vCmd
}) })
sessionM.send("INIT") sessionM.send("INIT")
// fetchS.baseSubmit()
}) })
// //
const reset = () => { const reset = () => {
@ -72,7 +76,6 @@ const logout = async () => {
}) })
restBtnclass.value = "animate-spin-rev-pause" restBtnclass.value = "animate-spin-rev-pause"
} }
const login = async () => { const login = async () => {
sessionM.send("SUBMIT", { sessionM.send("SUBMIT", {
value: { value: {
@ -99,59 +102,103 @@ const resetAllClass = () => {
}).then(response => { }).then(response => {
const result = (response as CommonRes).body.results[0] const result = (response as CommonRes).body.results[0]
if (result.type === "reset") { if (result.type === "reset") {
publicS.isSuccess=true publicS.isSuccess = true
publicS.SuccessMessage = JSON.stringify(result.affect) publicS.SuccessMessage = JSON.stringify(result.affect)
} }
}) })
} }
const tools:[string,()=>void][] = [ 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
},
{
name:'terminal',
url:'terminal',
icon:TerminalIcon
}
]
const tools: [string, () => void][] = [
["forceGc", forceGc], ["forceGc", forceGc],
["shutdown", shutdown], ["shutdown", shutdown],
["reset class", resetAllClass] ["reset class", resetAllClass]
] ]
const router = useRouter()
const routePath = computed(() => useRoute().path)
const toNext = (url: string) => {
if(url === "terminal") {
window.open("/","_blank")
} else router.push(url)
}
</script> </script>
<template> <template>
<nav class=" h-[10vh] flex justify-between items-center min-h-max border-b-2 shadow-orange-300"> <nav class=" h-[10vh] border-b-2 navbar">
<a class="w-40 flex items-center justify-center" href="https://arthas.aliyun.com/doc/commands.html" target="_blank"> <div class=" navbar-start flex items-stretch ">
<img src="/arthas.png" alt="logo" class=" w-3/4" /> <!-- <div class=" indicator mx-3"> -->
</a> <a class="flex items-center justify-center mx-2" href="https://arthas.aliyun.com/doc/commands.html"
target="_blank">
<div class="flex items-center h-20"> <img src="/arthas.png" alt="logo" class="w-32" />
<div class=" mr-4 bg-info text-info-content h-12 rounded-full flex justify-center items-center font-bold p-2"> </a>
sessionId: {{fetchS.sessionId}}</div> <span class="badge badge-ghost self-end text-sm">v{{version}}</span>
<div class=" mr-4 bg-info text-info-content h-12 p-2 rounded-full flex justify-center items-center font-bold"> <!-- </div> -->
version:{{ version }} </div>
</div> <div class="navbar-center">
<ul class="menu menu-horizontal p-0">
<li v-for="(tab, idx) in tabs" :key="idx" @click="toNext(tab.url)">
<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>
</div>
<div class="flex items-center h-20 navbar-end">
<button v-if="fetchS.jobRunning" @click.prevent="interruptEvent" <button v-if="fetchS.jobRunning" @click.prevent="interruptEvent"
class="btn-error btn rounded-full h-1/2 p-2 transition mr-4">interrupt</button> class="btn-error btn h-1/2 p-2">interrupt</button>
<button class=" rounded-full btn btn-info btn-circle h-12 w-12 flex justify-center items-center mr-4 " @click="reset"> <div class="dropdown dropdown-end mr-2">
<refresh-icon class="h-3/4 w-3/4" :class="restBtnclass" /> <label tabindex="0" class="btn btn-ghost m-1">
<MenuIcon class=" w-6 h-6"></MenuIcon>
</label>
<ul tabindex="0" class="menu dropdown-content p-2 shadow-xl bg-base-200 rounded-box w-40">
<li class="" v-for="(v,i) in tools" :key="i">
<a @click.prevent="v[1]">{{v[0]}}</a>
</li>
</ul>
</div>
<button class=" btn btn-ghost"
:class="{ 'btn-primary': !fetchS.online, 'btn-error': fetchS.online }">
<LogoutIcon class="h-6 w-6" @click="logout" v-if="fetchS.online" />
<login-icon class="h-6 w-6" @click="login" v-else />
</button> </button>
<button class="hover:opacity-50 h-12 w-12 grid place-items-center rounded-full mr-2 transition-all" <button class="btn-ghost btn"
:class="{ 'bg-primary': !fetchS.online, 'bg-error': fetchS.online }"> @click="reset">
<LogoutIcon class="h-1/2 w-1/2 text-error-content" @click="logout" v-if="fetchS.online" /> <refresh-icon class="h-6 w-6" :class="restBtnclass" />
<login-icon class="h-1/2 w-1/2 text-primary-content" @click="login" v-else />
</button> </button>
<Menu as="div" class="relative mr-4">
<MenuButton
class="w-12 h-12 input-btn-style grid place-items-center rounded-full bg-primary transition">
<MenuIcon class="h-3/4 w-3/4 text-primary-content"></MenuIcon>
<!-- <XCirleIcon class="h-3/4 w-3/4"></XCirleIcon> -->
</MenuButton>
<MenuItems class="absolute right-0 top-full input-btn-style mt-4 bg-white px-0 z-10 w-40">
<MenuItem v-slot="{ active }" v-for="(v,i) in tools" :key="i">
<div :class='{ "bg-blue-500 text-primary-content": active }' class="px-4 py-2">
<button @click.prevent="v[1]">{{v[0]}}</button>
</div>
</MenuItem>
</MenuItems>
</Menu>
</div> </div>
</nav> </nav>
</template> </template>
<style scoped>
</style>

@ -24,9 +24,9 @@ onBeforeMount(()=>{fetchStore().curPolling.close()})
<Dialog @close="setIsOpen" class="min-w-max z-20"> <Dialog @close="setIsOpen" class="min-w-max z-20">
<TransitionChild enter="transition-opacity duration-300" enter-from="opacity-0" enter-to="opacity-100" <TransitionChild enter="transition-opacity duration-300" enter-from="opacity-0" enter-to="opacity-100"
leave="transition-opacity duration-300" leave-from="opacity-100" leave-to="opacity-0"> leave="transition-opacity duration-300" leave-from="opacity-100" leave-to="opacity-0">
<div class="fixed inset-0 bg-black bg-opacity-25" /> <div class="fixed inset-0 bg-black bg-opacity-25 z-20" />
</TransitionChild> </TransitionChild>
<div class="fixed inset-0 grid place-items-center min-w-max"> <div class="fixed inset-0 grid place-items-center min-w-max z-30">
<TransitionChild as="template" enter="duration-300 ease-out" enter-from="opacity-0 scale-95" <TransitionChild as="template" enter="duration-300 ease-out" enter-from="opacity-0 scale-95"
enter-to="opacity-100 scale-100" leave="duration-200 ease-in" leave-from="opacity-100 scale-100" enter-to="opacity-100 scale-100" leave="duration-200 ease-in" leave-from="opacity-100 scale-100"
leave-to="opacity-0 scale-95"> leave-to="opacity-0 scale-95">

@ -8,9 +8,8 @@ import {
TransitionChild, TransitionChild,
TransitionRoot TransitionRoot
} from '@headlessui/vue' } from '@headlessui/vue'
import { onMounted, ref, onBeforeMount } from 'vue'; import { onMounted, ref } from 'vue';
const store = publicStore() const store = publicStore()
const debug = (e: any) => console.log(e)
const inputV = ref("") const inputV = ref("")
onMounted(() => { onMounted(() => {
@ -20,10 +19,11 @@ onMounted(() => {
function setIsOpen() { function setIsOpen() {
store.inputVal = inputV.value store.inputVal = inputV.value
console.log(store.inputVal, inputV.value) store.inputE = true
store.isInput = false store.isInput = false
} }
function setIsOpenCancel() { function setIsOpenCancel() {
store.inputE = false
store.isInput = false store.isInput = false
} }
</script> </script>
@ -33,9 +33,9 @@ function setIsOpenCancel() {
<Dialog @close="setIsOpenCancel" class="min-w-max z-20"> <Dialog @close="setIsOpenCancel" class="min-w-max z-20">
<TransitionChild enter="transition-opacity duration-300" enter-from="opacity-0" enter-to="opacity-100" <TransitionChild enter="transition-opacity duration-300" enter-from="opacity-0" enter-to="opacity-100"
leave="transition-opacity duration-300" leave-from="opacity-100" leave-to="opacity-0"> leave="transition-opacity duration-300" leave-from="opacity-100" leave-to="opacity-0">
<div class="fixed inset-0 bg-black bg-opacity-25" /> <div class="fixed inset-0 bg-black bg-opacity-25 z-20" />
</TransitionChild> </TransitionChild>
<div class="fixed inset-0 grid place-items-center min-w-max"> <div class="fixed inset-0 grid place-items-center min-w-max z-30">
<TransitionChild as="template" enter="duration-300 ease-out" enter-from="opacity-0 scale-95" <TransitionChild as="template" enter="duration-300 ease-out" enter-from="opacity-0 scale-95"
enter-to="opacity-100 scale-100" leave="duration-200 ease-in" leave-from="opacity-100 scale-100" enter-to="opacity-100 scale-100" leave="duration-200 ease-in" leave-from="opacity-100 scale-100"
leave-to="opacity-0 scale-95"> leave-to="opacity-0 scale-95">

@ -22,9 +22,9 @@ function setIsOpen(value: boolean) {
<Dialog @close="setIsOpen" class="min-w-max z-20"> <Dialog @close="setIsOpen" class="min-w-max z-20">
<TransitionChild enter="transition-opacity duration-300" enter-from="opacity-0" enter-to="opacity-100" <TransitionChild enter="transition-opacity duration-300" enter-from="opacity-0" enter-to="opacity-100"
leave="transition-opacity duration-300" leave-from="opacity-100" leave-to="opacity-0"> leave="transition-opacity duration-300" leave-from="opacity-100" leave-to="opacity-0">
<div class="fixed inset-0 bg-black bg-opacity-25" /> <div class="fixed inset-0 bg-black bg-opacity-25 z-20" />
</TransitionChild> </TransitionChild>
<div class="fixed inset-0 grid place-items-center min-w-max"> <div class="fixed inset-0 grid place-items-center min-w-max z-30">
<TransitionChild as="template" enter="duration-300 ease-out" enter-from="opacity-0 scale-95" <TransitionChild as="template" enter="duration-300 ease-out" enter-from="opacity-0 scale-95"
enter-to="opacity-100 scale-100" leave="duration-200 ease-in" leave-from="opacity-100 scale-100" enter-to="opacity-100 scale-100" leave="duration-200 ease-in" leave-from="opacity-100 scale-100"
leave-to="opacity-0 scale-95"> leave-to="opacity-0 scale-95">

@ -29,9 +29,9 @@
<Dialog @close="setIsOpenCancel" class="min-w-max min-h-max z-20"> <Dialog @close="setIsOpenCancel" class="min-w-max min-h-max z-20">
<TransitionChild enter="transition-opacity duration-300" enter-from="opacity-0" enter-to="opacity-100" <TransitionChild enter="transition-opacity duration-300" enter-from="opacity-0" enter-to="opacity-100"
leave="transition-opacity duration-300" leave-from="opacity-100" leave-to="opacity-0"> leave="transition-opacity duration-300" leave-from="opacity-100" leave-to="opacity-0">
<div class="fixed inset-0 bg-black bg-opacity-25" /> <div class="fixed inset-0 bg-black bg-opacity-25 z-20" />
</TransitionChild> </TransitionChild>
<div class="fixed inset-0 grid place-items-center min-w-max"> <div class="fixed inset-0 grid place-items-center min-w-max z-30">
<TransitionChild as="template" enter="duration-300 ease-out" enter-from="opacity-0 scale-95" <TransitionChild as="template" enter="duration-300 ease-out" enter-from="opacity-0 scale-95"
enter-to="opacity-100 scale-100" leave="duration-200 ease-in" leave-from="opacity-100 scale-100" enter-to="opacity-100 scale-100" leave="duration-200 ease-in" leave-from="opacity-100 scale-100"
leave-to="opacity-0 scale-95"> leave-to="opacity-0 scale-95">

@ -91,7 +91,7 @@ const blurF = (event:Event)=>{
'bg-blue-600 text-white': selected, 'bg-blue-600 text-white': selected,
'text-gray-900': !active && !selected, 'text-gray-900': !active && !selected,
}"> }">
<span class="block truncate" <span class="block"
:class="{ 'font-medium': selected, 'font-normal': !selected, 'text-white': active, 'text-teal-600': !active && !selected }"> :class="{ 'font-medium': selected, 'font-normal': !selected, 'text-white': active, 'text-teal-600': !active && !selected }">
{{ item.name }} {{ item.name }}
</span> </span>

@ -84,7 +84,7 @@ const setExpress = publicStore().inputDialogFactory(
raw => raw, raw => raw,
_ => _.value _ => _.value
) )
const { increase, decrease } = publicStore().numberCondition(autoStop, { min: 0, max: 100 })
const filterfn = (_: any, item: Item) => true const filterfn = (_: any, item: Item) => true
</script> </script>
@ -95,9 +95,16 @@ const filterfn = (_: any, item: Item) => true
<AutoComplete label="method" :option-items="optionMethod" <AutoComplete label="method" :option-items="optionMethod"
:input-fn="(value: string) => changeMethod(slotClass.selectItem.value as string, value)" :filter-fn="filterfn" :input-fn="(value: string) => changeMethod(slotClass.selectItem.value as string, value)" :filter-fn="filterfn"
v-slot="slotMethod"> v-slot="slotMethod">
<button v-if="nexpress" class="btn btn-sm btn-outline ml-2" @click="setExpress">express:{{express}}</button> <button v-if="nexpress" class="btn btn-sm btn-outline ml-2"
<button v-if="ncondition" class="btn btn-sm btn-outline ml-2" @click="setConditon">condition:{{conditon}}</button> @click.prevent="setExpress">express: <span class="normal-case">{{express}}</span></button>
<button v-if="ncount" class="btn btn-sm btn-outline ml-2" @click="setCount">count:{{autoStop}}</button> <button v-if="ncondition" class="btn btn-sm btn-outline ml-2"
@click.prevent="setConditon">condition: <span class="normal-case">{{conditon}}</span></button>
<div class="btn-group ml-2" v-if="ncount">
<button class="btn btn-sm btn-outline" @click.prevent="decrease">-</button>
<button class="btn btn-sm btn-outline border-x-0" @click.prevent="setCount">count:{{autoStop}}</button>
<button class="btn btn-sm btn-outline" @click.prevent="increase">+</button>
</div>
<slot name="others" :methodItem="slotMethod.selectItem" :classItem="slotClass.selectItem"></slot> <slot name="others" :methodItem="slotMethod.selectItem" :classItem="slotClass.selectItem"></slot>
<button @click.prevent="submitF({ <button @click.prevent="submitF({
classItem: slotClass.selectItem, classItem: slotClass.selectItem,

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

@ -11,7 +11,7 @@ const routePath = computed(() => route.path)
</script> </script>
<template> <template>
<ul class=" w-[10vw] menu bg-base-300 menu-compact"> <ul class=" w-[10vw] menu bg-base-200 menu-compact">
<li v-for="(v, i) in routes" :key="i"> <li v-for="(v, i) in routes" :key="i">
<a @click="() => router.push(v.url)" :class='{"bg-secondary text-secondary-content":routePath.includes(v.url)}'> <a @click="() => router.push(v.url)" :class='{"bg-secondary text-secondary-content":routePath.includes(v.url)}'>
{{ v.cmd }} {{ v.cmd }}

@ -19,7 +19,9 @@ if (result.type === "enhancer") {
<div class="stat-title">{{kv[0]}}</div> <div class="stat-title">{{kv[0]}}</div>
<div class="stat-value">{{kv[1]}}</div> <div class="stat-value">{{kv[1]}}</div>
</div> </div>
<slot name="otherStat">
</slot>
</div> </div>
</template> </template>

@ -406,8 +406,19 @@ const machine =
result.message === result.message ===
"all consumers are unhealthy, current job was interrupted." "all consumers are unhealthy, current job was interrupted."
) { ) {
return false; return false;
} }
if (
result.type === "options" &&
Object.hasOwn(result, "changeResult") &&
result.changeResult.afterValue === result.changeResult.beforeValue &&
(result.changeResult.afterValue as string).toString() !== (context.inputValue as CommandReq).command.split(" ")[2]
) {
console.log("?????")
// arthas 本身不会对 options抛错得手动抛错
return false
}
return true; return true;
}); });
} else { } else {

@ -276,8 +276,8 @@ const permachine = createMachine({
isErr: true, isErr: true,
ErrMessage: context.err, ErrMessage: context.err,
}); });
} else{ } else {
console.error(context.err) console.error(context.err);
} }
return { return {
err: "", err: "",
@ -302,14 +302,13 @@ const permachine = createMachine({
}; };
}), }),
needReportSuccess: (context, e) => { needReportSuccess: (context, e) => {
if (context.inputValue?.action === "close_session") { if (context.inputValue?.action === "close_session") {
context.fetchStore.$patch({ context.fetchStore.$patch({
sessionId: "", sessionId: "",
consumerId: "", consumerId: "",
online: false, online: false,
}); });
if(context.publicStore.ignore) return; if (context.publicStore.ignore) return;
context.publicStore.$patch({ context.publicStore.$patch({
isSuccess: true, isSuccess: true,
SuccessMessage: `close session success!`, SuccessMessage: `close session success!`,
@ -323,7 +322,7 @@ const permachine = createMachine({
consumerId: response.consumerId, consumerId: response.consumerId,
online: true, online: true,
}); });
if(context.publicStore.ignore) return; if (context.publicStore.ignore) return;
context.publicStore.$patch({ context.publicStore.$patch({
isSuccess: true, isSuccess: true,
SuccessMessage: `init_session success!`, SuccessMessage: `init_session success!`,
@ -391,7 +390,27 @@ const permachine = createMachine({
if (Object.hasOwn(event.data, "body")) { if (Object.hasOwn(event.data, "body")) {
if (Object.hasOwn(event.data.body, "results")) { if (Object.hasOwn(event.data.body, "results")) {
return (event.data as CommonRes).body.results.every((result) => { return (event.data as CommonRes).body.results.every((result) => {
return result.type === "status" ? result.statusCode === 0 : true; if (result.type === "status" && result.statusCode !== 0) {
return false;
}
if (
result.type === "message" &&
result.message ===
"all consumers are unhealthy, current job was interrupted."
) {
return false;
}
if (
result.type === "options" &&
Object.hasOwn(result, "changeResult") &&
(result.changeResult.afterValue as string).toString() !==
(context.inputValue as CommandReq).command.split(" ")[2]
) {
// console.warn("?????");
// arthas 本身不会对 options抛错得手动抛错
return false;
}
return true;
}); });
} else { } else {
return ["READY", "TERMINATED"].includes( return ["READY", "TERMINATED"].includes(

@ -8,11 +8,31 @@ const routes: RouteRecordRaw[] = [
{ {
path: "/config", path: "/config",
component: () => import("@/views/Config.vue"), component: () => import("@/views/Config.vue"),
children:[
{
path:"",
redirect:"/config/perCounter"
}, {
path: "perCounter",
component:()=>import("@/views/config/PerCounter.vue")
},{
path:"sysenv",
component:()=>import("@/views/config/Sysenv.vue")
},{
path:"sysprop",
component:()=>import("@/views/config/Sysprop.vue")
},{
path:"jvm",
component:()=>import("@/views/config/Jvm.vue")
},{
path:"vmoption",
component:()=>import("@/views/config/Vmoption.vue")
},{
path:"options",
component:()=>import("@/views/config/Options.vue")
}
]
}, },
// {
// path: "/console",
// component: () => import("@/views/Console.vue"),
// },
{ {
path: "/dashboard", path: "/dashboard",
component: () => import("@/views/DashBoard.vue"), component: () => import("@/views/DashBoard.vue"),
@ -29,18 +49,15 @@ const routes: RouteRecordRaw[] = [
path: "thread", path: "thread",
component: () => import("@/views/sync/Thread.vue"), component: () => import("@/views/sync/Thread.vue"),
}, },
// {
// path: "memory",
// component: () => import("@/views/sync/Memory.vue"),
// },
{ {
path: "jad", path: "jad",
component: () => import("@/views/sync/Jad.vue"), component: () => import("@/views/sync/Jad.vue"),
}, },
{
path: "retransform", // {
component: () => import("@/views/sync/Retransform.vue"), // path: "retransform",
}, // component: () => import("@/views/sync/Retransform.vue"),
// },
{ {
path: "mbean", path: "mbean",
component: () => import("@/views/sync/Mbean.vue"), component: () => import("@/views/sync/Mbean.vue"),
@ -110,6 +127,9 @@ const routes: RouteRecordRaw[] = [
component: ()=>import("@/views/async/Profiler.vue") component: ()=>import("@/views/async/Profiler.vue")
} }
], ],
}, },{
path:"/console",
component:()=>import("@/views/Console.vue")
}
]; ];
export default routes; export default routes;

@ -51,6 +51,8 @@ export const fetchStore = defineStore("fetch", {
jobIdSet: new Set<string>(), jobIdSet: new Set<string>(),
//由于轮询只会轮询一个命令,可以直接挂载当前的轮询机 //由于轮询只会轮询一个命令,可以直接挂载当前的轮询机
curPolling: nullLoop, curPolling: nullLoop,
//获取osName 通过dashboard
osName:""
}), }),
getters: { getters: {
getRequest: (state) => getRequest: (state) =>

@ -23,6 +23,10 @@ export const publicStore = defineStore("public", { // Public项目唯一id
*/ */
isInput: false, isInput: false,
inputVal: "", inputVal: "",
/**
* inputEtruefalse
*/
inputE: false,
ErrMessage: "bug!!!", ErrMessage: "bug!!!",
isSuccess: false, isSuccess: false,
SuccessMessage: "bug!!!", SuccessMessage: "bug!!!",
@ -59,10 +63,9 @@ export const publicStore = defineStore("public", { // Public项目唯一id
}); });
}, },
/** /**
*
* @param inputRef * @param inputRef
* @param getVal inputRef * @param getVal inputRef
* @param setVal inputRef * @param setVal inputRef
* @returns * @returns
*/ */
inputDialogFactory<T = string>( inputDialogFactory<T = string>(
@ -78,11 +81,15 @@ export const publicStore = defineStore("public", { // Public项目唯一id
//先上锁,防止再次触发该副作用 //先上锁,防止再次触发该副作用
mutex.value = false; mutex.value = false;
// 把缓冲区的值输入到需要使用的组件里 // 把缓冲区的值输入到需要使用的组件里
inputRef.value = getVal(this.inputVal); // 触发确认输入事件再输入
if(this.inputE) inputRef.value = getVal(this.inputVal);
// reset
this.inputE = false;
// 清空缓冲区 // 清空缓冲区
this.inputVal = ""; this.inputVal = "";
} }
}); });
return () => { return () => {
this.$patch({ this.$patch({
// 打开缓冲区 // 打开缓冲区
@ -94,6 +101,19 @@ export const publicStore = defineStore("public", { // Public项目唯一id
mutex.value = true; mutex.value = true;
}; };
}, },
numberCondition(
raw: Ref<number>,
scope: { min?: number; max?: number },
) {
return {
increase() {
(scope.max === undefined || raw.value < scope.max) && raw.value++;
},
decrease() {
(scope.min === undefined || raw.value > scope.min) && raw.value--;
},
};
},
nanoToMillis(nanoSeconds: number): number { nanoToMillis(nanoSeconds: number): number {
return nanoSeconds / 1000000; return nanoSeconds / 1000000;
}, },

@ -1,168 +1,35 @@
<script setup lang="ts"> <script setup lang="ts">
import machine from '@/machines/consoleMachine'; import SelectCmd from '@/components/routeTo/SelectCmd.vue';
import { useInterpret, useMachine } from '@xstate/vue';
import { onBeforeMount, reactive, ref, watchEffect } from 'vue';
import OptionConfigMenu from '@/components/show/OptionConfigMenu.vue';
import SwitchInput from '@/components/input/SwitchInput.vue';
import { publicStore } from '@/stores/public';
import CmdResMenu from '@/components/show/CmdResMenu.vue';
import { fetchStore } from '@/stores/fetch';
import permachine from '@/machines/perRequestMachine';
const fetchS = fetchStore()
const sysEnvMap = reactive(new Map<string, string[]>())
const sysPropMap = reactive(new Map<string, string[]>())
const perfcounterMap = reactive(new Map<string, string[]>())
const vmOptionM = useMachine(machine)
const pwd = ref("?")
const vmOptionMTree = reactive([] as VmOption[])
// //
onBeforeMount(() => { const routes: { cmd: string, url: string }[] = [
fetchS.baseSubmit(useInterpret(permachine), { {
action: "exec", cmd: "JVM",
command: "pwd" url: "jvm"
}).then( },{
res => { cmd:"system property",
const result = (res as CommonRes).body.results[0] url:"sysprop"
if (result.type == "pwd") { },{
pwd.value = result.workingDir cmd:"system environment variables",
} url:"sysenv"
} },{
) cmd:"JVM Perf Counter information",
url:"PerCounter"
vmOptionM.send("INIT") },{
vmOptionM.send({ cmd:"JVM diagnostic options",
type: "SUBMIT", url:"vmoption"
value: { },{
action: "exec", cmd:"global options",
command: "vmoption" url:"options"
}
})
})
//
const handleTree = (data: Record<string, string | boolean | number>, map: Map<string, string[]>): string[] => {
map.clear()
let res: string[] = []
Object.entries(data).forEach(([k, v]) => {
res.push(k)
if (typeof v === "boolean") v = v.toString()
if (typeof v === "number") v = v.toString()
if (k.toLowerCase().includes("path")) {
map.set(k, v.split(":").filter(v => v.trim() !== ''))
} else if (v.includes(";")) {
map.set(k, v.split(";").filter(v => v.trim() !== ''))
} else {
map.set(k, [v])
}
})
return res
}
const handleEnvTree = (data: Record<string, string>) => handleTree(data, sysEnvMap)
const handlePropTree = (data: Record<string, string>) => handleTree(data, sysPropMap)
watchEffect(() => {
const response = vmOptionM.state.value.context.response
if (response) {
if (Object.hasOwn(response, "body")) {
console.log(response, "vmoption")
const result = (response as CommonRes).body.results[0]
if (result.type == "vmoption") {
// clear西
vmOptionMTree.length = 0
console.log(result.vmOptions, "watchEffect!!!")
result.vmOptions.forEach(v => {
vmOptionMTree.push(v)
})
}
}
}
})
const vmOptionSend = (pre: string) => (v: { key: string, value: boolean | string }) => {
if (pre === "HeapDumpPath" && v.value === "") {
publicStore().$patch({ ErrMessage: "HeapDumpPath can't be set \"\" ", isErr: true })
return
} vmOptionM.send({
type: 'SUBMIT', value: {
action: "exec",
command: `vmoption ${pre} ${v.value === "" ? '\"\"' : v.value}`
}
})
}
const jvmMap = reactive(new Map<string, string[]>())
const getJvm = () => fetchS.baseSubmit(useInterpret(permachine), {
action: "exec",
command: "jvm"
}).then(res => {
const result = (res as CommonRes).body.results[0]
if (result.type === "jvm") {
jvmMap.clear()
Object.entries(result.jvmInfo).forEach(([k, v]) => {
jvmMap.set(k, v.map(v => `${v.name} : ${v.value}`))
})
}
})
const getSysenv = () => fetchS.baseSubmit(useInterpret(permachine), {
action: "exec",
command: "sysenv",
}).then(res => {
let result = (res as CommonRes).body.results[0]
if (result.type == "sysenv") {
handleEnvTree(result.env)
}
})
const getSysprop = () => fetchS.baseSubmit(useInterpret(permachine), {
action: "exec",
command: "sysprop",
}).then(res => {
let result = (res as CommonRes).body.results[0]
if (result.type == "sysprop") {
handlePropTree(result.props)
}
})
const getPerCounter = () => fetchS.baseSubmit(useInterpret(permachine), { action: "exec", command: "perfcounter -d" }).then(res => {
const result = (res as CommonRes).body.results[0]
if (result.type === "perfcounter") {
const perfcounters = result.perfCounters
perfcounterMap.clear()
perfcounters.forEach(v => {
perfcounterMap.set(v.name, Object.entries(v).filter(v => v[0] !== "name").map(([key, value]) => `${key} : ${value}`))
})
} }
}) ]
</script> </script>
<template> <template>
<div class="p-2 h-[90vh] overflow-y-scroll"> <div class="h-[90vh] overflow-auto flex">
<article> <SelectCmd :routes="routes"></SelectCmd>
<div class="flex items-center"> <div class="overflow-auto py-2 w-full flex flex-col flex-1 pointer-events-auto">
<div class="btn-info btn my-2 btn-sm normal-case">workingDir</div> <RouterView></RouterView>
<div class="bg-base-200 w-full text-base-content pl-2"> {{ pwd }}</div> </div>
</div>
<CmdResMenu title="sysenv" :map="sysEnvMap" @click="getSysenv" />
<CmdResMenu title="sysprop" :map="sysPropMap" @click="getSysprop" />
<option-config-menu title="vmOption" :list="vmOptionMTree" title-key-name="name">
<template #item="{ kv, itemTitle, idx }">
<switch-input :send="vmOptionSend(itemTitle)" :data="{ key: kv[0], value: kv[1] }" v-if="kv[0] === 'value'"
:class="{ 'border-t-4': (idx > 0), 'border-base-100': (idx > 0) }">
</switch-input>
<div v-else class="flex " :class="{ 'border-t-4': (idx > 0), 'border-base-100': (idx > 0) }">
<div class="bg-blue-200 w-1/5 p-1">{{ kv[0] }}</div>
<div class="grid place-items-center w-3/5">{{ kv[1] }}</div>
</div>
</template>
</option-config-menu>
<CmdResMenu title="jvm" :map="jvmMap" class="w-full" @click="getJvm" />
<CmdResMenu title="perfcounter" :map="perfcounterMap" @click="getPerCounter" />
</article>
</div> </div>
</template> </template>

@ -15,14 +15,12 @@ onBeforeMount(()=>{
}) })
const submitCommand = ()=>{ const submitCommand = ()=>{
console.log('别报错了')
fetchM.send({ type: 'SUBMIT', value: val.value}) fetchM.send({ type: 'SUBMIT', value: val.value})
} }
</script> </script>
<template> <template>
<div class="flex flex-col p-2"> <div class="flex flex-col ">
<form class="h-[10vh] flex items-center border shadow" @submit.prevent="submitCommand"> <form class="h-[10vh] flex items-center border shadow" @submit.prevent="submitCommand">
<label for="command-input" class=" m-2 ">command:</label> <label for="command-input" class=" m-2 ">command:</label>
<div class=" flex-auto grid place-items-start"> <div class=" flex-auto grid place-items-start">
@ -47,4 +45,4 @@ const submitCommand = ()=>{
</template> </template>
<style scoped> <style scoped>
</style>· </style>

@ -181,6 +181,7 @@ const setPri = publiC.inputDialogFactory(
}, },
(input) => input.value.toString(), (input) => input.value.toString(),
) )
const { increase, decrease } = publiC.numberCondition(pri, { min: 1 })
const transformRuntimeInfo = (result: ArthasResResult) => { const transformRuntimeInfo = (result: ArthasResResult) => {
if (result.type !== "dashboard") return; if (result.type !== "dashboard") return;
for (const key in result.runtimeInfo as RuntimeInfo) { for (const key in result.runtimeInfo as RuntimeInfo) {
@ -457,23 +458,30 @@ onBeforeUnmount(async () => {
<div id="nonheapMemory" class="w-80 h-80 flex-1 input-btn-style mr-4"></div> <div id="nonheapMemory" class="w-80 h-80 flex-1 input-btn-style mr-4"></div>
<div id="bufferPoolMemory" class="w-80 h-80 flex-1 input-btn-style"></div> <div id="bufferPoolMemory" class="w-80 h-80 flex-1 input-btn-style"></div>
</div> </div>
<div class="w-full flex justify-start items-start flex-1"> <div class="w-full flex justify-start items-start flex-1">
<div id="gc-info" class="w-[40rem] h-80 input-btn-style p-2 mr-4"></div> <div id="gc-info" class="w-[40rem] h-80 input-btn-style p-2 mr-4"></div>
<div class="input-btn-style overflow-auto flex-1 h-80"> <div class="input-btn-style flex-1 h-80 overflow-auto w-0">
<div class="flex justify-end mb-2"> <div class="flex justify-end mb-2">
<div class="btn-group">
<button class="btn btn-sm btn-outline" @click="setPri">limit:{{pri}}</button> <button class="btn btn-sm btn-outline" @click="decrease">-</button>
<button class="btn btn-sm btn-outline border-x-0" @click="setPri">limit:{{pri}}</button>
<button class="btn btn-sm btn-outline" @click="increase">+</button>
</div>
</div> </div>
<div class="overflow-x-auto"> <div class="overflow-x-auto">
<table class="table table-compact w-full group"> <table class="table table-compact w-full">
<thead> <thead>
<tr> <tr>
<th class="border-slate-300" v-for="(v,i) in keyList" :key="i" :class="{'group-first:z-0':i==0}">{{v}}</th> <th></th>
<th v-for="(v,i) in keyList" :key="i" class="normal-case">{{v}}
</th>
</tr> </tr>
</thead> </thead>
<tbody class=""> <tbody>
<tr v-for="(map, i) in tableResults" :key="i"> <tr v-for="(map, i) in tableResults" :key="i" class="hover">
<td class="border border-slate-300" v-for="(key,j) in keyList" :key="j"> <th>{{i + 1}}</th>
<td v-for="(key,j) in keyList" :key="j">
{{map.get(key)}} {{map.get(key)}}
</td> </td>
</tr> </tr>

@ -16,9 +16,9 @@ const routes: { cmd: string, url: string }[] = [
}, { }, {
cmd: "jad", cmd: "jad",
url: "jad" url: "jad"
}, { // }, {
cmd: "retransform", // cmd: "retransform",
url: "retransform" // url: "retransform"
}, { }, {
cmd: "mbean", cmd: "mbean",
url: "mbean" url: "mbean"

@ -40,7 +40,7 @@ import {
import { import {
SVGRenderer SVGRenderer
} from 'echarts/renderers'; } from 'echarts/renderers';
import { ECharts} from 'echarts/core'; import { ECharts } from 'echarts/core';
echarts.use( echarts.use(
[TitleComponent, ToolboxComponent, TooltipComponent, GridComponent, LegendComponent, DataZoomComponent, BarChart, LineChart, SVGRenderer, UniversalTransition] [TitleComponent, ToolboxComponent, TooltipComponent, GridComponent, LegendComponent, DataZoomComponent, BarChart, LineChart, SVGRenderer, UniversalTransition]
@ -63,12 +63,16 @@ const modelist: { name: string, value: string }[] = [
] ]
const mode = ref(modelist[1]) const mode = ref(modelist[1])
const averageRT = ref({
totalCost: 0,
totalCount: 0,
})
const chartContext: { const chartContext: {
count: number, count: number,
myChart?: ECharts, myChart?: ECharts,
costChart?: ECharts, costChart?: ECharts,
categories: number[], categories: string[],
data: number[], data: number[],
cur: number, cur: number,
max: number, max: number,
@ -85,7 +89,7 @@ const chartContext: {
successData: [], successData: [],
failureData: [], failureData: [],
} }
for (let i = 0; i < chartContext.count; i++) { chartContext.categories[i] = i + 1 } // for (let i = 0; i < chartContext.count; i++) { chartContext.categories[i] = i + 1 }
const chartOption = { const chartOption = {
tooltip: { tooltip: {
@ -107,8 +111,12 @@ const chartOption = {
xAxis: [ xAxis: [
{ {
type: 'category', type: 'category',
boundaryGap: true, data: chartContext.categories,
data: chartContext.categories axisLabel: {
formatter(value: string) {
return value.split(" ")[1]
}
}
} }
], ],
yAxis: [{ yAxis: [{
@ -154,23 +162,26 @@ const costOption = {
xAxis: [ xAxis: [
{ {
type: 'category', type: 'category',
boundaryGap: true, data: chartContext.categories,
data: chartContext.categories axisLabel: {
formatter(value: string) {
return value.split(" ")[1]
}
}
} }
], ],
yAxis: [ yAxis: [
{ {
type: 'value', type: 'value',
scale: true, scale: true,
name: 'cost(ms)', name: 'rt(ms)',
min: 0, min: 0,
boundaryGap: [0.2, 0.2]
} }
], ],
series: [ series: [
{ {
name: 'cost', name: 'rt',
type: 'bar', type: 'line',
data: chartContext.data data: chartContext.data
} }
] ]
@ -180,11 +191,13 @@ const updateChart = (data: MonitorData) => {
chartContext.data.shift() chartContext.data.shift()
chartContext.successData.shift() chartContext.successData.shift()
chartContext.failureData.shift() chartContext.failureData.shift()
chartContext.categories.shift()
chartContext.cur-- chartContext.cur--
} }
chartContext.data.push(data.cost) chartContext.data.push(data.cost / data.total)
chartContext.failureData.push(data.failed) chartContext.failureData.push(data.failed)
chartContext.successData.push(data.success) chartContext.successData.push(data.success)
chartContext.categories.push(data.timestamp)
chartContext.cur++ chartContext.cur++
chartContext.myChart!.setOption<EChartsOption>({ chartContext.myChart!.setOption<EChartsOption>({
@ -286,15 +299,16 @@ onBeforeUnmount(() => {
const submit = async (data: { classItem: Item, methodItem: Item, conditon: string }) => { const submit = async (data: { classItem: Item, methodItem: Item, conditon: string }) => {
enhancer.value = undefined enhancer.value = undefined
// tableResults.length = 0 // tableResults.length = 0
averageRT.value.totalCost =0
averageRT.value.totalCount = 0
let condition = data.conditon.trim() == "" ? "" : `'${data.conditon.trim()}'` let condition = data.conditon.trim() == "" ? "" : `'${data.conditon.trim()}'`
let cycle = `-c ${cycleV.value}` let cycle = `-c ${cycleV.value}`
fetchS.baseSubmit(fetchM, { fetchS.baseSubmit(fetchM, {
action: "async_exec", action: "async_exec",
command: `monitor -c 5 ${data.classItem.value} ${data.methodItem.value} ${condition}`, command: `monitor ${cycle} ${data.classItem.value as string} ${data.methodItem.value} ${condition}`,
sessionId: undefined sessionId: undefined
}).then( }).then(
res => loop.open() _res => loop.open()
) )
} }
</script> </script>
@ -321,7 +335,9 @@ const submit = async (data: { classItem: Item, methodItem: Item, conditon: strin
<button class="btn btn-sm btn-outline" @click="changeCycle">cycle time:{{cycleV}}</button> <button class="btn btn-sm btn-outline" @click="changeCycle">cycle time:{{cycleV}}</button>
</template> </template>
</MethodInput> </MethodInput>
<Enhancer :result="enhancer" v-if="enhancer" class="mb-4"></Enhancer> <Enhancer :result="enhancer" v-if="enhancer" class="mb-4">
</Enhancer>
<div id="monitorchart" class="input-btn-style h-60 w-full pointer-events-auto transition mb-2"></div> <div id="monitorchart" class="input-btn-style h-60 w-full pointer-events-auto transition mb-2"></div>
<div id="monitorchartcost" class="input-btn-style h-60 w-full pointer-events-auto transition"></div> <div id="monitorchartcost" class="input-btn-style h-60 w-full pointer-events-auto transition"></div>

@ -19,7 +19,7 @@ let eventList = reactive([] as string[]);
let selectEvent = ref("cpu") let selectEvent = ref("cpu")
let includesVal = reactive(new Set<string>()) let includesVal = reactive(new Set<string>())
let excludesVal = reactive(new Set<string>()) let excludesVal = reactive(new Set<string>())
let framebuf = ref(1000000) let framebuf = ref(1_000_000)
let duration = ref(300) let duration = ref(300)
let profilerStatus = ref({ let profilerStatus = ref({
is: false, is: false,
@ -29,6 +29,7 @@ let outputPath = ref("")
let samples = ref(0) let samples = ref(0)
const support = ref(false) const support = ref(false)
let fileformat = ref("%t-%p.html") let fileformat = ref("%t-%p.html")
const getStatusLoop = fetchS.getPollingLoop(() => { const getStatusLoop = fetchS.getPollingLoop(() => {
const statusM = interpret(permachine) const statusM = interpret(permachine)
fetchS.baseSubmit(statusM, { fetchS.baseSubmit(statusM, {
@ -55,7 +56,8 @@ const getStatusLoop = fetchS.getPollingLoop(() => {
}, { }, {
step: 2000, step: 2000,
}) })
const handleFramebuf = publicS.numberCondition(framebuf, {})
const handleduration = publicS.numberCondition(duration, {})
const getSampleLoop = fetchS.getPollingLoop(() => { const getSampleLoop = fetchS.getPollingLoop(() => {
let statusM = interpret(permachine) let statusM = interpret(permachine)
fetchS.baseSubmit(statusM, { fetchS.baseSubmit(statusM, {
@ -227,8 +229,16 @@ onBeforeUnmount(() => {
</ListboxOptions> </ListboxOptions>
</div> </div>
</Listbox> </Listbox>
<button class="btn btn-sm btn-outline mr-2" @click="changeDuration">duration :{{duration}}</button> <div class="btn-group mr-2">
<button class="btn btn-sm btn-outline mr-2" @click="changeFramebuf">framebuf :{{framebuf}}</button> <button class="btn btn-sm btn-outline" @click.prevent="handleduration.decrease">-</button>
<button class="btn btn-sm btn-outline border-x-0" @click.prevent="changeDuration">duration :{{duration}}</button>
<button class="btn btn-sm btn-outline" @click.prevent="handleduration.increase">+</button>
</div>
<div class="btn-group mr-2">
<button class="btn btn-sm btn-outline" @click.prevent="handleFramebuf.decrease">-</button>
<button class="btn btn-sm btn-outline border-x-0" @click.prevent="changeFramebuf">framebuf :{{framebuf}}</button>
<button class="btn btn-sm btn-outline" @click.prevent="handleFramebuf.increase">+</button>
</div>
<button class="btn btn-sm btn-outline mr-2" @click="changeFile">file :<span <button class="btn btn-sm btn-outline mr-2" @click="changeFile">file :<span
class="normal-case">{{fileformat}}</span></button> class="normal-case">{{fileformat}}</span></button>
<TodoList title="include" :val-set="includesVal" class=" mr-2"></TodoList> <TodoList title="include" :val-set="includesVal" class=" mr-2"></TodoList>

@ -91,16 +91,18 @@ const submit = async (data: { classItem: Item, methodItem: Item, conditon: strin
<MethodInput :submit-f="submit" ncondition ncount></MethodInput> <MethodInput :submit-f="submit" ncondition ncount></MethodInput>
<Enhancer :result="enhancer" v-if="enhancer"></Enhancer> <Enhancer :result="enhancer" v-if="enhancer"></Enhancer>
<div class="w-full flex justify-center items-center mt-4"> <div class="mt-4 overflow-x-auto w-full">
<table class="table w-full table-compact group"> <table class="table w-full table-compact">
<thead> <thead>
<tr> <tr>
<th class="border border-slate-300" v-for="(v,i) in keyList" :key="i" :class="{'group-first:z-0':i===0}">{{v}}</th> <th></th>
<th v-for="(v,i) in keyList" :key="i">{{v}}</th>
</tr> </tr>
</thead> </thead>
<tbody class=""> <tbody class="">
<tr v-for="(map, i) in tableResults" :key="i"> <tr v-for="(map, i) in tableResults" :key="i">
<td class="border border-slate-300" v-for="(key,j) in keyList" :key="j"> <th>{{i + 1}}</th>
<td v-for="(key,j) in keyList" :key="j">
<template v-if="key!== 'stackTrace'"> <template v-if="key!== 'stackTrace'">
{{map.get(key)}} {{map.get(key)}}
</template> </template>
@ -113,6 +115,12 @@ const submit = async (data: { classItem: Item, methodItem: Item, conditon: strin
</td> </td>
</tr> </tr>
</tbody> </tbody>
<tfoot>
<tr>
<th></th>
<th v-for="(v,i) in keyList" :key="i">{{v}}</th>
</tr>
</tfoot>
</table> </table>
</div> </div>

@ -126,7 +126,7 @@ const submit = (data: { classItem: Item, methodItem: Item, conditon: string, cou
<MethodInput :submit-f="submit" class="mb-2" ncondition ncount> <MethodInput :submit-f="submit" class="mb-2" ncondition ncount>
<template #others> <template #others>
<label class="label cursor-pointer btn-sm border border-neutral ml-2"> <label class="label cursor-pointer btn-sm ml-2">
<span class="label-text uppercase font-bold mr-1">skip JDK Method</span> <span class="label-text uppercase font-bold mr-1">skip JDK Method</span>
<input v-model="enabled" type="checkbox" class="toggle"/> <input v-model="enabled" type="checkbox" class="toggle"/>
</label> </label>

@ -187,7 +187,7 @@ getPullResultsEffect(
console.log(tf.index) console.log(tf.index)
// if(!timeFragmentSet.has(tf.index)){ // if(!timeFragmentSet.has(tf.index)){
// timeFragmentSet.add(tf.index) // timeFragmentSet.add(tf.index)
tableResults.unshift(transform(tf)) tableResults.unshift(transform(tf))
// } // }
}) })
@ -291,7 +291,7 @@ const searchTt = () => {
tableResults.unshift(transform(tf)) tableResults.unshift(transform(tf))
}) })
} }
}).catch(err=>{ }).catch(err => {
console.error(err) console.error(err)
}) })
} }
@ -327,35 +327,42 @@ const searchTt = () => {
</template> </template>
</CmdResMenu> </CmdResMenu>
</div> </div>
<Enhancer :result="enhancer" v-if="enhancer"></Enhancer> <Enhancer :result="enhancer" v-if="enhancer">
<div class="w-full flex justify-center items-center overflow-auto flex-1"> </Enhancer>
<table class="table table-compact group w-full"> <div class="overflow-x-auto w-full">
<thead> <table class="table table-compact w-full">
<tr> <thead>
<th class="border group-first:z-0" v-for="(v,i) in keyList" :key="i">{{v}}</th> <tr>
<th class="border">invoke</th> <th></th>
</tr> <th class="normal-case" v-for="(v,i) in keyList" :key="i">{{v}}</th>
</thead> </tr>
<tbody class=""> </thead>
<tr v-for="(map, i) in tableResults" :key="i"> <tbody class="">
<td class="border" v-for="(key,j) in keyList" :key="j"> <tr v-for="(map, i) in tableResults" :key="i">
<template v-if=" key !== 'params'"> <th class="">
{{map.get(key)}} <button class="btn btn-primary btn-sm btn-outline" @click="reTrigger(map.get('index')!)">invoke</button>
</template> </th>
<td class="" v-for="(key,j) in keyList" :key="j">
<template v-if=" key !== 'params'">
{{map.get(key)}}
</template>
<div class="flex flex-col" v-else> <div class="flex flex-col" v-else>
<div v-for="(row, k) in map.get(key)" :key="k"> <div v-for="(row, k) in map.get(key)" :key="k">
{{row}} {{row}}
</div>
</div> </div>
</td> </div>
<td class="border"> </td>
<button class="btn btn-primary btn-sm btn-outline" @click="reTrigger(map.get('index')!)">invoke</button> </tr>
</td> </tbody>
</tr> <tfoot>
</tbody> <tr>
</table> <th></th>
</div> <th class="normal-case" v-for="(v,i) in keyList" :key="i">{{v}}</th>
</tr>
</tfoot>
</table>
</div>
</div> </div>
</template> </template>

@ -18,6 +18,7 @@ const pollResults = reactive([] as [string, Map<string, string[]>, TreeNode][])
const enhancer = ref(undefined as EnchanceResult | undefined) const enhancer = ref(undefined as EnchanceResult | undefined)
const depth = ref(1) const depth = ref(1)
const tableResults = reactive([] as Map<string, string | TreeNode>[]) const tableResults = reactive([] as Map<string, string | TreeNode>[])
const { increase, decrease } = publiC.numberCondition(depth, { min: 1, max: 6 })
const keyList = [ const keyList = [
"ts", "ts",
"accessPoint", "accessPoint",
@ -150,7 +151,8 @@ const submit = async (data: { classItem: Item, methodItem: Item, conditon: strin
<template #others> <template #others>
<div class="relative group ml-2"> <div class="relative group ml-2">
<div class="btn btn-sm btn-outline">watching point</div> <div class="btn btn-sm btn-outline">watching point</div>
<div class="h-0 group-hover:h-auto group-focus-within:h-auto absolute overflow-clip transition z-10 top-full pt-2"> <div
class="h-0 group-hover:h-auto group-focus-within:h-auto absolute overflow-clip transition z-10 top-full pt-2">
<label class="label cursor-pointer btn-sm border border-neutral ml-2 bg-base-100" <label class="label cursor-pointer btn-sm border border-neutral ml-2 bg-base-100"
v-for="(mode,i) in modereflist" :key="i"> v-for="(mode,i) in modereflist" :key="i">
@ -161,33 +163,36 @@ const submit = async (data: { classItem: Item, methodItem: Item, conditon: strin
</div> </div>
</div> </div>
<button class="btn btn-sm btn-outline ml-2" @click="setDepth">depth:{{depth}}</button> <div class="btn-group ml-2">
<button class="btn btn-sm btn-outline" @click.prevent="decrease">-</button>
<button class="btn btn-sm btn-outline border-x-0" @click.prevent="setDepth">depth:{{depth}}</button>
<button class="btn btn-sm btn-outline" @click.prevent="increase">+</button>
</div>
</template> </template>
</MethodInput> </MethodInput>
<Enhancer :result="enhancer" v-if="enhancer"></Enhancer> <Enhancer :result="enhancer" v-if="enhancer"></Enhancer>
<div class="flex justify-center mt-4 overflow-auto"> <div class="overflow-x-auto w-full mt-4">
<table class="table w-full group"> <table class="table w-full table-compact">
<thead> <thead>
<tr> <tr>
<th class="border border-slate-300" v-for="(v,i) in keyList" :key="i" :class="{'group-first:z-0':i===0}">{{v}} <th></th>
<th class="0" v-for="(v,i) in keyList" :key="i">{{v}}
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="(map, i) in tableResults" :key="i"> <tr v-for="(map, i) in tableResults" :key="i" class="hover">
<td class="border border-slate-300" v-for="(key,j) in keyList" :key="j"> <th>{{i+1}}</th>
<td class="" v-for="(key,j) in keyList" :key="j">
<div v-if=" key !== 'value'"> <div v-if=" key !== 'value'">
{{map.get(key)}} {{map.get(key)}}
</div> </div>
<div class="flex flex-col" v-else> <div class="flex flex-col" v-else>
<Tree :root="(map.get('value') as TreeNode)" class="mt-2" button-class=" "> <Tree :root="(map.get('value') as TreeNode)" class="mt-2" button-class=" ">
<template #meta="{ data, active }"> <template #meta="{ data, active }">
<div <div class="bg-info px-2 rounded-r rounded-br mr-2 text-info-content" :class='{
class="bg-info px-2 rounded-r rounded-br mr-2 text-info-content" :class='{ "hover:opacity-50":active
"hover:opacity-50":active }'>
}'
>
{{data}} {{data}}
</div> </div>
</template> </template>
@ -196,6 +201,14 @@ const submit = async (data: { classItem: Item, methodItem: Item, conditon: strin
</td> </td>
</tr> </tr>
</tbody> </tbody>
<tfoot>
<tr>
<th></th>
<th class="0" v-for="(v,i) in keyList" :key="i">{{v}}
</th>
</tr>
</tfoot>
</table> </table>
</div> </div>
</template> </template>

@ -0,0 +1,67 @@
<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};
const tableResultList: ResultType[] = reactive([])
// tree
const transformToString: <T=Record<string,unknown>>(obj:T)=>T = (obj)=>{
type Out = typeof obj
let output = {} as Out
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
const element = obj[key];
if( typeof element === "object") {
output[key] = transformToString(element as Record<string,unknown>) as Out[Extract<keyof Out, string>]
} else {
output[key] = (element as (string|number|boolean)).toString() as Out[Extract<keyof Out, string>]
}
}
}
return output
}
const getJvm = () => fetchS.baseSubmit(interpret(permachine), {
action: "exec",
command: "jvm"
}).then(res => {
const result = (res as CommonRes).body.results[0]
if (result.type === "jvm") {
tableResultList.length = 0
Object.entries(result.jvmInfo).forEach(([key, value]) => {
let row = {
key,
value:JSON.stringify(value)
}
tableResultList.push(row)
})
}
})
onBeforeMount(() => {
getJvm()
})
</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>{{map.key}}</th>
<td>{{map.value}}</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>key</th>
<th>value</th>
</tr>
</tfoot>
</table>
</template>

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

@ -15,30 +15,7 @@ const classFields = reactive(new Map<string, string[]>())
const classMethodMap = reactive(new Map<string, string[]>()) const classMethodMap = reactive(new Map<string, string[]>())
const dumpMap = reactive(new Map<string, string[]>()) const dumpMap = reactive(new Map<string, string[]>())
const { getCommonResEffect } = publicStore() const { getCommonResEffect } = publicStore()
const publicS = publicStore()
const fetchS = fetchStore() const fetchS = fetchStore()
// getCommonResEffect(classInfoM, body => {
// const result = body.results[0]
// if (result.type === "sc" && result.detailed === true && result.withField === true) {
// classDetailMap.clear()
// classFields.clear()
// Object.entries(result.classInfo).filter(([k, v]) => k !== "fields").forEach(([k, v]) => {
// let value: string[] = []
// if (!["interfaces", "annotations", "classloader", "superClass"].includes(k)) value.push(v.toString())
// else value = v as string[]
// classDetailMap.set(k, value)
// })
// result.classInfo.fields.forEach(field => {
// classFields.set(field.name, Object.entries(field).filter(([k, v]) => k !== "name").map(([k, v]) => {
// if (k === "value") v = JSON.stringify(v)
// return `${k}: ${v}`
// }))
// })
// }
// })
getCommonResEffect(classMethodInfoM, body => { getCommonResEffect(classMethodInfoM, body => {
classMethodMap.clear() classMethodMap.clear()
body.results.forEach(result => { body.results.forEach(result => {

@ -140,9 +140,9 @@ const getCategorizedByClassType = () => {
for (const name in result.classLoaderStats) { for (const name in result.classLoaderStats) {
const map = new Map() const map = new Map()
for (const key in result.classLoaderStats[name]) { map.set("loadedCount", result.classLoaderStats[name].loadedCount)
map.set(key, result.classLoaderStats[name][key]) map.set("numberOfInstance", result.classLoaderStats[name].numberOfInstance)
} // "loadedCount"|"numberOfInstance"
map.set("name", name) map.set("name", name)
tableResults.push(map) tableResults.push(map)
} }
@ -250,7 +250,8 @@ const resetClassloader = () => {
</span> </span>
</div> </div>
<!-- <div class="">count:{{data[0]}}</div> --> <!-- <div class="">count:{{data[0]}}</div> -->
<button @click="selectClassLoader({name:data[1],hash:data[2],count:data[0]})" class="btn btn-primary btn-xs btn-outline opacity-0 group-hover:opacity-100" <button @click="selectClassLoader({name:data[1],hash:data[2],count:data[0]})"
class="btn btn-primary btn-xs btn-outline opacity-0 group-hover:opacity-100"
v-if="data[2]!== 'null'"> v-if="data[2]!== 'null'">
select classloader select classloader
</button> </button>
@ -261,12 +262,11 @@ const resetClassloader = () => {
</div> </div>
</div> </div>
<div class="w-1/3 ml-2 overflow-y-scroll transition-all duration-500" :class='{ <div class=" ml-2 overflow-y-scroll transition-all duration-500" :class='{
"w-0":loaderCache.hash === "", "w-0":loaderCache.hash === "",
"input-btn-style":loaderCache.hash !=="" "input-btn-style w-1/3":loaderCache.hash !==""
}'> }'>
<!-- <div class="overflow-auto h-full"> -->
<div class="mb-2"> <div class="mb-2">
<div class="overflow-auto"> <div class="overflow-auto">
<span class="bg-primary-focus px-2 rounded-l text-primary-content border border-primary-focus"> <span class="bg-primary-focus px-2 rounded-l text-primary-content border border-primary-focus">
@ -293,7 +293,6 @@ const resetClassloader = () => {
</span> </span>
</div> </div>
</div> </div>
<template v-if="loaderCache.hash.trim() !== ''"> <template v-if="loaderCache.hash.trim() !== ''">
<div class="flex mb-2 w-full"> <div class="flex mb-2 w-full">
<div class=" cursor-default <div class=" cursor-default
@ -351,20 +350,26 @@ const resetClassloader = () => {
<button class="btn btn-primary btn-sm" @click="getCategorizedByClassType">refresh</button> <button class="btn btn-primary btn-sm" @click="getCategorizedByClassType">refresh</button>
</div> </div>
<div class="overflow-auto"> <div class="overflow-auto">
<table class="table w-full group table-compact"> <table class="table w-full table-compact">
<thead> <thead>
<tr> <tr>
<th class="border border-slate-300 p-2" v-for="(v,i) in keyList" :key="i" :class="{'group-first:z-0':i==0}">{{v}}</th> <th></th>
</tr> <th class=" normal-case" v-for="(v,i) in keyList" :key="i" :class="{'group-first:z-0':i==0}">{{v}}
</thead> </th>
<tbody class=""> </tr>
<tr v-for="(map, i) in tableResults" :key="i"> </thead>
<td class="border border-slate-300 p-2" v-for="(key,j) in keyList" :key="j"> <tbody class="">
{{map.get(key)}} <tr v-for="(map, i) in tableResults" :key="i">
</td> <th>{{i + 1}}</th>
</tr> <template v-for="(key, j) in keyList">
</tbody> <td class="">
</table> {{map.get(key)}}
</td>
</template>
</tr>
</tbody>
</table>
</div> </div>
</div> </div>
</div> </div>

@ -46,10 +46,10 @@ const submitCommand = (e: Event) => {
class="w-full border-none py-2 pl-3 pr-10 leading-5 text-gray-900 focus-visible:outline-none"> class="w-full border-none py-2 pl-3 pr-10 leading-5 text-gray-900 focus-visible:outline-none">
</div> </div>
<label class="label cursor-pointer btn-sm border border-neutral mr-2"> <label class="label cursor-pointer btn-sm mr-2">
<span class="label-text uppercase font-bold mr-1">only live object</span> <span class="label-text uppercase font-bold mr-1">only live object</span>
<input v-model="enabled" type="checkbox" class="toggle" /> <input v-model="enabled" type="checkbox" class="toggle" />
</label> </label>
</label> </label>
<button @click.prevent="submitCommand" <button @click.prevent="submitCommand"

@ -23,6 +23,7 @@ const setDepth = publiC.inputDialogFactory(
}, },
(input) => input.value.toString(), (input) => input.value.toString(),
) )
const {increase, decrease} = publiC.numberCondition(depth,{min:1})
const setHash = publiC.inputDialogFactory( const setHash = publiC.inputDialogFactory(
hashcode, hashcode,
(raw) => raw, (raw) => raw,
@ -67,7 +68,11 @@ const getSource = () => {
<input type="text" v-model="express" <input type="text" v-model="express"
class="w-full border-none py-2 pl-3 pr-10 leading-5 text-gray-900 focus-visible:outline-none"> class="w-full border-none py-2 pl-3 pr-10 leading-5 text-gray-900 focus-visible:outline-none">
</div> </div>
<button class="btn btn-sm btn-outline mr-2" @click.prevent="setDepth">depth:{{depth}}</button> <div class="btn-group mr-2">
<button class="btn btn-outline btn-sm" @click.prevent="decrease">-</button>
<button class="btn btn-outline btn-sm border-x-0" @click.prevent="setDepth">depth:{{depth}}</button>
<button class="btn btn-outline btn-sm" @click.prevent="increase">+</button>
</div>
<button class="btn btn-sm btn-outline mr-2" @click.prevent="setClassLoader" v-if="hashcode === ''">ClassLoaderClass:{{classloaderName}}</button> <button class="btn btn-sm btn-outline mr-2" @click.prevent="setClassLoader" v-if="hashcode === ''">ClassLoaderClass:{{classloaderName}}</button>
<button class="btn btn-sm btn-outline mr-2" @click.prevent="setHash" v-if="classloaderName === ''">hashcode:{{hashcode}}</button> <button class="btn btn-sm btn-outline mr-2" @click.prevent="setHash" v-if="classloaderName === ''">hashcode:{{hashcode}}</button>
</label> </label>

@ -69,7 +69,7 @@ const openList = () => {
class="w-full border-none py-2 pl-3 pr-10 leading-5 text-gray-900 focus-visible:outline-none"> class="w-full border-none py-2 pl-3 pr-10 leading-5 text-gray-900 focus-visible:outline-none">
</div> </div>
</label> </label>
<label class="label cursor-pointer btn-sm border border-neutral mr-2"> <label class="label cursor-pointer btn-sm mr-2">
<span class="label-text uppercase font-bold mr-1">explicitly trigger</span> <span class="label-text uppercase font-bold mr-1">explicitly trigger</span>
<input v-model="enabled" type="checkbox" class="toggle" /> <input v-model="enabled" type="checkbox" class="toggle" />
</label> </label>

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
// import machine from '@/machines/consoleMachine'; // import machine from '@/machines/consoleMachine';
import { useInterpret, } from '@xstate/vue'; import { useInterpret, } from '@xstate/vue';
import { onBeforeMount, reactive, ref } from 'vue'; import { onBeforeMount, reactive, ref, computed } from 'vue';
import { fetchStore } from '@/stores/fetch'; import { fetchStore } from '@/stores/fetch';
import { publicStore } from '@/stores/public'; import { publicStore } from '@/stores/public';
import TodoList from '@/components/input/TodoList.vue'; import TodoList from '@/components/input/TodoList.vue';
@ -10,7 +10,7 @@ import {
} from '@headlessui/vue'; } from '@headlessui/vue';
import { transfromStore } from "@/stores/resTransform" import { transfromStore } from "@/stores/resTransform"
import permachine from '@/machines/perRequestMachine'; import permachine from '@/machines/perRequestMachine';
import { computed } from '@vue/reactivity'; import { watch } from 'fs';
const fetchS = fetchStore() const fetchS = fetchStore()
const FetchService = useInterpret(permachine) const FetchService = useInterpret(permachine)
@ -43,7 +43,8 @@ const keyList: thkey[] = [
"blockedCount", "blockedCount",
"blockedTime", "blockedTime",
] ]
const statsList: (keyof ThreadStats)[] = ["id", const statsList: (keyof ThreadStats)[] = [
"id",
"name", "name",
"cpu", "cpu",
"daemon", "daemon",
@ -62,9 +63,15 @@ const infoCount = ref({
TERMINATED: 0 TERMINATED: 0
} as ThreadStateCount) } as ThreadStateCount)
const tableResults = reactive([] as Map<string, string>[]) const tableResults = reactive([] as Map<string, string>[])
const limitResults = tableResults
// watchEffect(()=>{
// if(count.value > 0) {
// tableResults.length = count.value
// }
// })
const tableFilter = computed(() => { const tableFilter = computed(() => {
// //
let res = tableResults let res = count.value > 0 ? tableResults.filter((v, i)=>i < count.value) : tableResults
if (includesVal.size === 0) return res; if (includesVal.size === 0) return res;
// //
includesVal.forEach((v1) => { includesVal.forEach((v1) => {
@ -106,8 +113,9 @@ onBeforeMount(() => {
}) })
const getThreads = () => { const getThreads = () => {
let i = leastTime.value > 0 ? "-i " + leastTime.value : "" let i = leastTime.value > 0 ? "-i " + leastTime.value : ""
let n = count.value > 0 ? "-n " + count.value : "" // block
const b = isBlock.value ? "-b" : "" let n = count.value > 0 && !isBlock ? "-n " + count.value : ""
const b = isBlock.value ? "-b --lockedMonitors --lockedSynchronizers" : ""
let state = threadState.value.value === "" ? "" : `--state ${threadState.value.value}` let state = threadState.value.value === "" ? "" : `--state ${threadState.value.value}`
tableResults.length = 0 tableResults.length = 0
for (const key in infoCount.value) { for (const key in infoCount.value) {
@ -173,12 +181,12 @@ const setleast = publiC.inputDialogFactory(
}, },
(input) => input.value.toString(), (input) => input.value.toString(),
) )
const {increase, decrease} = publiC.numberCondition(count,{min:0})
const getSpecialThreads = (threadid: number = -1) => { const getSpecialThreads = (threadid: number = -1) => {
let threadName = threadid > 0 ? `${threadid}` : "" let threadName = threadid > 0 ? `${threadid}` : ""
fetchS.baseSubmit(FetchService, { fetchS.baseSubmit(FetchService, {
action: "exec", action: "exec",
command: `thread ${threadName}` command: `thread ${threadName} `
}).then(res => { }).then(res => {
const result = (res as CommonRes).body.results[0] const result = (res as CommonRes).body.results[0]
if (result.type === "thread") { if (result.type === "thread") {
@ -195,12 +203,12 @@ const getSpecialThreads = (threadid: number = -1) => {
<div class="flex justify-end items-center h-[10vh]"> <div class="flex justify-end items-center h-[10vh]">
<TodoList title="filter" :val-set="includesVal" class=" mr-2"></TodoList> <TodoList title="filter" :val-set="includesVal" class=" mr-2"></TodoList>
<label class="label cursor-pointer btn-sm border border-neutral ">
<span class="label-text uppercase font-bold mr-1">is blocking:</span>
<input v-model="isBlock" type="checkbox" class="toggle"/>
</label>
<button class="btn ml-2 btn-sm btn-outline" @click="setleast">sample interval:{{leastTime}}</button> <button class="btn ml-2 btn-sm btn-outline" @click="setleast">sample interval:{{leastTime}}</button>
<button v-show="!isBlock" class="btn ml-2 btn-sm btn-outline" @click="setlimit"> top n threads:{{count}}</button> <div class="btn-group ml-2" v-show="!isBlock">
<button class="btn btn-outline btn-sm" @click.prevent="decrease">-</button>
<button class="btn btn-outline btn-sm border-x-0" @click.prevent="setlimit">top threads:{{count}}</button>
<button class="btn btn-outline btn-sm" @click.prevent="increase">+</button>
</div>
<Listbox v-model="threadState"> <Listbox v-model="threadState">
<div class=" relative mx-2 "> <div class=" relative mx-2 ">
<ListboxButton class="btn w-40 btn-sm btn-outline">state {{ threadState.name }}</ListboxButton> <ListboxButton class="btn w-40 btn-sm btn-outline">state {{ threadState.name }}</ListboxButton>
@ -217,7 +225,11 @@ const getSpecialThreads = (threadid: number = -1) => {
</ListboxOptions> </ListboxOptions>
</div> </div>
</Listbox> </Listbox>
<button class="btn btn-primary btn-sm btn-outline" @click="getThreads"> get threads</button> <label class="label cursor-pointer btn-sm ">
<span class="label-text uppercase font-bold mr-1">is blocking:</span>
<input v-model="isBlock" type="checkbox" class="toggle" />
</label>
<button class="btn btn-primary btn-sm btn-outline" @click="getThreads"> get threads </button>
</div> </div>
<div class="w-full h-[50vh] input-btn-style my-2 p-4 flex flex-col"> <div class="w-full h-[50vh] input-btn-style my-2 p-4 flex flex-col">
<div class="flex h-[8vh] flex-wrap flex-auto"> <div class="flex h-[8vh] flex-wrap flex-auto">
@ -231,31 +243,31 @@ const getSpecialThreads = (threadid: number = -1) => {
</div> </div>
</div> </div>
<div class="overflow-auto h-[40vh] w-full"> <div class="overflow-auto h-[40vh] w-full">
<table class="table w-full group"> <table class="table w-full">
<thead> <thead>
<tr> <tr>
<th class="border border-slate-300 p-2 group-first:z-0">get stackTrace</th> <th class=""></th>
<template v-if="count===0"> <template v-if="count === 0">
<th class="border border-slate-300 p-2" v-for="(v,i) in keyList" :key="i">{{v}}</th> <th class="normal-case" v-for="(v,i) in keyList" :key="i">{{v}}</th>
</template> </template>
<template v-else> <template v-else>
<th class="border border-slate-300 p-2" v-for="(v,i) in statsList" :key="i">{{v}}</th> <th class="normal-case" v-for="(v,i) in statsList" :key="i">{{v}}</th>
</template> </template>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="(map, i) in tableFilter" :key="i"> <tr v-for="(map, i) in tableFilter" :key="i">
<td class="border border-slate-300 p-2"><button class="btn-outline btn-primary btn btn-sm" <th class="2"><button class="btn-outline btn-primary btn btn-sm"
@click="getSpecialThreads(parseInt(map.get('id')!))" v-if="map.get('id')!=='-1'"> @click="getSpecialThreads(parseInt(map.get('id')!))" v-if="map.get('id')!=='-1'">
get stackTrace get stackTrace
</button></td> </button></th>
<template v-if="count === 0"> <template v-if="count === 0">
<td class="border border-slate-300 p-2" v-for="(key,j) in keyList" :key="j"> <td class="" v-for="(key,j) in keyList" :key="j">
{{map.get(key)}} {{map.get(key)}}
</td> </td>
</template> </template>
<template v-else> <template v-else>
<td class="border border-slate-300 p-2" v-for="(key,j) in statsList" :key="j"> <td class="" v-for="(key,j) in statsList" :key="j">
{{map.get(key)}} {{map.get(key)}}
</td> </td>
</template> </template>

@ -11,6 +11,7 @@ const gcMachine = useInterpret(permachine)
const fetchS = fetchStore() const fetchS = fetchStore()
const publicS = publicStore() const publicS = publicStore()
const depth = ref(1) const depth = ref(1)
const {increase, decrease} = publicS.numberCondition(depth,{min:1})
const setDepth = publicS.inputDialogFactory( const setDepth = publicS.inputDialogFactory(
depth, depth,
(raw) => { (raw) => {
@ -87,7 +88,11 @@ const getInstance = (data:{classItem:Item}) => {
<ClassInput :submit-f="getInstance" class="mb-4" > <ClassInput :submit-f="getInstance" class="mb-4" >
<template #others> <template #others>
<button class="ml-2 btn btn-outline btn-sm" @click="setDepth">depth:{{depth}}</button> <div class="btn-group ml-2">
<button class="btn btn-outline btn-sm" @click.prevent="decrease">-</button>
<button class="btn btn-outline btn-sm border-x-0" @click.prevent="setDepth">depth:{{depth}}</button>
<button class="btn btn-outline btn-sm" @click.prevent="increase">+</button>
</div>
</template> </template>
</ClassInput> </ClassInput>
<template v-if="pollResults.length > 0"> <template v-if="pollResults.length > 0">

@ -5,8 +5,25 @@ import * as path from "path";
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig(({ mode }) => { export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), ""); const env = loadEnv(mode, process.cwd(), "");
const proxyTarget =`${env.VITE_ARTHAS_PROXY_IP}:${env.VITE_ARTHAS_PROXY_PORT}`; const proxyTarget =
`${env.VITE_ARTHAS_PROXY_IP}:${env.VITE_ARTHAS_PROXY_PORT}`;
console.log("Arthas proxy :", proxyTarget); console.log("Arthas proxy :", proxyTarget);
let outDir, input
console.log(env.VITE_AGENT)
if (env.VITE_AGENT === "true") {
outDir = `./dist/tunnel`
input = {
tunnel: path.resolve(__dirname, "index.html")
}
} else {
outDir = `./dist`
input = {
main: path.resolve(__dirname, "index.html"),
ui: path.resolve(__dirname, "ui/index.html"),
}
}
return { return {
plugins: [vue({ plugins: [vue({
reactivityTransform: true, reactivityTransform: true,
@ -18,12 +35,10 @@ export default defineConfig(({ mode }) => {
}, },
build: { build: {
emptyOutDir: true, emptyOutDir: true,
outDir,
minify: "esbuild", minify: "esbuild",
rollupOptions: { rollupOptions: {
input: { input,
main: path.resolve(__dirname, "index.html"),
ui: path.resolve(__dirname, "ui/index.html"),
},
output: { output: {
chunkFileNames: "static/js/[name]-[hash].js", chunkFileNames: "static/js/[name]-[hash].js",
entryFileNames: "static/js/[name]-[hash].js", entryFileNames: "static/js/[name]-[hash].js",
@ -43,7 +58,7 @@ export default defineConfig(({ mode }) => {
"/api": { "/api": {
target: `http://${proxyTarget}`, target: `http://${proxyTarget}`,
changeOrigin: true, changeOrigin: true,
} },
}, },
}, },
}; };

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save