mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-05-14 17:05:10 +00:00
resolved conflicts
This commit is contained in:
commit
f18e5c7149
75
package-lock.json
generated
75
package-lock.json
generated
@ -21,6 +21,7 @@
|
|||||||
"element-plus": "^2.0.2",
|
"element-plus": "^2.0.2",
|
||||||
"jquery": "^3.6.0",
|
"jquery": "^3.6.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
"monaco-editor": "^0.27.0",
|
||||||
"pinia": "^2.0.5",
|
"pinia": "^2.0.5",
|
||||||
"sockjs": "^0.3.24",
|
"sockjs": "^0.3.24",
|
||||||
"sockjs-client": "^1.6.0",
|
"sockjs-client": "^1.6.0",
|
||||||
@ -60,6 +61,7 @@
|
|||||||
"eslint-plugin-vue": "^7.0.0",
|
"eslint-plugin-vue": "^7.0.0",
|
||||||
"husky": "^7.0.4",
|
"husky": "^7.0.4",
|
||||||
"lint-staged": "^12.1.3",
|
"lint-staged": "^12.1.3",
|
||||||
|
"monaco-editor-webpack-plugin": "^4.1.2",
|
||||||
"node-sass": "^6.0.1",
|
"node-sass": "^6.0.1",
|
||||||
"postcss-html": "^1.3.0",
|
"postcss-html": "^1.3.0",
|
||||||
"postcss-scss": "^4.0.2",
|
"postcss-scss": "^4.0.2",
|
||||||
@ -11233,9 +11235,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eventsource": {
|
"node_modules/eventsource": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.1.tgz",
|
||||||
"integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==",
|
"integrity": "sha512-qV5ZC0h7jYIAOhArFJgSfdyz6rALJyb270714o7ZtNnw2WSJ+eexhKtE0O8LYPRsHZHf2osHKZBxGPvm3kPkCA==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"original": "^1.0.0"
|
"original": "^1.0.0"
|
||||||
},
|
},
|
||||||
@ -18371,6 +18374,38 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/monaco-editor": {
|
||||||
|
"version": "0.27.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.27.0.tgz",
|
||||||
|
"integrity": "sha512-UhwP78Wb8w0ZSYoKXQNTV/0CHObp6NS3nCt51QfKE6sKyBo5PBsvuDOHoI2ooBakc6uIwByRLHVeT7+yXQe2fQ=="
|
||||||
|
},
|
||||||
|
"node_modules/monaco-editor-webpack-plugin": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-snmHecygICKT0UlHhva+Cs2WaLPpxy3111xbvInhjjTr5m0xQTFHlmJ2QQDcB14Vzmm7f07uc1TtbvOpmL50BA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"loader-utils": "^2.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"monaco-editor": "0.25.x || 0.26.x || 0.27.x",
|
||||||
|
"webpack": "^4.5.0 || 5.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/monaco-editor-webpack-plugin/node_modules/loader-utils": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"big.js": "^5.2.2",
|
||||||
|
"emojis-list": "^3.0.0",
|
||||||
|
"json5": "^2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/move-concurrently": {
|
"node_modules/move-concurrently": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||||
@ -37989,9 +38024,10 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"eventsource": {
|
"eventsource": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.1.tgz",
|
||||||
"integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==",
|
"integrity": "sha512-qV5ZC0h7jYIAOhArFJgSfdyz6rALJyb270714o7ZtNnw2WSJ+eexhKtE0O8LYPRsHZHf2osHKZBxGPvm3kPkCA==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"original": "^1.0.0"
|
"original": "^1.0.0"
|
||||||
}
|
}
|
||||||
@ -43595,6 +43631,33 @@
|
|||||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
|
||||||
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
|
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
|
||||||
},
|
},
|
||||||
|
"monaco-editor": {
|
||||||
|
"version": "0.27.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.27.0.tgz",
|
||||||
|
"integrity": "sha512-UhwP78Wb8w0ZSYoKXQNTV/0CHObp6NS3nCt51QfKE6sKyBo5PBsvuDOHoI2ooBakc6uIwByRLHVeT7+yXQe2fQ=="
|
||||||
|
},
|
||||||
|
"monaco-editor-webpack-plugin": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-snmHecygICKT0UlHhva+Cs2WaLPpxy3111xbvInhjjTr5m0xQTFHlmJ2QQDcB14Vzmm7f07uc1TtbvOpmL50BA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"loader-utils": "^2.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"loader-utils": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"big.js": "^5.2.2",
|
||||||
|
"emojis-list": "^3.0.0",
|
||||||
|
"json5": "^2.1.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"move-concurrently": {
|
"move-concurrently": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
"element-plus": "^2.0.2",
|
"element-plus": "^2.0.2",
|
||||||
"jquery": "^3.6.0",
|
"jquery": "^3.6.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
"monaco-editor": "^0.27.0",
|
||||||
"pinia": "^2.0.5",
|
"pinia": "^2.0.5",
|
||||||
"sockjs": "^0.3.24",
|
"sockjs": "^0.3.24",
|
||||||
"sockjs-client": "^1.6.0",
|
"sockjs-client": "^1.6.0",
|
||||||
@ -62,6 +63,7 @@
|
|||||||
"eslint-plugin-vue": "^7.0.0",
|
"eslint-plugin-vue": "^7.0.0",
|
||||||
"husky": "^7.0.4",
|
"husky": "^7.0.4",
|
||||||
"lint-staged": "^12.1.3",
|
"lint-staged": "^12.1.3",
|
||||||
|
"monaco-editor-webpack-plugin": "^4.1.2",
|
||||||
"node-sass": "^6.0.1",
|
"node-sass": "^6.0.1",
|
||||||
"postcss-html": "^1.3.0",
|
"postcss-html": "^1.3.0",
|
||||||
"postcss-scss": "^4.0.2",
|
"postcss-scss": "^4.0.2",
|
||||||
|
@ -13,11 +13,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<router-view :key="$route.fullPath" />
|
<router-view />
|
||||||
</template>
|
</template>
|
||||||
<style>
|
<style>
|
||||||
#app {
|
#app {
|
||||||
color: var(--spp-white);
|
color: var(--spp-white);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
min-width: 1024px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
15
src/assets/icons/add_fill.svg
Normal file
15
src/assets/icons/add_fill.svg
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License. -->
|
||||||
|
<svg t="1655799536378" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9286" width="48" height="48"><path d="M563.2 614.4v51.2c0 30.72-20.48 51.2-51.2 51.2s-51.2-20.48-51.2-51.2v-51.2H409.6c-30.72 0-51.2-20.48-51.2-51.2s20.48-51.2 51.2-51.2h51.2V460.8c0-30.72 20.48-51.2 51.2-51.2s51.2 20.48 51.2 51.2v51.2h51.2c30.72 0 51.2 20.48 51.2 51.2s-20.48 51.2-51.2 51.2h-51.2z m51.2-563.2c158.72 15.36 281.6 143.36 281.6 307.2v512c0 56.32-46.08 102.4-102.4 102.4h-563.2c-56.32 0-102.4-46.08-102.4-102.4V153.6c0-56.32 46.08-102.4 102.4-102.4H614.4z m163.84 230.4c-25.6-61.44-76.8-107.52-138.24-122.88v71.68c0 30.72 20.48 51.2 51.2 51.2h87.04zM537.6 153.6h-256c-30.72 0-51.2 20.48-51.2 51.2v614.4c0 30.72 20.48 51.2 51.2 51.2h460.8c30.72 0 51.2-20.48 51.2-51.2V384h-153.6c-56.32 0-102.4-46.08-102.4-102.4V153.6z" fill="#707070" p-id="9287"></path></svg>
|
After Width: | Height: | Size: 1.6 KiB |
16
src/assets/icons/demand.svg
Normal file
16
src/assets/icons/demand.svg
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License. -->
|
||||||
|
|
||||||
|
<svg t="1654161407133" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1721" width="16" height="16"><path d="M804.224 86.144c0-19.264-15.616-34.944-34.944-34.944l-734.336 0c-19.264 0-34.944 15.68-34.944 34.944l0 82.048 804.224 0 0-82.048zM738.88 602.432c0 47.072-38.176 85.248-85.248 85.248s-85.248-38.176-85.248-85.248c0-47.072 38.176-85.248 85.248-85.248s85.248 38.176 85.248 85.248zM804.992 264.64l0-62.976-804.224 0 0 665.408c0 18.56 14.656 33.472 32.96 34.56l402.24 0c61.12 44.544 136.192 71.168 217.664 71.168 204.544 0 370.368-165.824 370.368-370.368 0-150.592-89.984-279.936-219.008-337.792zM412.096 298.24l30.528 0c-10.624 7.36-20.8 15.36-30.528 23.744l0-23.744zM63.04 298.24l153.024 0 0 153.024-153.024 0 0-153.024zM216.064 805.056l-153.024 0 0-153.024 153.024 0 0 153.024zM219.136 631.232l-153.024 0 0-153.024 153.024 0 0 153.024zM237.568 805.056l0-153.024 49.408 0c7.488 55.936 27.264 107.904 56.832 153.024l-106.24 0zM284.672 631.232l-44.032 0 0-153.024 64.384 0c-13.824 38.848-21.824 80.576-21.824 124.224 0 9.728 0.768 19.264 1.472 28.8zM390.592 341.76c-31.168 31.424-56.512 68.544-74.88 109.44l-78.144 0 0-152.96 153.024 0 0 43.52zM899.136 638.4l-63.36 12.864c-4.288 16.064-10.688 31.296-18.816 45.376l35.712 53.888-50.944 50.944-53.888-35.712c-14.08 8.128-29.312 14.528-45.376 18.816l-12.864 63.36-72 0-12.864-63.36c-16.064-4.288-31.296-10.688-45.376-18.816l-53.888 35.712-50.944-50.944 35.712-53.888c-8.128-14.08-14.528-29.312-18.816-45.376l-63.36-12.864 0-72 63.36-12.864c4.352-16.064 10.688-31.296 18.816-45.312l-35.712-53.952 50.944-50.944 53.888 35.776c14.08-8.128 29.312-14.464 45.376-18.816l12.864-63.36 72 0 12.864 63.36c16.064 4.288 31.296 10.688 45.376 18.816l53.888-35.712 50.944 50.944-35.712 53.824c8.128 14.08 14.528 29.312 18.816 45.376l63.36 12.864 0 72z" p-id="1722" fill="#707070"></path></svg>
|
After Width: | Height: | Size: 2.6 KiB |
15
src/assets/icons/event.svg
Normal file
15
src/assets/icons/event.svg
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License. -->
|
||||||
|
<svg t="1655695739627" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2218" width="48" height="48"><path d="M173.292308 177.230769C86.646154 265.846154 39.384615 382.030769 39.384615 504.123077 39.384615 531.692308 61.046154 551.384615 86.646154 551.384615s47.261538-21.661538 47.261538-47.261538c-1.969231-96.492308 37.415385-189.046154 106.338462-257.969231s163.446154-106.338462 257.969231-106.338461c27.569231 0 47.261538-21.661538 47.261538-47.261539 0-27.569231-21.661538-47.261538-47.261538-47.261538C378.092308 43.323077 259.938462 90.584615 173.292308 177.230769z m57.107692 326.892308c0 27.569231 19.692308 47.261538 47.261538 47.261538s47.261538-21.661538 47.261539-47.261538c0-45.292308 17.723077-90.584615 51.2-122.092308 33.476923-33.476923 76.8-49.230769 122.092308-51.2 27.569231 0 47.261538-21.661538 47.261538-47.261538 0-27.569231-19.692308-47.261538-47.261538-47.261539-70.892308 0-139.815385 27.569231-191.015385 76.8-7.876923 9.846154-80.738462 82.707692-76.8 191.015385z m665.6-204.8c-17.723077-23.630769-41.353846-51.2-45.292308-55.138462-5.907692-3.938462-13.784615-7.876923-21.661538-7.876923-7.876923 0-15.753846 1.969231-19.692308 7.876923L610.461538 441.107692c-47.261538-39.384615-118.153846-37.415385-163.446153 7.876923-45.292308 45.292308-47.261538 116.184615-7.876923 163.446154l-191.015385 191.015385c-5.907692 5.907692-9.846154 13.784615-9.846154 21.661538 0 9.846154 3.938462 19.692308 11.815385 25.6l53.16923 39.384616c72.861538 57.107692 163.446154 88.615385 259.938462 88.615384 232.369231 0 421.415385-189.046154 421.415385-421.415384 0-94.523077-33.476923-185.107692-88.615385-257.969231z" p-id="2219" fill="#707070"></path></svg>
|
After Width: | Height: | Size: 2.4 KiB |
@ -247,7 +247,7 @@ limitations under the License. -->
|
|||||||
(state.showMinutes = state.showSeconds = false)
|
(state.showMinutes = state.showSeconds = false)
|
||||||
"
|
"
|
||||||
:class="{ on: state.showHours }"
|
:class="{ on: state.showHours }"
|
||||||
>{{ state.hour || dd }}</a
|
>{{ dd(state.hour) }}</a
|
||||||
>
|
>
|
||||||
<span>:</span>
|
<span>:</span>
|
||||||
<a
|
<a
|
||||||
@ -257,7 +257,7 @@ limitations under the License. -->
|
|||||||
(state.showHours = state.showSeconds = false)
|
(state.showHours = state.showSeconds = false)
|
||||||
"
|
"
|
||||||
:class="{ on: state.showMinutes }"
|
:class="{ on: state.showMinutes }"
|
||||||
>{{ state.minute || dd }}</a
|
>{{ dd(state.minute) }}</a
|
||||||
>
|
>
|
||||||
<span v-show="state.m !== 'D'">
|
<span v-show="state.m !== 'D'">
|
||||||
<span>:</span>
|
<span>:</span>
|
||||||
@ -268,7 +268,7 @@ limitations under the License. -->
|
|||||||
(state.showHours = state.showMinutes = false)
|
(state.showHours = state.showMinutes = false)
|
||||||
"
|
"
|
||||||
:class="{ on: state.showSeconds }"
|
:class="{ on: state.showSeconds }"
|
||||||
>{{ state.second || dd }}</a
|
>{{ dd(state.second) }}</a
|
||||||
>
|
>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -464,7 +464,6 @@ const status = (
|
|||||||
const minutes = time.getMinutes();
|
const minutes = time.getMinutes();
|
||||||
const seconds = time.getSeconds();
|
const seconds = time.getSeconds();
|
||||||
const milliseconds = time.getMilliseconds();
|
const milliseconds = time.getMilliseconds();
|
||||||
const dd = (t: number) => `0${t}`.slice(-2);
|
|
||||||
const map: { [key: string]: string | number } = {
|
const map: { [key: string]: string | number } = {
|
||||||
YYYY: year,
|
YYYY: year,
|
||||||
MM: dd(month + 1),
|
MM: dd(month + 1),
|
||||||
|
@ -53,9 +53,6 @@ const available = computed(
|
|||||||
(Array.isArray(props.option.series.data) && props.option.series.data[0])
|
(Array.isArray(props.option.series.data) && props.option.series.data[0])
|
||||||
);
|
);
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
if (!available.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await setOptions(props.option);
|
await setOptions(props.option);
|
||||||
chartRef.value && addResizeListener(unref(chartRef), resize);
|
chartRef.value && addResizeListener(unref(chartRef), resize);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -23,19 +23,31 @@ export enum TimeType {
|
|||||||
export const Languages = [
|
export const Languages = [
|
||||||
{ label: "English", value: "en" },
|
{ label: "English", value: "en" },
|
||||||
{ label: "Chinese", value: "zh" },
|
{ label: "Chinese", value: "zh" },
|
||||||
|
{ label: "Spanish", value: "es" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const RoutesMap: { [key: string]: string } = {
|
export const RoutesMap: { [key: string]: string } = {
|
||||||
GeneralServices: "GENERAL",
|
GeneralServices: "GENERAL",
|
||||||
|
GeneralServicesActiveTabIndex: "GENERAL",
|
||||||
Database: "VIRTUAL_DATABASE",
|
Database: "VIRTUAL_DATABASE",
|
||||||
|
DatabaseActiveTabIndex: "VIRTUAL_DATABASE",
|
||||||
MeshServices: "MESH",
|
MeshServices: "MESH",
|
||||||
|
MeshServicesActiveTabIndex: "MESH",
|
||||||
ControlPanel: "MESH_CP",
|
ControlPanel: "MESH_CP",
|
||||||
|
ControlPanelActiveTabIndex: "MESH_CP",
|
||||||
DataPanel: "MESH_DP",
|
DataPanel: "MESH_DP",
|
||||||
|
DataPanelActiveTabIndex: "MESH_DP",
|
||||||
Linux: "OS_LINUX",
|
Linux: "OS_LINUX",
|
||||||
SkyWalkingServer: "SO11Y_OAP",
|
SkyWalkingServer: "SO11Y_OAP",
|
||||||
|
SkyWalkingServerActiveTabIndex: "SO11Y_OAP",
|
||||||
|
SatelliteActiveTabIndex: "SO11Y_SATELLITE",
|
||||||
Satellite: "SO11Y_SATELLITE",
|
Satellite: "SO11Y_SATELLITE",
|
||||||
Functions: "FAAS",
|
Functions: "FAAS",
|
||||||
|
FunctionsActiveTabIndex: "FAAS",
|
||||||
Browser: "BROWSER",
|
Browser: "BROWSER",
|
||||||
|
BrowserActiveTabIndex: "BROWSER",
|
||||||
KubernetesCluster: "K8S",
|
KubernetesCluster: "K8S",
|
||||||
|
KubernetesClusterActiveTabIndex: "K8S",
|
||||||
KubernetesService: "K8S_SERVICE",
|
KubernetesService: "K8S_SERVICE",
|
||||||
|
KubernetesServiceActiveTabIndex: "K8S_SERVICE",
|
||||||
};
|
};
|
||||||
|
@ -45,6 +45,5 @@ export const Alarm = {
|
|||||||
endTime
|
endTime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
total
|
|
||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
|
36
src/graphql/fragments/demand-log.ts
Normal file
36
src/graphql/fragments/demand-log.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const queryContainers = {
|
||||||
|
variable: "$condition: OndemandContainergQueryCondition!",
|
||||||
|
query: `
|
||||||
|
containers: listContainers(condition: $condition) {
|
||||||
|
errorReason
|
||||||
|
containers
|
||||||
|
}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const queryStreamingLogs = {
|
||||||
|
variable: "$condition: OndemandLogQueryCondition",
|
||||||
|
query: `
|
||||||
|
logs: ondemandPodLogs(condition: $condition) {
|
||||||
|
errorReason
|
||||||
|
logs {
|
||||||
|
content
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
};
|
@ -48,9 +48,9 @@ export const queryEBPFTasks = {
|
|||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
export const queryEBPFSchedules = {
|
export const queryEBPFSchedules = {
|
||||||
variable: "$taskId: ID!, $duration: Duration!",
|
variable: "$taskId: ID!",
|
||||||
query: `
|
query: `
|
||||||
eBPFSchedules: queryEBPFProfilingSchedules(taskId: $taskId, duration: $duration) {
|
eBPFSchedules: queryEBPFProfilingSchedules(taskId: $taskId) {
|
||||||
scheduleId
|
scheduleId
|
||||||
taskId
|
taskId
|
||||||
process {
|
process {
|
||||||
@ -60,7 +60,6 @@ export const queryEBPFSchedules = {
|
|||||||
serviceName
|
serviceName
|
||||||
instanceId
|
instanceId
|
||||||
instanceName
|
instanceName
|
||||||
layer
|
|
||||||
agentId
|
agentId
|
||||||
detectType
|
detectType
|
||||||
attributes {
|
attributes {
|
||||||
@ -76,9 +75,9 @@ export const queryEBPFSchedules = {
|
|||||||
|
|
||||||
export const analysisEBPFResult = {
|
export const analysisEBPFResult = {
|
||||||
variable:
|
variable:
|
||||||
"$scheduleIdList: [ID!]!, $timeRanges: [EBPFProfilingAnalyzeTimeRange!]!",
|
"$scheduleIdList: [ID!]!, $timeRanges: [EBPFProfilingAnalyzeTimeRange!]!, $aggregateType: EBPFProfilingAnalyzeAggregateType",
|
||||||
query: `
|
query: `
|
||||||
analysisEBPFResult: analysisEBPFProfilingResult(scheduleIdList: $scheduleIdList, timeRanges: $timeRanges) {
|
analysisEBPFResult: analysisEBPFProfilingResult(scheduleIdList: $scheduleIdList, timeRanges: $timeRanges, aggregateType: $aggregateType) {
|
||||||
tip
|
tip
|
||||||
trees {
|
trees {
|
||||||
elements {
|
elements {
|
||||||
|
@ -35,6 +35,5 @@ export const FetchEvents = {
|
|||||||
startTime
|
startTime
|
||||||
endTime
|
endTime
|
||||||
}
|
}
|
||||||
total
|
|
||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
|
@ -30,7 +30,6 @@ export const QueryBrowserErrorLogs = {
|
|||||||
stack
|
stack
|
||||||
grade
|
grade
|
||||||
}
|
}
|
||||||
total
|
|
||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -54,7 +53,6 @@ export const QueryServiceLogs = {
|
|||||||
value
|
value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
total
|
|
||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,3 +61,15 @@ export const QueryLogsByKeywords = {
|
|||||||
query: `
|
query: `
|
||||||
support: supportQueryLogsByKeywords`,
|
support: supportQueryLogsByKeywords`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const LogTagKeys = {
|
||||||
|
variable: "$duration: Duration!",
|
||||||
|
query: `
|
||||||
|
tagKeys: queryLogTagAutocompleteKeys(duration: $duration)`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LogTagValues = {
|
||||||
|
variable: "$tagKey: String!, $duration: Duration!",
|
||||||
|
query: `
|
||||||
|
tagValues: queryLogTagAutocompleteValues(tagKey: $tagKey, duration: $duration)`,
|
||||||
|
};
|
||||||
|
@ -41,7 +41,6 @@ export const Instances = {
|
|||||||
label: name
|
label: name
|
||||||
language
|
language
|
||||||
instanceUUID
|
instanceUUID
|
||||||
layer
|
|
||||||
attributes {
|
attributes {
|
||||||
name
|
name
|
||||||
value
|
value
|
||||||
@ -83,7 +82,6 @@ export const getInstance = {
|
|||||||
label: name
|
label: name
|
||||||
language
|
language
|
||||||
instanceUUID
|
instanceUUID
|
||||||
layer
|
|
||||||
attributes {
|
attributes {
|
||||||
name
|
name
|
||||||
value
|
value
|
||||||
|
@ -27,7 +27,6 @@ export const Traces = {
|
|||||||
isError
|
isError
|
||||||
traceIds
|
traceIds
|
||||||
}
|
}
|
||||||
total
|
|
||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -74,3 +73,14 @@ export const TraceSpans = {
|
|||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
export const TraceTagKeys = {
|
||||||
|
variable: "$duration: Duration!",
|
||||||
|
query: `
|
||||||
|
tagKeys: queryTraceTagAutocompleteKeys(duration: $duration)`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TraceTagValues = {
|
||||||
|
variable: "$tagKey: String!, $duration: Duration!",
|
||||||
|
query: `
|
||||||
|
tagValues: queryTraceTagAutocompleteValues(tagKey: $tagKey, duration: $duration)`,
|
||||||
|
};
|
||||||
|
@ -26,6 +26,7 @@ import * as profile from "./query/profile";
|
|||||||
import * as alarm from "./query/alarm";
|
import * as alarm from "./query/alarm";
|
||||||
import * as event from "./query/event";
|
import * as event from "./query/event";
|
||||||
import * as ebpf from "./query/ebpf";
|
import * as ebpf from "./query/ebpf";
|
||||||
|
import * as demandLog from "./query/demand-log";
|
||||||
|
|
||||||
const query: { [key: string]: string } = {
|
const query: { [key: string]: string } = {
|
||||||
...app,
|
...app,
|
||||||
@ -38,6 +39,7 @@ const query: { [key: string]: string } = {
|
|||||||
...alarm,
|
...alarm,
|
||||||
...event,
|
...event,
|
||||||
...ebpf,
|
...ebpf,
|
||||||
|
...demandLog,
|
||||||
};
|
};
|
||||||
class Graphql {
|
class Graphql {
|
||||||
private queryData = "";
|
private queryData = "";
|
||||||
|
22
src/graphql/query/demand-log.ts
Normal file
22
src/graphql/query/demand-log.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { queryContainers, queryStreamingLogs } from "../fragments/demand-log";
|
||||||
|
|
||||||
|
export const fetchContainers = `query listContainers(${queryContainers.variable}) {${queryContainers.query}}`;
|
||||||
|
|
||||||
|
export const fetchDemandPodLogs = `query ondemandPodLogs(${queryStreamingLogs.variable}) {${queryStreamingLogs.query}}`;
|
@ -19,9 +19,13 @@ import {
|
|||||||
QueryBrowserErrorLogs,
|
QueryBrowserErrorLogs,
|
||||||
QueryServiceLogs,
|
QueryServiceLogs,
|
||||||
QueryLogsByKeywords,
|
QueryLogsByKeywords,
|
||||||
|
LogTagValues,
|
||||||
|
LogTagKeys,
|
||||||
} from "../fragments/log";
|
} from "../fragments/log";
|
||||||
|
|
||||||
export const queryBrowserErrorLogs = `query queryBrowserErrorLogs(${QueryBrowserErrorLogs.variable}) {
|
export const queryBrowserErrorLogs = `query queryBrowserErrorLogs(${QueryBrowserErrorLogs.variable}) {
|
||||||
${QueryBrowserErrorLogs.query}}`;
|
${QueryBrowserErrorLogs.query}}`;
|
||||||
export const queryServiceLogs = `query queryLogs(${QueryServiceLogs.variable}) {${QueryServiceLogs.query}}`;
|
export const queryServiceLogs = `query queryLogs(${QueryServiceLogs.variable}) {${QueryServiceLogs.query}}`;
|
||||||
export const queryLogsByKeywords = `query queryLogsByKeywords {${QueryLogsByKeywords.query}}`;
|
export const queryLogsByKeywords = `query queryLogsByKeywords {${QueryLogsByKeywords.query}}`;
|
||||||
|
export const queryLogTagValues = `query queryTagValues(${LogTagValues.variable}) {${LogTagValues.query}}`;
|
||||||
|
export const queryLogTagKeys = `query queryTagKeys(${LogTagKeys.variable}) {${LogTagKeys.query}}`;
|
||||||
|
@ -15,8 +15,17 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Traces, TraceSpans } from "../fragments/trace";
|
import {
|
||||||
|
Traces,
|
||||||
|
TraceSpans,
|
||||||
|
TraceTagKeys,
|
||||||
|
TraceTagValues,
|
||||||
|
} from "../fragments/trace";
|
||||||
|
|
||||||
export const queryTraces = `query queryTraces(${Traces.variable}) {${Traces.query}}`;
|
export const queryTraces = `query queryTraces(${Traces.variable}) {${Traces.query}}`;
|
||||||
|
|
||||||
export const queryTrace = `query queryTrace(${TraceSpans.variable}) {${TraceSpans.query}}`;
|
export const queryTrace = `query queryTrace(${TraceSpans.variable}) {${TraceSpans.query}}`;
|
||||||
|
|
||||||
|
export const queryTraceTagKeys = `query queryTraceTagKeys(${TraceTagKeys.variable}) {${TraceTagKeys.query}}`;
|
||||||
|
|
||||||
|
export const queryTraceTagValues = `query queryTraceTagValues(${TraceTagValues.variable}) {${TraceTagValues.query}}`;
|
||||||
|
@ -79,7 +79,11 @@ export function useECharts(
|
|||||||
if (!el || !unref(el)) {
|
if (!el || !unref(el)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const { width, height } = el.getBoundingClientRect();
|
||||||
|
|
||||||
|
if (!width || !height) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
chartInstance = echarts.init(el, t);
|
chartInstance = echarts.init(el, t);
|
||||||
const { removeEvent } = useEventListener({
|
const { removeEvent } = useEventListener({
|
||||||
el: window,
|
el: window,
|
||||||
|
@ -331,7 +331,7 @@ export function useQueryTopologyMetrics(metrics: string[], ids: string[]) {
|
|||||||
}
|
}
|
||||||
function calculateExp(
|
function calculateExp(
|
||||||
arr: { value: number }[],
|
arr: { value: number }[],
|
||||||
config: { calculation: string }
|
config: { calculation?: string }
|
||||||
): (number | string)[] {
|
): (number | string)[] {
|
||||||
const sum = arr
|
const sum = arr
|
||||||
.map((d: { value: number }) => d.value)
|
.map((d: { value: number }) => d.value)
|
||||||
@ -356,7 +356,7 @@ function calculateExp(
|
|||||||
|
|
||||||
export function aggregation(
|
export function aggregation(
|
||||||
val: number,
|
val: number,
|
||||||
config: { calculation: string }
|
config: { calculation?: string }
|
||||||
): number | string {
|
): number | string {
|
||||||
let data: number | string = Number(val);
|
let data: number | string = Number(val);
|
||||||
|
|
||||||
|
@ -13,7 +13,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div class="nav-bar flex-h" :class="{ dark: theme === 'dark' }" v-if="$route.query['portal'] !== 'true'">
|
<div
|
||||||
|
class="nav-bar flex-h"
|
||||||
|
:class="{ dark: theme === 'dark' }"
|
||||||
|
v-if="$route.query['portal'] !== 'true'"
|
||||||
|
>
|
||||||
<div class="title">{{ appStore.pageTitle || t(pageName) }}</div>
|
<div class="title">{{ appStore.pageTitle || t(pageName) }}</div>
|
||||||
<div class="app-config">
|
<div class="app-config">
|
||||||
<span class="red" v-show="timeRange">{{ t("timeTips") }}</span>
|
<span class="red" v-show="timeRange">{{ t("timeTips") }}</span>
|
||||||
@ -94,9 +98,6 @@ watch(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
async function getVersion() {
|
async function getVersion() {
|
||||||
if (appStore.version) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const res = await appStore.fetchVersion();
|
const res = await appStore.fetchVersion();
|
||||||
if (res.errors) {
|
if (res.errors) {
|
||||||
ElMessage.error(res.errors);
|
ElMessage.error(res.errors);
|
||||||
|
@ -41,7 +41,7 @@ limitations under the License. -->
|
|||||||
<el-icon class="menu-icons" :style="{ marginRight: '12px' }">
|
<el-icon class="menu-icons" :style="{ marginRight: '12px' }">
|
||||||
<Icon size="lg" :iconName="menu.meta.icon" />
|
<Icon size="lg" :iconName="menu.meta.icon" />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
<span :class="isCollapse ? 'collapse' : ''">
|
<span class="title" :class="isCollapse ? 'collapse' : ''">
|
||||||
{{ t(menu.meta.title) }}
|
{{ t(menu.meta.title) }}
|
||||||
</span>
|
</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
@ -55,9 +55,9 @@ limitations under the License. -->
|
|||||||
<router-link
|
<router-link
|
||||||
class="items"
|
class="items"
|
||||||
:to="m.path"
|
:to="m.path"
|
||||||
:exact="m.meta.exact || false"
|
:exact="(m.meta && m.meta.exact) || false"
|
||||||
>
|
>
|
||||||
<span>{{ t(m.meta.title) }}</span>
|
<span class="title">{{ m.meta && t(m.meta.title) }}</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</el-menu-item-group>
|
</el-menu-item-group>
|
||||||
@ -82,7 +82,7 @@ limitations under the License. -->
|
|||||||
:to="menu.children[0].path"
|
:to="menu.children[0].path"
|
||||||
:exact="menu.meta.exact"
|
:exact="menu.meta.exact"
|
||||||
>
|
>
|
||||||
<span>{{ t(menu.meta.title) }}</span>
|
<span class="title">{{ t(menu.meta.title) }}</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
@ -109,8 +109,9 @@ import { computed, ref } from "vue";
|
|||||||
import { useRouter, RouteRecordRaw, useRoute } from "vue-router";
|
import { useRouter, RouteRecordRaw, useRoute } from "vue-router";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import Icon from "@/components/Icon.vue";
|
import Icon from "@/components/Icon.vue";
|
||||||
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
|
|
||||||
const { path, query } = useRoute();
|
const { query } = useRoute();
|
||||||
|
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
let portalStyle = reactive({});
|
let portalStyle = reactive({});
|
||||||
@ -126,13 +127,19 @@ if (query["portal"] === "true") {
|
|||||||
const isPortalView = computed(() => {
|
const isPortalView = computed(() => {
|
||||||
return query["portal"] === "true";
|
return query["portal"] === "true";
|
||||||
});
|
});
|
||||||
|
const appStore = useAppStoreWithOut();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const name = ref<any>(String(useRouter().currentRoute.value.name));
|
const name = ref<string>(String(useRouter().currentRoute.value.name));
|
||||||
const theme = ["VirtualMachine", "Kubernetes"].includes(name.value || "")
|
const theme = ["VirtualMachine", "Kubernetes"].includes(name.value || "")
|
||||||
? ref("light")
|
? ref("light")
|
||||||
: ref("black");
|
: ref("black");
|
||||||
const routes = ref<any>(useRouter().options.routes);
|
const routes = ref<RouteRecordRaw[] | any>(useRouter().options.routes);
|
||||||
const isCollapse = ref(query["portal"] === "true");
|
if (/Android|webOS|iPhone|iPod|iPad|BlackBerry/i.test(navigator.userAgent)) {
|
||||||
|
appStore.setIsMobile(true);
|
||||||
|
} else {
|
||||||
|
appStore.setIsMobile(false);
|
||||||
|
}
|
||||||
|
const isCollapse = ref(appStore.isMobile ? true : false);
|
||||||
const controlMenu = () => {
|
const controlMenu = () => {
|
||||||
isCollapse.value = !isCollapse.value;
|
isCollapse.value = !isCollapse.value;
|
||||||
};
|
};
|
||||||
@ -216,4 +223,11 @@ span.collapse {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 110px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -17,10 +17,12 @@
|
|||||||
import { createI18n } from "vue-i18n";
|
import { createI18n } from "vue-i18n";
|
||||||
import zh from "./lang/zh";
|
import zh from "./lang/zh";
|
||||||
import en from "./lang/en";
|
import en from "./lang/en";
|
||||||
|
import es from "./lang/es";
|
||||||
|
|
||||||
const messages = {
|
const messages = {
|
||||||
en,
|
en,
|
||||||
zh,
|
zh,
|
||||||
|
es,
|
||||||
};
|
};
|
||||||
|
|
||||||
const savedLanguage = window.localStorage.getItem("language");
|
const savedLanguage = window.localStorage.getItem("language");
|
||||||
|
@ -134,8 +134,15 @@ const msg = {
|
|||||||
taskId: "Task ID",
|
taskId: "Task ID",
|
||||||
triggerType: "Trigger Type",
|
triggerType: "Trigger Type",
|
||||||
targetType: "Target Type",
|
targetType: "Target Type",
|
||||||
ebpfTip: "Don't have process could profiling",
|
ebpfTip: "Don't have a process for profiling",
|
||||||
processSelect: "Click to select processes",
|
processSelect: "Click to select processes",
|
||||||
|
container: "Container",
|
||||||
|
limit: "Limit",
|
||||||
|
page: "Page",
|
||||||
|
interval: "Refresh Interval",
|
||||||
|
pause: "Pause",
|
||||||
|
begin: "Start",
|
||||||
|
seconds: "Seconds",
|
||||||
hourTip: "Select Hour",
|
hourTip: "Select Hour",
|
||||||
minuteTip: "Select Minute",
|
minuteTip: "Select Minute",
|
||||||
secondTip: "Select Second",
|
secondTip: "Select Second",
|
||||||
@ -154,7 +161,7 @@ const msg = {
|
|||||||
dashboard: "Dashboard",
|
dashboard: "Dashboard",
|
||||||
topology: "Topology",
|
topology: "Topology",
|
||||||
trace: "Trace",
|
trace: "Trace",
|
||||||
alarm: "Alarms",
|
alarm: "Alerting",
|
||||||
auto: "Auto",
|
auto: "Auto",
|
||||||
reload: "Reload",
|
reload: "Reload",
|
||||||
version: "Version",
|
version: "Version",
|
||||||
@ -327,7 +334,7 @@ const msg = {
|
|||||||
addExcludingKeywordsOfContent: "Please input a keyword of excluding content",
|
addExcludingKeywordsOfContent: "Please input a keyword of excluding content",
|
||||||
noticeTag: "Please press Enter after inputting a tag(key=value).",
|
noticeTag: "Please press Enter after inputting a tag(key=value).",
|
||||||
conditionNotice:
|
conditionNotice:
|
||||||
"Notice: Please press Enter after inputting a tag, key of content, exclude key of content(key=value).",
|
"Notice: Please press Enter after inputting a key of content, exclude key of content(key=value).",
|
||||||
language: "Language",
|
language: "Language",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
342
src/locales/lang/es.ts
Normal file
342
src/locales/lang/es.ts
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
const msg = {
|
||||||
|
general: "Servicio General",
|
||||||
|
services: "Servicios",
|
||||||
|
service: "Servicio",
|
||||||
|
traces: "Trazas",
|
||||||
|
metrics: "Métricas",
|
||||||
|
serviceMesh: "Malla de Servicios",
|
||||||
|
infrastructure: "Infraestructura",
|
||||||
|
virtualMachine: "Máquina Virtual",
|
||||||
|
dashboardNew: "Nuevo Panel",
|
||||||
|
dashboardList: "Listado Paneles",
|
||||||
|
logs: "Logs",
|
||||||
|
events: "Eventos",
|
||||||
|
alerts: "Alertas",
|
||||||
|
settings: "Ajustes",
|
||||||
|
dashboards: "Paneles",
|
||||||
|
profiles: "Perfiles",
|
||||||
|
database: "Base de Datos",
|
||||||
|
serviceName: "Nombre Servicio",
|
||||||
|
technologies: "Tecnologías",
|
||||||
|
generalServicePanel: "Panel Servicio General",
|
||||||
|
health: "Salud",
|
||||||
|
groupName: "Nombre Grupo",
|
||||||
|
topologies: "Topologías",
|
||||||
|
dataPanel: "Plano de Datos",
|
||||||
|
controlPanel: "Plano de Control",
|
||||||
|
eventList: "Listado Eventos",
|
||||||
|
newDashboard: "Crear panel nuevo",
|
||||||
|
dashboardEdit: "Editar el panel",
|
||||||
|
edit: "Editar",
|
||||||
|
delete: "Eliminar",
|
||||||
|
confirm: "Confirmar",
|
||||||
|
layer: "Capa",
|
||||||
|
endpoint: "Endpoint",
|
||||||
|
instance: "Instancia",
|
||||||
|
create: "Crear",
|
||||||
|
loading: "Cargando",
|
||||||
|
selectVisualization: "Visualiza tus métricas",
|
||||||
|
visualization: "Visualizaciones",
|
||||||
|
graphStyles: "Estilo de gráficas",
|
||||||
|
widgetOptions: "Opciones widget",
|
||||||
|
standardOptions: "Opciones estandar",
|
||||||
|
max: "Máx",
|
||||||
|
min: "Mín",
|
||||||
|
plus: "Más",
|
||||||
|
minus: "Menoss",
|
||||||
|
multiply: "Multiplcar",
|
||||||
|
divide: "Dividir",
|
||||||
|
convertToMilliseconds: "Convertir Unix Timestamp(milisegundos)",
|
||||||
|
convertToSeconds: "Convertir Unix Timestamp(segundos)",
|
||||||
|
smooth: "Suabe",
|
||||||
|
showSymbol: "Mostrar Símbolo",
|
||||||
|
step: "Paso",
|
||||||
|
showValues: "Mostrar Valores",
|
||||||
|
fontSize: "Tamaño Fuente",
|
||||||
|
showBackground: "Mostrar Fondo",
|
||||||
|
areaOpacity: "Opacidad Área",
|
||||||
|
editGraph: "Editar Opciones",
|
||||||
|
dashboardName: "Selecciona Nombre del Panel",
|
||||||
|
linkDashboard: "Nombre del panel relacionado con llamadas de la topología",
|
||||||
|
linkServerMetrics:
|
||||||
|
"Métricas de servidor relacionadas con llamadas de la topología",
|
||||||
|
linkClientMetrics:
|
||||||
|
"Métricas de cliente relacionadas con llamadas de la topología",
|
||||||
|
nodeDashboard: "Nombre del panel relacionado con nodos de la topología",
|
||||||
|
nodeMetrics: "Mêtricas relacionas con nodos de la topología",
|
||||||
|
instanceDashboard: "Nombre del panel relacionado con instancias de servicio",
|
||||||
|
endpointDashboard: "Nombre del panel relacionado con endpoints",
|
||||||
|
callSettings: "Ajustes Llamada",
|
||||||
|
nodeSettings: "Ajustes Nodo",
|
||||||
|
conditions: "Condiciones",
|
||||||
|
legendSettings: "Ajustes Leyenda",
|
||||||
|
setLegend: "Poner Leyenda",
|
||||||
|
backgroundColors: "Colores Fondo",
|
||||||
|
fontColors: "Colores Fuente",
|
||||||
|
iconTheme: "Tema Iconos",
|
||||||
|
default: "Por Defecto",
|
||||||
|
topSlow: "Top 5 lentos",
|
||||||
|
topChildren: "Top 5 hijos",
|
||||||
|
taskList: "Listado Tareas",
|
||||||
|
sampledTraces: "Trazas Muestreadas",
|
||||||
|
editTab: "Habilitar edición nombre pestanyas",
|
||||||
|
label: "Nombre Servicio",
|
||||||
|
id: "ID Servicio",
|
||||||
|
setRoot: "Ponerlo a raíz",
|
||||||
|
setNormal: "Ponerlo a normal",
|
||||||
|
export: "Exportar Plantilla Panel",
|
||||||
|
import: "Importar Plantilla Panel",
|
||||||
|
yes: "Sí",
|
||||||
|
no: "No",
|
||||||
|
tableHeaderCol1: "Nombre de la primera columna de la tabla",
|
||||||
|
tableHeaderCol2: "Nombre de la segunda columna de la tabla",
|
||||||
|
showXAxis: "Mostrar Eje X",
|
||||||
|
showYAxis: "Mostrar Eje Y",
|
||||||
|
nameError: "El nombre del panel no puede ser duplicado",
|
||||||
|
showGroup: "Mostrar Grupo",
|
||||||
|
noRoot: "Por favor ponga la raíz del panel",
|
||||||
|
noWidget: "Por favor añada widgets.",
|
||||||
|
rename: "Renombrar",
|
||||||
|
deleteTitle: "¿Está seguro que quiere eliminarlo?",
|
||||||
|
rootTitle: "¿Está seguro que quiere establecerlo?",
|
||||||
|
selfObservability: "Autoobservabilidad",
|
||||||
|
satellite: "Satéllite",
|
||||||
|
skyWalkingServer: "Servidor SkyWalking",
|
||||||
|
functions: "Funciones",
|
||||||
|
browser: "Navegador",
|
||||||
|
linux: "Linux",
|
||||||
|
editWarning: "Estás entrando en modo edición",
|
||||||
|
viewWarning: "Estás entrando en modo visualización",
|
||||||
|
virtualDatabase: "Base de Datos Virtual",
|
||||||
|
reloadDashboards: "Recargar Panel",
|
||||||
|
kubernetesService: "Servicio",
|
||||||
|
kubernetesCluster: "Cluster",
|
||||||
|
kubernetes: "Kubernetes",
|
||||||
|
textUrl: "Hipervínculo de Texto",
|
||||||
|
textAlign: "Alineación de Texto",
|
||||||
|
metricLabel: "Etiqueta de Métrica",
|
||||||
|
showUnit: "Mostrar Unidad",
|
||||||
|
noGraph: "Ningún Gráfico",
|
||||||
|
taskId: "ID Tarea",
|
||||||
|
triggerType: "Tipo de Disparador",
|
||||||
|
targetType: "Tipo de Objetivo",
|
||||||
|
ebpfTip: "Le falta el proceso para perfilar",
|
||||||
|
processSelect: "Click para seleccionar proceso",
|
||||||
|
page: "Página",
|
||||||
|
interval: "Intervalo de actualización",
|
||||||
|
pause: "Pausa",
|
||||||
|
begin: "Inicio",
|
||||||
|
seconds: "Segundos",
|
||||||
|
hourTip: "Seleccione Hora",
|
||||||
|
minuteTip: "Seleccione Minuto",
|
||||||
|
secondTip: "Seleccione Segundo",
|
||||||
|
second: "s",
|
||||||
|
yearSuffix: "Año",
|
||||||
|
monthsHead: "Ene_Feb_Mar_Abr_May_Jun_Jul_Ago_Set_Oct_Nov_Dic",
|
||||||
|
months: "Ene_Feb_Mar_Abr_May_Jun_Jul_Ago_Set_Oct_Nov_Dic",
|
||||||
|
weeks: "Lun_Mar_Mier_Jue_Vie_Sáb_Dom",
|
||||||
|
hello: "Hola",
|
||||||
|
helloMessage: "Bienvenido de vuelta, Apache SkyWalking APM System !",
|
||||||
|
username: "Usuario",
|
||||||
|
password: "Contraseña",
|
||||||
|
title: "Título",
|
||||||
|
width: "Ancho",
|
||||||
|
height: "Alto",
|
||||||
|
dashboard: "Panel",
|
||||||
|
topology: "Topología",
|
||||||
|
trace: "Traza",
|
||||||
|
alarm: "Recordatorio en curso",
|
||||||
|
auto: "Auto",
|
||||||
|
reload: "Recargar",
|
||||||
|
version: "Versión",
|
||||||
|
copy: "Copiar",
|
||||||
|
reset: "Resetear",
|
||||||
|
apply: "Aplicar",
|
||||||
|
template: "Plantilla",
|
||||||
|
cancel: "Cancelar",
|
||||||
|
createTab: "Crear Pestanya",
|
||||||
|
tabName: "Nombre de la Pestaña",
|
||||||
|
detectPoint: "Detectar Punto",
|
||||||
|
name: "Nombre",
|
||||||
|
types: "Tipos",
|
||||||
|
all: "Todo",
|
||||||
|
endpoints: "Endpoints",
|
||||||
|
cache: "Cache",
|
||||||
|
serviceinstance: "InstanciaServicio",
|
||||||
|
databaseaccess: "AccesoBaseDeDatos",
|
||||||
|
servicerelation: "RelaciónServicio",
|
||||||
|
serviceinstancerelation: "RelaciónInstanciaServicio",
|
||||||
|
endpointrelation: "RelaciónEndpoint",
|
||||||
|
status: "Estado",
|
||||||
|
endpointName: "Nombre Endpoint",
|
||||||
|
search: "Buscar",
|
||||||
|
clear: "Limpiar",
|
||||||
|
more: "Más",
|
||||||
|
traceID: "ID Traza",
|
||||||
|
range: "Rango",
|
||||||
|
timeRange: "Rango de Tiempo",
|
||||||
|
duration: "Duración",
|
||||||
|
startTime: "Hora Inicio",
|
||||||
|
start: "Incio",
|
||||||
|
spans: "Lapso",
|
||||||
|
spanInfo: "Info Lapso",
|
||||||
|
spanType: "Tipo de Lapso",
|
||||||
|
time: "Tiempo",
|
||||||
|
tags: "Etiquetas",
|
||||||
|
component: "Componente",
|
||||||
|
table: "Tabla",
|
||||||
|
list: "Lista",
|
||||||
|
tree: "Árbol",
|
||||||
|
filterScope: "Alcance de Filtro",
|
||||||
|
searchKeyword: "Palabra Clave",
|
||||||
|
quarterHourCutTip: "Últimos 15 mins",
|
||||||
|
halfHourCutTip: "Últimos 30 mins",
|
||||||
|
hourCutTip: "Última 1 hora",
|
||||||
|
dayCutTip: "Último 1 día",
|
||||||
|
weekCutTip: "Última 1 semana",
|
||||||
|
monthCutTip: "Última 1 mes",
|
||||||
|
serverZone: "Zona Horaria Servidor OAP",
|
||||||
|
exportImage: "Exportar imagen",
|
||||||
|
object: "Objecto",
|
||||||
|
profile: "Perfil",
|
||||||
|
newTask: "Nueva Tarea",
|
||||||
|
monitorTime: "Tiempo Monitorización",
|
||||||
|
monitorDuration: "Duración Monitorización",
|
||||||
|
minThreshold: "Mínn Umbral Duración",
|
||||||
|
dumpPeriod: "Volcar Periodo",
|
||||||
|
createTask: "Crear Tarea",
|
||||||
|
maxSamplingCount: "Máx Cantidad Mostreo",
|
||||||
|
analyze: "Analizar",
|
||||||
|
noData: "Ningún Dato",
|
||||||
|
taskInfo: "Información Tarea",
|
||||||
|
task: "Tarea",
|
||||||
|
operationType: "Tipo Operación",
|
||||||
|
operationTime: "Tiempo Operación",
|
||||||
|
taskView: "Ver Tarea",
|
||||||
|
includeChildren: "Incluir Hijos",
|
||||||
|
excludeChildren: "Excluir Hijos",
|
||||||
|
view: "Ver",
|
||||||
|
timeTips: "Intervalo de tiempo no puede excedir 60 dias",
|
||||||
|
entityType: "Tipo Entidad",
|
||||||
|
maxItemNum: "Máx número artículos",
|
||||||
|
unknownMetrics: "Métrica desconocida",
|
||||||
|
labels: "Etiquetas",
|
||||||
|
aggregation: "Cálculo",
|
||||||
|
unit: "Unidad",
|
||||||
|
labelsIndex: "Subíndice Etiqueta",
|
||||||
|
group: "Grupo Servicio",
|
||||||
|
browserView: "Navegador",
|
||||||
|
sortOrder: "Orden de clasificación",
|
||||||
|
chartType: "Tipo Gráfico",
|
||||||
|
currentDepth: "Profundidad actual",
|
||||||
|
showDepth: "Mostrar Selector Profundidad",
|
||||||
|
defaultDepth: "Profundidad Por Defecto",
|
||||||
|
traceTagsTip: `Solamente etiquetas definidas en core/default/searchableTracesTags pueden ser buscadas.
|
||||||
|
Más información en la página de Vocabulario de Configuración`,
|
||||||
|
logTagsTip: `Solamente etiquetas definidas en core/default/searchableLogsTags pueden ser buscadas.
|
||||||
|
Más información en la página de Vocabulario de Configuración`,
|
||||||
|
alarmTagsTip: `Solamente etiquetas definidas en core/default/searchableAlarmTags pueden ser buscadas.
|
||||||
|
Más información en la página de Vocabulario de Configuración`,
|
||||||
|
tagsLink: "Página de Vocabulario de Configuración",
|
||||||
|
addTag: "Por favor introduzca una etiqueta",
|
||||||
|
log: "Registro de Datos",
|
||||||
|
logCategory: "Categoría Registro de Datos",
|
||||||
|
errorCatalog: "Catálogo de Errores",
|
||||||
|
logDetail: "Detalle Registro de Datos",
|
||||||
|
timeReload: "Aviso: El intervalo de tiempo tiene que ser mayor que 0",
|
||||||
|
errorInfo: "Info Error",
|
||||||
|
stack: "Pila",
|
||||||
|
serviceVersion: "Versión Servicio",
|
||||||
|
errorPage: "Página de Error",
|
||||||
|
category: "Categoría",
|
||||||
|
grade: "Grado",
|
||||||
|
relatedTraceLogs: "Registro de Datos Relacionados",
|
||||||
|
setConditions: "Más Condiciones",
|
||||||
|
metricName: "Seleccionar Nombre Métrica",
|
||||||
|
keywordsOfContent: "Claves de Contenido",
|
||||||
|
excludingKeywordsOfContent: "Excluir Claves de Contenido",
|
||||||
|
return: "Volver",
|
||||||
|
isError: "Error",
|
||||||
|
contentType: "Tipo de Contenido",
|
||||||
|
content: "Contenido",
|
||||||
|
viewLogs: "Ver Registro de Datos",
|
||||||
|
logsTagsTip: `Solamente etiquetas definidas en core/default/searchableLogsTags pueden ser buscadas.
|
||||||
|
Más información en la página de Vocabulario de Configuración`,
|
||||||
|
keywordsOfContentLogTips:
|
||||||
|
"El almacenamiento actual del servidor SkyWalking OAP no lo soporta.",
|
||||||
|
setEvent: "Establecer Evento",
|
||||||
|
viewAttributes: "Ver",
|
||||||
|
serviceEvents: "Eventos Servico",
|
||||||
|
select: "Seleccionar",
|
||||||
|
eventID: "ID Evento",
|
||||||
|
eventName: "Nombre Evento",
|
||||||
|
endTime: "Hora Finalización",
|
||||||
|
instanceEvents: "Eventos Instancia",
|
||||||
|
endpointEvents: "Eventos Endpoint",
|
||||||
|
enableEvents: "Habilitar Eventos",
|
||||||
|
disableEvents: "Deshabilitar Eventos",
|
||||||
|
eventSeries: "Serie de Eventos",
|
||||||
|
eventsType: "Tipo de Evento",
|
||||||
|
eventsMessage: "Mensaje del Evento",
|
||||||
|
eventsParameters: "Parámetro del Evento",
|
||||||
|
eventDetail: "Detalle del Evento",
|
||||||
|
value: "Valor",
|
||||||
|
show: "Mostrar",
|
||||||
|
hide: "Oculatr",
|
||||||
|
statistics: "Estadísticas",
|
||||||
|
message: "Mensaje",
|
||||||
|
tooltipsContent: "Contenido de Información de Herramienta",
|
||||||
|
alarmDetail: "Detalle Alarma",
|
||||||
|
scope: "Alcance",
|
||||||
|
destService: "Servicio Destinación",
|
||||||
|
destServiceInstance: "Instancia Servicio Destinación",
|
||||||
|
destEndpoint: "Endpoint Destinación",
|
||||||
|
eventSource: "Fuente Envento",
|
||||||
|
modalTitle: "Inspección",
|
||||||
|
selectRedirectPage:
|
||||||
|
"Quiere inspeccionar las Trazas or Registros de datos del servicio %s?",
|
||||||
|
logAnalysis: "Lenguaje de Análisis de Registro de Datos",
|
||||||
|
logDataBody: "Contenido del Registro de Datos",
|
||||||
|
addType: "Por favor introduzca un tipo",
|
||||||
|
traceContext: "Registro de datos con contexto de traza",
|
||||||
|
traceSegmentId: "ID Segmento Traza",
|
||||||
|
spanId: "ID Lapso",
|
||||||
|
inputTraceSegmentId: "Por favor introduzca el ID del segmento de la traza",
|
||||||
|
inputSpanId: "Por favor introduzca el ID del lapso",
|
||||||
|
inputTraceId: "Por favor introduzca el ID de la traza",
|
||||||
|
dsl: "Entrada de guión para LAL",
|
||||||
|
logContentType: "Tipo del registro de datos",
|
||||||
|
logRespContent: "Contenido Registro de Datos",
|
||||||
|
analysis: "Análisis",
|
||||||
|
waitLoading: "Cargando",
|
||||||
|
dslEmpty: "Entrada de guión de LAL no puede estar vacio",
|
||||||
|
logContentEmpty: "El contenido del registro de datos no puede estar vacio.",
|
||||||
|
debug: "Debugar",
|
||||||
|
addTraceID: "Por favor introduzca el ID de la traza",
|
||||||
|
addTags: "Por favor introduzaca una etiqueta",
|
||||||
|
addKeywordsOfContent: "Por favor introduzca una clave de contenido",
|
||||||
|
addExcludingKeywordsOfContent:
|
||||||
|
"Por favor introduzca una clave excluyente de contenido",
|
||||||
|
noticeTag:
|
||||||
|
"Por favor presione Intro después de introducir una etiqueta(clave=valor).",
|
||||||
|
conditionNotice:
|
||||||
|
"Aviso: Por favor presione Intro después de introducir una clave de contenido, excluir clave de contenido(clave=valor).",
|
||||||
|
language: "Lenguaje",
|
||||||
|
};
|
||||||
|
export default msg;
|
@ -134,6 +134,13 @@ const msg = {
|
|||||||
targetType: "目标类型",
|
targetType: "目标类型",
|
||||||
processSelect: "点击选择进程",
|
processSelect: "点击选择进程",
|
||||||
ebpfTip: "没有进程可以分析",
|
ebpfTip: "没有进程可以分析",
|
||||||
|
container: "容器",
|
||||||
|
limit: "范围",
|
||||||
|
page: "页面",
|
||||||
|
interval: "刷新间隔时间",
|
||||||
|
pause: "暂停",
|
||||||
|
begin: "开始",
|
||||||
|
seconds: "秒",
|
||||||
hourTip: "选择小时",
|
hourTip: "选择小时",
|
||||||
minuteTip: "选择分钟",
|
minuteTip: "选择分钟",
|
||||||
secondTip: "选择秒数",
|
secondTip: "选择秒数",
|
||||||
@ -327,7 +334,7 @@ const msg = {
|
|||||||
addExcludingKeywordsOfContent: "请输入一个内容不包含的关键词",
|
addExcludingKeywordsOfContent: "请输入一个内容不包含的关键词",
|
||||||
noticeTag: "请输入一个标签(key=value)之后回车",
|
noticeTag: "请输入一个标签(key=value)之后回车",
|
||||||
conditionNotice:
|
conditionNotice:
|
||||||
"请输入一个标签、内容关键词或者内容不包含的关键词(key=value)之后回车",
|
"请输入一个内容关键词或者内容不包含的关键词(key=value)之后回车",
|
||||||
language: "语言",
|
language: "语言",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
@ -20,11 +20,18 @@ import router from "./router";
|
|||||||
import { store } from "./store";
|
import { store } from "./store";
|
||||||
import components from "@/components";
|
import components from "@/components";
|
||||||
import i18n from "./locales";
|
import i18n from "./locales";
|
||||||
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import "./styles/index.ts";
|
import "./styles/index.ts";
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
const appStore = useAppStoreWithOut();
|
||||||
|
|
||||||
app.use(components);
|
app.use(components);
|
||||||
app.use(i18n);
|
app.use(i18n);
|
||||||
app.use(store);
|
app.use(store);
|
||||||
app.use(router).mount("#app");
|
mountApp();
|
||||||
|
|
||||||
|
async function mountApp() {
|
||||||
|
await appStore.queryOAPTimeInfo();
|
||||||
|
app.use(router).mount("#app");
|
||||||
|
}
|
||||||
|
@ -30,13 +30,13 @@ export const routesAlarm: Array<RouteRecordRaw> = [
|
|||||||
component: Layout,
|
component: Layout,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/alarm",
|
path: "/alerting",
|
||||||
name: "Alarm",
|
name: "Alarm",
|
||||||
meta: {
|
meta: {
|
||||||
exact: false,
|
exact: false,
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "alarms" */ "@/views/Alarm.vue"),
|
import(/* webpackChunkName: "alerting" */ "@/views/Alarm.vue"),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -33,12 +33,20 @@ export const routesBrowser: Array<RouteRecordRaw> = [
|
|||||||
name: "Browser",
|
name: "Browser",
|
||||||
meta: {
|
meta: {
|
||||||
title: "browser",
|
title: "browser",
|
||||||
headPath: "/browser",
|
|
||||||
exact: true,
|
exact: true,
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/browser/tab/:activeTabIndex",
|
||||||
|
name: "BrowserActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
},
|
||||||
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -53,32 +53,79 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
exact: false,
|
exact: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
redirect: "/dashboard/:layerId/:entity/:name",
|
||||||
|
name: "Create",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:name",
|
path: "/dashboard/:layerId/:entity/:name",
|
||||||
component: () =>
|
component: () =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
),
|
),
|
||||||
name: "Create",
|
name: "CreateChild",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/dashboard/:layerId/:entity/:name/tab/:activeTabIndex",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "CreateActiveTabIndex",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "View",
|
||||||
|
redirect: "/dashboard/:layerId/:entity/:serviceId/:name",
|
||||||
meta: {
|
meta: {
|
||||||
title: "dashboardEdit",
|
|
||||||
exact: false,
|
|
||||||
notShow: true,
|
notShow: true,
|
||||||
},
|
},
|
||||||
},
|
children: [
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:serviceId/:name",
|
path: "/dashboard/:layerId/:entity/:serviceId/:name",
|
||||||
component: () =>
|
component: () =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
),
|
),
|
||||||
name: "View",
|
name: "ViewChild",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/dashboard/:layerId/:entity/:serviceId/:name/tab/:activeTabIndex",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewActiveTabIndex",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
redirect:
|
||||||
|
"/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewServiceRelation",
|
||||||
meta: {
|
meta: {
|
||||||
title: "dashboardEdit",
|
|
||||||
exact: false,
|
|
||||||
notShow: true,
|
notShow: true,
|
||||||
},
|
},
|
||||||
},
|
children: [
|
||||||
{
|
{
|
||||||
path: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name",
|
path: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name",
|
||||||
component: () =>
|
component: () =>
|
||||||
@ -86,12 +133,29 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
),
|
),
|
||||||
name: "ViewServiceRelation",
|
name: "ViewServiceRelation",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name/tab/:activeTabIndex",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewServiceRelationActiveTabIndex",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
redirect: "/dashboard/:layerId/:entity/:serviceId/:podId/:name",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewPod",
|
||||||
meta: {
|
meta: {
|
||||||
title: "dashboardEdit",
|
|
||||||
exact: false,
|
|
||||||
notShow: true,
|
notShow: true,
|
||||||
},
|
},
|
||||||
},
|
children: [
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:name",
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:name",
|
||||||
component: () =>
|
component: () =>
|
||||||
@ -99,12 +163,30 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
),
|
),
|
||||||
name: "ViewPod",
|
name: "ViewPod",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:name/tab/:activeTabIndex",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewPodActiveTabIndex",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
redirect:
|
||||||
|
"/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewPodRelation",
|
||||||
meta: {
|
meta: {
|
||||||
title: "dashboardEdit",
|
|
||||||
exact: false,
|
|
||||||
notShow: true,
|
notShow: true,
|
||||||
},
|
},
|
||||||
},
|
children: [
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name",
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name",
|
||||||
component: () =>
|
component: () =>
|
||||||
@ -112,11 +194,16 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
),
|
),
|
||||||
name: "ViewPodRelation",
|
name: "ViewPodRelation",
|
||||||
meta: {
|
|
||||||
title: "dashboardEdit",
|
|
||||||
exact: true,
|
|
||||||
notShow: true,
|
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name/tab/:activeTabIndex",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewPodRelationActiveTabIndex",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -34,12 +34,20 @@ export const routesDatabase: Array<RouteRecordRaw> = [
|
|||||||
name: "Database",
|
name: "Database",
|
||||||
meta: {
|
meta: {
|
||||||
title: "virtualDatabase",
|
title: "virtualDatabase",
|
||||||
headPath: "/database",
|
|
||||||
exact: true,
|
exact: true,
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/database/tab/:activeTabIndex",
|
||||||
|
name: "DatabaseActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
},
|
||||||
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -32,13 +32,17 @@ export const routesFunctions: Array<RouteRecordRaw> = [
|
|||||||
path: "/functions",
|
path: "/functions",
|
||||||
name: "Functions",
|
name: "Functions",
|
||||||
meta: {
|
meta: {
|
||||||
title: "functions",
|
|
||||||
headPath: "/functions",
|
|
||||||
exact: true,
|
exact: true,
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/functions/tab/:activeTabIndex",
|
||||||
|
name: "FunctionsActiveTabIndex",
|
||||||
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -33,8 +33,15 @@ export const routesGen: Array<RouteRecordRaw> = [
|
|||||||
path: "/general",
|
path: "/general",
|
||||||
name: "GeneralServices",
|
name: "GeneralServices",
|
||||||
meta: {
|
meta: {
|
||||||
title: "services",
|
exact: true,
|
||||||
headPath: "/general/service",
|
},
|
||||||
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "layers" */ "@/views/Layer.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/general/tab/:activeTabIndex",
|
||||||
|
name: "GeneralServicesActiveTabIndex",
|
||||||
|
meta: {
|
||||||
exact: true,
|
exact: true,
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
|
@ -20,7 +20,6 @@ import { routesMesh } from "./serviceMesh";
|
|||||||
import { routesDatabase } from "./database";
|
import { routesDatabase } from "./database";
|
||||||
import { routesInfra } from "./infrastructure";
|
import { routesInfra } from "./infrastructure";
|
||||||
import { routesDashboard } from "./dashboard";
|
import { routesDashboard } from "./dashboard";
|
||||||
import { routesEvent } from "./event";
|
|
||||||
import { routesSetting } from "./setting";
|
import { routesSetting } from "./setting";
|
||||||
import { routesAlarm } from "./alarm";
|
import { routesAlarm } from "./alarm";
|
||||||
import { routesSelf } from "./selfObservability";
|
import { routesSelf } from "./selfObservability";
|
||||||
@ -39,7 +38,6 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
...routesSelf,
|
...routesSelf,
|
||||||
...routesDashboard,
|
...routesDashboard,
|
||||||
...routesAlarm,
|
...routesAlarm,
|
||||||
...routesEvent,
|
|
||||||
...routesSetting,
|
...routesSetting,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -39,6 +39,16 @@ export const routesInfra: Array<RouteRecordRaw> = [
|
|||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/linux/tab/:activeTabIndex",
|
||||||
|
name: "LinuxActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
title: "linux",
|
||||||
|
notShow: true,
|
||||||
|
},
|
||||||
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// path: "/infrastructure/vm",
|
// path: "/infrastructure/vm",
|
||||||
// name: "VirtualMachine",
|
// name: "VirtualMachine",
|
||||||
|
@ -33,20 +33,42 @@ export const routesK8s: Array<RouteRecordRaw> = [
|
|||||||
path: "/kubernetes/cluster",
|
path: "/kubernetes/cluster",
|
||||||
name: "KubernetesCluster",
|
name: "KubernetesCluster",
|
||||||
meta: {
|
meta: {
|
||||||
|
notShow: false,
|
||||||
title: "kubernetesCluster",
|
title: "kubernetesCluster",
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/kubernetes/cluster/tab/:activeTabIndex",
|
||||||
|
name: "KubernetesClusterActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
title: "kubernetesClusterActiveTabIndex",
|
||||||
|
},
|
||||||
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/kubernetes/service",
|
path: "/kubernetes/service",
|
||||||
name: "KubernetesService",
|
name: "KubernetesService",
|
||||||
meta: {
|
meta: {
|
||||||
|
notShow: false,
|
||||||
title: "kubernetesService",
|
title: "kubernetesService",
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/kubernetes/service/tab/:activeTabIndex",
|
||||||
|
name: "KubernetesServiceActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
title: "kubernetesServiceActiveTabIndex",
|
||||||
|
},
|
||||||
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -34,7 +34,15 @@ export const routesSelf: Array<RouteRecordRaw> = [
|
|||||||
name: "SkyWalkingServer",
|
name: "SkyWalkingServer",
|
||||||
meta: {
|
meta: {
|
||||||
title: "skyWalkingServer",
|
title: "skyWalkingServer",
|
||||||
headPath: "/mesh/services",
|
},
|
||||||
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/self/skyWalkingServer/tab/:activeTabIndex",
|
||||||
|
name: "SkyWalkingServerActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
@ -44,7 +52,15 @@ export const routesSelf: Array<RouteRecordRaw> = [
|
|||||||
name: "Satellite",
|
name: "Satellite",
|
||||||
meta: {
|
meta: {
|
||||||
title: "satellite",
|
title: "satellite",
|
||||||
headPath: "/mesh/controlPanel",
|
},
|
||||||
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/self/satellite/tab/:activeTabIndex",
|
||||||
|
name: "SatelliteActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
|
@ -33,8 +33,17 @@ export const routesMesh: Array<RouteRecordRaw> = [
|
|||||||
path: "/mesh/services",
|
path: "/mesh/services",
|
||||||
name: "MeshServices",
|
name: "MeshServices",
|
||||||
meta: {
|
meta: {
|
||||||
|
notShow: false,
|
||||||
title: "services",
|
title: "services",
|
||||||
headPath: "/mesh/services",
|
},
|
||||||
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/mesh/services/tab/:activeTabIndex",
|
||||||
|
name: "MeshServicesActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
@ -43,8 +52,17 @@ export const routesMesh: Array<RouteRecordRaw> = [
|
|||||||
path: "/mesh/controlPanel",
|
path: "/mesh/controlPanel",
|
||||||
name: "ControlPanel",
|
name: "ControlPanel",
|
||||||
meta: {
|
meta: {
|
||||||
|
notShow: false,
|
||||||
title: "controlPanel",
|
title: "controlPanel",
|
||||||
headPath: "/mesh/controlPanel",
|
},
|
||||||
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/mesh/controlPanel/tab/:activeTabIndex",
|
||||||
|
name: "ControlPanelActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
@ -53,10 +71,21 @@ export const routesMesh: Array<RouteRecordRaw> = [
|
|||||||
path: "/mesh/dataPanel",
|
path: "/mesh/dataPanel",
|
||||||
name: "DataPanel",
|
name: "DataPanel",
|
||||||
meta: {
|
meta: {
|
||||||
|
notShow: false,
|
||||||
title: "dataPanel",
|
title: "dataPanel",
|
||||||
headPath: "/mesh/dataPanel",
|
|
||||||
},
|
},
|
||||||
component: () => import("@/views/Layer.vue"),
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/mesh/dataPanel/tab/:activeTabIndex",
|
||||||
|
name: "DataPanelActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
title: "dataPanelActiveTabIndex",
|
||||||
|
},
|
||||||
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -33,6 +33,8 @@ interface AppState {
|
|||||||
autoRefresh: boolean;
|
autoRefresh: boolean;
|
||||||
pageTitle: string;
|
pageTitle: string;
|
||||||
version: string;
|
version: string;
|
||||||
|
isMobile: boolean;
|
||||||
|
reloadTimer: Nullable<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const appStore = defineStore({
|
export const appStore = defineStore({
|
||||||
@ -51,6 +53,8 @@ export const appStore = defineStore({
|
|||||||
autoRefresh: false,
|
autoRefresh: false,
|
||||||
pageTitle: "",
|
pageTitle: "",
|
||||||
version: "",
|
version: "",
|
||||||
|
isMobile: false,
|
||||||
|
reloadTimer: null,
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
duration(): Duration {
|
duration(): Duration {
|
||||||
@ -122,6 +126,9 @@ export const appStore = defineStore({
|
|||||||
this.utcHour = utcHour;
|
this.utcHour = utcHour;
|
||||||
this.utc = `${utcHour}:${utcMin}`;
|
this.utc = `${utcHour}:${utcMin}`;
|
||||||
},
|
},
|
||||||
|
setIsMobile(mode: boolean) {
|
||||||
|
this.isMobile = mode;
|
||||||
|
},
|
||||||
setEventStack(funcs: (() => void)[]): void {
|
setEventStack(funcs: (() => void)[]): void {
|
||||||
this.eventStack = funcs;
|
this.eventStack = funcs;
|
||||||
},
|
},
|
||||||
@ -169,6 +176,9 @@ export const appStore = defineStore({
|
|||||||
this.version = res.data.data.version;
|
this.version = res.data.data.version;
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
|
setReloadTimer(timer: any): void {
|
||||||
|
this.reloadTimer = timer;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
export function useAppStoreWithOut(): any {
|
export function useAppStoreWithOut(): any {
|
||||||
|
@ -20,10 +20,8 @@ import { LayoutConfig } from "@/types/dashboard";
|
|||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import query from "@/graphql/fetch";
|
import query from "@/graphql/fetch";
|
||||||
import { DashboardItem } from "@/types/dashboard";
|
import { DashboardItem } from "@/types/dashboard";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
|
||||||
import { useSelectorStore } from "@/store/modules/selectors";
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
import { NewControl, TextConfig } from "../data";
|
import { NewControl, TextConfig } from "../data";
|
||||||
import { Duration } from "@/types/app";
|
|
||||||
import { AxiosResponse } from "axios";
|
import { AxiosResponse } from "axios";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
@ -35,7 +33,6 @@ interface DashboardState {
|
|||||||
entity: string;
|
entity: string;
|
||||||
layerId: string;
|
layerId: string;
|
||||||
activedGridItem: string;
|
activedGridItem: string;
|
||||||
durationTime: Duration;
|
|
||||||
selectorStore: any;
|
selectorStore: any;
|
||||||
showTopology: boolean;
|
showTopology: boolean;
|
||||||
fullView: boolean;
|
fullView: boolean;
|
||||||
@ -56,7 +53,6 @@ export const dashboardStore = defineStore({
|
|||||||
entity: "",
|
entity: "",
|
||||||
layerId: "",
|
layerId: "",
|
||||||
activedGridItem: "",
|
activedGridItem: "",
|
||||||
durationTime: useAppStoreWithOut().durationTime,
|
|
||||||
selectorStore: useSelectorStore(),
|
selectorStore: useSelectorStore(),
|
||||||
showTopology: false,
|
showTopology: false,
|
||||||
showLogTools: false,
|
showLogTools: false,
|
||||||
@ -123,12 +119,7 @@ export const dashboardStore = defineStore({
|
|||||||
: 3,
|
: 3,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (
|
if (["Trace", "Profile", "Log", "DemandLog", "Ebpf"].includes(type)) {
|
||||||
type === "Trace" ||
|
|
||||||
type === "Profile" ||
|
|
||||||
type === "Log" ||
|
|
||||||
type === "Ebpf"
|
|
||||||
) {
|
|
||||||
newItem.h = 36;
|
newItem.h = 36;
|
||||||
}
|
}
|
||||||
if (type === "Text") {
|
if (type === "Text") {
|
||||||
@ -183,7 +174,7 @@ export const dashboardStore = defineStore({
|
|||||||
showDepth: true,
|
showDepth: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (type === "Trace" || type === "Profile" || type === "Log") {
|
if (["Trace", "Profile", "Log", "DemandLog", "Ebpf"].includes(type)) {
|
||||||
newItem.h = 32;
|
newItem.h = 32;
|
||||||
}
|
}
|
||||||
if (type === "Text") {
|
if (type === "Text") {
|
||||||
|
126
src/store/modules/demand-log.ts
Normal file
126
src/store/modules/demand-log.ts
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
import { Instance } from "@/types/selector";
|
||||||
|
import { store } from "@/store";
|
||||||
|
import graphql from "@/graphql";
|
||||||
|
import { AxiosResponse } from "axios";
|
||||||
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
|
import { Conditions, Log } from "@/types/demand-log";
|
||||||
|
|
||||||
|
interface DemandLogState {
|
||||||
|
containers: Instance[];
|
||||||
|
instances: Instance[];
|
||||||
|
conditions: Conditions;
|
||||||
|
selectorStore: any;
|
||||||
|
logs: Log[];
|
||||||
|
loadLogs: boolean;
|
||||||
|
message: string;
|
||||||
|
total: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const demandLogStore = defineStore({
|
||||||
|
id: "demandLog",
|
||||||
|
state: (): DemandLogState => ({
|
||||||
|
containers: [{ label: "", value: "" }],
|
||||||
|
instances: [{ value: "", label: "" }],
|
||||||
|
conditions: {
|
||||||
|
container: "",
|
||||||
|
serviceInstanceId: "",
|
||||||
|
duration: useAppStoreWithOut().durationTime,
|
||||||
|
},
|
||||||
|
selectorStore: useSelectorStore(),
|
||||||
|
logs: [],
|
||||||
|
loadLogs: false,
|
||||||
|
message: "",
|
||||||
|
total: 0,
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
setLogCondition(data: Conditions) {
|
||||||
|
this.conditions = { ...this.conditions, ...data };
|
||||||
|
},
|
||||||
|
setLogs(logs: Log[], message?: string) {
|
||||||
|
this.logs = logs;
|
||||||
|
this.message = message || "";
|
||||||
|
},
|
||||||
|
async getInstances(id: string) {
|
||||||
|
const serviceId = this.selectorStore.currentService
|
||||||
|
? this.selectorStore.currentService.id
|
||||||
|
: id;
|
||||||
|
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
||||||
|
serviceId,
|
||||||
|
duration: useAppStoreWithOut().durationTime,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.data.errors) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
this.instances = res.data.data.pods || [];
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
|
async getContainers(serviceInstanceId: string) {
|
||||||
|
if (!serviceInstanceId) {
|
||||||
|
return new Promise((resolve) =>
|
||||||
|
resolve({ errors: "No service instance" })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const condition = {
|
||||||
|
serviceInstanceId,
|
||||||
|
};
|
||||||
|
const res: AxiosResponse = await graphql
|
||||||
|
.query("fetchContainers")
|
||||||
|
.params({ condition });
|
||||||
|
|
||||||
|
if (res.data.errors) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
if (res.data.data.containers.errorReason) {
|
||||||
|
this.containers = [{ label: "", value: "" }];
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
this.containers = res.data.data.containers.containers.map((d: string) => {
|
||||||
|
return { label: d, value: d };
|
||||||
|
});
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
|
async getDemandLogs() {
|
||||||
|
this.loadLogs = true;
|
||||||
|
const res: AxiosResponse = await graphql
|
||||||
|
.query("fetchDemandPodLogs")
|
||||||
|
.params({ condition: this.conditions });
|
||||||
|
this.loadLogs = false;
|
||||||
|
if (res.data.errors) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
if (res.data.data.logs.errorReason) {
|
||||||
|
this.setLogs("", res.data.data.logs.errorReason);
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
this.total = res.data.data.logs.logs.length;
|
||||||
|
const logs = res.data.data.logs.logs
|
||||||
|
.map((d: Log) => d.content)
|
||||||
|
.join("\n");
|
||||||
|
this.setLogs(logs);
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export function useDemandLogStore(): any {
|
||||||
|
return demandLogStore(store);
|
||||||
|
}
|
@ -15,21 +15,18 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { Duration, Option } from "@/types/app";
|
import { Option } from "@/types/app";
|
||||||
import {
|
import {
|
||||||
EBPFTaskCreationRequest,
|
EBPFTaskCreationRequest,
|
||||||
EBPFProfilingSchedule,
|
EBPFProfilingSchedule,
|
||||||
EBPFTaskList,
|
EBPFTaskList,
|
||||||
AnalyzationTrees,
|
AnalyzationTrees,
|
||||||
} from "@/types/ebpf";
|
} from "@/types/ebpf";
|
||||||
import { Trace, Span } from "@/types/trace";
|
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import { AxiosResponse } from "axios";
|
import { AxiosResponse } from "axios";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
|
||||||
|
|
||||||
interface EbpfStore {
|
interface EbpfStore {
|
||||||
durationTime: Duration;
|
|
||||||
taskList: EBPFTaskList[];
|
taskList: EBPFTaskList[];
|
||||||
eBPFSchedules: EBPFProfilingSchedule[];
|
eBPFSchedules: EBPFProfilingSchedule[];
|
||||||
currentSchedule: EBPFProfilingSchedule | Record<string, never>;
|
currentSchedule: EBPFProfilingSchedule | Record<string, never>;
|
||||||
@ -37,12 +34,13 @@ interface EbpfStore {
|
|||||||
labels: Option[];
|
labels: Option[];
|
||||||
couldProfiling: boolean;
|
couldProfiling: boolean;
|
||||||
tip: string;
|
tip: string;
|
||||||
|
selectedTask: Recordable<EBPFTaskList>;
|
||||||
|
aggregateType: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ebpfStore = defineStore({
|
export const ebpfStore = defineStore({
|
||||||
id: "eBPF",
|
id: "eBPF",
|
||||||
state: (): EbpfStore => ({
|
state: (): EbpfStore => ({
|
||||||
durationTime: useAppStoreWithOut().durationTime,
|
|
||||||
taskList: [],
|
taskList: [],
|
||||||
eBPFSchedules: [],
|
eBPFSchedules: [],
|
||||||
currentSchedule: {},
|
currentSchedule: {},
|
||||||
@ -50,14 +48,19 @@ export const ebpfStore = defineStore({
|
|||||||
labels: [{ value: "", label: "" }],
|
labels: [{ value: "", label: "" }],
|
||||||
couldProfiling: false,
|
couldProfiling: false,
|
||||||
tip: "",
|
tip: "",
|
||||||
|
selectedTask: {},
|
||||||
|
aggregateType: "COUNT",
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
setCurrentSpan(span: Span) {
|
setSelectedTask(task: EBPFTaskList) {
|
||||||
this.currentSpan = span;
|
this.selectedTask = task;
|
||||||
},
|
},
|
||||||
setCurrentSchedule(s: Trace) {
|
setCurrentSchedule(s: EBPFProfilingSchedule) {
|
||||||
this.currentSchedule = s;
|
this.currentSchedule = s;
|
||||||
},
|
},
|
||||||
|
setAnalyzeTrees(tree: AnalyzationTrees[]) {
|
||||||
|
this.analyzeTrees = tree;
|
||||||
|
},
|
||||||
async getCreateTaskData(serviceId: string) {
|
async getCreateTaskData(serviceId: string) {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql
|
||||||
.query("getCreateTaskData")
|
.query("getCreateTaskData")
|
||||||
@ -85,6 +88,9 @@ export const ebpfStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getTaskList(serviceId: string) {
|
async getTaskList(serviceId: string) {
|
||||||
|
if (!serviceId) {
|
||||||
|
return new Promise((resolve) => resolve({}));
|
||||||
|
}
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql
|
||||||
.query("getEBPFTasks")
|
.query("getEBPFTasks")
|
||||||
.params({ serviceId });
|
.params({ serviceId });
|
||||||
@ -93,18 +99,20 @@ export const ebpfStore = defineStore({
|
|||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.taskList = res.data.data.queryEBPFTasks.reverse() || [];
|
this.taskList = res.data.data.queryEBPFTasks || [];
|
||||||
if (!this.taskList.length) {
|
if (!this.taskList.length) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.getEBPFSchedules({ taskId: this.taskList[0].taskId });
|
this.getEBPFSchedules({ taskId: this.taskList[0].taskId });
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getEBPFSchedules(params: { taskId: string; duration?: Duration }) {
|
async getEBPFSchedules(params: { taskId: string }) {
|
||||||
const duration = useAppStoreWithOut().durationTime;
|
if (!params.taskId) {
|
||||||
|
return new Promise((resolve) => resolve({}));
|
||||||
|
}
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql
|
||||||
.query("getEBPFSchedules")
|
.query("getEBPFSchedules")
|
||||||
.params({ ...params, duration });
|
.params({ ...params });
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
this.eBPFSchedules = [];
|
this.eBPFSchedules = [];
|
||||||
@ -116,14 +124,22 @@ export const ebpfStore = defineStore({
|
|||||||
this.eBPFSchedules = eBPFSchedules;
|
this.eBPFSchedules = eBPFSchedules;
|
||||||
if (!eBPFSchedules.length) {
|
if (!eBPFSchedules.length) {
|
||||||
this.eBPFSchedules = [];
|
this.eBPFSchedules = [];
|
||||||
}
|
|
||||||
this.analyzeTrees = [];
|
this.analyzeTrees = [];
|
||||||
|
}
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getEBPFAnalyze(params: {
|
async getEBPFAnalyze(params: {
|
||||||
scheduleIdList: string[];
|
scheduleIdList: string[];
|
||||||
timeRanges: Array<{ start: number; end: number }>;
|
timeRanges: Array<{ start: number; end: number }>;
|
||||||
|
aggregateType: string;
|
||||||
}) {
|
}) {
|
||||||
|
this.aggregateType = params.aggregateType;
|
||||||
|
if (!params.scheduleIdList.length) {
|
||||||
|
return new Promise((resolve) => resolve({}));
|
||||||
|
}
|
||||||
|
if (!params.timeRanges.length) {
|
||||||
|
return new Promise((resolve) => resolve({}));
|
||||||
|
}
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql
|
||||||
.query("getEBPFResult")
|
.query("getEBPFResult")
|
||||||
.params(params);
|
.params(params);
|
||||||
@ -142,7 +158,7 @@ export const ebpfStore = defineStore({
|
|||||||
this.analyzeTrees = [];
|
this.analyzeTrees = [];
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.analyzeTrees = analysisEBPFResult.trees[0].elements;
|
this.analyzeTrees = analysisEBPFResult.trees;
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -19,17 +19,16 @@ import { store } from "@/store";
|
|||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import { AxiosResponse } from "axios";
|
import { AxiosResponse } from "axios";
|
||||||
import { Event, QueryEventCondition } from "@/types/events";
|
import { Event, QueryEventCondition } from "@/types/events";
|
||||||
import { Instance, Endpoint, Service } from "@/types/selector";
|
import { Instance, Endpoint } from "@/types/selector";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
|
|
||||||
interface eventState {
|
interface eventState {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
events: Event[];
|
events: Event[];
|
||||||
total: number;
|
|
||||||
services: Service[];
|
|
||||||
instances: Instance[];
|
instances: Instance[];
|
||||||
endpoints: Endpoint[];
|
endpoints: Endpoint[];
|
||||||
condition: QueryEventCondition | any;
|
condition: Nullable<QueryEventCondition>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const eventStore = defineStore({
|
export const eventStore = defineStore({
|
||||||
@ -37,34 +36,18 @@ export const eventStore = defineStore({
|
|||||||
state: (): eventState => ({
|
state: (): eventState => ({
|
||||||
loading: false,
|
loading: false,
|
||||||
events: [],
|
events: [],
|
||||||
total: 0,
|
|
||||||
services: [{ value: "", label: "All" }],
|
|
||||||
instances: [{ value: "", label: "All" }],
|
instances: [{ value: "", label: "All" }],
|
||||||
endpoints: [{ value: "", label: "All" }],
|
endpoints: [{ value: "", label: "All" }],
|
||||||
condition: {
|
condition: null,
|
||||||
time: useAppStoreWithOut().durationTime,
|
|
||||||
paging: { pageNum: 1, pageSize: 15, needTotal: true },
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
setEventCondition(data: any) {
|
setEventCondition(data: QueryEventCondition) {
|
||||||
this.condition = { ...this.condition, ...data };
|
this.condition = data;
|
||||||
},
|
},
|
||||||
async getServices(layer: string) {
|
async getInstances() {
|
||||||
if (!layer) {
|
const serviceId = useSelectorStore().currentService
|
||||||
this.services = [{ value: "", label: "All" }];
|
? useSelectorStore().currentService.id
|
||||||
return new Promise((resolve) => resolve([]));
|
: "";
|
||||||
}
|
|
||||||
const res: AxiosResponse = await graphql.query("queryServices").params({
|
|
||||||
layer,
|
|
||||||
});
|
|
||||||
if (res.data.errors) {
|
|
||||||
return res.data;
|
|
||||||
}
|
|
||||||
this.services = res.data.data.services;
|
|
||||||
return res.data;
|
|
||||||
},
|
|
||||||
async getInstances(serviceId: string) {
|
|
||||||
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
||||||
serviceId,
|
serviceId,
|
||||||
duration: useAppStoreWithOut().durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
@ -78,7 +61,13 @@ export const eventStore = defineStore({
|
|||||||
];
|
];
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getEndpoints(serviceId: string) {
|
async getEndpoints() {
|
||||||
|
const serviceId = useSelectorStore().currentService
|
||||||
|
? useSelectorStore().currentService.id
|
||||||
|
: "";
|
||||||
|
if (!serviceId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
||||||
serviceId,
|
serviceId,
|
||||||
duration: useAppStoreWithOut().durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
@ -94,9 +83,12 @@ export const eventStore = defineStore({
|
|||||||
},
|
},
|
||||||
async getEvents() {
|
async getEvents() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql.query("queryEvents").params({
|
||||||
.query("queryEvents")
|
condition: {
|
||||||
.params({ condition: this.condition });
|
...this.condition,
|
||||||
|
time: useAppStoreWithOut().durationTime,
|
||||||
|
},
|
||||||
|
});
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
@ -115,7 +107,6 @@ export const eventStore = defineStore({
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
this.total = res.data.data.fetchEvents.total;
|
|
||||||
}
|
}
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { Duration } from "@/types/app";
|
|
||||||
import { Instance, Endpoint, Service } from "@/types/selector";
|
import { Instance, Endpoint, Service } from "@/types/selector";
|
||||||
import { ServiceLogColumn, BrowserLogColumn } from "@/types/log-column";
|
import { ServiceLogColumn, BrowserLogColumn } from "@/types/log-column";
|
||||||
import { ServiceLogConstants, BrowserLogConstants } from "../data";
|
import { ServiceLogConstants, BrowserLogConstants } from "../data";
|
||||||
@ -33,11 +32,9 @@ interface LogState {
|
|||||||
serviceLogColumn: ServiceLogColumn[];
|
serviceLogColumn: ServiceLogColumn[];
|
||||||
browserLogColumn: BrowserLogColumn[];
|
browserLogColumn: BrowserLogColumn[];
|
||||||
conditions: any;
|
conditions: any;
|
||||||
durationTime: Duration;
|
|
||||||
selectorStore: any;
|
selectorStore: any;
|
||||||
supportQueryLogsByKeywords: boolean;
|
supportQueryLogsByKeywords: boolean;
|
||||||
logs: any[];
|
logs: any[];
|
||||||
logsTotal: number;
|
|
||||||
loadLogs: boolean;
|
loadLogs: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,15 +46,13 @@ export const logStore = defineStore({
|
|||||||
endpoints: [{ value: "0", label: "All" }],
|
endpoints: [{ value: "0", label: "All" }],
|
||||||
conditions: {
|
conditions: {
|
||||||
queryDuration: useAppStoreWithOut().durationTime,
|
queryDuration: useAppStoreWithOut().durationTime,
|
||||||
paging: { pageNum: 1, pageSize: 15, needTotal: true },
|
paging: { pageNum: 1, pageSize: 15 },
|
||||||
},
|
},
|
||||||
serviceLogColumn: [...ServiceLogConstants],
|
serviceLogColumn: [...ServiceLogConstants],
|
||||||
browserLogColumn: [...BrowserLogConstants],
|
browserLogColumn: [...BrowserLogConstants],
|
||||||
supportQueryLogsByKeywords: true,
|
supportQueryLogsByKeywords: true,
|
||||||
durationTime: useAppStoreWithOut().durationTime,
|
|
||||||
selectorStore: useSelectorStore(),
|
selectorStore: useSelectorStore(),
|
||||||
logs: [],
|
logs: [],
|
||||||
logsTotal: 0,
|
|
||||||
loadLogs: false,
|
loadLogs: false,
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
@ -83,6 +78,12 @@ export const logStore = defineStore({
|
|||||||
setLogCondition(data: any) {
|
setLogCondition(data: any) {
|
||||||
this.conditions = { ...this.conditions, ...data };
|
this.conditions = { ...this.conditions, ...data };
|
||||||
},
|
},
|
||||||
|
resetCondition() {
|
||||||
|
this.conditions = {
|
||||||
|
queryDuration: useAppStoreWithOut().durationTime,
|
||||||
|
paging: { pageNum: 1, pageSize: 15 },
|
||||||
|
};
|
||||||
|
},
|
||||||
async getServices(layer: string) {
|
async getServices(layer: string) {
|
||||||
const res: AxiosResponse = await graphql.query("queryServices").params({
|
const res: AxiosResponse = await graphql.query("queryServices").params({
|
||||||
layer,
|
layer,
|
||||||
@ -99,7 +100,7 @@ export const logStore = defineStore({
|
|||||||
: id;
|
: id;
|
||||||
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
||||||
serviceId,
|
serviceId,
|
||||||
duration: this.durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
@ -117,7 +118,7 @@ export const logStore = defineStore({
|
|||||||
: id;
|
: id;
|
||||||
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
||||||
serviceId,
|
serviceId,
|
||||||
duration: this.durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
keyword: keyword || "",
|
keyword: keyword || "",
|
||||||
});
|
});
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
@ -159,7 +160,6 @@ export const logStore = defineStore({
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.logs = res.data.data.queryLogs.logs;
|
this.logs = res.data.data.queryLogs.logs;
|
||||||
this.logsTotal = res.data.data.queryLogs.total;
|
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getBrowserLogs() {
|
async getBrowserLogs() {
|
||||||
@ -173,7 +173,20 @@ export const logStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.logs = res.data.data.queryBrowserErrorLogs.logs;
|
this.logs = res.data.data.queryBrowserErrorLogs.logs;
|
||||||
this.logsTotal = res.data.data.queryBrowserErrorLogs.total;
|
return res.data;
|
||||||
|
},
|
||||||
|
async getLogTagKeys() {
|
||||||
|
const res: AxiosResponse = await graphql
|
||||||
|
.query("queryLogTagKeys")
|
||||||
|
.params({ duration: useAppStoreWithOut().durationTime });
|
||||||
|
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
|
async getLogTagValues(tagKey: string) {
|
||||||
|
const res: AxiosResponse = await graphql
|
||||||
|
.query("queryLogTagValues")
|
||||||
|
.params({ tagKey, duration: useAppStoreWithOut().durationTime });
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { Duration } from "@/types/app";
|
|
||||||
import { Endpoint } from "@/types/selector";
|
import { Endpoint } from "@/types/selector";
|
||||||
import {
|
import {
|
||||||
TaskListItem,
|
TaskListItem,
|
||||||
@ -33,7 +32,6 @@ import { useAppStoreWithOut } from "@/store/modules/app";
|
|||||||
interface ProfileState {
|
interface ProfileState {
|
||||||
endpoints: Endpoint[];
|
endpoints: Endpoint[];
|
||||||
taskEndpoints: Endpoint[];
|
taskEndpoints: Endpoint[];
|
||||||
durationTime: Duration;
|
|
||||||
condition: { serviceId: string; endpointName: string };
|
condition: { serviceId: string; endpointName: string };
|
||||||
taskList: TaskListItem[];
|
taskList: TaskListItem[];
|
||||||
segmentList: Trace[];
|
segmentList: Trace[];
|
||||||
@ -50,7 +48,6 @@ export const profileStore = defineStore({
|
|||||||
state: (): ProfileState => ({
|
state: (): ProfileState => ({
|
||||||
endpoints: [{ value: "", label: "All" }],
|
endpoints: [{ value: "", label: "All" }],
|
||||||
taskEndpoints: [{ value: "", label: "All" }],
|
taskEndpoints: [{ value: "", label: "All" }],
|
||||||
durationTime: useAppStoreWithOut().durationTime,
|
|
||||||
condition: { serviceId: "", endpointName: "" },
|
condition: { serviceId: "", endpointName: "" },
|
||||||
taskList: [],
|
taskList: [],
|
||||||
segmentList: [],
|
segmentList: [],
|
||||||
@ -80,7 +77,7 @@ export const profileStore = defineStore({
|
|||||||
async getEndpoints(serviceId: string, keyword?: string) {
|
async getEndpoints(serviceId: string, keyword?: string) {
|
||||||
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
||||||
serviceId,
|
serviceId,
|
||||||
duration: this.durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
keyword: keyword || "",
|
keyword: keyword || "",
|
||||||
});
|
});
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
@ -92,7 +89,7 @@ export const profileStore = defineStore({
|
|||||||
async getTaskEndpoints(serviceId: string, keyword?: string) {
|
async getTaskEndpoints(serviceId: string, keyword?: string) {
|
||||||
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
||||||
serviceId,
|
serviceId,
|
||||||
duration: this.durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
keyword: keyword || "",
|
keyword: keyword || "",
|
||||||
});
|
});
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
@ -122,6 +119,9 @@ export const profileStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getSegmentList(params: { taskID: string }) {
|
async getSegmentList(params: { taskID: string }) {
|
||||||
|
if (!params.taskID) {
|
||||||
|
return new Promise((resolve) => resolve({}));
|
||||||
|
}
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql
|
||||||
.query("getProfileTaskSegmentList")
|
.query("getProfileTaskSegmentList")
|
||||||
.params(params);
|
.params(params);
|
||||||
@ -148,6 +148,9 @@ export const profileStore = defineStore({
|
|||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getSegmentSpans(params: { segmentId: string }) {
|
async getSegmentSpans(params: { segmentId: string }) {
|
||||||
|
if (!params.segmentId) {
|
||||||
|
return new Promise((resolve) => resolve({}));
|
||||||
|
}
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql
|
||||||
.query("queryProfileSegment")
|
.query("queryProfileSegment")
|
||||||
.params(params);
|
.params(params);
|
||||||
@ -161,7 +164,13 @@ export const profileStore = defineStore({
|
|||||||
this.analyzeTrees = [];
|
this.analyzeTrees = [];
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.segmentSpans = segment.spans;
|
this.segmentSpans = segment.spans.map((d: SegmentSpan) => {
|
||||||
|
return {
|
||||||
|
...d,
|
||||||
|
segmentId: this.currentSegment.segmentId,
|
||||||
|
traceId: this.currentSegment.traceIds[0],
|
||||||
|
};
|
||||||
|
});
|
||||||
if (!(segment.spans && segment.spans.length)) {
|
if (!(segment.spans && segment.spans.length)) {
|
||||||
this.analyzeTrees = [];
|
this.analyzeTrees = [];
|
||||||
return res.data;
|
return res.data;
|
||||||
@ -174,6 +183,12 @@ export const profileStore = defineStore({
|
|||||||
segmentId: string;
|
segmentId: string;
|
||||||
timeRanges: Array<{ start: number; end: number }>;
|
timeRanges: Array<{ start: number; end: number }>;
|
||||||
}) {
|
}) {
|
||||||
|
if (!params.segmentId) {
|
||||||
|
return new Promise((resolve) => resolve({}));
|
||||||
|
}
|
||||||
|
if (!params.timeRanges.length) {
|
||||||
|
return new Promise((resolve) => resolve({}));
|
||||||
|
}
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql
|
||||||
.query("getProfileAnalyze")
|
.query("getProfileAnalyze")
|
||||||
.params(params);
|
.params(params);
|
||||||
|
@ -15,13 +15,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { Duration } from "@/types/app";
|
|
||||||
import { Service, Instance, Endpoint } from "@/types/selector";
|
import { Service, Instance, Endpoint } from "@/types/selector";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import { AxiosResponse } from "axios";
|
import { AxiosResponse } from "axios";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
|
|
||||||
interface SelectorState {
|
interface SelectorState {
|
||||||
services: Service[];
|
services: Service[];
|
||||||
destServices: Service[];
|
destServices: Service[];
|
||||||
@ -31,7 +29,6 @@ interface SelectorState {
|
|||||||
currentDestService: Nullable<Service>;
|
currentDestService: Nullable<Service>;
|
||||||
currentDestPod: Nullable<Instance | Endpoint>;
|
currentDestPod: Nullable<Instance | Endpoint>;
|
||||||
destPods: Array<Instance | Endpoint>;
|
destPods: Array<Instance | Endpoint>;
|
||||||
durationTime: Duration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const selectorStore = defineStore({
|
export const selectorStore = defineStore({
|
||||||
@ -45,7 +42,6 @@ export const selectorStore = defineStore({
|
|||||||
currentPod: null,
|
currentPod: null,
|
||||||
currentDestService: null,
|
currentDestService: null,
|
||||||
currentDestPod: null,
|
currentDestPod: null,
|
||||||
durationTime: useAppStoreWithOut().durationTime,
|
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
setCurrentService(service: Nullable<Service>) {
|
setCurrentService(service: Nullable<Service>) {
|
||||||
@ -86,7 +82,7 @@ export const selectorStore = defineStore({
|
|||||||
}
|
}
|
||||||
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
||||||
serviceId,
|
serviceId,
|
||||||
duration: this.durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
});
|
});
|
||||||
if (!res.data.errors) {
|
if (!res.data.errors) {
|
||||||
if (param && param.isRelation) {
|
if (param && param.isRelation) {
|
||||||
@ -112,7 +108,7 @@ export const selectorStore = defineStore({
|
|||||||
}
|
}
|
||||||
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
||||||
serviceId,
|
serviceId,
|
||||||
duration: this.durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
keyword: params.keyword || "",
|
keyword: params.keyword || "",
|
||||||
limit: params.limit,
|
limit: params.limit,
|
||||||
});
|
});
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { Duration } from "@/types/app";
|
|
||||||
import { Instance, Endpoint, Service } from "@/types/selector";
|
import { Instance, Endpoint, Service } from "@/types/selector";
|
||||||
import { Trace, Span } from "@/types/trace";
|
import { Trace, Span } from "@/types/trace";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
@ -28,19 +27,10 @@ interface TraceState {
|
|||||||
instances: Instance[];
|
instances: Instance[];
|
||||||
endpoints: Endpoint[];
|
endpoints: Endpoint[];
|
||||||
traceList: Trace[];
|
traceList: Trace[];
|
||||||
activeFilter: string;
|
|
||||||
displayMode: string;
|
|
||||||
currentView: string;
|
|
||||||
traceTotal: number;
|
|
||||||
traceSpans: Span[];
|
traceSpans: Span[];
|
||||||
currentTrace: Trace | any;
|
currentTrace: Trace | any;
|
||||||
conditions: any;
|
conditions: any;
|
||||||
traceSpanLogs: any[];
|
traceSpanLogs: any[];
|
||||||
traceSpanLogsTotal: number;
|
|
||||||
// traceListErrors: string;
|
|
||||||
// traceSpanErrors: string;
|
|
||||||
// traceSpanLogErrors: string;
|
|
||||||
durationTime: Duration;
|
|
||||||
selectorStore: any;
|
selectorStore: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,27 +40,21 @@ export const traceStore = defineStore({
|
|||||||
services: [{ value: "0", label: "All" }],
|
services: [{ value: "0", label: "All" }],
|
||||||
instances: [{ value: "0", label: "All" }],
|
instances: [{ value: "0", label: "All" }],
|
||||||
endpoints: [{ value: "0", label: "All" }],
|
endpoints: [{ value: "0", label: "All" }],
|
||||||
displayMode: "List",
|
|
||||||
currentView: "traceList",
|
|
||||||
activeFilter: "",
|
|
||||||
traceList: [],
|
traceList: [],
|
||||||
traceSpans: [],
|
traceSpans: [],
|
||||||
traceTotal: 0,
|
|
||||||
currentTrace: {},
|
currentTrace: {},
|
||||||
conditions: {
|
conditions: {
|
||||||
queryDuration: useAppStoreWithOut().durationTime,
|
queryDuration: useAppStoreWithOut().durationTime,
|
||||||
traceState: "ALL",
|
traceState: "ALL",
|
||||||
queryOrder: "BY_START_TIME",
|
queryOrder: "BY_START_TIME",
|
||||||
paging: { pageNum: 1, pageSize: 15, needTotal: true },
|
paging: { pageNum: 1, pageSize: 20 },
|
||||||
},
|
},
|
||||||
traceSpanLogs: [],
|
traceSpanLogs: [],
|
||||||
traceSpanLogsTotal: 0,
|
|
||||||
durationTime: useAppStoreWithOut().durationTime,
|
|
||||||
selectorStore: useSelectorStore(),
|
selectorStore: useSelectorStore(),
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
setTraceCondition(data: any) {
|
setTraceCondition(data: any) {
|
||||||
this.condition = { ...this.condition, ...data };
|
this.conditions = { ...this.conditions, ...data };
|
||||||
},
|
},
|
||||||
setDisplayMode(data: string) {
|
setDisplayMode(data: string) {
|
||||||
this.displayMode = data;
|
this.displayMode = data;
|
||||||
@ -104,7 +88,7 @@ export const traceStore = defineStore({
|
|||||||
: id;
|
: id;
|
||||||
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
const res: AxiosResponse = await graphql.query("queryInstances").params({
|
||||||
serviceId: serviceId,
|
serviceId: serviceId,
|
||||||
duration: this.durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
@ -119,7 +103,7 @@ export const traceStore = defineStore({
|
|||||||
: id;
|
: id;
|
||||||
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
|
||||||
serviceId,
|
serviceId,
|
||||||
duration: this.durationTime,
|
duration: useAppStoreWithOut().durationTime,
|
||||||
keyword: keyword || "",
|
keyword: keyword || "",
|
||||||
});
|
});
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
@ -131,12 +115,11 @@ export const traceStore = defineStore({
|
|||||||
async getTraces() {
|
async getTraces() {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql
|
||||||
.query("queryTraces")
|
.query("queryTraces")
|
||||||
.params({ condition: this.condition });
|
.params({ condition: this.conditions });
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
if (!res.data.data.data.traces.length) {
|
if (!res.data.data.data.traces.length) {
|
||||||
this.traceTotal = 0;
|
|
||||||
this.traceList = [];
|
this.traceList = [];
|
||||||
this.setCurrentTrace({});
|
this.setCurrentTrace({});
|
||||||
this.setTraceSpans([]);
|
this.setTraceSpans([]);
|
||||||
@ -149,7 +132,6 @@ export const traceStore = defineStore({
|
|||||||
});
|
});
|
||||||
return d;
|
return d;
|
||||||
});
|
});
|
||||||
this.traceTotal = res.data.data.data.total;
|
|
||||||
this.setCurrentTrace(res.data.data.data.traces[0] || {});
|
this.setCurrentTrace(res.data.data.data.traces[0] || {});
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
@ -169,11 +151,23 @@ export const traceStore = defineStore({
|
|||||||
.params(params);
|
.params(params);
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
this.traceSpanLogs = [];
|
this.traceSpanLogs = [];
|
||||||
this.traceSpanLogsTotal = 0;
|
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.traceSpanLogs = res.data.data.queryLogs.logs || [];
|
this.traceSpanLogs = res.data.data.queryLogs.logs || [];
|
||||||
this.traceSpanLogsTotal = res.data.data.queryLogs.total;
|
return res.data;
|
||||||
|
},
|
||||||
|
async getTagKeys() {
|
||||||
|
const res: AxiosResponse = await graphql
|
||||||
|
.query("queryTraceTagKeys")
|
||||||
|
.params({ duration: useAppStoreWithOut().durationTime });
|
||||||
|
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
|
async getTagValues(tagKey: string) {
|
||||||
|
const res: AxiosResponse = await graphql
|
||||||
|
.query("queryTraceTagValues")
|
||||||
|
.params({ tagKey, duration: useAppStoreWithOut().durationTime });
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -15,10 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.show-xs,
|
.show-xs {
|
||||||
.show-sm,
|
|
||||||
.show-md,
|
|
||||||
.show-lg {
|
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
@ -30,145 +27,6 @@
|
|||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media (min-width: 768px) and (max-width: 1023px) {
|
|
||||||
.show-sm {
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hide-sm {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (min-width: 1024px) and (max-width: 1279px) {
|
|
||||||
.show-md {
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hide-md {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (min-width: 1280px) {
|
|
||||||
.show-lg {
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hide-lg {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-1,
|
|
||||||
.g-xs-2,
|
|
||||||
.g-xs-3,
|
|
||||||
.g-xs-4,
|
|
||||||
.g-xs-5,
|
|
||||||
.g-xs-6,
|
|
||||||
.g-xs-7,
|
|
||||||
.g-xs-8,
|
|
||||||
.g-xs-9,
|
|
||||||
.g-xs-10,
|
|
||||||
.g-xs-11,
|
|
||||||
.g-xs-12 {
|
|
||||||
float: left;
|
|
||||||
min-height: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-12 {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-11 {
|
|
||||||
width: 91.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-10 {
|
|
||||||
width: 83.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-9 {
|
|
||||||
width: 75%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-8 {
|
|
||||||
width: 66.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-7 {
|
|
||||||
width: 58.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-6 {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-5 {
|
|
||||||
width: 41.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-4 {
|
|
||||||
width: 33.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-3 {
|
|
||||||
width: 25%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-2 {
|
|
||||||
width: 16.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-1 {
|
|
||||||
width: 8.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-space-12 {
|
|
||||||
margin-left: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-space-11 {
|
|
||||||
margin-left: 91.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-space-10 {
|
|
||||||
margin-left: 83.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-space-9 {
|
|
||||||
margin-left: 75%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-space-8 {
|
|
||||||
margin-left: 66.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-space-7 {
|
|
||||||
margin-left: 58.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-space-6 {
|
|
||||||
margin-left: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-space-5 {
|
|
||||||
margin-left: 41.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-space-4 {
|
|
||||||
margin-left: 33.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-space-3 {
|
|
||||||
margin-left: 25%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-space-2 {
|
|
||||||
margin-left: 16.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-xs-space-1 {
|
|
||||||
margin-left: 8.333%;
|
|
||||||
}
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.g-sm-1,
|
.g-sm-1,
|
||||||
.g-sm-2,
|
.g-sm-2,
|
||||||
@ -233,278 +91,4 @@
|
|||||||
.g-sm-1 {
|
.g-sm-1 {
|
||||||
width: 8.333%;
|
width: 8.333%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.g-sm-space-12 {
|
|
||||||
margin-left: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-sm-space-11 {
|
|
||||||
margin-left: 91.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-sm-space-10 {
|
|
||||||
margin-left: 83.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-sm-space-9 {
|
|
||||||
margin-left: 75%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-sm-space-8 {
|
|
||||||
margin-left: 66.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-sm-space-7 {
|
|
||||||
margin-left: 58.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-sm-space-6 {
|
|
||||||
margin-left: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-sm-space-5 {
|
|
||||||
margin-left: 41.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-sm-space-4 {
|
|
||||||
margin-left: 33.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-sm-space-3 {
|
|
||||||
margin-left: 25%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-sm-space-2 {
|
|
||||||
margin-left: 16.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-sm-space-1 {
|
|
||||||
margin-left: 8.333%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (min-width: 1024px) {
|
|
||||||
.g-md-1,
|
|
||||||
.g-md-2,
|
|
||||||
.g-md-3,
|
|
||||||
.g-md-4,
|
|
||||||
.g-md-5,
|
|
||||||
.g-md-6,
|
|
||||||
.g-md-7,
|
|
||||||
.g-md-8,
|
|
||||||
.g-md-9,
|
|
||||||
.g-md-10,
|
|
||||||
.g-md-11,
|
|
||||||
.g-md-12 {
|
|
||||||
float: left;
|
|
||||||
min-height: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-12 {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-11 {
|
|
||||||
width: 91.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-10 {
|
|
||||||
width: 83.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-9 {
|
|
||||||
width: 75%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-8 {
|
|
||||||
width: 66.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-7 {
|
|
||||||
width: 58.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-6 {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-5 {
|
|
||||||
width: 41.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-4 {
|
|
||||||
width: 33.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-3 {
|
|
||||||
width: 25%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-2 {
|
|
||||||
width: 16.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-1 {
|
|
||||||
width: 8.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-space-12 {
|
|
||||||
margin-left: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-space-11 {
|
|
||||||
margin-left: 91.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-space-10 {
|
|
||||||
margin-left: 83.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-space-9 {
|
|
||||||
margin-left: 75%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-space-8 {
|
|
||||||
margin-left: 66.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-space-7 {
|
|
||||||
margin-left: 58.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-space-6 {
|
|
||||||
margin-left: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-space-5 {
|
|
||||||
margin-left: 41.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-space-4 {
|
|
||||||
margin-left: 33.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-space-3 {
|
|
||||||
margin-left: 25%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-space-2 {
|
|
||||||
margin-left: 16.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-md-space-1 {
|
|
||||||
margin-left: 8.333%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (min-width: 1280px) {
|
|
||||||
.g-lg-1,
|
|
||||||
.g-lg-2,
|
|
||||||
.g-lg-3,
|
|
||||||
.g-lg-4,
|
|
||||||
.g-lg-5,
|
|
||||||
.g-lg-6,
|
|
||||||
.g-lg-7,
|
|
||||||
.g-lg-8,
|
|
||||||
.g-lg-9,
|
|
||||||
.g-lg-10,
|
|
||||||
.g-lg-11,
|
|
||||||
.g-lg-12 {
|
|
||||||
float: left;
|
|
||||||
min-height: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-12 {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-11 {
|
|
||||||
width: 91.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-10 {
|
|
||||||
width: 83.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-9 {
|
|
||||||
width: 75%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-8 {
|
|
||||||
width: 66.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-7 {
|
|
||||||
width: 58.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-6 {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-5 {
|
|
||||||
width: 41.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-4 {
|
|
||||||
width: 33.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-3 {
|
|
||||||
width: 25%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-2 {
|
|
||||||
width: 16.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-1 {
|
|
||||||
width: 8.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-space-12 {
|
|
||||||
margin-left: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-space-11 {
|
|
||||||
margin-left: 91.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-space-10 {
|
|
||||||
margin-left: 83.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-space-9 {
|
|
||||||
margin-left: 75%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-space-8 {
|
|
||||||
margin-left: 66.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-space-7 {
|
|
||||||
margin-left: 58.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-space-6 {
|
|
||||||
margin-left: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-space-5 {
|
|
||||||
margin-left: 41.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-space-4 {
|
|
||||||
margin-left: 33.333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-space-3 {
|
|
||||||
margin-left: 25%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-space-2 {
|
|
||||||
margin-left: 16.666%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.g-lg-space-1 {
|
|
||||||
margin-left: 8.333%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
0
src/styles/jb-ui-styles.scss
Normal file
0
src/styles/jb-ui-styles.scss
Normal file
@ -56,15 +56,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.blue {
|
.blue {
|
||||||
color: #6897BB;
|
color: #6897bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.purple {
|
.purple {
|
||||||
color: #9876AA;
|
color: #9876aa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.yellow {
|
.yellow {
|
||||||
color: #FFC66D;
|
color: #ffc66d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grey {
|
.grey {
|
||||||
@ -84,15 +84,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bg-blue {
|
.bg-blue {
|
||||||
background-color: #6897BB;
|
background-color: #6897bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-purple {
|
.bg-purple {
|
||||||
background-color: #9876AA;
|
background-color: #9876aa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-yellow {
|
.bg-yellow {
|
||||||
background-color: #FFC66D;
|
background-color: #ffc66d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-grey {
|
.bg-grey {
|
||||||
@ -171,3 +171,21 @@
|
|||||||
color: #ddd;
|
color: #ddd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scroll_bar_style::-webkit-scrollbar {
|
||||||
|
width: 9px;
|
||||||
|
height: 4px;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll_bar_style::-webkit-scrollbar-track {
|
||||||
|
background-color: #eee;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: inset 0 0 6px #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll_bar_style::-webkit-scrollbar-thumb {
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: inset 0 0 6px #ccc;
|
||||||
|
background-color: #aaa;
|
||||||
|
}
|
||||||
|
@ -29,6 +29,7 @@ body {
|
|||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
div,
|
div,
|
||||||
@ -153,3 +154,38 @@ pre {
|
|||||||
.switch {
|
.switch {
|
||||||
margin: 0 5px;
|
margin: 0 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.vis-tooltip {
|
||||||
|
max-width: 600px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #fff !important;
|
||||||
|
white-space: normal !important;
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vis-item {
|
||||||
|
cursor: pointer;
|
||||||
|
height: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vis-item.Error {
|
||||||
|
background-color: #e66;
|
||||||
|
opacity: 0.8;
|
||||||
|
border-color: #e66;
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vis-item.Normal {
|
||||||
|
background-color: #fac858;
|
||||||
|
border-color: #fac858;
|
||||||
|
color: #666 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vis-item .vis-item-content {
|
||||||
|
padding: 0 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vis-item.vis-selected.Error,
|
||||||
|
.vis-item.vis-selected.Normal {
|
||||||
|
color: #1a1a1a !important;
|
||||||
|
}
|
||||||
|
4
src/types/app.d.ts
vendored
4
src/types/app.d.ts
vendored
@ -28,3 +28,7 @@ export interface DurationTime {
|
|||||||
end: string;
|
end: string;
|
||||||
step: string;
|
step: string;
|
||||||
}
|
}
|
||||||
|
export type Paging = {
|
||||||
|
pageNum: number;
|
||||||
|
pageSize: number;
|
||||||
|
};
|
||||||
|
6
src/types/dashboard.d.ts
vendored
6
src/types/dashboard.d.ts
vendored
@ -39,9 +39,9 @@ export interface LayoutConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type MetricConfigOpt = {
|
export type MetricConfigOpt = {
|
||||||
unit: string;
|
unit?: string;
|
||||||
label: string;
|
label?: string;
|
||||||
calculation: string;
|
calculation?: string;
|
||||||
labelsIndex: string;
|
labelsIndex: string;
|
||||||
sortOrder: string;
|
sortOrder: string;
|
||||||
topN?: number;
|
topN?: number;
|
||||||
|
31
src/types/demand-log.ts
Normal file
31
src/types/demand-log.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import { DurationTime } from "./app";
|
||||||
|
|
||||||
|
export interface Conditions {
|
||||||
|
container: string;
|
||||||
|
serviceInstanceId: string;
|
||||||
|
duration: DurationTime;
|
||||||
|
keywordsOfContent?: string[];
|
||||||
|
excludingKeywordsOfContent?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Log {
|
||||||
|
content: string;
|
||||||
|
timestamp: number;
|
||||||
|
contentType: string;
|
||||||
|
}
|
5
src/types/ebpf.d.ts
vendored
5
src/types/ebpf.d.ts
vendored
@ -50,10 +50,9 @@ export type Process = {
|
|||||||
serviceName: string;
|
serviceName: string;
|
||||||
instanceId: string;
|
instanceId: string;
|
||||||
instanceName: string;
|
instanceName: string;
|
||||||
layer: string;
|
|
||||||
agentId: string;
|
agentId: string;
|
||||||
detectType: string;
|
detectType: string;
|
||||||
attributes: { name: string; value: string };
|
attributes: { name: string; value: string }[];
|
||||||
labels: string[];
|
labels: string[];
|
||||||
};
|
};
|
||||||
export type StackElement = {
|
export type StackElement = {
|
||||||
@ -66,6 +65,8 @@ export type StackElement = {
|
|||||||
stackType: string;
|
stackType: string;
|
||||||
value: number;
|
value: number;
|
||||||
children?: StackElement[];
|
children?: StackElement[];
|
||||||
|
rateOfRoot?: string;
|
||||||
|
rateOfParent: string;
|
||||||
};
|
};
|
||||||
export type AnalyzationTrees = {
|
export type AnalyzationTrees = {
|
||||||
id: string;
|
id: string;
|
||||||
|
17
src/types/monaco-editor.ts
Normal file
17
src/types/monaco-editor.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
declare module "monaco-editor";
|
1
src/types/selector.d.ts
vendored
1
src/types/selector.d.ts
vendored
@ -26,7 +26,6 @@ export type Service = {
|
|||||||
export type Instance = {
|
export type Instance = {
|
||||||
value: string;
|
value: string;
|
||||||
label: string;
|
label: string;
|
||||||
layer?: string;
|
|
||||||
language?: string;
|
language?: string;
|
||||||
instanceUUID?: string;
|
instanceUUID?: string;
|
||||||
attributes?: { name: string; value: string }[];
|
attributes?: { name: string; value: string }[];
|
||||||
|
9
src/types/trace.d.ts
vendored
9
src/types/trace.d.ts
vendored
@ -46,8 +46,15 @@ export interface Span {
|
|||||||
children?: Span[];
|
children?: Span[];
|
||||||
tags?: Array<Map<string, string>>;
|
tags?: Array<Map<string, string>>;
|
||||||
logs?: log[];
|
logs?: log[];
|
||||||
|
parentSegmentId?: string;
|
||||||
|
refs?: Ref[];
|
||||||
}
|
}
|
||||||
|
export type Ref = {
|
||||||
|
type: string;
|
||||||
|
parentSegmentId: string;
|
||||||
|
parentSpanId: number;
|
||||||
|
traceId: string;
|
||||||
|
};
|
||||||
export interface log {
|
export interface log {
|
||||||
time: number;
|
time: number;
|
||||||
data: Map<string, string>;
|
data: Map<string, string>;
|
||||||
|
@ -24,7 +24,7 @@ import Header from "./alarm/Header.vue";
|
|||||||
import Content from "./alarm/Content.vue";
|
import Content from "./alarm/Content.vue";
|
||||||
|
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
appStore.setPageTitle("Alarm");
|
appStore.setPageTitle("Alerting");
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.alarm {
|
.alarm {
|
||||||
|
@ -69,7 +69,7 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, reactive } from "vue";
|
import { ref } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import timeFormat from "@/utils/timeFormat";
|
import timeFormat from "@/utils/timeFormat";
|
||||||
@ -78,9 +78,6 @@ import Selector from "@/components/Selector.vue";
|
|||||||
|
|
||||||
const { t, locale } = useI18n();
|
const { t, locale } = useI18n();
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
const state = reactive<{ timer: ReturnType<typeof setInterval> | null }>({
|
|
||||||
timer: null,
|
|
||||||
});
|
|
||||||
const lang = ref<string>(locale.value || "en");
|
const lang = ref<string>(locale.value || "en");
|
||||||
const autoTime = ref<number>(6);
|
const autoTime = ref<number>(6);
|
||||||
const auto = ref<boolean>(appStore.autoRefresh || false);
|
const auto = ref<boolean>(appStore.autoRefresh || false);
|
||||||
@ -101,10 +98,10 @@ const handleAuto = () => {
|
|||||||
appStore.setAutoRefresh(auto.value);
|
appStore.setAutoRefresh(auto.value);
|
||||||
if (auto.value) {
|
if (auto.value) {
|
||||||
handleReload();
|
handleReload();
|
||||||
state.timer = setInterval(handleReload, autoTime.value * 1000);
|
appStore.setReloadTimer(setInterval(handleReload, autoTime.value * 1000));
|
||||||
} else {
|
} else {
|
||||||
if (state.timer) {
|
if (appStore.reloadTimer) {
|
||||||
clearInterval(state.timer);
|
clearInterval(appStore.reloadTimer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -112,12 +109,12 @@ const changeAutoTime = () => {
|
|||||||
if (autoTime.value < 1) {
|
if (autoTime.value < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (state.timer) {
|
if (appStore.reloadTimer) {
|
||||||
clearInterval(state.timer);
|
clearInterval(appStore.reloadTimer);
|
||||||
}
|
}
|
||||||
if (auto.value) {
|
if (auto.value) {
|
||||||
handleReload();
|
handleReload();
|
||||||
state.timer = setInterval(handleReload, autoTime.value * 1000);
|
appStore.setReloadTimer(setInterval(handleReload, autoTime.value * 1000));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const setLang = (): void => {
|
const setLang = (): void => {
|
||||||
@ -194,10 +191,11 @@ const setUTCMin = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
width: 160px;
|
width: 180px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #000;
|
color: #000;
|
||||||
|
line-height: 25px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -39,8 +39,8 @@ limitations under the License. -->
|
|||||||
<el-pagination
|
<el-pagination
|
||||||
v-model:currentPage="pageNum"
|
v-model:currentPage="pageNum"
|
||||||
v-model:page-size="pageSize"
|
v-model:page-size="pageSize"
|
||||||
layout="prev, jumper, total, next"
|
layout="prev, pager, next"
|
||||||
:total="alarmStore.total"
|
:total="total"
|
||||||
@current-change="changePage"
|
@current-change="changePage"
|
||||||
:pager-count="5"
|
:pager-count="5"
|
||||||
small
|
small
|
||||||
@ -55,7 +55,7 @@ limitations under the License. -->
|
|||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref, computed } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import ConditionTags from "@/views/components/ConditionTags.vue";
|
import ConditionTags from "@/views/components/ConditionTags.vue";
|
||||||
import { AlarmOptions } from "./data";
|
import { AlarmOptions } from "./data";
|
||||||
@ -70,6 +70,11 @@ const pageSize = 20;
|
|||||||
const entity = ref<string>("");
|
const entity = ref<string>("");
|
||||||
const keyword = ref<string>("");
|
const keyword = ref<string>("");
|
||||||
const pageNum = ref<number>(1);
|
const pageNum = ref<number>(1);
|
||||||
|
const total = computed(() =>
|
||||||
|
alarmStore.alarms.length === pageSize
|
||||||
|
? pageSize * pageNum.value + 1
|
||||||
|
: pageSize * pageNum.value
|
||||||
|
);
|
||||||
|
|
||||||
refreshAlarms({ pageNum: 1 });
|
refreshAlarms({ pageNum: 1 });
|
||||||
|
|
||||||
@ -79,7 +84,6 @@ async function refreshAlarms(param: { pageNum: number; tagsMap?: any }) {
|
|||||||
paging: {
|
paging: {
|
||||||
pageNum: param.pageNum,
|
pageNum: param.pageNum,
|
||||||
pageSize,
|
pageSize,
|
||||||
needTotal: true,
|
|
||||||
},
|
},
|
||||||
tags: param.tagsMap,
|
tags: param.tagsMap,
|
||||||
};
|
};
|
||||||
|
@ -13,73 +13,107 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div class="flex-h" :class="{ light: theme === 'light' }">
|
<div>
|
||||||
<div class="flex-h items-center mr-5">
|
<span class="grey">{{ t("tags") }}: </span>
|
||||||
<span class="sm grey" v-show="theme === 'dark'">{{ t("tags") }}: </span>
|
<span
|
||||||
<span v-if="tagsList.length" class="trace-tags">
|
v-if="tagsList.length"
|
||||||
<!-- :style="type === 'LOG' ? `min-width: 122px;` : ''" -->
|
class="trace-tags"
|
||||||
|
:style="type === 'LOG' ? `min-width: 122px;` : ''"
|
||||||
|
>
|
||||||
<span class="selected" v-for="(item, index) in tagsList" :key="index">
|
<span class="selected" v-for="(item, index) in tagsList" :key="index">
|
||||||
<span>{{ item }}</span>
|
<span>{{ item }}</span>
|
||||||
<span class="remove-icon" @click="removeTags(index)">×</span>
|
<span class="remove-icon" @click="removeTags(index)">×</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<el-input
|
<el-input
|
||||||
|
v-if="type === 'ALARM'"
|
||||||
size="small"
|
size="small"
|
||||||
v-model="tags"
|
v-model="tags"
|
||||||
class="trace-new-tag"
|
class="trace-new-tag"
|
||||||
@change="addLabels"
|
@change="addLabels"
|
||||||
:placeholder="t('addTags')"
|
:placeholder="t('addTags')"
|
||||||
/>
|
/>
|
||||||
<span class="tags-tip">
|
<span v-else>
|
||||||
|
<el-input
|
||||||
|
size="small"
|
||||||
|
v-model="tags"
|
||||||
|
class="trace-new-tag"
|
||||||
|
@click="showClick"
|
||||||
|
/>
|
||||||
|
<el-dropdown
|
||||||
|
ref="dropdownTag"
|
||||||
|
trigger="contextmenu"
|
||||||
|
:hide-on-click="false"
|
||||||
|
style="margin: 20px 0 0 -130px"
|
||||||
|
v-if="tagArr.length"
|
||||||
|
>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item v-for="(item, index) in tagArr" :key="index">
|
||||||
|
<span @click="selectTag(item)" class="tag-item">
|
||||||
|
{{ item }}
|
||||||
|
</span>
|
||||||
|
</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="tags-tip"
|
||||||
|
:class="type !== 'ALARM' && tagArr.length ? 'link-tips' : ''"
|
||||||
|
>
|
||||||
<a
|
<a
|
||||||
v-if="false"
|
|
||||||
target="blank"
|
target="blank"
|
||||||
href="https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/configuration-vocabulary.md"
|
href="https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/configuration-vocabulary.md"
|
||||||
>
|
>
|
||||||
{{ t("tagsLink") }}
|
{{ t("tagsLink") }}
|
||||||
</a>
|
</a>
|
||||||
<el-tooltip
|
<el-tooltip :content="t(tipsMap[type])">
|
||||||
:content="
|
|
||||||
t(
|
|
||||||
type === 'LOG'
|
|
||||||
? 'logTagsTip'
|
|
||||||
: type === 'TRACE'
|
|
||||||
? 'traceTagsTip'
|
|
||||||
: 'alarmTagsTip'
|
|
||||||
)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span>
|
<span>
|
||||||
<Icon class="icon-help mr-5" iconName="help" size="middle" />
|
<Icon class="icon-help mr-5" iconName="help" size="middle" />
|
||||||
</span>
|
</span>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<!-- <b v-if="type !== 'LOG'">{{ t("noticeTag") }}</b> -->
|
<b v-if="type === 'AL'">{{ t("noticeTag") }}</b>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, defineExpose } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { useTraceStore } from "@/store/modules/trace";
|
||||||
|
import { useLogStore } from "@/store/modules/log";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
|
|
||||||
/*global defineEmits, defineProps */
|
/*global Nullable, defineEmits, defineProps */
|
||||||
const emit = defineEmits(["update"]);
|
const emit = defineEmits(["update"]);
|
||||||
|
const props = defineProps({
|
||||||
defineProps({
|
|
||||||
type: { type: String, default: "TRACE" },
|
type: { type: String, default: "TRACE" },
|
||||||
});
|
});
|
||||||
|
const traceStore = useTraceStore();
|
||||||
|
const logStore = useLogStore();
|
||||||
|
const appStore = useAppStoreWithOut();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const theme = ref<string>("dark");
|
|
||||||
const tags = ref<string>("");
|
const tags = ref<string>("");
|
||||||
const tagsList = ref<string[]>([]);
|
const tagsList = ref<string[]>([]);
|
||||||
|
const tagArr = ref<string[]>([]);
|
||||||
|
const tagKeys = ref<string[]>([]);
|
||||||
|
const tipsMap = {
|
||||||
|
LOG: "logTagsTip",
|
||||||
|
TRACE: "traceTagsTip",
|
||||||
|
ALARM: "alarmTagsTip",
|
||||||
|
};
|
||||||
|
const dropdownTag = ref<Nullable<any>>(null);
|
||||||
|
|
||||||
defineExpose({
|
fetchTagKeys();
|
||||||
tagsList,
|
|
||||||
emptyTags
|
// defineExpose({
|
||||||
})
|
// tagsList,
|
||||||
function emptyTags (){
|
// emptyTags
|
||||||
tagsList.value = []
|
// })
|
||||||
}
|
// function emptyTags (){
|
||||||
|
// tagsList.value = []
|
||||||
|
// }
|
||||||
function removeTags(index: number) {
|
function removeTags(index: number) {
|
||||||
tagsList.value.splice(index, 1);
|
tagsList.value.splice(index, 1);
|
||||||
updateTags();
|
updateTags();
|
||||||
@ -102,11 +136,67 @@ function updateTags() {
|
|||||||
});
|
});
|
||||||
emit("update", { tagsMap, tagsList: tagsList.value });
|
emit("update", { tagsMap, tagsList: tagsList.value });
|
||||||
}
|
}
|
||||||
|
async function fetchTagKeys() {
|
||||||
|
let resp: any = {};
|
||||||
|
if (props.type === "TRACE") {
|
||||||
|
resp = await traceStore.getTagKeys();
|
||||||
|
} else {
|
||||||
|
resp = await logStore.getLogTagKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.errors) {
|
||||||
|
ElMessage.error(resp.errors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tagArr.value = resp.data.tagKeys;
|
||||||
|
tagKeys.value = resp.data.tagKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchTagValues() {
|
||||||
|
const param = tags.value.split("=")[0];
|
||||||
|
let resp: any = {};
|
||||||
|
if (props.type === "TRACE") {
|
||||||
|
resp = await traceStore.getTagValues(param);
|
||||||
|
} else {
|
||||||
|
resp = await logStore.getLogTagValues(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.errors) {
|
||||||
|
ElMessage.error(resp.errors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tagArr.value = resp.data.tagValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectTag(item: string) {
|
||||||
|
if (tags.value.includes("=")) {
|
||||||
|
tags.value += item;
|
||||||
|
addLabels();
|
||||||
|
tagArr.value = tagKeys.value;
|
||||||
|
dropdownTag.value.handleClose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tags.value = item + "=";
|
||||||
|
fetchTagValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showClick() {
|
||||||
|
if (dropdownTag.value) {
|
||||||
|
dropdownTag.value.handleOpen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
watch(
|
||||||
|
() => appStore.durationTime,
|
||||||
|
() => {
|
||||||
|
fetchTagKeys();
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.items-center {
|
.items-center {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trace-tags {
|
.trace-tags {
|
||||||
padding: 1px 5px 0 0;
|
padding: 1px 5px 0 0;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
@ -131,7 +221,6 @@ function updateTags() {
|
|||||||
padding: 2px 5px;
|
padding: 2px 5px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
margin-right: 3px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.remove-icon {
|
.remove-icon {
|
||||||
@ -140,10 +229,20 @@ function updateTags() {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tag-item {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 210px;
|
||||||
|
}
|
||||||
|
|
||||||
.tags-tip {
|
.tags-tip {
|
||||||
color: #a7aebb;
|
color: #a7aebb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.link-tips {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 130px;
|
||||||
|
}
|
||||||
|
|
||||||
.light {
|
.light {
|
||||||
color: #3d444f;
|
color: #3d444f;
|
||||||
|
|
||||||
|
@ -146,9 +146,10 @@ import type { ElTable } from "element-plus";
|
|||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
import { DashboardItem } from "@/types/dashboard";
|
import { DashboardItem, LayoutConfig } from "@/types/dashboard";
|
||||||
import { saveFile, readFile } from "@/utils/file";
|
import { saveFile, readFile } from "@/utils/file";
|
||||||
import { EntityType } from "./data";
|
import { EntityType } from "./data";
|
||||||
|
import { isEmptyObject } from "@/utils/is";
|
||||||
|
|
||||||
/*global Nullable*/
|
/*global Nullable*/
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
@ -221,12 +222,77 @@ function exportTemplates() {
|
|||||||
const layout = JSON.parse(sessionStorage.getItem(key) || "{}");
|
const layout = JSON.parse(sessionStorage.getItem(key) || "{}");
|
||||||
return layout;
|
return layout;
|
||||||
});
|
});
|
||||||
|
for (const item of templates) {
|
||||||
|
optimizeTemplate(item.configuration.children);
|
||||||
|
}
|
||||||
const name = `dashboards.json`;
|
const name = `dashboards.json`;
|
||||||
saveFile(templates, name);
|
saveFile(templates, name);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
multipleTableRef.value!.clearSelection();
|
multipleTableRef.value!.clearSelection();
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
function optimizeTemplate(
|
||||||
|
children: (LayoutConfig & { moved?: boolean; standard?: unknown })[]
|
||||||
|
) {
|
||||||
|
for (const child of children || []) {
|
||||||
|
delete child.moved;
|
||||||
|
delete child.activedTabIndex;
|
||||||
|
delete child.standard;
|
||||||
|
if (isEmptyObject(child.graph)) {
|
||||||
|
delete child.graph;
|
||||||
|
}
|
||||||
|
if (child.widget) {
|
||||||
|
if (child.widget.title === "") {
|
||||||
|
delete child.widget.title;
|
||||||
|
}
|
||||||
|
if (child.widget.tips === "") {
|
||||||
|
delete child.widget.tips;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isEmptyObject(child.widget)) {
|
||||||
|
delete child.widget;
|
||||||
|
}
|
||||||
|
if (!(child.metrics && child.metrics.length && child.metrics[0])) {
|
||||||
|
delete child.metrics;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
!(child.metricTypes && child.metricTypes.length && child.metricTypes[0])
|
||||||
|
) {
|
||||||
|
delete child.metricTypes;
|
||||||
|
}
|
||||||
|
if (child.metricConfig && child.metricConfig.length) {
|
||||||
|
child.metricConfig.forEach((c, index) => {
|
||||||
|
if (!c.calculation) {
|
||||||
|
delete c.calculation;
|
||||||
|
}
|
||||||
|
if (!c.unit) {
|
||||||
|
delete c.unit;
|
||||||
|
}
|
||||||
|
if (!c.label) {
|
||||||
|
delete c.label;
|
||||||
|
}
|
||||||
|
if (isEmptyObject(c)) {
|
||||||
|
(child.metricConfig || []).splice(index, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!(child.metricConfig && child.metricConfig.length)) {
|
||||||
|
delete child.metricConfig;
|
||||||
|
}
|
||||||
|
if (child.type === "Tab") {
|
||||||
|
for (const item of child.children || []) {
|
||||||
|
optimizeTemplate(item.children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
["Trace", "Topology", "Tab", "Profile", "Ebpf", "Log"].includes(
|
||||||
|
child.type
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
delete child.widget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
function handleEdit(row: DashboardItem) {
|
function handleEdit(row: DashboardItem) {
|
||||||
dashboardStore.setMode(true);
|
dashboardStore.setMode(true);
|
||||||
dashboardStore.setEntity(row.entity);
|
dashboardStore.setEntity(row.entity);
|
||||||
|
@ -41,7 +41,6 @@ import { useDashboardStore } from "@/store/modules/dashboard";
|
|||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const { selectedGrid } = dashboardStore;
|
|
||||||
const widget = dashboardStore.selectedGrid.widget || {};
|
const widget = dashboardStore.selectedGrid.widget || {};
|
||||||
const title = ref<string>(widget.title || "");
|
const title = ref<string>(widget.title || "");
|
||||||
const tips = ref<string>(widget.tips || "");
|
const tips = ref<string>(widget.tips || "");
|
||||||
@ -51,6 +50,7 @@ function updateWidgetConfig(param: { [key: string]: string }) {
|
|||||||
if (!key) {
|
if (!key) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const { selectedGrid } = dashboardStore;
|
||||||
const widget = {
|
const widget = {
|
||||||
...dashboardStore.selectedGrid.widget,
|
...dashboardStore.selectedGrid.widget,
|
||||||
[key]: decodeURIComponent(param[key]),
|
[key]: decodeURIComponent(param[key]),
|
||||||
|
93
src/views/dashboard/controls/DemandLog.vue
Normal file
93
src/views/dashboard/controls/DemandLog.vue
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License. -->
|
||||||
|
<template>
|
||||||
|
<div class="log-wrapper flex-v">
|
||||||
|
<el-popover
|
||||||
|
placement="bottom"
|
||||||
|
trigger="click"
|
||||||
|
:width="100"
|
||||||
|
v-if="dashboardStore.editMode"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<span class="delete cp">
|
||||||
|
<Icon iconName="ellipsis_v" size="middle" class="operation" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<div class="tools" @click="removeWidget">
|
||||||
|
<span>{{ t("delete") }}</span>
|
||||||
|
</div>
|
||||||
|
</el-popover>
|
||||||
|
<div class="header">
|
||||||
|
<Header />
|
||||||
|
</div>
|
||||||
|
<Content />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
|
import Header from "../related/demand-log/Header.vue";
|
||||||
|
import Content from "../related/demand-log/Content.vue";
|
||||||
|
|
||||||
|
/*global defineProps */
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
activeIndex: { type: String, default: "" },
|
||||||
|
});
|
||||||
|
const { t } = useI18n();
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
|
||||||
|
function removeWidget() {
|
||||||
|
dashboardStore.removeControls(props.data);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.log-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
font-size: 12px;
|
||||||
|
position: relative;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
border-bottom: 1px solid #dcdfe6;
|
||||||
|
min-width: 1024px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tools {
|
||||||
|
padding: 5px 0;
|
||||||
|
color: #999;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #409eff;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -29,7 +29,7 @@ limitations under the License. -->
|
|||||||
<span>{{ t("delete") }}</span>
|
<span>{{ t("delete") }}</span>
|
||||||
</div>
|
</div>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
<Header />
|
<Header :needQuery="needQuery" />
|
||||||
<Content />
|
<Content />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -47,6 +47,7 @@ const props = defineProps({
|
|||||||
default: () => ({ graph: {} }),
|
default: () => ({ graph: {} }),
|
||||||
},
|
},
|
||||||
activeIndex: { type: String, default: "" },
|
activeIndex: { type: String, default: "" },
|
||||||
|
needQuery: { type: Boolean, default: true },
|
||||||
});
|
});
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
|
102
src/views/dashboard/controls/Event.vue
Normal file
102
src/views/dashboard/controls/Event.vue
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License. -->
|
||||||
|
<template>
|
||||||
|
<div class="event-wrapper flex-v">
|
||||||
|
<el-popover
|
||||||
|
placement="bottom"
|
||||||
|
trigger="click"
|
||||||
|
:width="100"
|
||||||
|
v-if="dashboardStore.editMode"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<span class="delete cp">
|
||||||
|
<Icon iconName="ellipsis_v" size="middle" class="operation" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<div class="tools" @click="removeWidget">
|
||||||
|
<span>{{ t("delete") }}</span>
|
||||||
|
</div>
|
||||||
|
</el-popover>
|
||||||
|
<div class="header">
|
||||||
|
<Header :needQuery="needQuery" />
|
||||||
|
</div>
|
||||||
|
<div class="event">
|
||||||
|
<Content />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
|
import Header from "../related/event/Header.vue";
|
||||||
|
import Content from "../related/event/Content.vue";
|
||||||
|
|
||||||
|
/*global defineProps */
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
activeIndex: { type: String, default: "" },
|
||||||
|
needQuery: { type: Boolean, default: true },
|
||||||
|
});
|
||||||
|
const { t } = useI18n();
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
|
||||||
|
function removeWidget() {
|
||||||
|
dashboardStore.removeControls(props.data);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.event-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
font-size: 12px;
|
||||||
|
position: relative;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
right: 3px;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
border-bottom: 1px solid #dcdfe6;
|
||||||
|
min-width: 1024px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tools {
|
||||||
|
padding: 5px 0;
|
||||||
|
color: #999;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #409eff;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.event {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 80px);
|
||||||
|
}
|
||||||
|
</style>
|
@ -13,10 +13,88 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="log-wrapper flex-v">
|
||||||
<JbLog />
|
<el-popover
|
||||||
|
placement="bottom"
|
||||||
|
trigger="click"
|
||||||
|
:width="100"
|
||||||
|
v-if="dashboardStore.editMode"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<span class="delete cp">
|
||||||
|
<Icon iconName="ellipsis_v" size="middle" class="operation" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<div class="tools" @click="removeWidget">
|
||||||
|
<span>{{ t("delete") }}</span>
|
||||||
|
</div>
|
||||||
|
</el-popover>
|
||||||
|
<div class="header">
|
||||||
|
<Header :needQuery="needQuery" />
|
||||||
|
</div>
|
||||||
|
<div class="log">
|
||||||
|
<List />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import JbLog from "./JbLog.vue";
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
|
import Header from "../related/log/Header.vue";
|
||||||
|
import List from "../related/log/List.vue";
|
||||||
|
|
||||||
|
/*global defineProps */
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
activeIndex: { type: String, default: "" },
|
||||||
|
needQuery: { type: Boolean, default: true },
|
||||||
|
});
|
||||||
|
const { t } = useI18n();
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
|
||||||
|
function removeWidget() {
|
||||||
|
dashboardStore.removeControls(props.data);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.log-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
font-size: 12px;
|
||||||
|
position: relative;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
border-bottom: 1px solid #dcdfe6;
|
||||||
|
min-width: 1024px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tools {
|
||||||
|
padding: 5px 0;
|
||||||
|
color: #999;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #409eff;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.log {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -29,7 +29,7 @@ limitations under the License. -->
|
|||||||
<span>{{ t("delete") }}</span>
|
<span>{{ t("delete") }}</span>
|
||||||
</div>
|
</div>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
<Header />
|
<Header :needQuery="needQuery" />
|
||||||
<Content />
|
<Content />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -47,6 +47,7 @@ const props = defineProps({
|
|||||||
default: () => ({ graph: {} }),
|
default: () => ({ graph: {} }),
|
||||||
},
|
},
|
||||||
activeIndex: { type: String, default: "" },
|
activeIndex: { type: String, default: "" },
|
||||||
|
needQuery: { type: Boolean, default: true },
|
||||||
});
|
});
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
|
@ -13,8 +13,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div ref="tabRef" class="flex-h tab-header">
|
<div class="flex-h tab-header">
|
||||||
<div class="tabs">
|
<div class="tabs scroll_bar_style" @click="handleClick">
|
||||||
<span
|
<span
|
||||||
v-for="(child, idx) in data.children || []"
|
v-for="(child, idx) in data.children || []"
|
||||||
:key="idx"
|
:key="idx"
|
||||||
@ -26,55 +26,48 @@ limitations under the License. -->
|
|||||||
v-model="child.name"
|
v-model="child.name"
|
||||||
placeholder="Please input"
|
placeholder="Please input"
|
||||||
class="tab-name"
|
class="tab-name"
|
||||||
:readonly="isNaN(editTabIndex)"
|
:readonly="isNaN(editTabIndex) && !canEditTabName"
|
||||||
:class="{ view: isNaN(editTabIndex) }"
|
:class="{ view: !canEditTabName }"
|
||||||
/>
|
/>
|
||||||
<Icon
|
<Icon
|
||||||
v-show="activeTabIndex === idx"
|
v-show="activeTabIndex === idx"
|
||||||
size="sm"
|
size="sm"
|
||||||
iconName="cancel"
|
iconName="cancel"
|
||||||
@click="deleteTabItem($event, idx)"
|
@click="deleteTabItem($event, idx)"
|
||||||
v-if="dashboardStore.editMode"
|
v-if="dashboardStore.editMode && canEditTabName"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
<span class="tab-icons">
|
||||||
|
<el-tooltip content="Copy Link" placement="bottom">
|
||||||
|
<i @click="copyLink">
|
||||||
|
<Icon size="middle" iconName="review-list" class="tab-icon" />
|
||||||
|
</i>
|
||||||
|
</el-tooltip>
|
||||||
|
</span>
|
||||||
<span class="tab-icons" v-if="dashboardStore.editMode">
|
<span class="tab-icons" v-if="dashboardStore.editMode">
|
||||||
<el-tooltip content="Add tab items" placement="bottom">
|
<el-tooltip content="Add tab items" placement="bottom">
|
||||||
<i @click="addTabItem">
|
<i @click="addTabItem">
|
||||||
<Icon size="middle" iconName="add" />
|
<Icon size="middle" iconName="add_fill" class="tab-icon" />
|
||||||
</i>
|
</i>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="operations" v-if="dashboardStore.editMode">
|
<div class="operations" v-if="dashboardStore.editMode">
|
||||||
<el-popover
|
<el-dropdown placement="bottom" trigger="click" :width="200">
|
||||||
placement="bottom"
|
<span class="icon-operation">
|
||||||
trigger="click"
|
<Icon iconName="ellipsis_v" size="middle" />
|
||||||
:width="200"
|
|
||||||
v-model:visible="showTools"
|
|
||||||
>
|
|
||||||
<template #reference>
|
|
||||||
<span>
|
|
||||||
<Icon
|
|
||||||
iconName="ellipsis_v"
|
|
||||||
size="middle"
|
|
||||||
class="operation"
|
|
||||||
@click="showTools = true"
|
|
||||||
/>
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
<template #dropdown>
|
||||||
<div
|
<el-dropdown-menu>
|
||||||
class="tools"
|
<el-dropdown-item @click="canEditTabName = true">
|
||||||
@click="
|
|
||||||
canEditTabName = true;
|
|
||||||
showTools = false;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span class="edit-tab">{{ t("editTab") }}</span>
|
<span class="edit-tab">{{ t("editTab") }}</span>
|
||||||
</div>
|
</el-dropdown-item>
|
||||||
<div class="tools" @click="removeTab">
|
<el-dropdown-item @click="removeTab">
|
||||||
<span>{{ t("delete") }}</span>
|
<span>{{ t("delete") }}</span>
|
||||||
</div>
|
</el-dropdown-item>
|
||||||
</el-popover>
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-layout" @click="handleClick">
|
<div class="tab-layout" @click="handleClick">
|
||||||
@ -87,41 +80,6 @@ limitations under the License. -->
|
|||||||
:is-resizable="dashboardStore.editMode"
|
:is-resizable="dashboardStore.editMode"
|
||||||
@layout-updated="layoutUpdatedEvent"
|
@layout-updated="layoutUpdatedEvent"
|
||||||
>
|
>
|
||||||
<div
|
|
||||||
ref="tabObserveContainer"
|
|
||||||
class="scroll-tab-container"
|
|
||||||
v-if="dashboardStore.fullView"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-if="dashboardStore.currentTabItems.length > 1"
|
|
||||||
class="scroll-handler__wrapper"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
@click="scrollToGraph(item.i, index)"
|
|
||||||
v-for="(item, index) in dashboardStore.currentTabItems"
|
|
||||||
:key="item.i"
|
|
||||||
:class="[currentItem === index ? 'active' : '']"
|
|
||||||
class="scroll-to"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="tabitem"
|
|
||||||
:id="`tabitem${item.i}`"
|
|
||||||
v-for="item in dashboardStore.currentTabItems"
|
|
||||||
:key="item.i"
|
|
||||||
>
|
|
||||||
<component
|
|
||||||
:is="item.type"
|
|
||||||
:data="item"
|
|
||||||
:activeIndex="`${data.i}-${activeTabIndex}-${item.i}`"
|
|
||||||
:needQuery="needQuery"
|
|
||||||
@click="clickTabGrid($event, item)"
|
|
||||||
:class="{ active: activeTabWidget === item.i }"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<template v-else>
|
|
||||||
<grid-item
|
<grid-item
|
||||||
v-for="item in dashboardStore.currentTabItems"
|
v-for="item in dashboardStore.currentTabItems"
|
||||||
:x="item.x"
|
:x="item.x"
|
||||||
@ -141,14 +99,14 @@ limitations under the License. -->
|
|||||||
:needQuery="needQuery"
|
:needQuery="needQuery"
|
||||||
/>
|
/>
|
||||||
</grid-item>
|
</grid-item>
|
||||||
</template>
|
|
||||||
</grid-layout>
|
</grid-layout>
|
||||||
<div class="no-data-tips" v-else>{{ t("noWidget") }}</div>
|
<div class="no-data-tips" v-else>{{ t("noWidget") }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { ref, watch, onMounted, onBeforeUnmount, defineComponent, toRefs } from "vue";
|
import { ref, watch, defineComponent, toRefs } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { LayoutConfig } from "@/types/dashboard";
|
import { LayoutConfig } from "@/types/dashboard";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
@ -159,7 +117,10 @@ import Profile from "./Profile.vue";
|
|||||||
import Log from "./Log.vue";
|
import Log from "./Log.vue";
|
||||||
import Text from "./Text.vue";
|
import Text from "./Text.vue";
|
||||||
import Ebpf from "./Ebpf.vue";
|
import Ebpf from "./Ebpf.vue";
|
||||||
|
import Event from "./Event.vue";
|
||||||
import { dragIgnoreFrom } from "../data";
|
import { dragIgnoreFrom } from "../data";
|
||||||
|
import DemandLog from "./DemandLog.vue";
|
||||||
|
import copy from "@/utils/copy";
|
||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
data: {
|
data: {
|
||||||
@ -170,92 +131,40 @@ const props = {
|
|||||||
};
|
};
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "Tab",
|
name: "Tab",
|
||||||
components: { Topology, Widget, Trace, Profile, Log, Text, Ebpf },
|
components: {
|
||||||
|
Topology,
|
||||||
|
Widget,
|
||||||
|
Trace,
|
||||||
|
Profile,
|
||||||
|
Log,
|
||||||
|
Text,
|
||||||
|
Ebpf,
|
||||||
|
DemandLog,
|
||||||
|
Event,
|
||||||
|
},
|
||||||
props,
|
props,
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const activeTabIndex = ref<number>(0);
|
const route = useRoute();
|
||||||
|
const activeTabIndex = ref<number>(
|
||||||
|
Number(route.params.activeTabIndex) || 0
|
||||||
|
);
|
||||||
const activeTabWidget = ref<string>("");
|
const activeTabWidget = ref<string>("");
|
||||||
const editTabIndex = ref<number>(NaN); // edit tab item name
|
const editTabIndex = ref<number>(NaN); // edit tab item name
|
||||||
const canEditTabName = ref<boolean>(false);
|
const canEditTabName = ref<boolean>(false);
|
||||||
const needQuery = ref<boolean>(false);
|
const needQuery = ref<boolean>(false);
|
||||||
const showTools = ref<boolean>(false);
|
|
||||||
const tabRef = ref<any>("");
|
|
||||||
const tabObserveContainer = ref<any>(null);
|
|
||||||
const arrayOfItems = ref<Element[]>([]);
|
|
||||||
const currentItem = ref<number>(0);
|
|
||||||
const isScrolling = ref(false);
|
|
||||||
|
|
||||||
const l = dashboardStore.layout.findIndex((d: LayoutConfig) => d.i === props.data.i);
|
dashboardStore.setActiveTabIndex(activeTabIndex);
|
||||||
|
const l = dashboardStore.layout.findIndex(
|
||||||
|
(d: LayoutConfig) => d.i === props.data.i
|
||||||
|
);
|
||||||
if (dashboardStore.layout[l].children.length) {
|
if (dashboardStore.layout[l].children.length) {
|
||||||
dashboardStore.setCurrentTabItems(
|
dashboardStore.setCurrentTabItems(
|
||||||
dashboardStore.layout[l].children[activeTabIndex.value].children
|
dashboardStore.layout[l].children[activeTabIndex.value].children
|
||||||
);
|
);
|
||||||
dashboardStore.setActiveTabIndex(activeTabIndex.value, props.data.i);
|
dashboardStore.setActiveTabIndex(activeTabIndex.value, props.data.i);
|
||||||
setTimeout(() => {
|
|
||||||
observeItems();
|
|
||||||
}, 1500);
|
|
||||||
}
|
}
|
||||||
function scrollToGraph(e: any, index: number) {
|
|
||||||
document?.getElementById(`tabitem${e}`)?.scrollIntoView();
|
|
||||||
currentItem.value = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
function observeItems(kill = false) {
|
|
||||||
const observer = new IntersectionObserver((entries) => {
|
|
||||||
entries.forEach((element) => {
|
|
||||||
if (element.isIntersecting && element.intersectionRatio > 0) {
|
|
||||||
setTimeout(() => {
|
|
||||||
// currentItem.value = element.target.id;
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
document.querySelectorAll(".tabitem").forEach((element) => {
|
|
||||||
arrayOfItems.value.push(element);
|
|
||||||
observer.observe(element);
|
|
||||||
});
|
|
||||||
if (kill) {
|
|
||||||
document.querySelectorAll(".tabitem").forEach((element) => {
|
|
||||||
observer.unobserve(element);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function scrollUp() {
|
|
||||||
if (currentItem.value > 0) {
|
|
||||||
currentItem.value--;
|
|
||||||
scrollTo(currentItem.value);
|
|
||||||
} else if (currentItem.value === 0) {
|
|
||||||
isScrolling.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function scrollDown() {
|
|
||||||
if (currentItem.value < arrayOfItems?.value?.length - 1) {
|
|
||||||
currentItem.value++;
|
|
||||||
scrollTo(currentItem.value);
|
|
||||||
} else if (currentItem.value === arrayOfItems?.value?.length - 1) {
|
|
||||||
isScrolling.value = true;
|
|
||||||
currentItem.value = 0;
|
|
||||||
scrollTo(currentItem.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function scrollTo(index: number) {
|
|
||||||
arrayOfItems.value[index]?.scrollIntoView();
|
|
||||||
if (isScrolling.value) {
|
|
||||||
setTimeout(() => {
|
|
||||||
isScrolling.value = false;
|
|
||||||
}, 800);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
watch(
|
|
||||||
() => dashboardStore.currentTabItems,
|
|
||||||
() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
observeItems();
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
function clickTabs(e: Event, idx: number) {
|
function clickTabs(e: Event, idx: number) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@ -270,6 +179,11 @@ export default defineComponent({
|
|||||||
dashboardStore.layout[l].children[activeTabIndex.value].children
|
dashboardStore.layout[l].children[activeTabIndex.value].children
|
||||||
);
|
);
|
||||||
needQuery.value = true;
|
needQuery.value = true;
|
||||||
|
if (route.params.activeTabIndex) {
|
||||||
|
let p = location.href.split("/tab/")[0];
|
||||||
|
p = p + "/tab/" + activeTabIndex.value;
|
||||||
|
history.replaceState({}, "", p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function removeTab(e: Event) {
|
function removeTab(e: Event) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@ -296,6 +210,7 @@ export default defineComponent({
|
|||||||
editTabIndex.value = index;
|
editTabIndex.value = index;
|
||||||
}
|
}
|
||||||
function handleClick(el: any) {
|
function handleClick(el: any) {
|
||||||
|
needQuery.value = true;
|
||||||
if (["tab-name", "edit-tab"].includes(el.target.className)) {
|
if (["tab-name", "edit-tab"].includes(el.target.className)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -305,7 +220,9 @@ export default defineComponent({
|
|||||||
function clickTabGrid(e: Event, item: LayoutConfig) {
|
function clickTabGrid(e: Event, item: LayoutConfig) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
activeTabWidget.value = item.i;
|
activeTabWidget.value = item.i;
|
||||||
dashboardStore.activeGridItem(`${props.data.i}-${activeTabIndex.value}-${item.i}`);
|
dashboardStore.activeGridItem(
|
||||||
|
`${props.data.i}-${activeTabIndex.value}-${item.i}`
|
||||||
|
);
|
||||||
handleClick(e);
|
handleClick(e);
|
||||||
}
|
}
|
||||||
function layoutUpdatedEvent() {
|
function layoutUpdatedEvent() {
|
||||||
@ -316,18 +233,15 @@ export default defineComponent({
|
|||||||
dashboardStore.layout[l].children[activeTabIndex.value].children
|
dashboardStore.layout[l].children[activeTabIndex.value].children
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
function copyLink() {
|
||||||
function initScrollWatcher() {
|
let path = "";
|
||||||
tabObserveContainer?.value?.addEventListener("wheel", (e: WheelEvent) => {
|
if (route.params.activeTabIndex === undefined) {
|
||||||
if (isScrolling.value === false) {
|
path = location.href + "/tab/" + activeTabIndex.value;
|
||||||
isScrolling.value = true;
|
|
||||||
if (e.deltaY < 0) {
|
|
||||||
scrollUp();
|
|
||||||
} else {
|
} else {
|
||||||
scrollDown();
|
const p = location.href.split("/tab/")[0];
|
||||||
|
path = p + "/tab/" + activeTabIndex.value;
|
||||||
}
|
}
|
||||||
}
|
copy(path);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
document.body.addEventListener("click", handleClick, false);
|
document.body.addEventListener("click", handleClick, false);
|
||||||
watch(
|
watch(
|
||||||
@ -345,17 +259,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
onMounted(() => {
|
|
||||||
initScrollWatcher();
|
|
||||||
tabRef?.value["parentElement"]?.classList?.toggle("item");
|
|
||||||
});
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
observeItems(true);
|
|
||||||
});
|
|
||||||
return {
|
return {
|
||||||
currentItem,
|
|
||||||
tabObserveContainer,
|
|
||||||
scrollToGraph,
|
|
||||||
handleClick,
|
handleClick,
|
||||||
layoutUpdatedEvent,
|
layoutUpdatedEvent,
|
||||||
clickTabGrid,
|
clickTabGrid,
|
||||||
@ -364,15 +268,14 @@ export default defineComponent({
|
|||||||
deleteTabItem,
|
deleteTabItem,
|
||||||
removeTab,
|
removeTab,
|
||||||
clickTabs,
|
clickTabs,
|
||||||
|
copyLink,
|
||||||
...toRefs(props),
|
...toRefs(props),
|
||||||
tabRef,
|
|
||||||
activeTabWidget,
|
activeTabWidget,
|
||||||
dashboardStore,
|
dashboardStore,
|
||||||
activeTabIndex,
|
activeTabIndex,
|
||||||
editTabIndex,
|
editTabIndex,
|
||||||
needQuery,
|
needQuery,
|
||||||
canEditTabName,
|
canEditTabName,
|
||||||
showTools,
|
|
||||||
t,
|
t,
|
||||||
dragIgnoreFrom,
|
dragIgnoreFrom,
|
||||||
};
|
};
|
||||||
@ -380,76 +283,33 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.tab-layout::-webkit-scrollbar {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
.scroll-tab-container {
|
|
||||||
position: relative;
|
|
||||||
height: 80vh;
|
|
||||||
display: block;
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
-webkit-backface-visibility: hidden;
|
|
||||||
backface-visibility: hidden;
|
|
||||||
perspective: 1000;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.scroll-tab-container::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.scroll-tab-container {
|
|
||||||
-ms-overflow-style: none;
|
|
||||||
scrollbar-width: none;
|
|
||||||
}
|
|
||||||
.tabitem {
|
|
||||||
scroll-snap-align: start;
|
|
||||||
height: 100%;
|
|
||||||
margin: 0 0;
|
|
||||||
}
|
|
||||||
.scroll-handler__wrapper {
|
|
||||||
z-index: 20;
|
|
||||||
position: fixed;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
right: 0;
|
|
||||||
top: 40vh;
|
|
||||||
height: auto;
|
|
||||||
width: 17px;
|
|
||||||
.scroll-to {
|
|
||||||
opacity: 0.5;
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
margin: 5px 0;
|
|
||||||
border-radius: 50%;
|
|
||||||
cursor: pointer;
|
|
||||||
background: #4f4f4f;
|
|
||||||
}
|
|
||||||
.scroll-to.active {
|
|
||||||
opacity: 1;
|
|
||||||
padding: 6px;
|
|
||||||
background: #252a2f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.tabs {
|
.tabs {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-y: hidden;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0 10px;
|
|
||||||
margin: 0 10px;
|
|
||||||
height: 40px;
|
height: 40px;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-name {
|
.tab-name {
|
||||||
max-width: 130px;
|
max-width: 110px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
outline: none;
|
outline: none;
|
||||||
color: #333;
|
color: #333;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-icons {
|
.tab-icons {
|
||||||
@ -470,12 +330,13 @@ export default defineComponent({
|
|||||||
|
|
||||||
span.active {
|
span.active {
|
||||||
border-bottom: 1px solid #409eff;
|
border-bottom: 1px solid #409eff;
|
||||||
|
|
||||||
|
.tab-name {
|
||||||
color: #409eff;
|
color: #409eff;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.tab-header .tabs .span.active {
|
|
||||||
color: red !important;
|
|
||||||
}
|
|
||||||
.operations {
|
.operations {
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -484,6 +345,11 @@ export default defineComponent({
|
|||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-operation {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.tab-header {
|
.tab-header {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -506,6 +372,10 @@ export default defineComponent({
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-icon {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
.vue-grid-item.active {
|
.vue-grid-item.active {
|
||||||
border: 1px solid #409eff;
|
border: 1px solid #409eff;
|
||||||
}
|
}
|
||||||
@ -517,17 +387,4 @@ export default defineComponent({
|
|||||||
padding-top: 30px;
|
padding-top: 30px;
|
||||||
color: #888;
|
color: #888;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tools {
|
|
||||||
padding: 5px 0;
|
|
||||||
color: #999;
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #409eff;
|
|
||||||
background-color: #eee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -29,6 +29,9 @@ limitations under the License. -->
|
|||||||
<span>{{ t("delete") }}</span>
|
<span>{{ t("delete") }}</span>
|
||||||
</div>
|
</div>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
|
<div class="header">
|
||||||
|
<Filter :needQuery="needQuery" />
|
||||||
|
</div>
|
||||||
<div class="trace flex-h">
|
<div class="trace flex-h">
|
||||||
<TraceList @show:trace="showTraceDetails" v-if="traceListActive" />
|
<TraceList @show:trace="showTraceDetails" v-if="traceListActive" />
|
||||||
<TraceDetail @show:list="showTraceList" v-if="!traceListActive" />
|
<TraceDetail @show:list="showTraceList" v-if="!traceListActive" />
|
||||||
@ -51,6 +54,7 @@ const props = defineProps({
|
|||||||
default: () => ({ graph: {} }),
|
default: () => ({ graph: {} }),
|
||||||
},
|
},
|
||||||
activeIndex: { type: String, default: "" },
|
activeIndex: { type: String, default: "" },
|
||||||
|
needQuery: { type: Boolean, default: true },
|
||||||
});
|
});
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
@ -81,6 +85,7 @@ onBeforeUnmount(() => {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.delete {
|
.delete {
|
||||||
@ -93,6 +98,7 @@ onBeforeUnmount(() => {
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
border-bottom: 1px solid #dcdfe6;
|
border-bottom: 1px solid #dcdfe6;
|
||||||
|
min-width: 1200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tools {
|
.tools {
|
||||||
@ -112,5 +118,6 @@ onBeforeUnmount(() => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
min-width: 1200px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -22,5 +22,18 @@ import Profile from "./Profile.vue";
|
|||||||
import Log from "./Log.vue";
|
import Log from "./Log.vue";
|
||||||
import Text from "./Text.vue";
|
import Text from "./Text.vue";
|
||||||
import Ebpf from "./Ebpf.vue";
|
import Ebpf from "./Ebpf.vue";
|
||||||
|
import DemandLog from "./DemandLog.vue";
|
||||||
|
import Event from "./Event.vue";
|
||||||
|
|
||||||
export default { Tab, Widget, Trace, Topology, Profile, Log, Text, Ebpf };
|
export default {
|
||||||
|
Tab,
|
||||||
|
Widget,
|
||||||
|
Trace,
|
||||||
|
Topology,
|
||||||
|
Profile,
|
||||||
|
Log,
|
||||||
|
Text,
|
||||||
|
Ebpf,
|
||||||
|
DemandLog,
|
||||||
|
Event,
|
||||||
|
};
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
export const dragIgnoreFrom =
|
export const dragIgnoreFrom =
|
||||||
"svg.d3-trace-tree, .dragger, .micro-topo-chart, .schedules";
|
"svg.d3-trace-tree, .dragger, .micro-topo-chart, .schedules, .vis-item, .vis-timeline";
|
||||||
|
|
||||||
export const PodsChartTypes = ["EndpointList", "InstanceList"];
|
export const PodsChartTypes = ["EndpointList", "InstanceList"];
|
||||||
|
|
||||||
@ -178,14 +178,16 @@ export const AllTools = [
|
|||||||
{ name: "assignment", content: "Add Log", id: "addLog" },
|
{ name: "assignment", content: "Add Log", id: "addLog" },
|
||||||
];
|
];
|
||||||
export const ServiceTools = [
|
export const ServiceTools = [
|
||||||
{ name: "playlist_add", content: "Widget", id: "addWidget" },
|
{ name: "playlist_add", content: "Add Widget", id: "addWidget" },
|
||||||
{ name: "all_inbox", content: "Tab", id: "addTab" },
|
{ name: "all_inbox", content: "Add Tab", id: "addTab" },
|
||||||
{ name: "library_books", content: "Text", id: "addText" },
|
{ name: "library_books", content: "Add Text", id: "addText" },
|
||||||
{ name: "device_hub", content: "Topology", id: "addTopology" },
|
{ name: "device_hub", content: "Add Topology", id: "addTopology" },
|
||||||
{ name: "merge", content: "Trace", id: "addTrace" },
|
{ name: "merge", content: "Add Trace", id: "addTrace" },
|
||||||
{ name: "timeline", content: "Trace Profiling", id: "addProfile" },
|
{ name: "timeline", content: "Add Trace Profiling", id: "addProfile" },
|
||||||
{ name: "insert_chart", content: "eBPF Profiling", id: "addEbpf" },
|
{ name: "insert_chart", content: "Add eBPF Profiling", id: "addEbpf" },
|
||||||
{ name: "assignment", content: "Log", id: "addLog" },
|
{ name: "assignment", content: "Add Log", id: "addLog" },
|
||||||
|
{ name: "demand", content: "Add On Demand Log", id: "addDemandLog" },
|
||||||
|
{ name: "event", content: "Add Event", id: "addEvent" },
|
||||||
];
|
];
|
||||||
export const InstanceTools = [
|
export const InstanceTools = [
|
||||||
{ name: "playlist_add", content: "Add Widget", id: "addWidget" },
|
{ name: "playlist_add", content: "Add Widget", id: "addWidget" },
|
||||||
@ -193,6 +195,8 @@ export const InstanceTools = [
|
|||||||
{ name: "library_books", content: "Add Text", id: "addText" },
|
{ name: "library_books", content: "Add Text", id: "addText" },
|
||||||
{ name: "merge", content: "Add Trace", id: "addTrace" },
|
{ name: "merge", content: "Add Trace", id: "addTrace" },
|
||||||
{ name: "assignment", content: "Add Log", id: "addLog" },
|
{ name: "assignment", content: "Add Log", id: "addLog" },
|
||||||
|
{ name: "demand", content: "Add On Demand Log", id: "addDemandLog" },
|
||||||
|
{ name: "event", content: "Add Event", id: "addEvent" },
|
||||||
];
|
];
|
||||||
export const EndpointTools = [
|
export const EndpointTools = [
|
||||||
{ name: "playlist_add", content: "Add Widget", id: "addWidget" },
|
{ name: "playlist_add", content: "Add Widget", id: "addWidget" },
|
||||||
@ -201,6 +205,7 @@ export const EndpointTools = [
|
|||||||
{ name: "device_hub", content: "Add Topology", id: "addTopology" },
|
{ name: "device_hub", content: "Add Topology", id: "addTopology" },
|
||||||
{ name: "merge", content: "Add Trace", id: "addTrace" },
|
{ name: "merge", content: "Add Trace", id: "addTrace" },
|
||||||
{ name: "assignment", content: "Add Log", id: "addLog" },
|
{ name: "assignment", content: "Add Log", id: "addLog" },
|
||||||
|
{ name: "event", content: "Add Event", id: "addEvent" },
|
||||||
];
|
];
|
||||||
export const ServiceRelationTools = [
|
export const ServiceRelationTools = [
|
||||||
{ name: "playlist_add", content: "Add Widget", id: "addWidget" },
|
{ name: "playlist_add", content: "Add Widget", id: "addWidget" },
|
||||||
|
@ -46,6 +46,7 @@ limitations under the License. -->
|
|||||||
:intervalTime="intervalTime"
|
:intervalTime="intervalTime"
|
||||||
:colMetrics="colMetrics"
|
:colMetrics="colMetrics"
|
||||||
:config="config"
|
:config="config"
|
||||||
|
v-if="colMetrics.length"
|
||||||
/>
|
/>
|
||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
@ -96,7 +97,9 @@ const dashboardStore = useDashboardStore();
|
|||||||
const chartLoading = ref<boolean>(false);
|
const chartLoading = ref<boolean>(false);
|
||||||
const endpoints = ref<Endpoint[]>([]);
|
const endpoints = ref<Endpoint[]>([]);
|
||||||
const searchText = ref<string>("");
|
const searchText = ref<string>("");
|
||||||
const colMetrics = computed(() => props.config.metrics.map((d: string) => d));
|
const colMetrics = computed(() =>
|
||||||
|
(props.config.metrics || []).filter((d: string) => d)
|
||||||
|
);
|
||||||
|
|
||||||
if (props.needQuery) {
|
if (props.needQuery) {
|
||||||
queryEndpoints();
|
queryEndpoints();
|
||||||
@ -119,7 +122,7 @@ async function queryEndpointMetrics(currentPods: Endpoint[]) {
|
|||||||
if (!currentPods.length) {
|
if (!currentPods.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const metrics = (props.config.metrics || []).filter((d: string) => d);
|
const metrics = props.config.metrics || [];
|
||||||
const metricTypes = props.config.metricTypes || [];
|
const metricTypes = props.config.metricTypes || [];
|
||||||
if (metrics.length && metrics[0] && metricTypes.length && metricTypes[0]) {
|
if (metrics.length && metrics[0] && metricTypes.length && metricTypes[0]) {
|
||||||
const params = await useQueryPodsMetrics(
|
const params = await useQueryPodsMetrics(
|
||||||
|
@ -43,6 +43,7 @@ limitations under the License. -->
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<ColumnGraph
|
<ColumnGraph
|
||||||
|
v-if="colMetrics.length"
|
||||||
:intervalTime="intervalTime"
|
:intervalTime="intervalTime"
|
||||||
:colMetrics="colMetrics"
|
:colMetrics="colMetrics"
|
||||||
:config="config"
|
:config="config"
|
||||||
@ -126,7 +127,9 @@ const chartLoading = ref<boolean>(false);
|
|||||||
const instances = ref<Instance[]>([]); // current instances
|
const instances = ref<Instance[]>([]); // current instances
|
||||||
const pageSize = 10;
|
const pageSize = 10;
|
||||||
const searchText = ref<string>("");
|
const searchText = ref<string>("");
|
||||||
const colMetrics = computed(() => props.config.metrics.map((d: string) => d));
|
const colMetrics = computed(() =>
|
||||||
|
(props.config.metrics || []).filter((d: string) => d)
|
||||||
|
);
|
||||||
if (props.needQuery) {
|
if (props.needQuery) {
|
||||||
queryInstance();
|
queryInstance();
|
||||||
}
|
}
|
||||||
@ -151,7 +154,8 @@ async function queryInstanceMetrics(currentInstances: Instance[]) {
|
|||||||
if (!currentInstances.length) {
|
if (!currentInstances.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { metrics, metricTypes } = props.config;
|
const metrics = props.config.metrics || [];
|
||||||
|
const metricTypes = props.config.metricTypes || [];
|
||||||
|
|
||||||
if (metrics.length && metrics[0] && metricTypes.length && metricTypes[0]) {
|
if (metrics.length && metrics[0] && metricTypes.length && metricTypes[0]) {
|
||||||
const params = await useQueryPodsMetrics(
|
const params = await useQueryPodsMetrics(
|
||||||
|
@ -58,6 +58,7 @@ limitations under the License. -->
|
|||||||
:intervalTime="intervalTime"
|
:intervalTime="intervalTime"
|
||||||
:colMetrics="colMetrics"
|
:colMetrics="colMetrics"
|
||||||
:config="config"
|
:config="config"
|
||||||
|
v-if="colMetrics.length"
|
||||||
/>
|
/>
|
||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
@ -117,7 +118,7 @@ const searchText = ref<string>("");
|
|||||||
const groups = ref<any>({});
|
const groups = ref<any>({});
|
||||||
const sortServices = ref<(Service & { merge: boolean })[]>([]);
|
const sortServices = ref<(Service & { merge: boolean })[]>([]);
|
||||||
const colMetrics = computed(() =>
|
const colMetrics = computed(() =>
|
||||||
props.config.metrics.filter((d: string) => d)
|
(props.config.metrics || []).filter((d: string) => d)
|
||||||
);
|
);
|
||||||
queryServices();
|
queryServices();
|
||||||
|
|
||||||
@ -195,7 +196,8 @@ async function queryServiceMetrics(currentServices: Service[]) {
|
|||||||
if (!currentServices.length) {
|
if (!currentServices.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { metrics, metricTypes } = props.config;
|
const metrics = props.config.metrics || [];
|
||||||
|
const metricTypes = props.config.metricTypes || [];
|
||||||
|
|
||||||
if (metrics.length && metrics[0] && metricTypes.length && metricTypes[0]) {
|
if (metrics.length && metrics[0] && metricTypes.length && metricTypes[0]) {
|
||||||
const params = await useQueryPodsMetrics(
|
const params = await useQueryPodsMetrics(
|
||||||
|
@ -17,13 +17,13 @@ limitations under the License. -->
|
|||||||
<div class="top-list" v-if="available">
|
<div class="top-list" v-if="available">
|
||||||
<div class="chart-slow-i" v-for="(i, index) in data[key]" :key="index">
|
<div class="chart-slow-i" v-for="(i, index) in data[key]" :key="index">
|
||||||
<div class="ell tools flex-h">
|
<div class="ell tools flex-h">
|
||||||
<div>
|
<div class="desc">
|
||||||
<span class="calls mr-10">{{ i.value }}</span>
|
<span class="calls mr-10">{{ i.value }}</span>
|
||||||
<span class="cp mr-20">
|
<span class="cp mr-20">
|
||||||
{{ i.name }}
|
{{ i.name }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="copy">
|
||||||
<Icon
|
<Icon
|
||||||
iconName="review-list"
|
iconName="review-list"
|
||||||
size="middle"
|
size="middle"
|
||||||
@ -103,6 +103,16 @@ function handleClick(i: string) {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
flex-grow: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy {
|
||||||
|
width: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
.calls {
|
.calls {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
|
@ -155,7 +155,7 @@ function getLabel(metric: string, index: string) {
|
|||||||
|
|
||||||
.value {
|
.value {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: calc(100% - 30px);
|
flex-grow: 2;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -31,7 +31,7 @@ limitations under the License. -->
|
|||||||
:h="item.h"
|
:h="item.h"
|
||||||
:i="item.i"
|
:i="item.i"
|
||||||
:key="item.i"
|
:key="item.i"
|
||||||
@click="clickGrid(item)"
|
@click="clickGrid(item, $event)"
|
||||||
:class="{ active: dashboardStore.activedGridItem === item.i }"
|
:class="{ active: dashboardStore.activedGridItem === item.i }"
|
||||||
:drag-ignore-from="dragIgnoreFrom"
|
:drag-ignore-from="dragIgnoreFrom"
|
||||||
>
|
>
|
||||||
@ -63,10 +63,13 @@ export default defineComponent({
|
|||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const selectorStore = useSelectorStore();
|
const selectorStore = useSelectorStore();
|
||||||
|
|
||||||
function clickGrid(item: LayoutConfig) {
|
function clickGrid(item: LayoutConfig, event: Event) {
|
||||||
dashboardStore.activeGridItem(item.i);
|
dashboardStore.activeGridItem(item.i);
|
||||||
dashboardStore.selectWidget(item);
|
dashboardStore.selectWidget(item);
|
||||||
if (item.type === "Tab") {
|
if (
|
||||||
|
item.type === "Tab" &&
|
||||||
|
(event.target as HTMLDivElement)?.className !== "tab-layout"
|
||||||
|
) {
|
||||||
dashboardStore.setActiveTabIndex(0);
|
dashboardStore.setActiveTabIndex(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,13 +131,61 @@ limitations under the License. -->
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="selectors-item" v-if="key === 3 || key === 4">
|
||||||
class="flex-h tools"
|
<span class="label">
|
||||||
v-loading="loading"
|
{{
|
||||||
v-if="$route.query['portal'] !== 'true'"
|
["EndpointRelation", "Endpoint"].includes(dashboardStore.entity)
|
||||||
>
|
? "$Endpoint"
|
||||||
|
: "$ServiceInstance"
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
<Selector
|
||||||
|
v-model="states.currentPod"
|
||||||
|
:options="selectorStore.pods"
|
||||||
|
size="small"
|
||||||
|
placeholder="Select a data"
|
||||||
|
@change="changePods"
|
||||||
|
@query="searchPods"
|
||||||
|
class="selectorPod"
|
||||||
|
:isRemote="
|
||||||
|
['EndpointRelation', 'Endpoint'].includes(dashboardStore.entity)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="selectors-item" v-if="key === 2 || key === 4">
|
||||||
|
<span class="label">$DestinationService</span>
|
||||||
|
<Selector
|
||||||
|
v-model="states.currentDestService"
|
||||||
|
:options="selectorStore.destServices"
|
||||||
|
size="small"
|
||||||
|
placeholder="Select a service"
|
||||||
|
@change="changeDestService"
|
||||||
|
class="selectors"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="selectors-item" v-if="key === 4">
|
||||||
|
<span class="label">
|
||||||
|
{{
|
||||||
|
dashboardStore.entity === "EndpointRelation"
|
||||||
|
? "$DestinationEndpoint"
|
||||||
|
: "$DestinationServiceInstance"
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
<Selector
|
||||||
|
v-model="states.currentDestPod"
|
||||||
|
:options="selectorStore.destPods"
|
||||||
|
size="small"
|
||||||
|
placeholder="Select a data"
|
||||||
|
@change="changeDestPods"
|
||||||
|
class="selectorPod"
|
||||||
|
@query="searchDestPods"
|
||||||
|
:isRemote="dashboardStore.entity === 'EndpointRelation'"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-h tools" v-loading="loading" v-if="!appStore.isMobile">
|
||||||
<div class="tool-icons flex-h" v-if="dashboardStore.editMode">
|
<div class="tool-icons flex-h" v-if="dashboardStore.editMode">
|
||||||
<el-dropdown content="Controls" placement="bottom">
|
<el-dropdown content="Controls" placement="bottom" :persistent="false">
|
||||||
<i>
|
<i>
|
||||||
<Icon class="icon-btn" size="sm" iconName="control" />
|
<Icon class="icon-btn" size="sm" iconName="control" />
|
||||||
</i>
|
</i>
|
||||||
@ -174,7 +222,6 @@ limitations under the License. -->
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<Header v-if="showLogHeader" />
|
<Header v-if="showLogHeader" />
|
||||||
<TraceDetailsTools
|
<TraceDetailsTools
|
||||||
v-if="showTraceHeader && currentTraceView === 'traceDetails'"
|
v-if="showTraceHeader && currentTraceView === 'traceDetails'"
|
||||||
@ -423,7 +470,12 @@ async function getServices() {
|
|||||||
states.currentService = selectorStore.currentService.value;
|
states.currentService = selectorStore.currentService.value;
|
||||||
const e = dashboardStore.entity.split("Relation")[0];
|
const e = dashboardStore.entity.split("Relation")[0];
|
||||||
if (
|
if (
|
||||||
[EntityType[2].value, EntityType[3].value].includes(dashboardStore.entity)
|
[
|
||||||
|
EntityType[2].value,
|
||||||
|
EntityType[3].value,
|
||||||
|
EntityType[5].value,
|
||||||
|
EntityType[6].value,
|
||||||
|
].includes(dashboardStore.entity)
|
||||||
) {
|
) {
|
||||||
fetchPods(e, selectorStore.currentService.id, true);
|
fetchPods(e, selectorStore.currentService.id, true);
|
||||||
}
|
}
|
||||||
@ -443,7 +495,10 @@ async function changeService(service: any) {
|
|||||||
if (service[0]) {
|
if (service[0]) {
|
||||||
states.currentService = service[0].value;
|
states.currentService = service[0].value;
|
||||||
selectorStore.setCurrentService(service[0]);
|
selectorStore.setCurrentService(service[0]);
|
||||||
fetchPods(dashboardStore.entity, selectorStore.currentService.id, true);
|
const e = dashboardStore.entity.split("Relation")[0];
|
||||||
|
selectorStore.setCurrentPod(null);
|
||||||
|
states.currentPod = "";
|
||||||
|
fetchPods(e, selectorStore.currentService.id, true);
|
||||||
} else {
|
} else {
|
||||||
selectorStore.setCurrentService(null);
|
selectorStore.setCurrentService(null);
|
||||||
}
|
}
|
||||||
@ -453,6 +508,9 @@ function changeDestService(service: any) {
|
|||||||
if (service[0]) {
|
if (service[0]) {
|
||||||
states.currentDestService = service[0].value;
|
states.currentDestService = service[0].value;
|
||||||
selectorStore.setCurrentDestService(service[0]);
|
selectorStore.setCurrentDestService(service[0]);
|
||||||
|
selectorStore.setCurrentDestPod(null);
|
||||||
|
states.currentDestPod = "";
|
||||||
|
fetchPods(dashboardStore.entity, selectorStore.currentDestService.id, true);
|
||||||
} else {
|
} else {
|
||||||
selectorStore.setCurrentDestService(null);
|
selectorStore.setCurrentDestService(null);
|
||||||
}
|
}
|
||||||
@ -527,6 +585,12 @@ function setTabControls(id: string) {
|
|||||||
case "addText":
|
case "addText":
|
||||||
dashboardStore.addTabControls("Text");
|
dashboardStore.addTabControls("Text");
|
||||||
break;
|
break;
|
||||||
|
case "addDemandLog":
|
||||||
|
dashboardStore.addTabControls("DemandLog");
|
||||||
|
break;
|
||||||
|
case "addEvent":
|
||||||
|
dashboardStore.addTabControls("Event");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ElMessage.info("Don't support this control");
|
ElMessage.info("Don't support this control");
|
||||||
break;
|
break;
|
||||||
@ -559,6 +623,12 @@ function setControls(id: string) {
|
|||||||
case "addText":
|
case "addText":
|
||||||
dashboardStore.addControl("Text");
|
dashboardStore.addControl("Text");
|
||||||
break;
|
break;
|
||||||
|
case "addDemandLog":
|
||||||
|
dashboardStore.addControl("DemandLog");
|
||||||
|
break;
|
||||||
|
case "addEvent":
|
||||||
|
dashboardStore.addControl("Event");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dashboardStore.addControl("Widget");
|
dashboardStore.addControl("Widget");
|
||||||
}
|
}
|
||||||
@ -615,11 +685,11 @@ async function fetchPods(
|
|||||||
if (setPod) {
|
if (setPod) {
|
||||||
let p;
|
let p;
|
||||||
if (states.currentDestPod) {
|
if (states.currentDestPod) {
|
||||||
p = selectorStore.pods.find(
|
p = selectorStore.destPods.find(
|
||||||
(d: { label: string }) => d.label === states.currentDestPod
|
(d: { label: string }) => d.label === states.currentDestPod
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
p = selectorStore.pods.find(
|
p = selectorStore.destPods.find(
|
||||||
(d: { label: string }, index: number) => index === 0
|
(d: { label: string }, index: number) => index === 0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -635,11 +705,11 @@ async function fetchPods(
|
|||||||
if (setPod) {
|
if (setPod) {
|
||||||
let p;
|
let p;
|
||||||
if (states.currentDestPod) {
|
if (states.currentDestPod) {
|
||||||
p = selectorStore.pods.find(
|
p = selectorStore.destPods.find(
|
||||||
(d: { label: string }) => d.label === states.currentDestPod
|
(d: { label: string }) => d.label === states.currentDestPod
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
p = selectorStore.pods.find(
|
p = selectorStore.destPods.find(
|
||||||
(d: { label: string }, index: number) => index === 0
|
(d: { label: string }, index: number) => index === 0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -15,24 +15,21 @@ limitations under the License. -->
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="log">
|
<div class="log">
|
||||||
<div :class="{ 'd-flex': visibleColumns.length < 6 }" class="log-header">
|
|
||||||
<template v-for="(item, index) in columns">
|
|
||||||
<template v-if="item.isVisible">
|
|
||||||
<div
|
<div
|
||||||
class="method"
|
class="log-header"
|
||||||
:style="`width: ${item.method}px`"
|
:class="
|
||||||
v-if="item.drag"
|
type === 'browser' ? ['browser-header', 'flex-h'] : 'service-header'
|
||||||
:key="index"
|
"
|
||||||
|
>
|
||||||
|
<template v-for="(item, index) in columns" :key="`col${index}`">
|
||||||
|
<div
|
||||||
|
:class="[
|
||||||
|
item.label,
|
||||||
|
['message', 'stack'].includes(item.label) ? 'max-item' : '',
|
||||||
|
]"
|
||||||
>
|
>
|
||||||
<span class="r cp" ref="dragger" :data-index="index">
|
|
||||||
<Icon iconName="settings_ethernet" size="sm" />
|
|
||||||
</span>
|
|
||||||
{{ t(item.value) }}
|
{{ t(item.value) }}
|
||||||
</div>
|
</div>
|
||||||
<div v-else :class="item.label" :key="`col${index}`">
|
|
||||||
{{ t(item.value) }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="type === 'browser'">
|
<div v-if="type === 'browser'">
|
||||||
@ -60,40 +57,41 @@ limitations under the License. -->
|
|||||||
@closed="showDetail = false"
|
@closed="showDetail = false"
|
||||||
:title="t('logDetail')"
|
:title="t('logDetail')"
|
||||||
>
|
>
|
||||||
<LogDetail :currentLog="currentLog" />
|
<LogDetail :currentLog="currentLog" :columns="columns" />
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed } from "vue";
|
import { ref } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import LogBrowser from "./LogBrowser.vue";
|
import LogBrowser from "./LogBrowser.vue";
|
||||||
import LogService from "./LogService.vue";
|
import LogService from "./LogService.vue";
|
||||||
import LogDetail from "./LogDetail.vue";
|
import LogDetail from "./LogDetail.vue";
|
||||||
import { logStore } from "@/store/modules/log";
|
// import { logStore } from "@/store/modules/log";
|
||||||
|
import { BrowserLogConstants, ServiceLogConstants } from "./data";
|
||||||
|
|
||||||
/*global defineProps, Nullable */
|
/*global defineProps */
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
type: { type: String, default: "service" },
|
type: { type: String, default: "service" },
|
||||||
tableData: { type: Array, default: () => [] },
|
tableData: { type: Array, default: () => [] },
|
||||||
noLink: { type: Boolean, default: true },
|
noLink: { type: Boolean, default: true },
|
||||||
});
|
});
|
||||||
const useLogStore = logStore();
|
// const useLogStore = logStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const currentLog = ref<any>({});
|
const currentLog = ref<any>({});
|
||||||
const showDetail = ref<boolean>(false);
|
const showDetail = ref<boolean>(false);
|
||||||
const dragger = ref<Nullable<HTMLSpanElement>>(null);
|
const columns: any[] =
|
||||||
// const method = ref<number>(380);
|
props.type === "browser" ? BrowserLogConstants : ServiceLogConstants;
|
||||||
|
|
||||||
const columns = ref<any[]>(
|
// const columns = ref<any[]>(
|
||||||
props.type === "browser"
|
// props.type === "browser"
|
||||||
? useLogStore.browserLogColumn
|
// ? useLogStore.browserLogColumn
|
||||||
: useLogStore.serviceLogColumn
|
// : useLogStore.serviceLogColumn
|
||||||
);
|
// );
|
||||||
|
|
||||||
const visibleColumns = computed(() =>
|
// const visibleColumns = computed(() =>
|
||||||
columns.value.filter((column) => column.isVisible)
|
// columns.value.filter((column) => column.isVisible)
|
||||||
);
|
// );
|
||||||
function setCurrentLog(log: any) {
|
function setCurrentLog(log: any) {
|
||||||
showDetail.value = true;
|
showDetail.value = true;
|
||||||
currentLog.value = log;
|
currentLog.value = log;
|
||||||
@ -103,17 +101,18 @@ function setCurrentLog(log: any) {
|
|||||||
.log {
|
.log {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
width: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.log-header {
|
.log-header {
|
||||||
/*display: flex;*/
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
/*background-color: #f3f4f9;*/
|
|
||||||
.traceId {
|
.traceId {
|
||||||
width: 390px;
|
width: 390px;
|
||||||
}
|
}
|
||||||
@ -131,11 +130,8 @@ function setCurrentLog(log: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.log-header div {
|
.log-header div {
|
||||||
/*min-width: 140px;*/
|
|
||||||
width: 140px;
|
|
||||||
/*flex-grow: 1;*/
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0 4px;
|
padding: 0 5px;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
border-right: 1px dotted silver;
|
border-right: 1px dotted silver;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
@ -145,10 +141,18 @@ function setCurrentLog(log: any) {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.d-flex{
|
.browser-header {
|
||||||
display: flex;
|
div {
|
||||||
div{
|
min-width: 140px;
|
||||||
flex-grow: 1;
|
width: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-item {
|
||||||
|
width: 20%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.service-header div {
|
||||||
|
width: 140px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -14,18 +14,18 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div @click="showSelectSpan" :class="['log-item', 'clearfix']" ref="logItem">
|
<div
|
||||||
|
@click="showSelectSpan"
|
||||||
|
:class="['log-item', 'clearfix', 'flex-h']"
|
||||||
|
ref="logItem"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(item, index) in columns"
|
v-for="(item, index) in columns"
|
||||||
:key="index"
|
:key="index"
|
||||||
:class="[
|
:class="[
|
||||||
'method',
|
'log',
|
||||||
['message', 'stack'].includes(item.label) ? 'autoHeight' : '',
|
['message', 'stack'].includes(item.label) ? 'max-item' : '',
|
||||||
]"
|
]"
|
||||||
:style="{
|
|
||||||
lineHeight: 1.3,
|
|
||||||
width: `${item.drag ? item.method : ''}px`,
|
|
||||||
}"
|
|
||||||
>
|
>
|
||||||
<span v-if="item.label === 'time'">{{ dateFormat(data.time) }}</span>
|
<span v-if="item.label === 'time'">{{ dateFormat(data.time) }}</span>
|
||||||
<span v-else-if="item.label === 'errorUrl'">{{ data.pagePath }}</span>
|
<span v-else-if="item.label === 'errorUrl'">{{ data.pagePath }}</span>
|
||||||
@ -44,7 +44,7 @@ import { BrowserLogConstants } from "./data";
|
|||||||
|
|
||||||
/*global defineProps, defineEmits, NodeListOf */
|
/*global defineProps, defineEmits, NodeListOf */
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: { type: Array as any, default: () => [] },
|
data: { type: Object as any, default: () => ({}) },
|
||||||
});
|
});
|
||||||
const columns = BrowserLogConstants;
|
const columns = BrowserLogConstants;
|
||||||
const emit = defineEmits(["select"]);
|
const emit = defineEmits(["select"]);
|
||||||
@ -84,7 +84,8 @@ function showSelectSpan() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.log-item > div {
|
.log-item > div {
|
||||||
width: 140px;
|
width: 10%;
|
||||||
|
min-width: 140px;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
@ -95,6 +96,10 @@ function showSelectSpan() {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.max-item.log {
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
|
||||||
.log-item .text {
|
.log-item .text {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -103,8 +108,7 @@ function showSelectSpan() {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.log-item > div.method {
|
.log-item > div.log {
|
||||||
padding: 7px 5px;
|
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -20,7 +20,10 @@ limitations under the License. -->
|
|||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
<span class="g-sm-4 grey">{{ t(item.value) }}:</span>
|
<span class="g-sm-4 grey">{{ t(item.value) }}:</span>
|
||||||
<span v-if="item.label === 'timestamp'" class="g-sm-8 mb-10">
|
<span
|
||||||
|
v-if="['timestamp', 'time'].includes(item.label)"
|
||||||
|
class="g-sm-8 mb-10"
|
||||||
|
>
|
||||||
{{ dateFormat(currentLog[item.label]) }}
|
{{ dateFormat(currentLog[item.label]) }}
|
||||||
</span>
|
</span>
|
||||||
<textarea
|
<textarea
|
||||||
@ -41,14 +44,14 @@ import { computed } from "vue";
|
|||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { ServiceLogDetail } from "./data";
|
import { Option } from "@/types/app";
|
||||||
|
|
||||||
/*global defineProps */
|
/*global defineProps */
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
currentLog: { type: Object as PropType<any>, default: () => ({}) },
|
currentLog: { type: Object as PropType<any>, default: () => ({}) },
|
||||||
|
columns: { type: Array as PropType<Option[]>, default: () => [] },
|
||||||
});
|
});
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const columns = ServiceLogDetail;
|
|
||||||
const logTags = computed(() => {
|
const logTags = computed(() => {
|
||||||
if (!props.currentLog.tags) {
|
if (!props.currentLog.tags) {
|
||||||
return [];
|
return [];
|
||||||
|
@ -30,12 +30,12 @@ limitations under the License. -->
|
|||||||
<span v-else-if="item.label === 'tags'">
|
<span v-else-if="item.label === 'tags'">
|
||||||
{{ tags }}
|
{{ tags }}
|
||||||
</span>
|
</span>
|
||||||
<router-link
|
<!-- <router-link
|
||||||
v-else-if="item.label === 'traceId' && !noLink"
|
v-else-if="item.label === 'traceId' && !noLink"
|
||||||
:to="{ name: 'trace', query: { traceid: data[item.label] } }"
|
:to="{ name: 'trace', query: { traceid: data[item.label] } }"
|
||||||
>
|
>
|
||||||
<span :class="noLink ? '' : 'blue'">{{ data[item.label] }}</span>
|
<span :class="noLink ? '' : 'blue'">{{ data[item.label] }}</span>
|
||||||
</router-link>
|
</router-link> -->
|
||||||
<span v-else>{{ data[item.label] }}</span>
|
<span v-else>{{ data[item.label] }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -131,9 +131,10 @@ function showSelectSpan() {
|
|||||||
padding: 3px 8px;
|
padding: 3px 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.d-flex{
|
.d-flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
div{
|
|
||||||
|
div {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
99
src/views/dashboard/related/demand-log/Content.vue
Normal file
99
src/views/dashboard/related/demand-log/Content.vue
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License. -->
|
||||||
|
<template>
|
||||||
|
<span v-if="demandLogStore.message">{{ demandLogStore.message }}</span>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
v-loading="demandLogStore.loadLogs"
|
||||||
|
class="log-content"
|
||||||
|
ref="logContent"
|
||||||
|
style="width: calc(100% - 10px); height: calc(100% - 140px)"
|
||||||
|
></div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { onMounted, ref, onUnmounted, watch, toRaw } from "vue";
|
||||||
|
import { useDemandLogStore } from "@/store/modules/demand-log";
|
||||||
|
|
||||||
|
/*global Nullable */
|
||||||
|
const demandLogStore = useDemandLogStore();
|
||||||
|
const monacoInstance = ref();
|
||||||
|
const logContent = ref<Nullable<HTMLDivElement>>(null);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
async function init() {
|
||||||
|
const monaco = await import("monaco-editor");
|
||||||
|
setTimeout(() => {
|
||||||
|
monacoInstanceGen(monaco);
|
||||||
|
}, 500);
|
||||||
|
window.addEventListener("resize", () => {
|
||||||
|
editorLayout();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function monacoInstanceGen(monaco: any) {
|
||||||
|
monacoInstance.value = monaco.editor.create(logContent.value, {
|
||||||
|
value: "",
|
||||||
|
language: "text",
|
||||||
|
wordWrap: true,
|
||||||
|
minimap: { enabled: false },
|
||||||
|
readonly: true,
|
||||||
|
});
|
||||||
|
toRaw(monacoInstance.value).updateOptions({ readOnly: true });
|
||||||
|
editorLayout();
|
||||||
|
}
|
||||||
|
function editorLayout() {
|
||||||
|
if (!logContent.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { width, height } = logContent.value.getBoundingClientRect();
|
||||||
|
toRaw(monacoInstance.value).layout({
|
||||||
|
height: height,
|
||||||
|
width: width,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (!toRaw(monacoInstance.value)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toRaw(monacoInstance.value).dispose();
|
||||||
|
monacoInstance.value = null;
|
||||||
|
demandLogStore.setLogs("");
|
||||||
|
});
|
||||||
|
watch(
|
||||||
|
() => demandLogStore.logs,
|
||||||
|
() => {
|
||||||
|
if (!toRaw(monacoInstance.value)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toRaw(monacoInstance.value).setValue(demandLogStore.logs);
|
||||||
|
if (!demandLogStore.logs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
toRaw(monacoInstance.value).revealPosition({
|
||||||
|
column: 1,
|
||||||
|
lineNumber: demandLogStore.total,
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.log-content {
|
||||||
|
min-width: 600px;
|
||||||
|
min-height: 400px;
|
||||||
|
}
|
||||||
|
</style>
|
433
src/views/dashboard/related/demand-log/Header.vue
Normal file
433
src/views/dashboard/related/demand-log/Header.vue
Normal file
@ -0,0 +1,433 @@
|
|||||||
|
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License. -->
|
||||||
|
<template>
|
||||||
|
<div class="flex-h row">
|
||||||
|
<div class="mr-5 mb-5" v-if="dashboardStore.entity !== EntityType[3].value">
|
||||||
|
<span class="grey mr-5"> {{ t("instance") }}: </span>
|
||||||
|
<Selector
|
||||||
|
size="small"
|
||||||
|
:value="state.instance.value"
|
||||||
|
:options="demandLogStore.instances"
|
||||||
|
placeholder="Select a instance"
|
||||||
|
@change="changeField('instance', $event)"
|
||||||
|
class="selectors"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mr-5 mb-5" v-if="state.container">
|
||||||
|
<span class="grey mr-5">{{ t("container") }}:</span>
|
||||||
|
<Selector
|
||||||
|
size="small"
|
||||||
|
:value="state.container.value"
|
||||||
|
:options="demandLogStore.containers"
|
||||||
|
placeholder="Select a container"
|
||||||
|
@change="changeField('container', $event)"
|
||||||
|
class="selectors"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="mr-5">
|
||||||
|
<span class="grey mr-5">{{ t("limit") }}:</span>
|
||||||
|
<el-input-number
|
||||||
|
v-model="limit"
|
||||||
|
:min="1"
|
||||||
|
:max="1000"
|
||||||
|
size="small"
|
||||||
|
controls-position="right"
|
||||||
|
@change="changeField('limit', $event)"
|
||||||
|
/>
|
||||||
|
</div> -->
|
||||||
|
<div class="mr-5">
|
||||||
|
<span class="grey mr-5">{{ t("duration") }}:</span>
|
||||||
|
<Selector
|
||||||
|
size="small"
|
||||||
|
:value="state.duration.value"
|
||||||
|
:options="TimeRanges"
|
||||||
|
placeholder="Select a time range"
|
||||||
|
@change="changeField('duration', $event)"
|
||||||
|
class="duration-range"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mr-5">
|
||||||
|
<span class="grey mr-5">{{ t("interval") }}:</span>
|
||||||
|
<Selector
|
||||||
|
size="small"
|
||||||
|
:value="state.interval.value"
|
||||||
|
:options="IntervalOpts"
|
||||||
|
@change="changeField('interval', $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-h row">
|
||||||
|
<div class="mr-5">
|
||||||
|
<span class="mr-5 grey">{{ t("keywordsOfContent") }}:</span>
|
||||||
|
<span class="log-tags">
|
||||||
|
<span
|
||||||
|
class="selected"
|
||||||
|
v-for="(item, index) in keywordsOfContent"
|
||||||
|
:key="`keywordsOfContent${index}`"
|
||||||
|
>
|
||||||
|
<span>{{ item }}</span>
|
||||||
|
<span class="remove-icon" @click="removeContent(index)">×</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<el-input
|
||||||
|
size="small"
|
||||||
|
class="inputs-max"
|
||||||
|
:placeholder="t('addKeywordsOfContent')"
|
||||||
|
v-model="contentStr"
|
||||||
|
@change="addLabels('keywordsOfContent')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mr-5">
|
||||||
|
<span class="grey mr-5"> {{ t("excludingKeywordsOfContent") }}: </span>
|
||||||
|
<span class="log-tags">
|
||||||
|
<span
|
||||||
|
class="selected"
|
||||||
|
v-for="(item, index) in excludingKeywordsOfContent"
|
||||||
|
:key="`excludingKeywordsOfContent${index}`"
|
||||||
|
>
|
||||||
|
<span>{{ item }}</span>
|
||||||
|
<span class="remove-icon" @click="removeExcludeContent(index)">
|
||||||
|
×
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<el-input
|
||||||
|
class="inputs-max"
|
||||||
|
size="small"
|
||||||
|
:placeholder="t('addExcludingKeywordsOfContent')"
|
||||||
|
v-model="excludingContentStr"
|
||||||
|
@change="addLabels('excludingKeywordsOfContent')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-h row btn-row">
|
||||||
|
<el-button
|
||||||
|
class="search-btn mt-10"
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
@click="runInterval"
|
||||||
|
:disabled="disabled"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
size="middle"
|
||||||
|
iconName="retry"
|
||||||
|
:loading="!!intervalFn"
|
||||||
|
class="mr-5"
|
||||||
|
/>
|
||||||
|
{{ intervalFn ? t("pause") : t("start") }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, watch, onMounted, onUnmounted } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { useDemandLogStore } from "@/store/modules/demand-log";
|
||||||
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { EntityType } from "../../data";
|
||||||
|
import { TimeRanges, IntervalOpts } from "./data";
|
||||||
|
import getLocalTime from "@/utils/localtime";
|
||||||
|
import dateFormatStep from "@/utils/dateFormat";
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const appStore = useAppStoreWithOut();
|
||||||
|
const selectorStore = useSelectorStore();
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
const demandLogStore = useDemandLogStore();
|
||||||
|
const keywordsOfContent = ref<string[]>([]);
|
||||||
|
const excludingKeywordsOfContent = ref<string[]>([]);
|
||||||
|
const contentStr = ref<string>("");
|
||||||
|
const excludingContentStr = ref<string>("");
|
||||||
|
// const limit = ref<number>(20);
|
||||||
|
const state = reactive<any>({
|
||||||
|
instance: { value: "", label: "" },
|
||||||
|
container: { value: "", label: "" },
|
||||||
|
duration: { label: "From 30 minutes ago", value: 1800 },
|
||||||
|
interval: { label: "30 seconds", value: 30 },
|
||||||
|
});
|
||||||
|
const disabled = ref<boolean>(true);
|
||||||
|
/*global Nullable */
|
||||||
|
const intervalFn = ref<Nullable<any>>(null);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
fetchSelectors();
|
||||||
|
});
|
||||||
|
|
||||||
|
async function fetchSelectors() {
|
||||||
|
if (dashboardStore.entity !== EntityType[3].value) {
|
||||||
|
await getInstances();
|
||||||
|
}
|
||||||
|
getContainers();
|
||||||
|
if (intervalFn.value) {
|
||||||
|
clearTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function getContainers() {
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
state.instance.id ||
|
||||||
|
(selectorStore.currentPod && selectorStore.currentPod.id)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const resp = await demandLogStore.getContainers(
|
||||||
|
state.instance.id || selectorStore.currentPod.id
|
||||||
|
);
|
||||||
|
if (resp.errors) {
|
||||||
|
disabled.value = true;
|
||||||
|
ElMessage.error(resp.errors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (resp.data.containers.errorReason) {
|
||||||
|
disabled.value = true;
|
||||||
|
ElMessage.warning(resp.data.containers.errorReason);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (demandLogStore.containers.length) {
|
||||||
|
state.container = demandLogStore.containers[0];
|
||||||
|
disabled.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function getInstances() {
|
||||||
|
const resp = await demandLogStore.getInstances();
|
||||||
|
if (resp.errors) {
|
||||||
|
ElMessage.error(resp.errors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.instance = demandLogStore.instances[0];
|
||||||
|
}
|
||||||
|
function runInterval() {
|
||||||
|
if (intervalFn.value) {
|
||||||
|
clearTimer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
searchLogs();
|
||||||
|
if (state.interval.value === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
intervalFn.value = setInterval(searchLogs, state.interval.value * 1000);
|
||||||
|
setTimeout(() => {
|
||||||
|
clearTimer();
|
||||||
|
}, state.duration.value * 1000);
|
||||||
|
}
|
||||||
|
function searchLogs() {
|
||||||
|
let instance = "";
|
||||||
|
if (dashboardStore.entity === EntityType[3].value) {
|
||||||
|
instance = selectorStore.currentPod.id;
|
||||||
|
}
|
||||||
|
const serviceInstanceId =
|
||||||
|
instance || (state.instance && state.instance.id) || "";
|
||||||
|
demandLogStore.setLogCondition({
|
||||||
|
serviceInstanceId,
|
||||||
|
container: state.container.value,
|
||||||
|
duration: rangeTime(),
|
||||||
|
keywordsOfContent: keywordsOfContent.value.length
|
||||||
|
? keywordsOfContent.value
|
||||||
|
: undefined,
|
||||||
|
excludingKeywordsOfContent: excludingKeywordsOfContent.value.length
|
||||||
|
? excludingKeywordsOfContent.value
|
||||||
|
: undefined,
|
||||||
|
});
|
||||||
|
if (!serviceInstanceId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
queryLogs();
|
||||||
|
}
|
||||||
|
|
||||||
|
function rangeTime() {
|
||||||
|
{
|
||||||
|
const times = {
|
||||||
|
start: getLocalTime(
|
||||||
|
appStore.utc,
|
||||||
|
new Date(new Date().getTime() - state.duration.value * 1000)
|
||||||
|
),
|
||||||
|
end: getLocalTime(appStore.utc, new Date()),
|
||||||
|
step: "SECOND",
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
start: dateFormatStep(times.start, times.step, false),
|
||||||
|
end: dateFormatStep(times.end, times.step, false),
|
||||||
|
step: times.step,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function queryLogs() {
|
||||||
|
const res = await demandLogStore.getDemandLogs();
|
||||||
|
if (res && res.errors) {
|
||||||
|
ElMessage.error(res.errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function changeField(type: string, opt: any) {
|
||||||
|
clearTimer();
|
||||||
|
// if (["limit"].includes(type)) {
|
||||||
|
// state[type] = opt;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
state[type] = opt[0];
|
||||||
|
if (type === "instance") {
|
||||||
|
getContainers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function removeContent(index: number) {
|
||||||
|
const keywordsOfContentList = keywordsOfContent.value || [];
|
||||||
|
keywordsOfContentList.splice(index, 1);
|
||||||
|
demandLogStore.setLogCondition({
|
||||||
|
keywordsOfContent: keywordsOfContentList,
|
||||||
|
});
|
||||||
|
contentStr.value = "";
|
||||||
|
clearTimer();
|
||||||
|
}
|
||||||
|
function addLabels(type: string) {
|
||||||
|
if (type === "keywordsOfContent" && !contentStr.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type === "excludingKeywordsOfContent" && !excludingContentStr.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (type === "keywordsOfContent") {
|
||||||
|
keywordsOfContent.value.push(contentStr.value);
|
||||||
|
demandLogStore.setLogCondition({
|
||||||
|
[type]: keywordsOfContent.value,
|
||||||
|
});
|
||||||
|
contentStr.value = "";
|
||||||
|
} else if (type === "excludingKeywordsOfContent") {
|
||||||
|
excludingKeywordsOfContent.value.push(excludingContentStr.value);
|
||||||
|
demandLogStore.setLogCondition({
|
||||||
|
[type]: excludingKeywordsOfContent.value,
|
||||||
|
});
|
||||||
|
excludingContentStr.value = "";
|
||||||
|
}
|
||||||
|
clearTimer();
|
||||||
|
}
|
||||||
|
function removeExcludeContent(index: number) {
|
||||||
|
excludingKeywordsOfContent.value.splice(index, 1);
|
||||||
|
demandLogStore.setLogCondition({
|
||||||
|
excludingKeywordsOfContent: excludingKeywordsOfContent.value,
|
||||||
|
});
|
||||||
|
excludingContentStr.value = "";
|
||||||
|
clearTimer();
|
||||||
|
}
|
||||||
|
function clearTimer() {
|
||||||
|
if (!intervalFn.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clearInterval(intervalFn.value);
|
||||||
|
intervalFn.value = null;
|
||||||
|
}
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearTimer();
|
||||||
|
});
|
||||||
|
watch(
|
||||||
|
() => selectorStore.currentService,
|
||||||
|
() => {
|
||||||
|
if (dashboardStore.entity === EntityType[0].value) {
|
||||||
|
fetchSelectors();
|
||||||
|
demandLogStore.setLogs("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
watch(
|
||||||
|
() => [selectorStore.currentPod],
|
||||||
|
() => {
|
||||||
|
if (dashboardStore.entity === EntityType[3].value) {
|
||||||
|
fetchSelectors();
|
||||||
|
demandLogStore.setLogs("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.inputs {
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
position: relative;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputs-max {
|
||||||
|
width: 270px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.traceId {
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-tag {
|
||||||
|
width: 30%;
|
||||||
|
border-style: unset;
|
||||||
|
outline: 0;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
height: 30px;
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-tags {
|
||||||
|
padding: 1px 5px 0 0;
|
||||||
|
border-radius: 3px;
|
||||||
|
height: 24px;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #3d444f;
|
||||||
|
border: 1px dashed #aaa;
|
||||||
|
font-size: 12px;
|
||||||
|
margin: 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remove-icon {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectors {
|
||||||
|
width: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duration-range {
|
||||||
|
width: 210px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-row {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help {
|
||||||
|
color: #999;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
37
src/views/dashboard/related/demand-log/data.ts
Normal file
37
src/views/dashboard/related/demand-log/data.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
* (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const TimeRanges = [
|
||||||
|
{ label: "From 5 seconds ago -- Now", value: 5 },
|
||||||
|
{ label: "From 10 seconds ago -- Now", value: 10 },
|
||||||
|
{ label: "From 15 seconds ago -- Now", value: 15 },
|
||||||
|
{ label: "From 30 seconds ago -- Now", value: 30 },
|
||||||
|
{ label: "From 45 seconds ago -- Now", value: 45 },
|
||||||
|
{ label: "From 1 minute ago -- Now", value: 60 },
|
||||||
|
{ label: "From 5 minutes ago -- Now", value: 300 },
|
||||||
|
{ label: "From 15 minutes ago -- Now", value: 900 },
|
||||||
|
{ label: "From 30 minutes ago -- Now", value: 1800 },
|
||||||
|
];
|
||||||
|
export const IntervalOpts = [
|
||||||
|
{ label: "None", value: 0 },
|
||||||
|
{ label: "5 seconds", value: 5 },
|
||||||
|
{ label: "10 seconds", value: 10 },
|
||||||
|
{ label: "15 seconds", value: 15 },
|
||||||
|
{ label: "30 seconds", value: 30 },
|
||||||
|
{ label: "45 seconds", value: 45 },
|
||||||
|
{ label: "1 minute", value: 60 },
|
||||||
|
];
|
@ -16,7 +16,7 @@ limitations under the License. -->
|
|||||||
<div class="flex-h content">
|
<div class="flex-h content">
|
||||||
<TaskList />
|
<TaskList />
|
||||||
<div class="vis-graph ml-5">
|
<div class="vis-graph ml-5">
|
||||||
<div class="item">
|
<div class="schedules">
|
||||||
<EBPFSchedules />
|
<EBPFSchedules />
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
@ -38,13 +38,21 @@ import EBPFStack from "./components/EBPFStack.vue";
|
|||||||
|
|
||||||
.vis-graph {
|
.vis-graph {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: calc(100% - 300px);
|
flex-grow: 2;
|
||||||
|
min-width: 700px;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
height: calc(50% - 10px);
|
height: calc(100% - 100px);
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.schedules {
|
||||||
|
height: 90px;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -39,6 +39,10 @@ import { useDashboardStore } from "@/store/modules/dashboard";
|
|||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { EntityType } from "../../data";
|
import { EntityType } from "../../data";
|
||||||
|
|
||||||
|
/*global defineProps */
|
||||||
|
const props = defineProps({
|
||||||
|
needQuery: { type: Boolean, default: true },
|
||||||
|
});
|
||||||
const ebpfStore = useEbpfStore();
|
const ebpfStore = useEbpfStore();
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
const selectorStore = useSelectorStore();
|
const selectorStore = useSelectorStore();
|
||||||
@ -46,7 +50,9 @@ const dashboardStore = useDashboardStore();
|
|||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const newTask = ref<boolean>(false);
|
const newTask = ref<boolean>(false);
|
||||||
|
|
||||||
searchTasks();
|
if (props.needQuery) {
|
||||||
|
searchTasks();
|
||||||
|
}
|
||||||
|
|
||||||
async function searchTasks() {
|
async function searchTasks() {
|
||||||
const serviceId =
|
const serviceId =
|
||||||
|
@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div class="filters">
|
<div class="filters">
|
||||||
|
<div class="mb-10 flex-h">
|
||||||
<Selector
|
<Selector
|
||||||
:value="selectedLabels"
|
:value="selectedLabels"
|
||||||
:options="labels"
|
:options="labels"
|
||||||
@ -23,7 +24,28 @@ limitations under the License. -->
|
|||||||
class="inputs mr-10"
|
class="inputs mr-10"
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
/>
|
/>
|
||||||
<el-popover placement="bottom" :width="680" trigger="click">
|
<div class="mr-5 duration" v-if="duration.length">
|
||||||
|
<span>{{ duration[0] }}</span>
|
||||||
|
<span> ~ </span>
|
||||||
|
<span>{{ duration[1] }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-h">
|
||||||
|
<Selector
|
||||||
|
v-if="ebpfStore.selectedTask.targetType === 'OFF_CPU'"
|
||||||
|
:value="aggregateType"
|
||||||
|
:options="AggregateTypes"
|
||||||
|
size="small"
|
||||||
|
placeholder="Please select a type"
|
||||||
|
@change="changeAggregateType"
|
||||||
|
class="selector mr-10"
|
||||||
|
/>
|
||||||
|
<el-popover
|
||||||
|
placement="bottom"
|
||||||
|
:width="680"
|
||||||
|
trigger="click"
|
||||||
|
:persistent="false"
|
||||||
|
>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button type="primary" size="small">
|
<el-button type="primary" size="small">
|
||||||
{{ t("processSelect") }}
|
{{ t("processSelect") }}
|
||||||
@ -34,7 +56,7 @@ limitations under the License. -->
|
|||||||
placeholder="Please input name"
|
placeholder="Please input name"
|
||||||
class="input-with-search"
|
class="input-with-search"
|
||||||
size="small"
|
size="small"
|
||||||
@change="searchProcesses"
|
@change="searchProcesses(0)"
|
||||||
>
|
>
|
||||||
<template #append>
|
<template #append>
|
||||||
<el-button size="small">
|
<el-button size="small">
|
||||||
@ -77,41 +99,43 @@ limitations under the License. -->
|
|||||||
{{ t("analyze") }}
|
{{ t("analyze") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div ref="timeline" class="schedules"></div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { Option } from "@/types/app";
|
import { Option } from "@/types/app";
|
||||||
import { TableHeader } from "./data";
|
import { TableHeader, AggregateTypes } from "./data";
|
||||||
import { useEbpfStore } from "@/store/modules/ebpf";
|
import { useEbpfStore } from "@/store/modules/ebpf";
|
||||||
import { EBPFProfilingSchedule, Process } from "@/types/ebpf";
|
import { EBPFProfilingSchedule, Process } from "@/types/ebpf";
|
||||||
import { DataSet, Timeline } from "vis-timeline/standalone";
|
|
||||||
import "vis-timeline/styles/vis-timeline-graph2d.css";
|
|
||||||
import { ElMessage, ElTable } from "element-plus";
|
import { ElMessage, ElTable } from "element-plus";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const ebpfStore = useEbpfStore();
|
const ebpfStore = useEbpfStore();
|
||||||
const pageSize = 5;
|
const pageSize = 5;
|
||||||
/*global Nullable */
|
|
||||||
const multipleTableRef = ref<InstanceType<typeof ElTable>>();
|
const multipleTableRef = ref<InstanceType<typeof ElTable>>();
|
||||||
const selectedProcesses = ref<string[]>([]);
|
const selectedProcesses = ref<string[]>([]);
|
||||||
const timeline = ref<Nullable<HTMLDivElement>>(null);
|
|
||||||
const visGraph = ref<Nullable<any>>(null);
|
|
||||||
const labels = ref<Option[]>([{ label: "All", value: "0" }]);
|
const labels = ref<Option[]>([{ label: "All", value: "0" }]);
|
||||||
const processes = ref<Process[]>([]);
|
const processes = ref<Process[]>([]);
|
||||||
const currentProcesses = ref<Process[]>([]);
|
const currentProcesses = ref<Process[]>([]);
|
||||||
const selectedLabels = ref<string[]>(["0"]);
|
const selectedLabels = ref<string[]>(["0"]);
|
||||||
const searchText = ref<string>("");
|
const searchText = ref<string>("");
|
||||||
|
const aggregateType = ref<string>(AggregateTypes[0].value);
|
||||||
|
const duration = ref<string[]>([]);
|
||||||
const dateFormat = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") =>
|
const dateFormat = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") =>
|
||||||
new Date(dayjs(date).format(pattern));
|
dayjs(date).format(pattern);
|
||||||
|
|
||||||
function changeLabels(opt: any[]) {
|
function changeLabels(opt: any[]) {
|
||||||
const arr = opt.map((d) => d.value);
|
const arr = opt.map((d) => d.value);
|
||||||
selectedLabels.value = arr;
|
selectedLabels.value = arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeAggregateType(opt: any[]) {
|
||||||
|
aggregateType.value = opt[0].value;
|
||||||
|
ebpfStore.setAnalyzeTrees([]);
|
||||||
|
}
|
||||||
|
|
||||||
const handleSelectionChange = (arr: Process[]) => {
|
const handleSelectionChange = (arr: Process[]) => {
|
||||||
selectedProcesses.value = arr.map((d: Process) => d.id);
|
selectedProcesses.value = arr.map((d: Process) => d.id);
|
||||||
};
|
};
|
||||||
@ -152,85 +176,89 @@ async function analyzeEBPF() {
|
|||||||
const res = await ebpfStore.getEBPFAnalyze({
|
const res = await ebpfStore.getEBPFAnalyze({
|
||||||
scheduleIdList,
|
scheduleIdList,
|
||||||
timeRanges,
|
timeRanges,
|
||||||
|
aggregateType: aggregateType.value,
|
||||||
});
|
});
|
||||||
if (res.data.errors) {
|
if (res.data && res.data.errors) {
|
||||||
ElMessage.error(res.data.errors);
|
ElMessage.error(res.data.errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function visTimeline() {
|
function getSchedules() {
|
||||||
if (visGraph.value) {
|
|
||||||
visGraph.value.destroy();
|
|
||||||
}
|
|
||||||
labels.value = [{ label: "All", value: "0" }];
|
labels.value = [{ label: "All", value: "0" }];
|
||||||
selectedLabels.value = ["0"];
|
selectedLabels.value = ["0"];
|
||||||
processes.value = [];
|
processes.value = [];
|
||||||
const schedules = ebpfStore.eBPFSchedules.map(
|
const ranges = ebpfStore.eBPFSchedules.map((d: EBPFProfilingSchedule) => {
|
||||||
(d: EBPFProfilingSchedule, index: number) => {
|
|
||||||
for (const l of d.process.labels) {
|
for (const l of d.process.labels) {
|
||||||
labels.value.push({ label: l, value: l });
|
labels.value.push({ label: l, value: l });
|
||||||
}
|
}
|
||||||
processes.value.push(d.process);
|
processes.value.push(d.process);
|
||||||
return {
|
return [d.startTime / 10000, d.endTime / 10000];
|
||||||
id: index + 1,
|
});
|
||||||
content: d.process.name,
|
if (ranges.length) {
|
||||||
start: dateFormat(d.startTime),
|
const arr = ranges.flat(1);
|
||||||
end: dateFormat(d.endTime),
|
const min = Math.min(...arr);
|
||||||
};
|
const max = Math.max(...arr);
|
||||||
|
duration.value = [dateFormat(min * 10000), dateFormat(max * 10000)];
|
||||||
|
} else {
|
||||||
|
duration.value = [];
|
||||||
}
|
}
|
||||||
);
|
searchProcesses(0);
|
||||||
searchProcesses();
|
analyzeEBPF();
|
||||||
if (!timeline.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const h = timeline.value.getBoundingClientRect().height;
|
|
||||||
const items: any = new DataSet(schedules);
|
|
||||||
const options = {
|
|
||||||
height: h,
|
|
||||||
width: "100%",
|
|
||||||
locale: "en",
|
|
||||||
};
|
|
||||||
visGraph.value = new Timeline(timeline.value, items, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function changePage(pageIndex: number) {
|
function changePage(pageIndex: number) {
|
||||||
searchProcesses(pageIndex);
|
searchProcesses(pageIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchProcesses(pageIndex?: any) {
|
function searchProcesses(pageIndex: number) {
|
||||||
const arr = processes.value.filter(
|
const arr = processes.value.filter(
|
||||||
(d: { name: string; instanceName: string }) =>
|
(d: {
|
||||||
|
name: string;
|
||||||
|
instanceName: string;
|
||||||
|
attributes: { name: string; value: string }[];
|
||||||
|
}) =>
|
||||||
d.name.includes(searchText.value) ||
|
d.name.includes(searchText.value) ||
|
||||||
d.instanceName.includes(searchText.value)
|
d.instanceName.includes(searchText.value) ||
|
||||||
|
searchAttribute(d.attributes, searchText.value)
|
||||||
);
|
);
|
||||||
currentProcesses.value = arr.splice(
|
currentProcesses.value = arr.filter(
|
||||||
(pageIndex - 1 || 0) * pageSize,
|
(d, index: number) =>
|
||||||
pageSize * (pageIndex || 1)
|
(pageIndex - 1 || 0) * pageSize <= index &&
|
||||||
|
pageSize * (pageIndex || 1) > index
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function searchAttribute(
|
||||||
|
attributes: { name: string; value: string }[],
|
||||||
|
text: string
|
||||||
|
) {
|
||||||
|
const item = attributes.find(
|
||||||
|
(d: { name: string; value: string }) => d.name === "command_line"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!item) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return item.value.includes(text);
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => ebpfStore.eBPFSchedules,
|
() => ebpfStore.eBPFSchedules,
|
||||||
() => {
|
() => {
|
||||||
visTimeline();
|
getSchedules();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.filters {
|
.filters {
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
}
|
width: 100%;
|
||||||
|
min-width: 560px;
|
||||||
.schedules {
|
|
||||||
width: calc(100% - 5px);
|
|
||||||
margin: 0 5px 5px 0;
|
|
||||||
height: calc(100% - 60px);
|
|
||||||
min-height: 150px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.inputs {
|
.inputs {
|
||||||
width: 300px;
|
width: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-with-search {
|
.input-with-search {
|
||||||
@ -241,4 +269,12 @@ watch(
|
|||||||
.pagination {
|
.pagination {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.selector {
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duration {
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -24,13 +24,17 @@ import d3tip from "d3-tip";
|
|||||||
import { flamegraph } from "d3-flame-graph";
|
import { flamegraph } from "d3-flame-graph";
|
||||||
import { useEbpfStore } from "@/store/modules/ebpf";
|
import { useEbpfStore } from "@/store/modules/ebpf";
|
||||||
import { StackElement } from "@/types/ebpf";
|
import { StackElement } from "@/types/ebpf";
|
||||||
|
import { AggregateTypes } from "./data";
|
||||||
import "d3-flame-graph/dist/d3-flamegraph.css";
|
import "d3-flame-graph/dist/d3-flamegraph.css";
|
||||||
|
|
||||||
/*global Nullable*/
|
/*global Nullable*/
|
||||||
const ebpfStore = useEbpfStore();
|
const ebpfStore = useEbpfStore();
|
||||||
const stackTree = ref<Nullable<StackElement>>(null);
|
const stackTree = ref<Nullable<StackElement>>(null);
|
||||||
|
const selectStack = ref<Nullable<StackElement>>(null);
|
||||||
const graph = ref<Nullable<HTMLDivElement>>(null);
|
const graph = ref<Nullable<HTMLDivElement>>(null);
|
||||||
const flameChart = ref<any>(null);
|
const flameChart = ref<any>(null);
|
||||||
|
const min = ref<number>(1);
|
||||||
|
const max = ref<number>(1);
|
||||||
|
|
||||||
function drawGraph() {
|
function drawGraph() {
|
||||||
if (flameChart.value) {
|
if (flameChart.value) {
|
||||||
@ -39,53 +43,109 @@ function drawGraph() {
|
|||||||
if (!ebpfStore.analyzeTrees.length) {
|
if (!ebpfStore.analyzeTrees.length) {
|
||||||
return (stackTree.value = null);
|
return (stackTree.value = null);
|
||||||
}
|
}
|
||||||
stackTree.value = processTree(ebpfStore.analyzeTrees);
|
const root: StackElement = {
|
||||||
|
parentId: "0",
|
||||||
const w = (graph.value && graph.value.getBoundingClientRect().width) || 10;
|
originId: "1",
|
||||||
|
name: "Virtual Root",
|
||||||
|
children: [],
|
||||||
|
value: 0,
|
||||||
|
id: "1",
|
||||||
|
symbol: "Virtual Root",
|
||||||
|
dumpCount: 0,
|
||||||
|
stackType: "",
|
||||||
|
rateOfRoot: "",
|
||||||
|
rateOfParent: "",
|
||||||
|
};
|
||||||
|
countRange();
|
||||||
|
for (const tree of ebpfStore.analyzeTrees) {
|
||||||
|
const ele = processTree(tree.elements);
|
||||||
|
root.children && root.children.push(ele);
|
||||||
|
}
|
||||||
|
const param = (root.children || []).reduce(
|
||||||
|
(prev: number[], curr: StackElement) => {
|
||||||
|
prev[0] += curr.value;
|
||||||
|
prev[1] += curr.dumpCount;
|
||||||
|
return prev;
|
||||||
|
},
|
||||||
|
[0, 0]
|
||||||
|
);
|
||||||
|
root.value = param[0];
|
||||||
|
root.dumpCount = param[1];
|
||||||
|
stackTree.value = root;
|
||||||
|
const width = (graph.value && graph.value.getBoundingClientRect().width) || 0;
|
||||||
|
const w = width < 800 ? 802 : width;
|
||||||
flameChart.value = flamegraph()
|
flameChart.value = flamegraph()
|
||||||
.width(w - 15)
|
.width(w - 15)
|
||||||
.cellHeight(18)
|
.cellHeight(18)
|
||||||
.transitionDuration(750)
|
.transitionDuration(750)
|
||||||
.minFrameSize(5)
|
.minFrameSize(1)
|
||||||
.transitionEase(d3.easeCubic as any)
|
.transitionEase(d3.easeCubic as any)
|
||||||
.sort(true)
|
.sort(true)
|
||||||
.title("")
|
.title("")
|
||||||
.selfValue(false)
|
.selfValue(false)
|
||||||
|
.inverted(true)
|
||||||
|
.onClick((d: { data: StackElement }) => {
|
||||||
|
selectStack.value = d.data;
|
||||||
|
})
|
||||||
.setColorMapper((d, originalColor) =>
|
.setColorMapper((d, originalColor) =>
|
||||||
d.highlight ? "#6aff8f" : originalColor
|
d.highlight ? "#6aff8f" : originalColor
|
||||||
);
|
);
|
||||||
const tip = (d3tip as any)()
|
const tip = (d3tip as any)()
|
||||||
.attr("class", "d3-tip")
|
.attr("class", "d3-tip")
|
||||||
.direction("w")
|
.direction("w")
|
||||||
.html(
|
.html((d: { data: StackElement } & { parent: { data: StackElement } }) => {
|
||||||
(d: { data: StackElement }) =>
|
const name = d.data.name.replace("<", "<").replace(">", ">");
|
||||||
`<div class="mb-5">Symbol: ${d.data.name}</div><div class="mb-5">Dump Count: ${d.data.dumpCount}</div>`
|
const valStr =
|
||||||
);
|
ebpfStore.aggregateType === AggregateTypes[0].value
|
||||||
|
? `<div class="mb-5">Dump Count: ${d.data.dumpCount}</div>`
|
||||||
|
: `<div class="mb-5">Duration: ${d.data.dumpCount} ns</div>`;
|
||||||
|
const rateOfParent =
|
||||||
|
(d.parent &&
|
||||||
|
`<div class="mb-5">Percentage Of Selected: ${
|
||||||
|
(
|
||||||
|
(d.data.dumpCount /
|
||||||
|
((selectStack.value && selectStack.value.dumpCount) ||
|
||||||
|
root.dumpCount)) *
|
||||||
|
100
|
||||||
|
).toFixed(3) + "%"
|
||||||
|
}</div>`) ||
|
||||||
|
"";
|
||||||
|
const rateOfRoot = `<div class="mb-5">Percentage Of Root: ${
|
||||||
|
((d.data.dumpCount / root.dumpCount) * 100).toFixed(3) + "%"
|
||||||
|
}</div>`;
|
||||||
|
return `<div class="mb-5 name">Symbol: ${name}</div>${valStr}${rateOfParent}${rateOfRoot}`;
|
||||||
|
})
|
||||||
|
.style("max-width", "500px");
|
||||||
flameChart.value.tooltip(tip);
|
flameChart.value.tooltip(tip);
|
||||||
d3.select("#graph-stack").datum(stackTree.value).call(flameChart.value);
|
d3.select("#graph-stack").datum(stackTree.value).call(flameChart.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function countRange() {
|
||||||
|
const list = [];
|
||||||
|
for (const tree of ebpfStore.analyzeTrees) {
|
||||||
|
for (const ele of tree.elements) {
|
||||||
|
list.push(ele.dumpCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
max.value = Math.max(...list);
|
||||||
|
min.value = Math.min(...list);
|
||||||
|
}
|
||||||
|
|
||||||
function processTree(arr: StackElement[]) {
|
function processTree(arr: StackElement[]) {
|
||||||
const copyArr = JSON.parse(JSON.stringify(arr));
|
const copyArr = (window as any).structuredClone(arr);
|
||||||
const obj: any = {};
|
const obj: any = {};
|
||||||
let res = null;
|
let res = null;
|
||||||
let min = 1;
|
|
||||||
let max = 1;
|
|
||||||
for (const item of copyArr) {
|
for (const item of copyArr) {
|
||||||
item.originId = item.id;
|
item.parentId = String(Number(item.parentId) + 1);
|
||||||
|
item.originId = String(Number(item.id) + 1);
|
||||||
item.name = item.symbol;
|
item.name = item.symbol;
|
||||||
delete item.id;
|
delete item.id;
|
||||||
obj[item.originId] = item;
|
obj[item.originId] = item;
|
||||||
if (item.dumpCount > max) {
|
|
||||||
max = item.dumpCount;
|
|
||||||
}
|
}
|
||||||
if (item.dumpCount < min) {
|
const scale = d3.scaleLinear().domain([min.value, max.value]).range([1, 200]);
|
||||||
min = item.dumpCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const scale = d3.scaleLinear().domain([min, max]).range([1, 200]);
|
|
||||||
for (const item of copyArr) {
|
for (const item of copyArr) {
|
||||||
if (item.parentId === "0") {
|
if (item.parentId === "1") {
|
||||||
const val = Number(scale(item.dumpCount).toFixed(4));
|
const val = Number(scale(item.dumpCount).toFixed(4));
|
||||||
res = item;
|
res = item;
|
||||||
res.value = val;
|
res.value = val;
|
||||||
@ -145,4 +205,8 @@ watch(
|
|||||||
color: red;
|
color: red;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -86,6 +86,7 @@ import { useSelectorStore } from "@/store/modules/selectors";
|
|||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { InitTaskField, TargetTypes } from "./data";
|
import { InitTaskField, TargetTypes } from "./data";
|
||||||
|
|
||||||
/* global defineEmits */
|
/* global defineEmits */
|
||||||
const emits = defineEmits(["close"]);
|
const emits = defineEmits(["close"]);
|
||||||
const eBPFStore = useEbpfStore();
|
const eBPFStore = useEbpfStore();
|
||||||
@ -97,6 +98,7 @@ const type = ref<string>(TargetTypes[0].value);
|
|||||||
const monitorTime = ref<string>(InitTaskField.monitorTimeEn[0].value);
|
const monitorTime = ref<string>(InitTaskField.monitorTimeEn[0].value);
|
||||||
const monitorDuration = ref<number>(10);
|
const monitorDuration = ref<number>(10);
|
||||||
const time = ref<Date>(appStore.durationRow.start);
|
const time = ref<Date>(appStore.durationRow.start);
|
||||||
|
const disabled = ref<boolean>(false);
|
||||||
|
|
||||||
function changeMonitorTime(opt: string) {
|
function changeMonitorTime(opt: string) {
|
||||||
monitorTime.value = opt;
|
monitorTime.value = opt;
|
||||||
@ -111,23 +113,24 @@ function changeType(opt: any[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function createTask() {
|
async function createTask() {
|
||||||
if (!labels.value.length) {
|
if (disabled.value) {
|
||||||
ElMessage.warning("no labels");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
disabled.value = true;
|
||||||
const date = monitorTime.value === "0" ? new Date() : time.value;
|
const date = monitorTime.value === "0" ? new Date() : time.value;
|
||||||
const params = {
|
const params = {
|
||||||
serviceId: selectorStore.currentService.id,
|
serviceId: selectorStore.currentService.id,
|
||||||
processLabels: labels.value,
|
processLabels: labels.value,
|
||||||
startTime: date.getTime(),
|
startTime: date.getTime(),
|
||||||
duration: monitorDuration.value * 60,
|
duration: monitorDuration.value * 60,
|
||||||
targetType: "ON_CPU",
|
targetType: type.value,
|
||||||
};
|
};
|
||||||
const res = await eBPFStore.createTask(params);
|
const res = await eBPFStore.createTask(params);
|
||||||
if (res.errors) {
|
if (res.errors) {
|
||||||
ElMessage.error(res.errors);
|
ElMessage.error(res.errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
disabled.value = false;
|
||||||
if (!res.data.createTaskData.status) {
|
if (!res.data.createTaskData.status) {
|
||||||
ElMessage.error(res.data.createTaskData.errorReason);
|
ElMessage.error(res.data.createTaskData.errorReason);
|
||||||
return;
|
return;
|
||||||
|
@ -34,7 +34,15 @@ limitations under the License. -->
|
|||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div class="ell">
|
<div class="ell">
|
||||||
<span>{{ i.processLabels.join(" ") }}</span>
|
<span>
|
||||||
|
{{
|
||||||
|
i.targetType +
|
||||||
|
": " +
|
||||||
|
(i.processLabels.length
|
||||||
|
? i.processLabels.join(" ")
|
||||||
|
: `All Processes`)
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
<a class="profile-btn r" @click="viewDetail = true">
|
<a class="profile-btn r" @click="viewDetail = true">
|
||||||
<Icon iconName="view" size="middle" />
|
<Icon iconName="view" size="middle" />
|
||||||
</a>
|
</a>
|
||||||
@ -74,7 +82,9 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
<div class="mb-10 clear item">
|
<div class="mb-10 clear item">
|
||||||
<span class="g-sm-4 grey">{{ t("labels") }}:</span>
|
<span class="g-sm-4 grey">{{ t("labels") }}:</span>
|
||||||
<span class="g-sm-8 wba">{{ selectedTask.processLabels }}</span>
|
<span class="g-sm-8 wba">
|
||||||
|
{{ selectedTask.processLabels.join(";") }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-10 clear item">
|
<div class="mb-10 clear item">
|
||||||
<span class="g-sm-4 grey">{{ t("monitorTime") }}:</span>
|
<span class="g-sm-4 grey">{{ t("monitorTime") }}:</span>
|
||||||
@ -117,6 +127,7 @@ const viewDetail = ref<boolean>(false);
|
|||||||
|
|
||||||
async function changeTask(item: EBPFTaskList) {
|
async function changeTask(item: EBPFTaskList) {
|
||||||
selectedTask.value = item;
|
selectedTask.value = item;
|
||||||
|
ebpfStore.setSelectedTask(item);
|
||||||
const res = await ebpfStore.getEBPFSchedules({
|
const res = await ebpfStore.getEBPFSchedules({
|
||||||
taskId: item.taskId,
|
taskId: item.taskId,
|
||||||
});
|
});
|
||||||
@ -128,6 +139,7 @@ watch(
|
|||||||
() => ebpfStore.taskList,
|
() => ebpfStore.taskList,
|
||||||
() => {
|
() => {
|
||||||
selectedTask.value = ebpfStore.taskList[0] || {};
|
selectedTask.value = ebpfStore.taskList[0] || {};
|
||||||
|
ebpfStore.setSelectedTask(selectedTask.value);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
@ -28,7 +28,15 @@ export const NewTaskField = {
|
|||||||
maxSamplingCount: { key: 5, label: "5" },
|
maxSamplingCount: { key: 5, label: "5" },
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TargetTypes = [{ label: "ON_CPU", value: "ON_CPU" }];
|
export const TargetTypes = [
|
||||||
|
{ label: "ON_CPU", value: "ON_CPU" },
|
||||||
|
{ label: "OFF_CPU", value: "OFF_CPU" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const AggregateTypes = [
|
||||||
|
{ label: "Count", value: "COUNT" },
|
||||||
|
{ label: "Duration", value: "DURATION" },
|
||||||
|
];
|
||||||
|
|
||||||
export const InitTaskField = {
|
export const InitTaskField = {
|
||||||
monitorTimeEn: [
|
monitorTimeEn: [
|
||||||
|
129
src/views/dashboard/related/event/Content.vue
Normal file
129
src/views/dashboard/related/event/Content.vue
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License. -->
|
||||||
|
<template>
|
||||||
|
<div ref="timeline" class="events"></div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch, onMounted } from "vue";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { useThrottleFn } from "@vueuse/core";
|
||||||
|
import { useEventStore } from "@/store/modules/event";
|
||||||
|
import { DataSet, Timeline } from "vis-timeline/standalone";
|
||||||
|
import "vis-timeline/styles/vis-timeline-graph2d.css";
|
||||||
|
|
||||||
|
const eventStore = useEventStore();
|
||||||
|
/*global Nullable */
|
||||||
|
const timeline = ref<Nullable<HTMLDivElement>>(null);
|
||||||
|
const visGraph = ref<Nullable<any>>(null);
|
||||||
|
const oldVal = ref<{ width: number; height: number }>({ width: 0, height: 0 });
|
||||||
|
const dateFormat = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") =>
|
||||||
|
new Date(dayjs(date).format(pattern));
|
||||||
|
const visDate = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") =>
|
||||||
|
dayjs(date).format(pattern);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
oldVal.value = (timeline.value && timeline.value.getBoundingClientRect()) || {
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
};
|
||||||
|
useThrottleFn(resize, 500)();
|
||||||
|
});
|
||||||
|
|
||||||
|
function visTimeline() {
|
||||||
|
if (!timeline.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (visGraph.value) {
|
||||||
|
visGraph.value.destroy();
|
||||||
|
}
|
||||||
|
const h = timeline.value.getBoundingClientRect().height;
|
||||||
|
const events = eventStore.events.map((d, index) => {
|
||||||
|
return {
|
||||||
|
id: index + 1,
|
||||||
|
content: d.name,
|
||||||
|
start: dateFormat(d.startTime),
|
||||||
|
end: dateFormat(d.endTime),
|
||||||
|
data: d,
|
||||||
|
className: d.type,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const items: any = new DataSet(events);
|
||||||
|
const options: any = {
|
||||||
|
height: h,
|
||||||
|
width: "100%",
|
||||||
|
locale: "en",
|
||||||
|
groupHeightMode: "fitItems",
|
||||||
|
autoResize: false,
|
||||||
|
tooltip: {
|
||||||
|
overflowMethod: "cap",
|
||||||
|
template(item) {
|
||||||
|
const data = item.data || {};
|
||||||
|
let tmp = `<div>ID: ${data.uuid || ""}</div>
|
||||||
|
<div>Name: ${data.name || ""}</div>
|
||||||
|
<div>Event Type: ${data.type || ""}</div>
|
||||||
|
<div>Start Time: ${data.startTime ? visDate(data.startTime) : ""}</div>
|
||||||
|
<div>End Time: ${data.endTime ? visDate(data.endTime) : ""}</div>
|
||||||
|
<div>Message: ${data.message || ""}</div>
|
||||||
|
<div>Service: ${data.source.service || ""}</div>`;
|
||||||
|
if (data.source.endpoint) {
|
||||||
|
tmp += `<div>Endpoint: ${data.source.endpoint}</div>`;
|
||||||
|
}
|
||||||
|
if (data.source.instance) {
|
||||||
|
tmp += `<div>Service Instance: ${data.source.instance}</div>`;
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
visGraph.value = new Timeline(timeline.value, items, options);
|
||||||
|
}
|
||||||
|
function resize() {
|
||||||
|
const observer = new ResizeObserver((entries) => {
|
||||||
|
const entry = entries[0];
|
||||||
|
const cr = entry.contentRect;
|
||||||
|
if (
|
||||||
|
Math.abs(cr.width - oldVal.value.width) < 3 &&
|
||||||
|
Math.abs(cr.height - oldVal.value.height) < 3
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
visTimeline();
|
||||||
|
oldVal.value = { width: cr.width, height: cr.height };
|
||||||
|
});
|
||||||
|
if (timeline.value) {
|
||||||
|
observer.observe(timeline.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
watch(
|
||||||
|
() => eventStore.events,
|
||||||
|
() => {
|
||||||
|
visTimeline();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.events {
|
||||||
|
width: calc(100% - 5px);
|
||||||
|
margin: 0 5px 5px 0;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
max-width: 400px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
235
src/views/dashboard/related/event/Header.vue
Normal file
235
src/views/dashboard/related/event/Header.vue
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
<!-- Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License. -->
|
||||||
|
<template>
|
||||||
|
<div class="flex-h row">
|
||||||
|
<div class="mr-5" v-if="dashboardStore.entity !== EntityType[3].value">
|
||||||
|
<span class="grey mr-5"> {{ t("instance") }}: </span>
|
||||||
|
<Selector
|
||||||
|
size="small"
|
||||||
|
:value="state.instance.value"
|
||||||
|
:options="eventStore.instances"
|
||||||
|
placeholder="Select a instance"
|
||||||
|
@change="changeField('instance', $event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mr-5" v-if="dashboardStore.entity !== EntityType[2].value">
|
||||||
|
<span class="grey mr-5"> {{ t("endpoint") }}: </span>
|
||||||
|
<Selector
|
||||||
|
size="small"
|
||||||
|
:value="state.endpoint.value"
|
||||||
|
:options="eventStore.endpoints"
|
||||||
|
placeholder="Select a endpoint"
|
||||||
|
@change="changeField('endpoint', $event)"
|
||||||
|
:isRemote="true"
|
||||||
|
@query="searchEndpoints"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mr-5">
|
||||||
|
<span class="grey">{{ t("eventsType") }}: </span>
|
||||||
|
<Selector
|
||||||
|
v-model="state.eventType"
|
||||||
|
:options="EventTypes"
|
||||||
|
placeholder="Select a type"
|
||||||
|
@change="changeField('eventType', $event)"
|
||||||
|
class="event-tool-input"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<el-pagination
|
||||||
|
v-model:currentPage="pageNum"
|
||||||
|
v-model:page-size="pageSize"
|
||||||
|
layout="prev, pager, next"
|
||||||
|
:total="total"
|
||||||
|
@current-change="updatePage"
|
||||||
|
:pager-count="5"
|
||||||
|
small
|
||||||
|
/>
|
||||||
|
<el-button
|
||||||
|
class="search-btn"
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
@click="queryEvents"
|
||||||
|
>
|
||||||
|
{{ t("search") }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed, reactive, watch } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { useEventStore } from "@/store/modules/event";
|
||||||
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { EntityType } from "../../data";
|
||||||
|
import { EventTypes } from "./data";
|
||||||
|
|
||||||
|
/*global defineProps */
|
||||||
|
const props = defineProps({
|
||||||
|
needQuery: { type: Boolean, default: true },
|
||||||
|
});
|
||||||
|
const { t } = useI18n();
|
||||||
|
const appStore = useAppStoreWithOut();
|
||||||
|
const selectorStore = useSelectorStore();
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
const eventStore = useEventStore();
|
||||||
|
const pageSize = 20;
|
||||||
|
const pageNum = ref<number>(1);
|
||||||
|
const state = reactive<any>({
|
||||||
|
instance: { value: "", label: "All", id: "" },
|
||||||
|
endpoint: { value: "", label: "All", id: "" },
|
||||||
|
eventType: { value: "", label: "All" },
|
||||||
|
});
|
||||||
|
const total = computed(() =>
|
||||||
|
eventStore.events.length === pageSize
|
||||||
|
? pageSize * pageNum.value + 1
|
||||||
|
: pageSize * pageNum.value
|
||||||
|
);
|
||||||
|
if (props.needQuery) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
async function init() {
|
||||||
|
fetchSelectors();
|
||||||
|
await queryEvents();
|
||||||
|
state.instance = { value: "", label: "All" };
|
||||||
|
state.endpoint = { value: "", label: "All" };
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchSelectors() {
|
||||||
|
if (dashboardStore.entity === EntityType[2].value) {
|
||||||
|
getInstances();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dashboardStore.entity === EntityType[3].value) {
|
||||||
|
getEndpoints();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dashboardStore.entity === EntityType[0].value) {
|
||||||
|
getInstances();
|
||||||
|
getEndpoints();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getEndpoints(id?: string) {
|
||||||
|
const resp = await eventStore.getEndpoints(id);
|
||||||
|
if (resp.errors) {
|
||||||
|
ElMessage.error(resp.errors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.endpoint = eventStore.endpoints[0];
|
||||||
|
}
|
||||||
|
async function getInstances(id?: string) {
|
||||||
|
const resp = await eventStore.getInstances(id);
|
||||||
|
if (resp.errors) {
|
||||||
|
ElMessage.error(resp.errors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.instance = eventStore.instances[0];
|
||||||
|
}
|
||||||
|
async function queryEvents() {
|
||||||
|
let endpoint = state.endpoint.value,
|
||||||
|
instance = state.instance.value;
|
||||||
|
if (dashboardStore.entity === EntityType[2].value) {
|
||||||
|
endpoint = selectorStore.currentPod.id;
|
||||||
|
}
|
||||||
|
if (dashboardStore.entity === EntityType[3].value) {
|
||||||
|
instance = selectorStore.currentPod.id;
|
||||||
|
}
|
||||||
|
eventStore.setEventCondition({
|
||||||
|
// layer: dashboardStore.layerId,
|
||||||
|
paging: {
|
||||||
|
pageNum: pageNum.value,
|
||||||
|
pageSize: pageSize,
|
||||||
|
},
|
||||||
|
source: {
|
||||||
|
service: selectorStore.currentService.value || "",
|
||||||
|
endpoint: endpoint || "",
|
||||||
|
serviceInstance: instance || "",
|
||||||
|
},
|
||||||
|
type: state.eventType.value || undefined,
|
||||||
|
});
|
||||||
|
const res = await eventStore.getEvents();
|
||||||
|
if (res && res.errors) {
|
||||||
|
ElMessage.error(res.errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function changeField(type: string, opt: any[]) {
|
||||||
|
state[type] = opt[0];
|
||||||
|
}
|
||||||
|
async function searchEndpoints(keyword: string) {
|
||||||
|
const resp = await eventStore.getEndpoints(keyword);
|
||||||
|
if (resp.errors) {
|
||||||
|
ElMessage.error(resp.errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePage(p: number) {
|
||||||
|
pageNum.value = p;
|
||||||
|
queryEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [selectorStore.currentService],
|
||||||
|
() => {
|
||||||
|
if (dashboardStore.entity === EntityType[0].value) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [selectorStore.currentPod],
|
||||||
|
() => {
|
||||||
|
if (dashboardStore.entity === EntityType[0].value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
watch(
|
||||||
|
() => appStore.durationTime,
|
||||||
|
() => {
|
||||||
|
if (dashboardStore.entity === EntityType[1].value) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.inputs {
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputs-max {
|
||||||
|
width: 270px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #3d444f;
|
||||||
|
border: 1px dashed #aaa;
|
||||||
|
font-size: 12px;
|
||||||
|
margin: 0 2px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -13,95 +13,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div class="flex-h log-wrapper">
|
<div class="flex-h row">
|
||||||
<div v-if="currentSearchTerm === 'column'" class="flex-h items-center mr-5">
|
<div class="mr-5" v-if="dashboardStore.entity === EntityType[1].value">
|
||||||
<el-dropdown class="dark" :hide-on-click="false">
|
|
||||||
<span class="cursor-pointer">
|
|
||||||
Select visible columns<el-icon class="el-icon--right"
|
|
||||||
><arrow-down
|
|
||||||
/></el-icon>
|
|
||||||
</span>
|
|
||||||
<template #dropdown>
|
|
||||||
<el-dropdown-menu id="toggleColumn" class="dropdownSelector">
|
|
||||||
<el-dropdown-item style="padding: 0">
|
|
||||||
<div
|
|
||||||
style="width: 100%; padding: 5px 16px"
|
|
||||||
class="flex-h items-center"
|
|
||||||
@click="logStore.toggleAllColumns(true)"
|
|
||||||
>
|
|
||||||
<el-icon><View /></el-icon>
|
|
||||||
<span style="margin-right: 10px">Show All</span>
|
|
||||||
</div>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item style="padding: 0">
|
|
||||||
<div
|
|
||||||
style="width: 100%; padding: 5px 16px"
|
|
||||||
class="flex-h items-center"
|
|
||||||
@click="logStore.toggleAllColumns(false)"
|
|
||||||
>
|
|
||||||
<el-icon><Hide /></el-icon>
|
|
||||||
<span style="margin-right: 10px">Hide All</span>
|
|
||||||
</div>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-divider />
|
|
||||||
<el-dropdown-item
|
|
||||||
style="padding: 0"
|
|
||||||
v-for="item in logStore.serviceLogColumn"
|
|
||||||
:key="item.value"
|
|
||||||
>
|
|
||||||
<el-checkbox class="custom-checkbox" v-model="item.isVisible">
|
|
||||||
<span>{{ item.value }}</span>
|
|
||||||
</el-checkbox>
|
|
||||||
</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</template>
|
|
||||||
</el-dropdown>
|
|
||||||
<el-button class="toggle-btn mx-3danger" @click="setSearchTerm('')">
|
|
||||||
<Icon iconSize="sm" iconName="cancel" />
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
<div v-if="!currentSearchTerm.length" class="flex-h items-center">
|
|
||||||
<div v-for="(item, index) in arrayOfFilters" :key="index">
|
|
||||||
<el-tooltip
|
|
||||||
class="box-item"
|
|
||||||
effect="dark"
|
|
||||||
:content="item.description"
|
|
||||||
placement="bottom-start"
|
|
||||||
>
|
|
||||||
<el-button
|
|
||||||
type="success"
|
|
||||||
:class="[activeTerms.includes(item.name) ? 'active-toggle' : '']"
|
|
||||||
class="toggle-btn mx-3"
|
|
||||||
v-show="item.isVisible"
|
|
||||||
@click="setSearchTerm(item.name)"
|
|
||||||
>
|
|
||||||
<Icon iconSize="sm" :iconName="item.iconName" />
|
|
||||||
</el-button>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
<el-tooltip
|
|
||||||
class="box-item"
|
|
||||||
effect="dark"
|
|
||||||
content="Toggle columns"
|
|
||||||
placement="bottom-start"
|
|
||||||
>
|
|
||||||
<el-button
|
|
||||||
type="success"
|
|
||||||
:class="[false ? 'active-toggle' : '']"
|
|
||||||
class="toggle-btn mx-3"
|
|
||||||
@click="toggleColumSelector"
|
|
||||||
>
|
|
||||||
<Icon iconSize="sm" iconName="epic" />
|
|
||||||
</el-button>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex-h items-center">
|
|
||||||
<div class="flex-h items-center" v-if="currentSearchTerm === 'service'">
|
|
||||||
<div
|
|
||||||
class="mr-5 flex-h items-center"
|
|
||||||
v-if="dashboardStore.entity === EntityType[1].value"
|
|
||||||
>
|
|
||||||
<span class="grey mr-5">{{ t("service") }}:</span>
|
<span class="grey mr-5">{{ t("service") }}:</span>
|
||||||
<Selector
|
<Selector
|
||||||
size="small"
|
size="small"
|
||||||
@ -111,17 +24,7 @@ limitations under the License. -->
|
|||||||
@change="changeField('service', $event)"
|
@change="changeField('service', $event)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<b v-else>{{ t("service") }} data not available</b>
|
<div class="mr-5" v-if="dashboardStore.entity !== EntityType[3].value">
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex-h items-center" v-if="currentSearchTerm === 'instance'">
|
|
||||||
<div
|
|
||||||
class="mr-5 items-center flex-h"
|
|
||||||
v-if="
|
|
||||||
dashboardStore.entity !== EntityType[3].value &&
|
|
||||||
currentSearchTerm === 'instance'
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span class="grey mr-5">
|
<span class="grey mr-5">
|
||||||
{{ isBrowser ? t("version") : t("instance") }}:
|
{{ isBrowser ? t("version") : t("instance") }}:
|
||||||
</span>
|
</span>
|
||||||
@ -133,20 +36,10 @@ limitations under the License. -->
|
|||||||
@change="changeField('instance', $event)"
|
@change="changeField('instance', $event)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<b v-else>{{ t("instance") }} data not available</b>
|
<div class="mr-5" v-if="dashboardStore.entity !== EntityType[2].value">
|
||||||
</div>
|
<span class="grey mr-5">
|
||||||
|
{{ isBrowser ? t("page") : t("endpoint") }}:
|
||||||
<div class="flex-h items-center" v-if="currentSearchTerm === 'endpoints'">
|
</span>
|
||||||
<div
|
|
||||||
class="mr-5 flex-h items-center"
|
|
||||||
v-if="
|
|
||||||
dashboardStore.entity !== EntityType[2].value &&
|
|
||||||
currentSearchTerm === 'endpoints'
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span class="grey mr-5"
|
|
||||||
>{{ isBrowser ? t("page") : t("endpoint") }}:</span
|
|
||||||
>
|
|
||||||
<Selector
|
<Selector
|
||||||
size="small"
|
size="small"
|
||||||
:value="state.endpoint.value"
|
:value="state.endpoint.value"
|
||||||
@ -157,34 +50,37 @@ limitations under the License. -->
|
|||||||
@query="searchEndpoints"
|
@query="searchEndpoints"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<b v-else>{{ t("endpoint") }} data not available</b>
|
<div class="mr-5" v-if="isBrowser">
|
||||||
|
<span class="grey mr-5"> {{ t("category") }}: </span>
|
||||||
|
<Selector
|
||||||
|
size="small"
|
||||||
|
:value="state.category.value"
|
||||||
|
:options="ErrorCategory"
|
||||||
|
placeholder="Select a category"
|
||||||
|
@change="changeField('category', $event)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<el-button
|
||||||
|
class="search-btn"
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
@click="searchLogs"
|
||||||
|
>
|
||||||
|
{{ t("search") }}
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="row tips">
|
<div class="flex-h row" v-show="!isBrowser">
|
||||||
<b>{{ t("conditionNotice") }}</b>
|
<div class="mr-5 traceId">
|
||||||
</div> -->
|
|
||||||
<div class="flex-h items-center">
|
|
||||||
<div class="mr-5 flex-h items-center traceId" v-show="!isBrowser">
|
|
||||||
<div class="flex-h items-center" v-if="currentSearchTerm === 'traceId'">
|
|
||||||
<span class="grey mr-5">{{ t("traceID") }}:</span>
|
<span class="grey mr-5">{{ t("traceID") }}:</span>
|
||||||
<el-input v-model="traceId" class="inputs-max" size="small" />
|
<el-input v-model="traceId" class="inputs-max" size="small" />
|
||||||
</div>
|
</div>
|
||||||
|
<ConditionTags :type="'LOG'" @update="updateTags" />
|
||||||
</div>
|
</div>
|
||||||
<keep-alive>
|
<div class="row tips" v-show="!isBrowser">
|
||||||
<ConditionTags
|
<b>{{ t("conditionNotice") }}</b>
|
||||||
ref="logTagsComponent"
|
|
||||||
v-if="currentSearchTerm === 'tags'"
|
|
||||||
:type="'LOG'"
|
|
||||||
@update="updateTags"
|
|
||||||
/>
|
|
||||||
</keep-alive>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex-h" v-show="!isBrowser">
|
||||||
<div class="flex-h items-center" v-show="!isBrowser">
|
<div class="mr-5" v-show="logStore.supportQueryLogsByKeywords">
|
||||||
<div
|
|
||||||
class="mr-5 flex-h items-center"
|
|
||||||
v-show="supportQueryLogsByKeywords && currentSearchTerm === 'keywords'"
|
|
||||||
>
|
|
||||||
<span class="mr-5 grey">{{ t("keywordsOfContent") }}:</span>
|
<span class="mr-5 grey">{{ t("keywordsOfContent") }}:</span>
|
||||||
<span class="log-tags">
|
<span class="log-tags">
|
||||||
<span
|
<span
|
||||||
@ -204,12 +100,7 @@ limitations under the License. -->
|
|||||||
@change="addLabels('keywordsOfContent')"
|
@change="addLabels('keywordsOfContent')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="mr-5" v-show="logStore.supportQueryLogsByKeywords">
|
||||||
class="mr-5 flex-h items-center"
|
|
||||||
v-show="
|
|
||||||
supportExcludeQueryLogsByKeywords && currentSearchTerm === 'exclude'
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span class="grey mr-5"> {{ t("excludingKeywordsOfContent") }}: </span>
|
<span class="grey mr-5"> {{ t("excludingKeywordsOfContent") }}: </span>
|
||||||
<span class="log-tags">
|
<span class="log-tags">
|
||||||
<span
|
<span
|
||||||
@ -236,36 +127,10 @@ limitations under the License. -->
|
|||||||
</span>
|
</span>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Search&cancel buttons -->
|
|
||||||
<div
|
|
||||||
v-if="currentSearchTerm.length && currentSearchTerm !== 'column'"
|
|
||||||
class="flex-h items-center"
|
|
||||||
>
|
|
||||||
<el-button
|
|
||||||
class="search-btn toggle-btn"
|
|
||||||
size="small"
|
|
||||||
type="primary"
|
|
||||||
@click="searchLogs"
|
|
||||||
>
|
|
||||||
<Icon iconSize="sm" iconName="search" />
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
class="search-btn toggle-btn"
|
|
||||||
size="small"
|
|
||||||
type="primary"
|
|
||||||
@click="cancelSearchTerm"
|
|
||||||
>
|
|
||||||
<Icon iconSize="sm" iconName="cancel" />
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ArrowDown, View, Hide } from "@element-plus/icons-vue";
|
import { ref, reactive, watch, onUnmounted } from "vue";
|
||||||
import { ref, reactive, watch, computed, onMounted } from "vue";
|
|
||||||
import { useRoute } from "vue-router";
|
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { Option } from "@/types/app";
|
import { Option } from "@/types/app";
|
||||||
import { useLogStore } from "@/store/modules/log";
|
import { useLogStore } from "@/store/modules/log";
|
||||||
@ -275,26 +140,20 @@ import { useSelectorStore } from "@/store/modules/selectors";
|
|||||||
import ConditionTags from "@/views/components/ConditionTags.vue";
|
import ConditionTags from "@/views/components/ConditionTags.vue";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { EntityType } from "../../data";
|
import { EntityType } from "../../data";
|
||||||
|
import { ErrorCategory } from "./data";
|
||||||
|
|
||||||
|
/*global defineProps */
|
||||||
|
const props = defineProps({
|
||||||
|
needQuery: { type: Boolean, default: true },
|
||||||
|
});
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
const selectorStore = useSelectorStore();
|
const selectorStore = useSelectorStore();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const { portal } = useRoute().query;
|
|
||||||
const logStore = useLogStore();
|
const logStore = useLogStore();
|
||||||
const showColumList = ref<boolean>(false);
|
|
||||||
const traceId = ref<string>("");
|
const traceId = ref<string>("");
|
||||||
const keywordsOfContent = ref<string[]>([]);
|
const keywordsOfContent = ref<string[]>([]);
|
||||||
const excludingKeywordsOfContent = ref<string[]>([]);
|
const excludingKeywordsOfContent = ref<string[]>([]);
|
||||||
const supportQueryLogsByKeywords = computed<boolean>(() => {
|
|
||||||
return logStore.supportQueryLogsByKeywords;
|
|
||||||
});
|
|
||||||
const supportExcludeQueryLogsByKeywords = computed<boolean>(() => {
|
|
||||||
return logStore.supportQueryLogsByKeywords;
|
|
||||||
});
|
|
||||||
|
|
||||||
const currentSearchTerm = ref<string>("");
|
|
||||||
const activeTerms = ref<string[]>([]);
|
|
||||||
const tagsList = ref<string[]>([]);
|
const tagsList = ref<string[]>([]);
|
||||||
const tagsMap = ref<Option[]>([]);
|
const tagsMap = ref<Option[]>([]);
|
||||||
const contentStr = ref<string>("");
|
const contentStr = ref<string>("");
|
||||||
@ -304,75 +163,10 @@ const state = reactive<any>({
|
|||||||
instance: { value: "0", label: "All" },
|
instance: { value: "0", label: "All" },
|
||||||
endpoint: { value: "0", label: "All" },
|
endpoint: { value: "0", label: "All" },
|
||||||
service: { value: "", label: "" },
|
service: { value: "", label: "" },
|
||||||
|
category: { value: "ALL", label: "All" },
|
||||||
});
|
});
|
||||||
const logTagsComponent = ref<InstanceType<typeof ConditionTags> | null>(null);
|
if (props.needQuery) {
|
||||||
interface filtersObject {
|
init();
|
||||||
name: string;
|
|
||||||
iconName: string;
|
|
||||||
description: string;
|
|
||||||
isVisible?: boolean | unknown; // one of the situations is dependent on an api call
|
|
||||||
}
|
|
||||||
const arrayOfFilters = ref<filtersObject[]>([
|
|
||||||
{
|
|
||||||
name: "traceId",
|
|
||||||
iconName: "timeline",
|
|
||||||
description: "Trace ID",
|
|
||||||
isVisible: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "tags",
|
|
||||||
iconName: "epic",
|
|
||||||
description: "Tags",
|
|
||||||
isVisible: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "keywords",
|
|
||||||
iconName: "library_books",
|
|
||||||
description: "Keywords",
|
|
||||||
isVisible: supportQueryLogsByKeywords,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "exclude",
|
|
||||||
iconName: "issue-child",
|
|
||||||
description: "Exclude keywords",
|
|
||||||
isVisible: supportExcludeQueryLogsByKeywords,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "instance",
|
|
||||||
iconName: "epic",
|
|
||||||
description: "Instance",
|
|
||||||
isVisible: dashboardStore.entity !== EntityType[3].value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "service",
|
|
||||||
iconName: "settings",
|
|
||||||
description: "Service",
|
|
||||||
isVisible: dashboardStore.entity === EntityType[1].value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "endpoints",
|
|
||||||
iconName: "timeline",
|
|
||||||
description: "Endpoints",
|
|
||||||
isVisible: dashboardStore.entity !== EntityType[2].value,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
onMounted(() => {
|
|
||||||
if (portal) {
|
|
||||||
["endpoint", "time", "contentType", "tags", "traceID"].forEach((col) =>
|
|
||||||
logStore.hideColumns(col)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
init();
|
|
||||||
function toggleColumSelector() {
|
|
||||||
showColumList.value = !showColumList.value;
|
|
||||||
setSearchTerm("column");
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideTags() {
|
|
||||||
let tagsWrap = document.querySelector(".el-select__tags");
|
|
||||||
if (!tagsWrap) return;
|
|
||||||
tagsWrap.style.display = "none";
|
|
||||||
}
|
}
|
||||||
async function init() {
|
async function init() {
|
||||||
const resp = await logStore.getLogsByKeywords();
|
const resp = await logStore.getLogsByKeywords();
|
||||||
@ -433,46 +227,7 @@ async function getInstances(id?: string) {
|
|||||||
}
|
}
|
||||||
state.instance = logStore.instances[0];
|
state.instance = logStore.instances[0];
|
||||||
}
|
}
|
||||||
function addToActiveTerms() {
|
|
||||||
activeTerms.value.push(currentSearchTerm.value);
|
|
||||||
}
|
|
||||||
function removeFromActiveTerms() {
|
|
||||||
activeTerms.value = activeTerms.value.filter(
|
|
||||||
(term) => term !== currentSearchTerm.value
|
|
||||||
);
|
|
||||||
}
|
|
||||||
function handleActiveSearchTerms() {
|
|
||||||
switch (currentSearchTerm.value) {
|
|
||||||
case "traceId":
|
|
||||||
if (!traceId.value.length) return;
|
|
||||||
addToActiveTerms();
|
|
||||||
break;
|
|
||||||
case "tags":
|
|
||||||
if (!tagsList.value.length) return;
|
|
||||||
addToActiveTerms();
|
|
||||||
break;
|
|
||||||
case "keywords":
|
|
||||||
if (!keywordsOfContent.value.length) return;
|
|
||||||
addToActiveTerms();
|
|
||||||
break;
|
|
||||||
case "exclude":
|
|
||||||
if (!excludingKeywordsOfContent.value.length) return;
|
|
||||||
addToActiveTerms();
|
|
||||||
break;
|
|
||||||
case "instance":
|
|
||||||
addToActiveTerms();
|
|
||||||
break;
|
|
||||||
case "service":
|
|
||||||
addToActiveTerms();
|
|
||||||
break;
|
|
||||||
case "endpoints":
|
|
||||||
addToActiveTerms();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function searchLogs() {
|
function searchLogs() {
|
||||||
handleActiveSearchTerms();
|
|
||||||
currentSearchTerm.value = "";
|
|
||||||
let endpoint = "",
|
let endpoint = "",
|
||||||
instance = "";
|
instance = "";
|
||||||
if (dashboardStore.entity === EntityType[2].value) {
|
if (dashboardStore.entity === EntityType[2].value) {
|
||||||
@ -481,6 +236,18 @@ function searchLogs() {
|
|||||||
if (dashboardStore.entity === EntityType[3].value) {
|
if (dashboardStore.entity === EntityType[3].value) {
|
||||||
instance = selectorStore.currentPod.id;
|
instance = selectorStore.currentPod.id;
|
||||||
}
|
}
|
||||||
|
if (dashboardStore.layerId === "BROWSER") {
|
||||||
|
logStore.setLogCondition({
|
||||||
|
serviceId: selectorStore.currentService
|
||||||
|
? selectorStore.currentService.id
|
||||||
|
: state.service.id,
|
||||||
|
pagePathId: endpoint || state.endpoint.id || undefined,
|
||||||
|
serviceVersionId: instance || state.instance.id || undefined,
|
||||||
|
paging: { pageNum: 1, pageSize: 15 },
|
||||||
|
queryDuration: appStore.durationTime,
|
||||||
|
category: state.category.value,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
logStore.setLogCondition({
|
logStore.setLogCondition({
|
||||||
serviceId: selectorStore.currentService
|
serviceId: selectorStore.currentService
|
||||||
? selectorStore.currentService.id
|
? selectorStore.currentService.id
|
||||||
@ -491,9 +258,10 @@ function searchLogs() {
|
|||||||
keywordsOfContent: keywordsOfContent.value,
|
keywordsOfContent: keywordsOfContent.value,
|
||||||
excludingKeywordsOfContent: excludingKeywordsOfContent.value,
|
excludingKeywordsOfContent: excludingKeywordsOfContent.value,
|
||||||
tags: tagsMap.value.length ? tagsMap.value : undefined,
|
tags: tagsMap.value.length ? tagsMap.value : undefined,
|
||||||
paging: { pageNum: 1, pageSize: 15, needTotal: true },
|
paging: { pageNum: 1, pageSize: 15 },
|
||||||
relatedTrace: traceId.value ? { traceId: traceId.value } : undefined,
|
relatedTrace: traceId.value ? { traceId: traceId.value } : undefined,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
queryLogs();
|
queryLogs();
|
||||||
}
|
}
|
||||||
async function queryLogs() {
|
async function queryLogs() {
|
||||||
@ -555,45 +323,9 @@ function removeExcludeContent(index: number) {
|
|||||||
});
|
});
|
||||||
excludingContentStr.value = "";
|
excludingContentStr.value = "";
|
||||||
}
|
}
|
||||||
function setSearchTerm(term: string) {
|
onUnmounted(() => {
|
||||||
currentSearchTerm.value = term;
|
logStore.resetCondition();
|
||||||
if (term === "column") {
|
});
|
||||||
setTimeout(() => {
|
|
||||||
hideTags();
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function cancelSearchTerm() {
|
|
||||||
switch (currentSearchTerm.value) {
|
|
||||||
case "traceId":
|
|
||||||
traceId.value = "";
|
|
||||||
break;
|
|
||||||
case "tags":
|
|
||||||
tagsList.value = [];
|
|
||||||
tagsMap.value = [];
|
|
||||||
logTagsComponent.value?.emptyTags();
|
|
||||||
break;
|
|
||||||
case "keywords":
|
|
||||||
keywordsOfContent.value = [];
|
|
||||||
break;
|
|
||||||
case "exclude":
|
|
||||||
excludingKeywordsOfContent.value = [];
|
|
||||||
break;
|
|
||||||
case "instance":
|
|
||||||
state.instance = { value: "0", label: "All" };
|
|
||||||
break;
|
|
||||||
case "endpoints":
|
|
||||||
state.endpoint = { value: "0", label: "All" };
|
|
||||||
getEndpoints();
|
|
||||||
break;
|
|
||||||
case "service":
|
|
||||||
state.service = { value: "", label: "" };
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
removeFromActiveTerms();
|
|
||||||
currentSearchTerm.value = "";
|
|
||||||
searchLogs();
|
|
||||||
}
|
|
||||||
watch(
|
watch(
|
||||||
() => selectorStore.currentService,
|
() => selectorStore.currentService,
|
||||||
() => {
|
() => {
|
||||||
@ -621,44 +353,13 @@ watch(
|
|||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
#toggleColumn.el-dropdown-menu {
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.el-checkbox.custom-checkbox {
|
|
||||||
width: 100%;
|
|
||||||
padding: 5px 16px;
|
|
||||||
}
|
|
||||||
.dropdownSelector {
|
|
||||||
background: var(--nice-black);
|
|
||||||
}
|
|
||||||
.el-dropdown-link {
|
|
||||||
cursor: pointer;
|
|
||||||
color: var(--el-color-primary);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.el-divider--horizontal {
|
|
||||||
margin: 0 !important;
|
|
||||||
}
|
|
||||||
.cursor-pointer {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-checkbox .el-checkbox__input.is-checked + .el-checkbox__label,
|
|
||||||
.custom-checkbox .el-checkbox__label {
|
|
||||||
color: var(--spp-white) !important;
|
|
||||||
}
|
|
||||||
.inputs {
|
.inputs {
|
||||||
width: 120px;
|
width: 120px;
|
||||||
}
|
}
|
||||||
.items-center {
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.justify-between {
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.row {
|
.row {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inputs-max {
|
.inputs-max {
|
||||||
@ -670,8 +371,11 @@ watch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
.search-btn {
|
.search-btn {
|
||||||
margin-left: 20px;
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
width: 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tips {
|
.tips {
|
||||||
@ -711,40 +415,4 @@ watch(
|
|||||||
margin-left: 3px;
|
margin-left: 3px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* buttons*/
|
|
||||||
.el-button span {
|
|
||||||
font-size: 10px !important;
|
|
||||||
}
|
|
||||||
.toggle-btn {
|
|
||||||
height: 18px;
|
|
||||||
margin: 0 5px;
|
|
||||||
}
|
|
||||||
.active-toggle.toggle-btn {
|
|
||||||
background: rgba(4, 147, 114, 1) !important;
|
|
||||||
span {
|
|
||||||
color: #275410 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.items-center {
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.space-between {
|
|
||||||
justify-content: space-between !important;
|
|
||||||
}
|
|
||||||
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected {
|
|
||||||
width: 100%;
|
|
||||||
padding: 0 32px 0 20px;
|
|
||||||
}
|
|
||||||
.el-select-dropdown__item.selected {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0 32px 0 20px;
|
|
||||||
}
|
|
||||||
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected::after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user