Compare commits
88 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1f98619a5b | ||
![]() |
aab44626da | ||
![]() |
0ff5d4d6bb | ||
![]() |
611731d6d0 | ||
![]() |
221751f034 | ||
![]() |
d4dde7e73b | ||
![]() |
5be106fc4f | ||
![]() |
d8f91bbdf3 | ||
![]() |
23e9742946 | ||
![]() |
7a1c83b5fb | ||
![]() |
7d802d490e | ||
![]() |
da1db8def6 | ||
![]() |
2230d05508 | ||
![]() |
e8d909792d | ||
![]() |
dc842609ba | ||
![]() |
670bef1d69 | ||
![]() |
882828b04a | ||
![]() |
ed6fb0448b | ||
![]() |
a0fc879eb1 | ||
![]() |
b37d65eaac | ||
![]() |
fd46211a37 | ||
![]() |
ae0b8c056d | ||
![]() |
4b88d8bbb3 | ||
![]() |
09051e916b | ||
![]() |
e597f91448 | ||
![]() |
4232161d36 | ||
![]() |
eda44db0cd | ||
![]() |
78f0096c00 | ||
![]() |
5e161f17c2 | ||
![]() |
77d189cdfb | ||
![]() |
9f57e35119 | ||
![]() |
2bf90d6a6d | ||
![]() |
0f4319499a | ||
![]() |
5bb58a00cd | ||
![]() |
d50e9fc261 | ||
![]() |
b235929c77 | ||
![]() |
4561e2e374 | ||
![]() |
214b34ddfd | ||
![]() |
26817e9f92 | ||
![]() |
9ed0121fd0 | ||
![]() |
0d63d538c3 | ||
![]() |
5da441ff9a | ||
![]() |
49bc349064 | ||
![]() |
61a4d2f759 | ||
![]() |
0b4e738699 | ||
![]() |
b88356ba46 | ||
![]() |
d8889f1787 | ||
![]() |
1a989a1434 | ||
![]() |
82b348a766 | ||
![]() |
42b20660e4 | ||
![]() |
cb3aa940b3 | ||
![]() |
87a5553e6d | ||
![]() |
e17562a766 | ||
![]() |
fdfdaab47b | ||
![]() |
a4fc5192ac | ||
![]() |
ffabc7c7a7 | ||
![]() |
2fd5fb9b1e | ||
![]() |
adb457d660 | ||
![]() |
9c0bb988e6 | ||
![]() |
973b51e9ca | ||
![]() |
f5bcd5da2e | ||
![]() |
732b834749 | ||
![]() |
4b43196bc2 | ||
![]() |
b01565b2b8 | ||
![]() |
3b3e790dd9 | ||
![]() |
dc8e4bf273 | ||
![]() |
2ba3c67d31 | ||
![]() |
673b1a41a8 | ||
![]() |
c7079ea17c | ||
![]() |
017f5bf709 | ||
![]() |
bec86e80fd | ||
![]() |
ec7a8bbfa9 | ||
![]() |
4e022ff29a | ||
![]() |
42ead4a572 | ||
![]() |
e144b43267 | ||
![]() |
b5c07e023b | ||
![]() |
04d109d0e3 | ||
![]() |
024cd1195d | ||
![]() |
7fbd6170de | ||
![]() |
3ff3d5d1cd | ||
![]() |
2230702d97 | ||
![]() |
9ad9362935 | ||
![]() |
2be0a84d48 | ||
![]() |
4c762a2458 | ||
![]() |
7813c92673 | ||
![]() |
f12d7899e4 | ||
![]() |
b697fe4713 | ||
![]() |
0828f8a7aa |
4
.github/workflows/nodejs.yml
vendored
@@ -44,9 +44,9 @@ jobs:
|
|||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
- name: npm install, lint, build, and test
|
- name: npm ci, lint, build, and test
|
||||||
run: |
|
run: |
|
||||||
npm install
|
npm ci
|
||||||
npm run lint
|
npm run lint
|
||||||
npm run build --if-present
|
npm run build --if-present
|
||||||
npm run test:unit
|
npm run test:unit
|
||||||
|
1577
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "skywalking-booster-ui",
|
"name": "skywalking-booster-ui",
|
||||||
"version": "9.1.0",
|
"version": "9.3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
@@ -19,12 +19,12 @@
|
|||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"monaco-editor": "^0.27.0",
|
"monaco-editor": "^0.27.0",
|
||||||
"pinia": "^2.0.5",
|
"pinia": "^2.0.5",
|
||||||
|
"vis-timeline": "^7.5.1",
|
||||||
"vue": "^3.0.0",
|
"vue": "^3.0.0",
|
||||||
"vue-grid-layout": "^3.0.0-beta1",
|
"vue-grid-layout": "^3.0.0-beta1",
|
||||||
"vue-i18n": "^9.1.9",
|
"vue-i18n": "^9.1.9",
|
||||||
"vue-router": "^4.0.0-0",
|
"vue-router": "^4.0.0-0",
|
||||||
"vue-types": "^4.1.1",
|
"vue-types": "^4.1.1"
|
||||||
"vuex": "^4.0.0-0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/d3": "^7.1.0",
|
"@types/d3": "^7.1.0",
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
"@typescript-eslint/eslint-plugin": "^4.18.0",
|
"@typescript-eslint/eslint-plugin": "^4.18.0",
|
||||||
"@typescript-eslint/parser": "^4.18.0",
|
"@typescript-eslint/parser": "^4.18.0",
|
||||||
"@vue/cli-plugin-babel": "~4.5.0",
|
"@vue/cli-plugin-babel": "~4.5.0",
|
||||||
"@vue/cli-plugin-e2e-cypress": "~4.5.0",
|
"@vue/cli-plugin-e2e-cypress": "~5.0.8",
|
||||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||||
"@vue/cli-plugin-router": "~4.5.0",
|
"@vue/cli-plugin-router": "~4.5.0",
|
||||||
"@vue/cli-plugin-typescript": "~4.5.0",
|
"@vue/cli-plugin-typescript": "~4.5.0",
|
||||||
|
@@ -19,7 +19,7 @@ limitations under the License. -->
|
|||||||
#app {
|
#app {
|
||||||
color: #2c3e50;
|
color: #2c3e50;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: auto;
|
overflow: hidden;
|
||||||
min-width: 1024px;
|
min-width: 1024px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
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 |
15
src/assets/icons/circle.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="1667899293763" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4705" width="16" height="16"><path d="M512 512m-368 0a368 368 0 1 0 736 0 368 368 0 1 0-736 0Z" p-id="4706"></path></svg>
|
After Width: | Height: | Size: 1001 B |
16
src/assets/icons/conditions.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="1666624449554" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2649" width="48" height="48"><path d="M381.482667 673.877333a90.389333 90.389333 0 0 1 85.226666 60.245334H853.333333v64H465.28a90.389333 90.389333 0 0 1-167.573333 0H170.666667v-64h125.610666a90.389333 90.389333 0 0 1 85.205334-60.245334z m0 64a26.346667 26.346667 0 1 0 0 52.693334 26.346667 26.346667 0 0 0 0-52.693334z m261.034666-304.938666a90.389333 90.389333 0 0 1 85.205334 60.245333H853.333333v64h-127.04a90.389333 90.389333 0 0 1-167.573333 0H170.666667v-64h386.624a90.389333 90.389333 0 0 1 85.226666-60.245333z m0 64a26.346667 26.346667 0 1 0 0 52.693333 26.346667 26.346667 0 0 0 0-52.693333zM381.482667 192a90.389333 90.389333 0 0 1 85.226666 60.224H853.333333v64H465.28a90.389333 90.389333 0 0 1-167.573333 0H170.666667v-64h125.610666A90.389333 90.389333 0 0 1 381.482667 192z m0 64a26.346667 26.346667 0 1 0 0 52.693333 26.346667 26.346667 0 0 0 0-52.693333z" p-id="2650"></path></svg>
|
After Width: | Height: | Size: 1.7 KiB |
@@ -12,4 +12,4 @@ distributed under the License is distributed on an "AS IS" BASIS,
|
|||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
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. -->
|
||||||
<svg t="1648717513168" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15451" width="48" height="48"><path d="M810.666667 213.333333v597.333334H213.333333V213.333333h597.333334m85.333333-85.333333H128v768h768V128z m-512 170.666667h-85.333333v85.333333h85.333333z m170.666667 0h-85.333334v85.333333h85.333334z m-170.666667 170.666666h-85.333333v85.333334h85.333333z m170.666667 0h-85.333334v85.333334h85.333334z m-170.666667 170.666667h-85.333333v85.333333h85.333333z m170.666667 0h-85.333334v85.333333h85.333334z m170.666666-341.333333h-85.333333v85.333333h85.333333z m0 170.666666h-85.333333v85.333334h85.333333z m0 170.666667h-85.333333v85.333333h85.333333z" p-id="15452" fill="#515151"></path></svg>
|
<svg t="1648717513168" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15451" width="48" height="48"><path d="M810.666667 213.333333v597.333334H213.333333V213.333333h597.333334m85.333333-85.333333H128v768h768V128z m-512 170.666667h-85.333333v85.333333h85.333333z m170.666667 0h-85.333334v85.333333h85.333334z m-170.666667 170.666666h-85.333333v85.333334h85.333333z m170.666667 0h-85.333334v85.333334h85.333334z m-170.666667 170.666667h-85.333333v85.333333h85.333333z m170.666667 0h-85.333334v85.333333h85.333334z m170.666666-341.333333h-85.333333v85.333333h85.333333z m0 170.666666h-85.333333v85.333334h85.333333z m0 170.666667h-85.333333v85.333333h85.333333z" p-id="15452"></path></svg>
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
15
src/assets/icons/copy.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="1664265269855" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4109" width="48" height="48"><path d="M866.461538 39.384615H354.461538c-43.323077 0-78.769231 35.446154-78.76923 78.769231v39.384616h472.615384c43.323077 0 78.769231 35.446154 78.769231 78.76923v551.384616h39.384615c43.323077 0 78.769231-35.446154 78.769231-78.769231V118.153846c0-43.323077-35.446154-78.769231-78.769231-78.769231z m-118.153846 275.692308c0-43.323077-35.446154-78.769231-78.76923-78.769231H157.538462c-43.323077 0-78.769231 35.446154-78.769231 78.769231v590.769231c0 43.323077 35.446154 78.769231 78.769231 78.769231h512c43.323077 0 78.769231-35.446154 78.76923-78.769231V315.076923z m-354.461538 137.846154c0 11.815385-7.876923 19.692308-19.692308 19.692308h-157.538461c-11.815385 0-19.692308-7.876923-19.692308-19.692308v-39.384615c0-11.815385 7.876923-19.692308 19.692308-19.692308h157.538461c11.815385 0 19.692308 7.876923 19.692308 19.692308v39.384615z m157.538461 315.076923c0 11.815385-7.876923 19.692308-19.692307 19.692308H216.615385c-11.815385 0-19.692308-7.876923-19.692308-19.692308v-39.384615c0-11.815385 7.876923-19.692308 19.692308-19.692308h315.076923c11.815385 0 19.692308 7.876923 19.692307 19.692308v39.384615z m78.769231-157.538462c0 11.815385-7.876923 19.692308-19.692308 19.692308H216.615385c-11.815385 0-19.692308-7.876923-19.692308-19.692308v-39.384615c0-11.815385 7.876923-19.692308 19.692308-19.692308h393.846153c11.815385 0 19.692308 7.876923 19.692308 19.692308v39.384615z" p-id="4110"></path></svg>
|
After Width: | Height: | Size: 2.3 KiB |
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 |
15
src/assets/icons/gateway.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="1664244255409" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2266" width="48" height="48"><path d="M523.776 430.592l-153.088 88.576 153.088 88.576 152.576-88.576-152.576-88.576z m-165.888 108.544l0.512 177.152 153.6 87.552-1.024-176.64-153.088-88.064z m330.24 0l-153.6 87.552-1.024 176.64 153.6-87.552 1.024-176.64z m131.072 205.824l-68.096-40.96 39.936-8.704-5.632-26.112-67.072 14.848-13.824 23.04 101.376 60.928 13.312-23.04z m-142.848 7.68l68.096 40.96-39.936 8.704 5.632 26.112 67.072-14.848 13.824-23.04-101.888-60.928-12.8 23.04zM481.28 424.96h26.624V306.176H481.28v79.36l-27.648-29.696-19.456 18.432L481.28 424.96z m53.76-118.784V424.96h26.624V345.088l27.648 29.696 19.456-18.432-47.104-50.176h-26.624z m-190.464 401.92l-13.312-23.04-68.608 40.448 11.264-38.912-25.6-7.168-18.944 66.048 13.312 23.04 101.888-60.416z m-89.088 82.944l13.312 23.04 68.608-39.936-11.264 38.912 25.6 7.168 19.456-66.048-13.312-23.04-102.4 59.904z m622.08-45.056c-45.568 0-82.432 36.864-82.432 82.432 0 45.568 36.864 82.432 82.432 82.432 45.568 0 82.432-36.864 82.432-82.432 0-45.568-36.864-82.432-82.432-82.432z m0 122.88c-22.528 0-40.448-17.92-40.448-40.448s17.92-40.448 40.448-40.448 40.448 17.92 40.448 40.448-17.92 40.448-40.448 40.448zM521.728 292.864c45.568 0 82.432-36.864 82.432-82.432 0-45.568-36.864-82.432-82.432-82.432-45.568 0-82.432 36.864-82.432 82.432 0 45.568 36.864 82.432 82.432 82.432z m0-122.88c22.528 0 40.448 17.92 40.448 40.448s-17.92 40.448-40.448 40.448-40.448-17.92-40.448-40.448 18.432-40.448 40.448-40.448zM167.936 749.056c-45.568 0-82.432 36.864-82.432 82.432 0 45.568 36.864 82.432 82.432 82.432 45.568 0 82.432-36.864 82.432-82.432 0-45.568-36.864-82.432-82.432-82.432z m0 122.88c-22.528 0-40.448-17.92-40.448-40.448s17.92-40.448 40.448-40.448 40.448 17.92 40.448 40.448-18.432 40.448-40.448 40.448z" p-id="2267"></path></svg>
|
After Width: | Height: | Size: 2.6 KiB |
@@ -13,6 +13,5 @@ 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. -->
|
||||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
<title>info_outline</title>
|
|
||||||
<path d="M11.016 9v-2.016h1.969v2.016h-1.969zM12 20.016q3.281 0 5.648-2.367t2.367-5.648-2.367-5.648-5.648-2.367-5.648 2.367-2.367 5.648 2.367 5.648 5.648 2.367zM12 2.016q4.125 0 7.055 2.93t2.93 7.055-2.93 7.055-7.055 2.93-7.055-2.93-2.93-7.055 2.93-7.055 7.055-2.93zM11.016 17.016v-6h1.969v6h-1.969z"></path>
|
<path d="M11.016 9v-2.016h1.969v2.016h-1.969zM12 20.016q3.281 0 5.648-2.367t2.367-5.648-2.367-5.648-5.648-2.367-5.648 2.367-2.367 5.648 2.367 5.648 5.648 2.367zM12 2.016q4.125 0 7.055 2.93t2.93 7.055-2.93 7.055-7.055 2.93-7.055-2.93-2.93-7.055 2.93-7.055 7.055-2.93zM11.016 17.016v-6h1.969v6h-1.969z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
17
src/assets/icons/keyboard_arrow_down.svg
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. -->
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M7.406 8.578l4.594 4.594 4.594-4.594 1.406 1.406-6 6-6-6z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 946 B |
17
src/assets/icons/keyboard_arrow_up.svg
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. -->
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M7.406 15.422l-1.406-1.406 6-6 6 6-1.406 1.406-4.594-4.594z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 948 B |
17
src/assets/icons/library_add.svg
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. -->
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M18.984 11.016v-2.016h-3.984v-3.984h-2.016v3.984h-3.984v2.016h3.984v3.984h2.016v-3.984h3.984zM20.016 2.016q0.797 0 1.383 0.586t0.586 1.383v12q0 0.797-0.586 1.406t-1.383 0.609h-12q-0.797 0-1.406-0.609t-0.609-1.406v-12q0-0.797 0.609-1.383t1.406-0.586h12zM3.984 6v14.016h14.016v1.969h-14.016q-0.797 0-1.383-0.586t-0.586-1.383v-14.016h1.969z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
15
src/assets/icons/operation.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="1664266918236" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5378" width="48" height="48"><path d="M571.178667 643.328a144 144 0 0 1-189.098667-193.450667l77.781333 77.866667a48 48 0 1 0 67.882667-67.84l-77.824-77.909333a144 144 0 0 1 193.450667 189.141333l226.517333 207.061333a64.896 64.896 0 1 1-91.690667 91.690667l-207.018666-226.56z m51.498666 134.656a288.298667 288.298667 0 0 1-38.656 12.928v95.488c0 5.290667-4.309333 9.6-9.642666 9.6h-124.757334a9.6 9.6 0 0 1-9.6-9.6v-95.488a286.293333 286.293333 0 0 1-74.325333-30.805333l-67.541333 67.541333a9.6 9.6 0 0 1-13.568 0L196.352 739.413333a9.6 9.6 0 0 1 0-13.568l67.541333-67.541333a286.293333 286.293333 0 0 1-30.805333-74.325333H137.6A9.6 9.6 0 0 1 128 574.378667v-124.757334c0-5.290667 4.309333-9.6 9.6-9.6h95.488c6.826667-26.453333 17.28-51.370667 30.805333-74.325333L196.352 298.154667a9.6 9.6 0 0 1 0-13.568L284.586667 196.352a9.6 9.6 0 0 1 13.568 0l67.541333 67.498667a287.146667 287.146667 0 0 1 74.325333-30.848V137.6c0-5.290667 4.266667-9.6 9.6-9.6h124.8c5.248 0 9.6 4.309333 9.6 9.6v95.488c26.368 6.826667 51.328 17.28 74.282667 30.805333l67.541333-67.541333a9.6 9.6 0 0 1 13.568 0l88.234667 88.234667a9.6 9.6 0 0 1 0 13.568l-67.498667 67.541333a287.146667 287.146667 0 0 1 30.848 74.282667h95.402667c5.290667 0 9.6 4.352 9.6 9.642666v124.757334c0 5.333333-4.266667 9.6-9.6 9.6h-95.488c-4.693333 18.133333-11.178667 35.754667-19.328 52.650666a9.6 9.6 0 0 1-15.018667 2.986667l-10.112-9.173333-38.314666-34.261334-12.16-10.88a9.6 9.6 0 0 1-2.688-10.24A192.298667 192.298667 0 0 0 512 320a192 192 0 1 0 63.018667 373.333333 9.6 9.6 0 0 1 10.24 2.645334l10.837333 12.074666 35.285333 39.338667 8.149334 9.130667a9.6 9.6 0 0 1-2.901334 15.061333 283.306667 283.306667 0 0 1-13.952 6.4z" p-id="5379"></path></svg>
|
After Width: | Height: | Size: 2.5 KiB |
16
src/assets/icons/setting_empty.svg
Normal file
After Width: | Height: | Size: 5.7 KiB |
19
src/assets/icons/time_range.svg
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<!-- 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="1660976558460" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="813" width="48" height="48">
|
||||||
|
<path d="M498.596 482.29H345.42v57.308h210.478V274.197h-57.301V482.29z m0 0M577.685 644.985h379.88v57.302h-379.88v-57.302z m0 0M577.685 773.765h379.88v57.307h-379.88v-57.307z m0 0M577.685 902.55h379.88v57.307h-379.88V902.55z m0 0" p-id="814"></path>
|
||||||
|
<path d="M102.523 382.29a28.668 28.668 0 0 0 23.367 2.56l190.81-61.886c15.053-4.883 23.298-21.04 18.415-36.09-4.882-15.052-21.04-23.297-36.093-18.415l-123.346 40c15.994-26.117 35.17-50.538 57.37-72.745 73.768-73.767 171.847-114.388 276.169-114.388 104.32 0 202.395 40.622 276.161 114.388S899.77 407.56 899.77 511.882c0 26.428-2.616 52.45-7.71 77.78h58.303c4.465-25.499 6.709-51.47 6.709-77.78 0-60.45-11.846-119.102-35.205-174.336-22.56-53.335-54.85-101.227-95.969-142.35-41.122-41.122-89.017-73.408-142.348-95.968-55.233-23.361-113.89-35.207-174.334-35.207-60.45 0-119.107 11.846-174.337 35.208-53.335 22.56-101.23 54.846-142.35 95.969-23.98 23.98-44.933 50.278-62.727 78.6l-20.738-105.654c-3.043-15.528-18.105-25.642-33.632-22.6-15.528 3.048-25.643 18.105-22.6 33.637l36.103 183.932a28.666 28.666 0 0 0 13.588 19.178z m0 0M126.02 587.942H67.768c5.76 33.679 15.368 66.544 28.79 98.278 22.56 53.334 54.85 101.225 95.972 142.348 41.123 41.123 89.014 73.409 142.349 95.969 54.112 22.888 111.518 34.711 170.668 35.182v-57.324c-102.95-0.941-199.595-41.446-272.5-114.349-55.501-55.502-92.237-124.77-107.027-200.104z m0 0" p-id="815">
|
||||||
|
</path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
BIN
src/assets/img/technologies/BOTTLE.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
src/assets/img/technologies/EVENTMESH.png
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
src/assets/img/technologies/HTTPDARK.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
src/assets/img/technologies/HTTPS.png
Normal file
After Width: | Height: | Size: 895 B |
BIN
src/assets/img/technologies/IMPALA.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
src/assets/img/technologies/MICRONAUT.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
src/assets/img/technologies/NATS.png
Normal file
After Width: | Height: | Size: 626 B |
@@ -552,7 +552,7 @@ const ok = (info: any) => {
|
|||||||
if (props.right && _time.getTime() / 100000 > start.value) {
|
if (props.right && _time.getTime() / 100000 > start.value) {
|
||||||
emit("setDates", _time, "right");
|
emit("setDates", _time, "right");
|
||||||
}
|
}
|
||||||
if (!(props.left && props.right)) {
|
if (!(props.left || props.right)) {
|
||||||
emit("setDates", _time);
|
emit("setDates", _time);
|
||||||
}
|
}
|
||||||
emit("ok", info === "h");
|
emit("ok", info === "h");
|
||||||
@@ -632,11 +632,6 @@ onMounted(() => {
|
|||||||
right: 24px;
|
right: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-next-month-btn .middle,
|
|
||||||
.calendar-prev-month-btn .middle {
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.calendar-body {
|
.calendar-body {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 196px;
|
width: 196px;
|
||||||
|
@@ -15,6 +15,28 @@ limitations under the License. -->
|
|||||||
<template>
|
<template>
|
||||||
<div class="chart" ref="chartRef" :style="`height:${height};width:${width};`">
|
<div class="chart" ref="chartRef" :style="`height:${height};width:${width};`">
|
||||||
<div v-if="!available" class="no-data">No Data</div>
|
<div v-if="!available" class="no-data">No Data</div>
|
||||||
|
<div class="menus" v-show="visMenus" ref="menus">
|
||||||
|
<div class="tools" @click="associateMetrics" v-if="associate.length">
|
||||||
|
{{ t("associateMetrics") }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="tools"
|
||||||
|
@click="viewTrace"
|
||||||
|
v-if="relatedTrace && relatedTrace.enableRelate"
|
||||||
|
>
|
||||||
|
{{ t("viewTrace") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-drawer
|
||||||
|
v-model="showTrace"
|
||||||
|
size="100%"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
:before-close="() => (showTrace = false)"
|
||||||
|
:append-to-body="true"
|
||||||
|
title="The Related Traces"
|
||||||
|
>
|
||||||
|
<Trace :data="traceOptions" />
|
||||||
|
</el-drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@@ -28,15 +50,28 @@ import {
|
|||||||
computed,
|
computed,
|
||||||
} from "vue";
|
} from "vue";
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { EventParams } from "@/types/app";
|
||||||
|
import { Filters, RelatedTrace } from "@/types/dashboard";
|
||||||
import { useECharts } from "@/hooks/useEcharts";
|
import { useECharts } from "@/hooks/useEcharts";
|
||||||
import { addResizeListener, removeResizeListener } from "@/utils/event";
|
import { addResizeListener, removeResizeListener } from "@/utils/event";
|
||||||
|
import Trace from "@/views/dashboard/related/trace/Index.vue";
|
||||||
|
import associateProcessor from "@/hooks/useAssociateProcessor";
|
||||||
|
|
||||||
/*global Nullable, defineProps, defineEmits*/
|
/*global Nullable, defineProps, defineEmits*/
|
||||||
const emits = defineEmits(["select"]);
|
const emits = defineEmits(["select"]);
|
||||||
|
const { t } = useI18n();
|
||||||
const chartRef = ref<Nullable<HTMLDivElement>>(null);
|
const chartRef = ref<Nullable<HTMLDivElement>>(null);
|
||||||
|
const menus = ref<Nullable<HTMLDivElement>>(null);
|
||||||
|
const visMenus = ref<boolean>(false);
|
||||||
const { setOptions, resize, getInstance } = useECharts(
|
const { setOptions, resize, getInstance } = useECharts(
|
||||||
chartRef as Ref<HTMLDivElement>
|
chartRef as Ref<HTMLDivElement>
|
||||||
);
|
);
|
||||||
|
const currentParams = ref<Nullable<EventParams>>(null);
|
||||||
|
const showTrace = ref<boolean>(false);
|
||||||
|
const traceOptions = ref<{ type: string; filters?: unknown }>({
|
||||||
|
type: "Trace",
|
||||||
|
});
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
height: { type: String, default: "100%" },
|
height: { type: String, default: "100%" },
|
||||||
width: { type: String, default: "100%" },
|
width: { type: String, default: "100%" },
|
||||||
@@ -44,6 +79,16 @@ const props = defineProps({
|
|||||||
type: Object as PropType<{ [key: string]: any }>,
|
type: Object as PropType<{ [key: string]: any }>,
|
||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
|
filters: {
|
||||||
|
type: Object as PropType<Filters>,
|
||||||
|
},
|
||||||
|
relatedTrace: {
|
||||||
|
type: Object as PropType<RelatedTrace>,
|
||||||
|
},
|
||||||
|
associate: {
|
||||||
|
type: Array as PropType<{ widgetId: string }[]>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const available = computed(
|
const available = computed(
|
||||||
() =>
|
() =>
|
||||||
@@ -55,17 +100,97 @@ const available = computed(
|
|||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await setOptions(props.option);
|
await setOptions(props.option);
|
||||||
chartRef.value && addResizeListener(unref(chartRef), resize);
|
chartRef.value && addResizeListener(unref(chartRef), resize);
|
||||||
|
instanceEvent();
|
||||||
|
});
|
||||||
|
|
||||||
|
function instanceEvent() {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const instance = getInstance();
|
const instance = getInstance();
|
||||||
|
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
instance.on("click", (params: any) => {
|
instance.on("click", (params: EventParams) => {
|
||||||
emits("select", params);
|
currentParams.value = params;
|
||||||
|
if (!menus.value || !chartRef.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
visMenus.value = true;
|
||||||
|
const w = chartRef.value.getBoundingClientRect().width || 0;
|
||||||
|
const h = chartRef.value.getBoundingClientRect().height || 0;
|
||||||
|
if (w - params.event.offsetX > 120) {
|
||||||
|
menus.value.style.left = params.event.offsetX + "px";
|
||||||
|
} else {
|
||||||
|
menus.value.style.left = params.event.offsetX - 120 + "px";
|
||||||
|
}
|
||||||
|
if (h - params.event.offsetY < 50) {
|
||||||
|
menus.value.style.top = params.event.offsetY - 40 + "px";
|
||||||
|
} else {
|
||||||
|
menus.value.style.top = params.event.offsetY + 2 + "px";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
document.addEventListener(
|
||||||
|
"click",
|
||||||
|
() => {
|
||||||
|
if (instance.isDisposed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
visMenus.value = false;
|
||||||
|
instance.dispatchAction({
|
||||||
|
type: "updateAxisPointer",
|
||||||
|
currTrigger: "leave",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
function associateMetrics() {
|
||||||
|
emits("select", currentParams.value);
|
||||||
|
const { dataIndex, seriesIndex } = currentParams.value || {
|
||||||
|
dataIndex: 0,
|
||||||
|
seriesIndex: 0,
|
||||||
|
};
|
||||||
|
updateOptions({ dataIndex, seriesIndex });
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateOptions(params?: { dataIndex: number; seriesIndex: number }) {
|
||||||
|
const instance = getInstance();
|
||||||
|
if (!instance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!props.filters) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (props.filters.isRange) {
|
||||||
|
const { eventAssociate } = associateProcessor(props);
|
||||||
|
const options = eventAssociate();
|
||||||
|
setOptions(options || props.option);
|
||||||
|
} else {
|
||||||
|
instance.dispatchAction({
|
||||||
|
type: "updateAxisPointer",
|
||||||
|
dataIndex: params ? params.dataIndex : props.filters.dataIndex,
|
||||||
|
seriesIndex: params ? params.seriesIndex : 0,
|
||||||
|
});
|
||||||
|
const ids = props.option.series.map((_: unknown, index: number) => index);
|
||||||
|
instance.dispatchAction({
|
||||||
|
type: "highlight",
|
||||||
|
dataIndex: params ? params.dataIndex : props.filters.dataIndex,
|
||||||
|
seriesIndex: ids,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function viewTrace() {
|
||||||
|
const item = associateProcessor(props).traceFilters(currentParams.value);
|
||||||
|
traceOptions.value = {
|
||||||
|
...traceOptions.value,
|
||||||
|
filters: item,
|
||||||
|
};
|
||||||
|
showTrace.value = true;
|
||||||
|
visMenus.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.option,
|
() => props.option,
|
||||||
@@ -76,7 +201,18 @@ watch(
|
|||||||
if (JSON.stringify(newVal) === JSON.stringify(oldVal)) {
|
if (JSON.stringify(newVal) === JSON.stringify(oldVal)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setOptions(newVal);
|
let options;
|
||||||
|
if (props.filters && props.filters.isRange) {
|
||||||
|
const { eventAssociate } = associateProcessor(props);
|
||||||
|
options = eventAssociate();
|
||||||
|
}
|
||||||
|
setOptions(options || props.option);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
watch(
|
||||||
|
() => props.filters,
|
||||||
|
() => {
|
||||||
|
updateOptions();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -98,5 +234,30 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
.chart {
|
.chart {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menus {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
white-space: nowrap;
|
||||||
|
z-index: 9999999;
|
||||||
|
box-shadow: #ddd 1px 2px 10px;
|
||||||
|
transition: all cubic-bezier(0.075, 0.82, 0.165, 1) linear;
|
||||||
|
background-color: rgb(255, 255, 255);
|
||||||
|
border-radius: 4px;
|
||||||
|
color: rgb(51, 51, 51);
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tools {
|
||||||
|
padding: 5px;
|
||||||
|
color: #999;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #409eff;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -24,8 +24,8 @@ import { ref } from "vue";
|
|||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
|
|
||||||
interface Option {
|
interface Option {
|
||||||
label: string;
|
label: string | number;
|
||||||
value: string;
|
value: string | number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*global defineProps, defineEmits */
|
/*global defineProps, defineEmits */
|
||||||
|
@@ -18,7 +18,6 @@ limitations under the License. -->
|
|||||||
v-model="selected"
|
v-model="selected"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
@change="changeSelected"
|
@change="changeSelected"
|
||||||
filterable
|
|
||||||
:multiple="multiple"
|
:multiple="multiple"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:style="{ borderRadius }"
|
:style="{ borderRadius }"
|
||||||
@@ -26,12 +25,13 @@ limitations under the License. -->
|
|||||||
:remote="isRemote"
|
:remote="isRemote"
|
||||||
:reserve-keyword="isRemote"
|
:reserve-keyword="isRemote"
|
||||||
:remote-method="remoteMethod"
|
:remote-method="remoteMethod"
|
||||||
|
:filterable="filterable"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in options"
|
v-for="item in options"
|
||||||
:key="item.value"
|
:key="item.value || ''"
|
||||||
:label="item.label"
|
:label="item.label || ''"
|
||||||
:value="item.value"
|
:value="item.value || ''"
|
||||||
>
|
>
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
@@ -66,6 +66,7 @@ const props = defineProps({
|
|||||||
disabled: { type: Boolean, default: false },
|
disabled: { type: Boolean, default: false },
|
||||||
clearable: { type: Boolean, default: false },
|
clearable: { type: Boolean, default: false },
|
||||||
isRemote: { type: Boolean, default: false },
|
isRemote: { type: Boolean, default: false },
|
||||||
|
filterable: { type: Boolean, default: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
const selected = ref<string[] | string>(props.value);
|
const selected = ref<string[] | string>(props.value);
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export enum TimeType {
|
export enum TimeType {
|
||||||
MINUTE_TIME = "MINUTE",
|
MINUTE_TIME = "MINUTE",
|
||||||
HOUR_TIME = "HOUR",
|
HOUR_TIME = "HOUR",
|
||||||
@@ -25,18 +26,3 @@ export const Languages = [
|
|||||||
{ label: "Chinese", value: "zh" },
|
{ label: "Chinese", value: "zh" },
|
||||||
{ label: "Spanish", value: "es" },
|
{ label: "Spanish", value: "es" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const RoutesMap: { [key: string]: string } = {
|
|
||||||
GeneralServices: "GENERAL",
|
|
||||||
Database: "VIRTUAL_DATABASE",
|
|
||||||
MeshServices: "MESH",
|
|
||||||
ControlPanel: "MESH_CP",
|
|
||||||
DataPanel: "MESH_DP",
|
|
||||||
Linux: "OS_LINUX",
|
|
||||||
SkyWalkingServer: "SO11Y_OAP",
|
|
||||||
Satellite: "SO11Y_SATELLITE",
|
|
||||||
Functions: "FAAS",
|
|
||||||
Browser: "BROWSER",
|
|
||||||
KubernetesCluster: "K8S",
|
|
||||||
KubernetesService: "K8S_SERVICE",
|
|
||||||
};
|
|
||||||
|
@@ -33,12 +33,15 @@ export const createEBPFTask = {
|
|||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
export const queryEBPFTasks = {
|
export const queryEBPFTasks = {
|
||||||
variable: "$serviceId: ID!",
|
variable:
|
||||||
|
"$serviceId: ID, $serviceInstanceId: ID, $targets: [EBPFProfilingTargetType!]",
|
||||||
query: `
|
query: `
|
||||||
queryEBPFTasks: queryEBPFProfilingTasks(serviceId: $serviceId) {
|
queryEBPFTasks: queryEBPFProfilingTasks(serviceId: $serviceId, serviceInstanceId: $serviceInstanceId, targets: $targets) {
|
||||||
taskId
|
taskId
|
||||||
serviceName
|
serviceName
|
||||||
serviceId
|
serviceId
|
||||||
|
serviceInstanceId
|
||||||
|
serviceInstanceName
|
||||||
processLabels
|
processLabels
|
||||||
taskStartTime
|
taskStartTime
|
||||||
triggerType
|
triggerType
|
||||||
@@ -90,3 +93,22 @@ export const analysisEBPFResult = {
|
|||||||
}
|
}
|
||||||
}`,
|
}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const createNetworkProfiling = {
|
||||||
|
variable: "$request: EBPFProfilingNetworkTaskRequest!",
|
||||||
|
query: `
|
||||||
|
createEBPFNetworkProfiling(request: $request) {
|
||||||
|
status
|
||||||
|
errorReason
|
||||||
|
id
|
||||||
|
}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const keepNetworkProfiling = {
|
||||||
|
variable: "$taskId: ID!",
|
||||||
|
query: `
|
||||||
|
keepEBPFNetworkProfiling(taskId: $taskId) {
|
||||||
|
status
|
||||||
|
errorReason
|
||||||
|
}`,
|
||||||
|
};
|
||||||
|
@@ -48,6 +48,29 @@ export const Instances = {
|
|||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const Processes = {
|
||||||
|
variable: "$instanceId: ID!, $duration: Duration!",
|
||||||
|
query: `
|
||||||
|
processes: listProcesses(instanceId: $instanceId, duration: $duration) {
|
||||||
|
id
|
||||||
|
value: name
|
||||||
|
label: name
|
||||||
|
serviceId
|
||||||
|
serviceName
|
||||||
|
instanceId
|
||||||
|
instanceName
|
||||||
|
agentId
|
||||||
|
detectType
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
value
|
||||||
|
}
|
||||||
|
labels
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
|
||||||
export const Endpoints = {
|
export const Endpoints = {
|
||||||
variable: "$serviceId: ID!, $keyword: String!",
|
variable: "$serviceId: ID!, $keyword: String!",
|
||||||
query: `
|
query: `
|
||||||
@@ -102,3 +125,24 @@ export const getEndpoint = {
|
|||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getProcess = {
|
||||||
|
variable: "$processId: ID!",
|
||||||
|
query: `
|
||||||
|
process: getProcess(processId: $processId) {
|
||||||
|
id
|
||||||
|
value: name
|
||||||
|
label: name
|
||||||
|
serviceId
|
||||||
|
serviceName
|
||||||
|
instanceId
|
||||||
|
instanceName
|
||||||
|
agentId
|
||||||
|
detectType
|
||||||
|
attributes {
|
||||||
|
name
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
@@ -75,3 +75,28 @@ export const InstanceTopology = {
|
|||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
export const ProcessTopology = {
|
||||||
|
variable: "$serviceInstanceId: ID!, $duration: Duration!",
|
||||||
|
query: `
|
||||||
|
topology: getProcessTopology(serviceInstanceId: $serviceInstanceId,
|
||||||
|
duration: $duration) {
|
||||||
|
nodes {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
isReal
|
||||||
|
serviceName
|
||||||
|
serviceId
|
||||||
|
serviceInstanceId
|
||||||
|
serviceInstanceName
|
||||||
|
}
|
||||||
|
calls {
|
||||||
|
id
|
||||||
|
source
|
||||||
|
detectPoints
|
||||||
|
target
|
||||||
|
sourceComponents
|
||||||
|
targetComponents
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
@@ -69,6 +69,25 @@ export const TraceSpans = {
|
|||||||
value
|
value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
attachedEvents {
|
||||||
|
startTime {
|
||||||
|
seconds
|
||||||
|
nanos
|
||||||
|
}
|
||||||
|
event
|
||||||
|
endTime {
|
||||||
|
seconds
|
||||||
|
nanos
|
||||||
|
}
|
||||||
|
tags {
|
||||||
|
key
|
||||||
|
value
|
||||||
|
}
|
||||||
|
summary {
|
||||||
|
key
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
@@ -21,6 +21,8 @@ import {
|
|||||||
queryEBPFTasks,
|
queryEBPFTasks,
|
||||||
queryEBPFSchedules,
|
queryEBPFSchedules,
|
||||||
analysisEBPFResult,
|
analysisEBPFResult,
|
||||||
|
createNetworkProfiling,
|
||||||
|
keepNetworkProfiling,
|
||||||
} from "../fragments/ebpf";
|
} from "../fragments/ebpf";
|
||||||
|
|
||||||
export const getCreateTaskData = `query queryCreateTaskData(${queryCreateTaskData.variable}) {${queryCreateTaskData.query}}`;
|
export const getCreateTaskData = `query queryCreateTaskData(${queryCreateTaskData.variable}) {${queryCreateTaskData.query}}`;
|
||||||
@@ -32,3 +34,7 @@ export const getEBPFTasks = `query queryEBPFTasks(${queryEBPFTasks.variable}) {$
|
|||||||
export const getEBPFSchedules = `query queryEBPFSchedules(${queryEBPFSchedules.variable}) {${queryEBPFSchedules.query}}`;
|
export const getEBPFSchedules = `query queryEBPFSchedules(${queryEBPFSchedules.variable}) {${queryEBPFSchedules.query}}`;
|
||||||
|
|
||||||
export const getEBPFResult = `query analysisEBPFResult(${analysisEBPFResult.variable}) {${analysisEBPFResult.query}}`;
|
export const getEBPFResult = `query analysisEBPFResult(${analysisEBPFResult.variable}) {${analysisEBPFResult.query}}`;
|
||||||
|
|
||||||
|
export const newNetworkProfiling = `mutation createNetworkProfiling(${createNetworkProfiling.variable}) {${createNetworkProfiling.query}}`;
|
||||||
|
|
||||||
|
export const aliveNetworkProfiling = `mutation keepNetworkProfiling(${keepNetworkProfiling.variable}) {${keepNetworkProfiling.query}}`;
|
||||||
|
@@ -22,6 +22,8 @@ import {
|
|||||||
getService,
|
getService,
|
||||||
getInstance,
|
getInstance,
|
||||||
getEndpoint,
|
getEndpoint,
|
||||||
|
Processes,
|
||||||
|
getProcess,
|
||||||
} from "../fragments/selector";
|
} from "../fragments/selector";
|
||||||
|
|
||||||
export const queryServices = `query queryServices(${Services.variable}) {${Services.query}}`;
|
export const queryServices = `query queryServices(${Services.variable}) {${Services.query}}`;
|
||||||
@@ -30,4 +32,6 @@ export const queryInstances = `query queryInstances(${Instances.variable}) {${In
|
|||||||
export const queryLayers = `query listLayer {${Layers.query}}`;
|
export const queryLayers = `query listLayer {${Layers.query}}`;
|
||||||
export const queryService = `query queryService(${getService.variable}) {${getService.query}}`;
|
export const queryService = `query queryService(${getService.variable}) {${getService.query}}`;
|
||||||
export const queryInstance = `query queryInstance(${getInstance.variable}) {${getInstance.query}}`;
|
export const queryInstance = `query queryInstance(${getInstance.variable}) {${getInstance.query}}`;
|
||||||
export const queryEndpoint = `query queryInstance(${getEndpoint.variable}) {${getEndpoint.query}}`;
|
export const queryEndpoint = `query queryEndpoint(${getEndpoint.variable}) {${getEndpoint.query}}`;
|
||||||
|
export const queryProcesses = `query queryProcesses(${Processes.variable}) {${Processes.query}}`;
|
||||||
|
export const queryProcess = `query queryProcess(${getProcess.variable}) {${getProcess.query}}`;
|
||||||
|
@@ -18,8 +18,10 @@ import {
|
|||||||
InstanceTopology,
|
InstanceTopology,
|
||||||
EndpointTopology,
|
EndpointTopology,
|
||||||
ServicesTopology,
|
ServicesTopology,
|
||||||
|
ProcessTopology,
|
||||||
} from "../fragments/topology";
|
} from "../fragments/topology";
|
||||||
|
|
||||||
export const getInstanceTopology = `query queryData(${InstanceTopology.variable}) {${InstanceTopology.query}}`;
|
export const getInstanceTopology = `query queryData(${InstanceTopology.variable}) {${InstanceTopology.query}}`;
|
||||||
export const getEndpointTopology = `query queryData(${EndpointTopology.variable}) {${EndpointTopology.query}}`;
|
export const getEndpointTopology = `query queryData(${EndpointTopology.variable}) {${EndpointTopology.query}}`;
|
||||||
export const getServicesTopology = `query queryData(${ServicesTopology.variable}) {${ServicesTopology.query}}`;
|
export const getServicesTopology = `query queryData(${ServicesTopology.variable}) {${ServicesTopology.query}}`;
|
||||||
|
export const getProcessTopology = `query queryData(${ProcessTopology.variable}) {${ProcessTopology.query}}`;
|
||||||
|
@@ -21,6 +21,7 @@ export enum MetricQueryTypes {
|
|||||||
ReadLabeledMetricsValues = "readLabeledMetricsValues",
|
ReadLabeledMetricsValues = "readLabeledMetricsValues",
|
||||||
READHEATMAP = "readHeatMap",
|
READHEATMAP = "readHeatMap",
|
||||||
ReadSampledRecords = "readSampledRecords",
|
ReadSampledRecords = "readSampledRecords",
|
||||||
|
ReadRecords = "readRecords",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Calculations {
|
export enum Calculations {
|
||||||
@@ -32,10 +33,12 @@ export enum Calculations {
|
|||||||
Precision = "precision",
|
Precision = "precision",
|
||||||
ConvertSeconds = "convertSeconds",
|
ConvertSeconds = "convertSeconds",
|
||||||
ConvertMilliseconds = "convertMilliseconds",
|
ConvertMilliseconds = "convertMilliseconds",
|
||||||
MsTos = "msTos",
|
MsToS = "msTos",
|
||||||
Average = "average",
|
Average = "average",
|
||||||
PercentageAvg = "percentageAvg",
|
PercentageAvg = "percentageAvg",
|
||||||
ApdexAvg = "apdexAvg",
|
ApdexAvg = "apdexAvg",
|
||||||
|
SecondToDay = "secondToDay",
|
||||||
|
NanosecondToMillisecond = "nanosecondToMillisecond",
|
||||||
}
|
}
|
||||||
export enum sizeEnum {
|
export enum sizeEnum {
|
||||||
XS = "XS",
|
XS = "XS",
|
||||||
@@ -99,4 +102,10 @@ export const RespFields: any = {
|
|||||||
value
|
value
|
||||||
refId
|
refId
|
||||||
}`,
|
}`,
|
||||||
|
readRecords: `{
|
||||||
|
id
|
||||||
|
name
|
||||||
|
value
|
||||||
|
refId
|
||||||
|
}`,
|
||||||
};
|
};
|
||||||
|
138
src/hooks/useAssociateProcessor.ts
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
/**
|
||||||
|
* 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 { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
|
import dateFormatStep from "@/utils/dateFormat";
|
||||||
|
import getLocalTime from "@/utils/localtime";
|
||||||
|
import { EventParams } from "@/types/app";
|
||||||
|
|
||||||
|
export default function associateProcessor(props: any) {
|
||||||
|
function eventAssociate() {
|
||||||
|
if (!props.filters) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!props.filters.duration) {
|
||||||
|
return props.option;
|
||||||
|
}
|
||||||
|
if (!props.option.series[0]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const list = props.option.series[0].data.map(
|
||||||
|
(d: (number | string)[]) => d[0]
|
||||||
|
);
|
||||||
|
if (!list.includes(props.filters.duration.endTime)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const markArea = {
|
||||||
|
silent: true,
|
||||||
|
itemStyle: {
|
||||||
|
opacity: 0.3,
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
xAxis: props.filters.duration.startTime,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xAxis: props.filters.duration.endTime,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const series = (window as any).structuredClone(props.option.series);
|
||||||
|
for (const [key, temp] of series.entries()) {
|
||||||
|
if (key === 0) {
|
||||||
|
temp.markArea = markArea;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const options = {
|
||||||
|
...props.option,
|
||||||
|
series,
|
||||||
|
};
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
function traceFilters(currentParams: Nullable<EventParams>) {
|
||||||
|
const appStore = useAppStoreWithOut();
|
||||||
|
|
||||||
|
if (!currentParams) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const start = appStore.intervalUnix[currentParams.dataIndex];
|
||||||
|
const { step } = appStore.durationRow;
|
||||||
|
let duration = undefined;
|
||||||
|
|
||||||
|
if (start) {
|
||||||
|
const end = start;
|
||||||
|
duration = {
|
||||||
|
start: dateFormatStep(
|
||||||
|
getLocalTime(appStore.utc, new Date(start)),
|
||||||
|
step,
|
||||||
|
true
|
||||||
|
),
|
||||||
|
end: dateFormatStep(
|
||||||
|
getLocalTime(appStore.utc, new Date(end)),
|
||||||
|
step,
|
||||||
|
true
|
||||||
|
),
|
||||||
|
step,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const relatedTrace = props.relatedTrace || {};
|
||||||
|
const status = relatedTrace.status;
|
||||||
|
const queryOrder = relatedTrace.queryOrder;
|
||||||
|
const latency = relatedTrace.latency;
|
||||||
|
const series = props.option.series || [];
|
||||||
|
const item: any = {
|
||||||
|
duration,
|
||||||
|
queryOrder,
|
||||||
|
status,
|
||||||
|
};
|
||||||
|
if (latency) {
|
||||||
|
const latencyList = series.map(
|
||||||
|
(d: { name: string; data: number[][] }, index: number) => {
|
||||||
|
const data = [
|
||||||
|
d.data[currentParams.dataIndex][1],
|
||||||
|
series[index + 1]
|
||||||
|
? series[index + 1].data[currentParams.dataIndex][1]
|
||||||
|
: Infinity,
|
||||||
|
];
|
||||||
|
return {
|
||||||
|
label:
|
||||||
|
d.name +
|
||||||
|
"--" +
|
||||||
|
(series[index + 1] ? series[index + 1].name : "Infinity"),
|
||||||
|
value: String(index),
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
item.latency = latencyList;
|
||||||
|
}
|
||||||
|
const value = series.map(
|
||||||
|
(d: { name: string; data: number[][] }, index: number) => {
|
||||||
|
return {
|
||||||
|
label: d.name,
|
||||||
|
value: String(index),
|
||||||
|
data: d.data[currentParams.dataIndex][1],
|
||||||
|
date: d.data[currentParams.dataIndex][0],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
item.metricValue = value;
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
return { eventAssociate, traceFilters };
|
||||||
|
}
|
@@ -14,19 +14,68 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
|
import { LayoutConfig } from "@/types/dashboard";
|
||||||
|
|
||||||
export default function getDashboard(param: {
|
export default function getDashboard(param?: {
|
||||||
name: string;
|
name: string;
|
||||||
layer: string;
|
layer: string;
|
||||||
entity: string;
|
entity: string;
|
||||||
}) {
|
}) {
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
const opt = param || dashboardStore.currentDashboard;
|
||||||
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
|
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
|
||||||
const dashboard = list.find(
|
const dashboard = list.find(
|
||||||
(d: { name: string; layer: string; entity: string }) =>
|
(d: { name: string; layer: string; entity: string }) =>
|
||||||
d.name === param.name &&
|
d.name === opt.name && d.entity === opt.entity && d.layer === opt.layer
|
||||||
d.entity === param.entity &&
|
|
||||||
d.layer === param.layer
|
|
||||||
);
|
);
|
||||||
|
const all = dashboardStore.layout;
|
||||||
|
const widgets: LayoutConfig[] = [];
|
||||||
|
for (const item of all) {
|
||||||
|
if (item.type === "Tab") {
|
||||||
|
widgets.push(item);
|
||||||
|
if (item.children && item.children.length) {
|
||||||
|
for (const child of item.children) {
|
||||||
|
if (child.children && child.children.length) {
|
||||||
|
widgets.push(...child.children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
widgets.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function associationWidget(sourceId: string, filters: unknown, type: string) {
|
||||||
|
const widget = widgets.find((d: { type: string }) => d.type === type);
|
||||||
|
if (!widget) {
|
||||||
|
return ElMessage.info(`There has no a ${type} widget in the dashboard`);
|
||||||
|
}
|
||||||
|
const item = {
|
||||||
|
...widget,
|
||||||
|
filters,
|
||||||
|
};
|
||||||
|
dashboardStore.setWidget(item);
|
||||||
|
const targetTabIndex = (widget.id || "").split("-");
|
||||||
|
const sourceTabindex = (sourceId || "").split("-") || [];
|
||||||
|
let container: Nullable<Element>;
|
||||||
|
|
||||||
return dashboard;
|
if (targetTabIndex[1] === undefined) {
|
||||||
|
container = document.querySelector(".ds-main");
|
||||||
|
} else {
|
||||||
|
const w = widgets.find((d: any) => d.id === targetTabIndex[0]);
|
||||||
|
container = document.querySelector(".tab-layout");
|
||||||
|
const layout: Nullable<Element> = document.querySelector(".ds-main");
|
||||||
|
if (w && layout) {
|
||||||
|
layout.scrollTop = w.y * 10 + w.h * 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (targetTabIndex[1] && targetTabIndex[1] !== sourceTabindex[1]) {
|
||||||
|
dashboardStore.setActiveTabIndex(Number(targetTabIndex[1]));
|
||||||
|
}
|
||||||
|
if (container && widget) {
|
||||||
|
container.scrollTop = widget.y * 10 + widget.h * 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { dashboard, widgets, associationWidget };
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,6 @@ import {
|
|||||||
BarSeriesOption,
|
BarSeriesOption,
|
||||||
LineSeriesOption,
|
LineSeriesOption,
|
||||||
HeatmapSeriesOption,
|
HeatmapSeriesOption,
|
||||||
PieSeriesOption,
|
|
||||||
SankeySeriesOption,
|
SankeySeriesOption,
|
||||||
} from "echarts/charts";
|
} from "echarts/charts";
|
||||||
import {
|
import {
|
||||||
@@ -46,7 +45,6 @@ export type ECOption = echarts.ComposeOption<
|
|||||||
| DatasetComponentOption
|
| DatasetComponentOption
|
||||||
| LegendComponentOption
|
| LegendComponentOption
|
||||||
| HeatmapSeriesOption
|
| HeatmapSeriesOption
|
||||||
| PieSeriesOption
|
|
||||||
| SankeySeriesOption
|
| SankeySeriesOption
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
142
src/hooks/useLegendProcessor.ts
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
/**
|
||||||
|
* 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 { LegendOptions } from "@/types/dashboard";
|
||||||
|
import { isDef } from "@/utils/is";
|
||||||
|
|
||||||
|
export default function useLegendProcess(legend?: LegendOptions) {
|
||||||
|
let isRight = false;
|
||||||
|
if (legend && legend.toTheRight) {
|
||||||
|
isRight = true;
|
||||||
|
}
|
||||||
|
function showEchartsLegend(keys: string[]) {
|
||||||
|
if (legend && isDef(legend.show)) {
|
||||||
|
if (legend.asTable && legend.show) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return legend.show;
|
||||||
|
}
|
||||||
|
if (keys.length === 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (legend && legend.asTable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function aggregations(
|
||||||
|
data: { [key: string]: number[] },
|
||||||
|
intervalTime: string[]
|
||||||
|
) {
|
||||||
|
const source: { [key: string]: unknown }[] = [];
|
||||||
|
const keys = Object.keys(data || {}).filter(
|
||||||
|
(i: any) => Array.isArray(data[i]) && data[i].length
|
||||||
|
);
|
||||||
|
const headers = [];
|
||||||
|
|
||||||
|
for (const [key, value] of keys.entries()) {
|
||||||
|
const arr = JSON.parse(JSON.stringify(data[value]));
|
||||||
|
const item: { [key: string]: unknown } = {
|
||||||
|
name: value,
|
||||||
|
topN: arr
|
||||||
|
.map((d: number, index: number) => {
|
||||||
|
return {
|
||||||
|
key: intervalTime[index],
|
||||||
|
value: d,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.sort(
|
||||||
|
(
|
||||||
|
a: { key: string; value: number },
|
||||||
|
b: { key: string; value: number }
|
||||||
|
) => b.value - a.value
|
||||||
|
)
|
||||||
|
.filter((_: unknown, index: number) => index < 10),
|
||||||
|
};
|
||||||
|
if (legend) {
|
||||||
|
if (legend.min) {
|
||||||
|
item.min = Math.min(...data[value]).toFixed(2);
|
||||||
|
if (key === 0) {
|
||||||
|
headers.push({ value: "min", label: "Min" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (legend.max) {
|
||||||
|
item.max = Math.max(...data[value]).toFixed(2);
|
||||||
|
if (key === 0) {
|
||||||
|
headers.push({ value: "max", label: "Max" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (legend.mean) {
|
||||||
|
const total = data[value].reduce((prev: number, next: number) => {
|
||||||
|
prev += Number(next);
|
||||||
|
return prev;
|
||||||
|
}, 0);
|
||||||
|
item.mean = (total / data[value].length).toFixed(4);
|
||||||
|
if (key === 0) {
|
||||||
|
headers.push({ value: "mean", label: "Mean" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (legend.total) {
|
||||||
|
item.total = data[value]
|
||||||
|
.reduce((prev: number, next: number) => {
|
||||||
|
prev += Number(next);
|
||||||
|
return prev;
|
||||||
|
}, 0)
|
||||||
|
.toFixed(2);
|
||||||
|
if (key === 0) {
|
||||||
|
headers.push({ value: "total", label: "Total" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
source.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { source, headers };
|
||||||
|
}
|
||||||
|
function chartColors(keys: string[]) {
|
||||||
|
let color: string[] = [];
|
||||||
|
switch (keys.length) {
|
||||||
|
case 2:
|
||||||
|
color = ["#FF6A84", "#a0b1e6"];
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
color = ["#3f96e3"];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
color = [
|
||||||
|
"#30A4EB",
|
||||||
|
"#45BFC0",
|
||||||
|
"#FFCC55",
|
||||||
|
"#FF6A84",
|
||||||
|
"#a0a7e6",
|
||||||
|
"#c23531",
|
||||||
|
"#2f4554",
|
||||||
|
"#61a0a8",
|
||||||
|
"#d48265",
|
||||||
|
"#91c7ae",
|
||||||
|
"#749f83",
|
||||||
|
"#ca8622",
|
||||||
|
"#bda29a",
|
||||||
|
"#6e7074",
|
||||||
|
"#546570",
|
||||||
|
"#c4ccd3",
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
return { showEchartsLegend, isRight, aggregations, chartColors };
|
||||||
|
}
|
@@ -26,14 +26,18 @@ export function useListConfig(config: any, index: string) {
|
|||||||
config.metricConfig &&
|
config.metricConfig &&
|
||||||
config.metricConfig[i] &&
|
config.metricConfig[i] &&
|
||||||
config.metricConfig[i].calculation;
|
config.metricConfig[i].calculation;
|
||||||
const line =
|
const isLinear =
|
||||||
config.metricTypes[i] === MetricQueryTypes.ReadMetricsValues &&
|
[
|
||||||
!types.includes(calculation);
|
MetricQueryTypes.ReadMetricsValues,
|
||||||
|
MetricQueryTypes.ReadLabeledMetricsValues,
|
||||||
|
].includes(config.metricTypes[i]) && !types.includes(calculation);
|
||||||
const isAvg =
|
const isAvg =
|
||||||
config.metricTypes[i] === MetricQueryTypes.ReadMetricsValues &&
|
[
|
||||||
types.includes(calculation);
|
MetricQueryTypes.ReadMetricsValues,
|
||||||
|
MetricQueryTypes.ReadLabeledMetricsValues,
|
||||||
|
].includes(config.metricTypes[i]) && types.includes(calculation);
|
||||||
return {
|
return {
|
||||||
isLinear: line,
|
isLinear,
|
||||||
isAvg,
|
isAvg,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -46,6 +46,7 @@ export function useQueryProcessor(config: any) {
|
|||||||
"ServiceRelation",
|
"ServiceRelation",
|
||||||
"ServiceInstanceRelation",
|
"ServiceInstanceRelation",
|
||||||
"EndpointRelation",
|
"EndpointRelation",
|
||||||
|
"ProcessRelation",
|
||||||
].includes(dashboardStore.entity);
|
].includes(dashboardStore.entity);
|
||||||
if (isRelation && !selectorStore.currentDestService) {
|
if (isRelation && !selectorStore.currentDestService) {
|
||||||
return;
|
return;
|
||||||
@@ -73,50 +74,73 @@ export function useQueryProcessor(config: any) {
|
|||||||
order: c.sortOrder || "DES",
|
order: c.sortOrder || "DES",
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) {
|
const entity = {
|
||||||
const labels = (c.labelsIndex || "")
|
scope: config.catalog,
|
||||||
.split(",")
|
serviceName:
|
||||||
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
dashboardStore.entity === "All"
|
||||||
variables.push(`$labels${index}: [String!]!`);
|
? undefined
|
||||||
conditions[`labels${index}`] = labels;
|
: selectorStore.currentService.value,
|
||||||
}
|
normal:
|
||||||
variables.push(`$condition${index}: MetricsCondition!`);
|
dashboardStore.entity === "All"
|
||||||
conditions[`condition${index}`] = {
|
? undefined
|
||||||
name,
|
: selectorStore.currentService.normal,
|
||||||
entity: {
|
serviceInstanceName: [
|
||||||
scope: dashboardStore.entity,
|
"ServiceInstance",
|
||||||
serviceName:
|
"ServiceInstanceRelation",
|
||||||
dashboardStore.entity === "All"
|
"ProcessRelation",
|
||||||
? undefined
|
].includes(dashboardStore.entity)
|
||||||
: selectorStore.currentService.value,
|
? selectorStore.currentPod && selectorStore.currentPod.value
|
||||||
normal:
|
: undefined,
|
||||||
dashboardStore.entity === "All"
|
endpointName: dashboardStore.entity.includes("Endpoint")
|
||||||
? undefined
|
? selectorStore.currentPod && selectorStore.currentPod.value
|
||||||
: selectorStore.currentService.normal,
|
: undefined,
|
||||||
serviceInstanceName: dashboardStore.entity.includes("ServiceInstance")
|
processName: dashboardStore.entity.includes("Process")
|
||||||
? selectorStore.currentPod && selectorStore.currentPod.value
|
? selectorStore.currentProcess && selectorStore.currentProcess.value
|
||||||
|
: undefined,
|
||||||
|
destNormal: isRelation
|
||||||
|
? selectorStore.currentDestService.normal
|
||||||
|
: undefined,
|
||||||
|
destServiceName: isRelation
|
||||||
|
? selectorStore.currentDestService.value
|
||||||
|
: undefined,
|
||||||
|
destServiceInstanceName: [
|
||||||
|
"ServiceInstanceRelation",
|
||||||
|
"ProcessRelation",
|
||||||
|
].includes(dashboardStore.entity)
|
||||||
|
? selectorStore.currentDestPod && selectorStore.currentDestPod.value
|
||||||
|
: undefined,
|
||||||
|
destEndpointName:
|
||||||
|
dashboardStore.entity === "EndpointRelation"
|
||||||
|
? selectorStore.currentDestPod && selectorStore.currentDestPod.value
|
||||||
: undefined,
|
: undefined,
|
||||||
endpointName: dashboardStore.entity.includes("Endpoint")
|
destProcessName: dashboardStore.entity.includes("ProcessRelation")
|
||||||
? selectorStore.currentPod && selectorStore.currentPod.value
|
? selectorStore.currentDestProcess &&
|
||||||
: undefined,
|
selectorStore.currentDestProcess.value
|
||||||
destNormal: isRelation
|
: undefined,
|
||||||
? selectorStore.currentDestService.normal
|
|
||||||
: undefined,
|
|
||||||
destServiceName: isRelation
|
|
||||||
? selectorStore.currentDestService.value
|
|
||||||
: undefined,
|
|
||||||
destServiceInstanceName:
|
|
||||||
dashboardStore.entity === "ServiceInstanceRelation"
|
|
||||||
? selectorStore.currentDestPod &&
|
|
||||||
selectorStore.currentDestPod.value
|
|
||||||
: undefined,
|
|
||||||
destEndpointName:
|
|
||||||
dashboardStore.entity === "EndpointRelation"
|
|
||||||
? selectorStore.currentDestPod &&
|
|
||||||
selectorStore.currentDestPod.value
|
|
||||||
: undefined,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
if ([MetricQueryTypes.ReadRecords].includes(metricType)) {
|
||||||
|
variables.push(`$condition${index}: RecordCondition!`);
|
||||||
|
conditions[`condition${index}`] = {
|
||||||
|
name,
|
||||||
|
parentEntity: entity,
|
||||||
|
topN: c.topN || 10,
|
||||||
|
order: c.sortOrder || "DES",
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
entity.scope = dashboardStore.entity;
|
||||||
|
if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) {
|
||||||
|
const labels = (c.labelsIndex || "")
|
||||||
|
.split(",")
|
||||||
|
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
||||||
|
variables.push(`$labels${index}: [String!]!`);
|
||||||
|
conditions[`labels${index}`] = labels;
|
||||||
|
}
|
||||||
|
variables.push(`$condition${index}: MetricsCondition!`);
|
||||||
|
conditions[`condition${index}`] = {
|
||||||
|
name,
|
||||||
|
entity,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) {
|
if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) {
|
||||||
return `${name}${index}: ${metricType}(condition: $condition${index}, labels: $labels${index}, duration: $duration)${RespFields[metricType]}`;
|
return `${name}${index}: ${metricType}(condition: $condition${index}, labels: $labels${index}, duration: $duration)${RespFields[metricType]}`;
|
||||||
@@ -125,6 +149,7 @@ export function useQueryProcessor(config: any) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
const queryStr = `query queryData(${variables}) {${fragment}}`;
|
const queryStr = `query queryData(${variables}) {${fragment}}`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
queryStr,
|
queryStr,
|
||||||
conditions,
|
conditions,
|
||||||
@@ -142,6 +167,10 @@ export function useSourceProcessor(
|
|||||||
ElMessage.error(resp.errors);
|
ElMessage.error(resp.errors);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
if (!resp.data) {
|
||||||
|
ElMessage.error("The query is wrong");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
const source: { [key: string]: unknown } = {};
|
const source: { [key: string]: unknown } = {};
|
||||||
const keys = Object.keys(resp.data);
|
const keys = Object.keys(resp.data);
|
||||||
|
|
||||||
@@ -150,7 +179,10 @@ export function useSourceProcessor(
|
|||||||
const c = (config.metricConfig && config.metricConfig[index]) || {};
|
const c = (config.metricConfig && config.metricConfig[index]) || {};
|
||||||
|
|
||||||
if (type === MetricQueryTypes.ReadMetricsValues) {
|
if (type === MetricQueryTypes.ReadMetricsValues) {
|
||||||
source[m] = calculateExp(resp.data[keys[index]].values.values, c);
|
source[c.label || m] =
|
||||||
|
(resp.data[keys[index]] &&
|
||||||
|
calculateExp(resp.data[keys[index]].values.values, c)) ||
|
||||||
|
[];
|
||||||
}
|
}
|
||||||
if (type === MetricQueryTypes.ReadLabeledMetricsValues) {
|
if (type === MetricQueryTypes.ReadLabeledMetricsValues) {
|
||||||
const resVal = Object.values(resp.data)[0] || [];
|
const resVal = Object.values(resp.data)[0] || [];
|
||||||
@@ -176,8 +208,13 @@ export function useSourceProcessor(
|
|||||||
source[m] = aggregation(Number(Object.values(resp.data)[0]), c);
|
source[m] = aggregation(Number(Object.values(resp.data)[0]), c);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
type === MetricQueryTypes.SortMetrics ||
|
(
|
||||||
type === MetricQueryTypes.ReadSampledRecords
|
[
|
||||||
|
MetricQueryTypes.ReadRecords,
|
||||||
|
MetricQueryTypes.ReadSampledRecords,
|
||||||
|
MetricQueryTypes.SortMetrics,
|
||||||
|
] as string[]
|
||||||
|
).includes(type)
|
||||||
) {
|
) {
|
||||||
source[m] = (Object.values(resp.data)[0] || []).map(
|
source[m] = (Object.values(resp.data)[0] || []).map(
|
||||||
(d: { value: unknown; name: string }) => {
|
(d: { value: unknown; name: string }) => {
|
||||||
@@ -218,13 +255,19 @@ export function useSourceProcessor(
|
|||||||
|
|
||||||
export function useQueryPodsMetrics(
|
export function useQueryPodsMetrics(
|
||||||
pods: Array<Instance | Endpoint | Service | any>,
|
pods: Array<Instance | Endpoint | Service | any>,
|
||||||
config: { metrics: string[]; metricTypes: string[] },
|
config: {
|
||||||
|
metrics: string[];
|
||||||
|
metricTypes: string[];
|
||||||
|
metricConfig: MetricConfigOpt[];
|
||||||
|
},
|
||||||
scope: string
|
scope: string
|
||||||
) {
|
) {
|
||||||
if (!(config.metrics && config.metrics[0])) {
|
const metricTypes = (config.metricTypes || []).filter((m: string) => m);
|
||||||
|
if (!metricTypes.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!(config.metricTypes && config.metricTypes[0])) {
|
const metrics = (config.metrics || []).filter((m: string) => m);
|
||||||
|
if (!metrics.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
@@ -246,14 +289,24 @@ export function useQueryPodsMetrics(
|
|||||||
endpointName: scope === "Endpoint" ? d.label : undefined,
|
endpointName: scope === "Endpoint" ? d.label : undefined,
|
||||||
normal: scope === "Service" ? d.normal : currentService.normal,
|
normal: scope === "Service" ? d.normal : currentService.normal,
|
||||||
};
|
};
|
||||||
const f = config.metrics.map((name: string, idx: number) => {
|
const f = metrics.map((name: string, idx: number) => {
|
||||||
const metricType = config.metricTypes[idx] || "";
|
const metricType = metricTypes[idx] || "";
|
||||||
|
variables.push(`$condition${index}${idx}: MetricsCondition!`);
|
||||||
conditions[`condition${index}${idx}`] = {
|
conditions[`condition${index}${idx}`] = {
|
||||||
name,
|
name,
|
||||||
entity: param,
|
entity: param,
|
||||||
};
|
};
|
||||||
variables.push(`$condition${index}${idx}: MetricsCondition!`);
|
let labelStr = "";
|
||||||
return `${name}${index}${idx}: ${metricType}(condition: $condition${index}${idx}, duration: $duration)${RespFields[metricType]}`;
|
if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) {
|
||||||
|
const c = config.metricConfig[idx] || {};
|
||||||
|
variables.push(`$labels${index}${idx}: [String!]!`);
|
||||||
|
labelStr = `labels: $labels${index}${idx}, `;
|
||||||
|
const labels = (c.labelsIndex || "")
|
||||||
|
.split(",")
|
||||||
|
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
||||||
|
conditions[`labels${index}${idx}`] = labels;
|
||||||
|
}
|
||||||
|
return `${name}${index}${idx}: ${metricType}(condition: $condition${index}${idx}, ${labelStr}duration: $duration)${RespFields[metricType]}`;
|
||||||
});
|
});
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
@@ -263,6 +316,7 @@ export function useQueryPodsMetrics(
|
|||||||
|
|
||||||
return { queryStr, conditions };
|
return { queryStr, conditions };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function usePodsSource(
|
export function usePodsSource(
|
||||||
pods: Array<Instance | Endpoint>,
|
pods: Array<Instance | Endpoint>,
|
||||||
resp: { errors: string; data: { [key: string]: any } },
|
resp: { errors: string; data: { [key: string]: any } },
|
||||||
@@ -276,12 +330,20 @@ export function usePodsSource(
|
|||||||
ElMessage.error(resp.errors);
|
ElMessage.error(resp.errors);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
const names: string[] = [];
|
||||||
|
const metricConfigArr: MetricConfigOpt[] = [];
|
||||||
|
const metricTypesArr: string[] = [];
|
||||||
const data = pods.map((d: Instance | any, idx: number) => {
|
const data = pods.map((d: Instance | any, idx: number) => {
|
||||||
config.metrics.map((name: string, index: number) => {
|
config.metrics.map((name: string, index: number) => {
|
||||||
const c: any = (config.metricConfig && config.metricConfig[index]) || {};
|
const c: any = (config.metricConfig && config.metricConfig[index]) || {};
|
||||||
const key = name + idx + index;
|
const key = name + idx + index;
|
||||||
if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValue) {
|
if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValue) {
|
||||||
d[name] = aggregation(resp.data[key], c);
|
d[name] = aggregation(resp.data[key], c);
|
||||||
|
if (idx === 0) {
|
||||||
|
names.push(name);
|
||||||
|
metricConfigArr.push(c);
|
||||||
|
metricTypesArr.push(config.metricTypes[index]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValues) {
|
if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValues) {
|
||||||
d[name] = {};
|
d[name] = {};
|
||||||
@@ -297,12 +359,56 @@ export function usePodsSource(
|
|||||||
d[name]["values"] = resp.data[key].values.values.map(
|
d[name]["values"] = resp.data[key].values.values.map(
|
||||||
(val: { value: number }) => aggregation(val.value, c)
|
(val: { value: number }) => aggregation(val.value, c)
|
||||||
);
|
);
|
||||||
|
if (idx === 0) {
|
||||||
|
names.push(name);
|
||||||
|
metricConfigArr.push(c);
|
||||||
|
metricTypesArr.push(config.metricTypes[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
config.metricTypes[index] === MetricQueryTypes.ReadLabeledMetricsValues
|
||||||
|
) {
|
||||||
|
const resVal = resp.data[key] || [];
|
||||||
|
const labels = (c.label || "")
|
||||||
|
.split(",")
|
||||||
|
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
||||||
|
const labelsIdx = (c.labelsIndex || "")
|
||||||
|
.split(",")
|
||||||
|
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
||||||
|
for (let i = 0; i < resVal.length; i++) {
|
||||||
|
const item = resVal[i];
|
||||||
|
const values = item.values.values.map((d: { value: number }) =>
|
||||||
|
aggregation(Number(d.value), c)
|
||||||
|
);
|
||||||
|
const indexNum = labelsIdx.findIndex((d: string) => d === item.label);
|
||||||
|
let key = item.label;
|
||||||
|
if (labels[indexNum] && indexNum > -1) {
|
||||||
|
key = labels[indexNum];
|
||||||
|
}
|
||||||
|
if (!d[key]) {
|
||||||
|
d[key] = {};
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
[
|
||||||
|
Calculations.Average,
|
||||||
|
Calculations.ApdexAvg,
|
||||||
|
Calculations.PercentageAvg,
|
||||||
|
].includes(c.calculation)
|
||||||
|
) {
|
||||||
|
d[key]["avg"] = calculateExp(item.values.values, c);
|
||||||
|
}
|
||||||
|
d[key]["values"] = values;
|
||||||
|
if (idx === 0) {
|
||||||
|
names.push(key);
|
||||||
|
metricConfigArr.push({ ...c, index: i });
|
||||||
|
metricTypesArr.push(config.metricTypes[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
});
|
});
|
||||||
return data;
|
return { data, names, metricConfigArr, metricTypesArr };
|
||||||
}
|
}
|
||||||
export function useQueryTopologyMetrics(metrics: string[], ids: string[]) {
|
export function useQueryTopologyMetrics(metrics: string[], ids: string[]) {
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
@@ -377,23 +483,26 @@ export function aggregation(
|
|||||||
data = (val / 1024 / 1024 / 1024).toFixed(2);
|
data = (val / 1024 / 1024 / 1024).toFixed(2);
|
||||||
break;
|
break;
|
||||||
case Calculations.Apdex:
|
case Calculations.Apdex:
|
||||||
data = val / 10000;
|
data = (val / 10000).toFixed(2);
|
||||||
break;
|
|
||||||
case Calculations.ApdexAvg:
|
|
||||||
data = val / 10000;
|
|
||||||
break;
|
break;
|
||||||
case Calculations.ConvertSeconds:
|
case Calculations.ConvertSeconds:
|
||||||
data = dayjs(val).format("YYYY-MM-DD HH:mm:ss");
|
data = dayjs(val * 1000).format("YYYY-MM-DD HH:mm:ss");
|
||||||
break;
|
break;
|
||||||
case Calculations.ConvertMilliseconds:
|
case Calculations.ConvertMilliseconds:
|
||||||
data = dayjs.unix(val).format("YYYY-MM-DD HH:mm:ss");
|
data = dayjs(val).format("YYYY-MM-DD HH:mm:ss");
|
||||||
break;
|
break;
|
||||||
case Calculations.Precision:
|
case Calculations.Precision:
|
||||||
data = data.toFixed(2);
|
data = data.toFixed(2);
|
||||||
break;
|
break;
|
||||||
case Calculations.MsTos:
|
case Calculations.MsToS:
|
||||||
data = (val / 1000).toFixed(2);
|
data = (val / 1000).toFixed(2);
|
||||||
break;
|
break;
|
||||||
|
case Calculations.SecondToDay:
|
||||||
|
data = (val / 86400).toFixed(2);
|
||||||
|
break;
|
||||||
|
case Calculations.NanosecondToMillisecond:
|
||||||
|
data = (val / 1000 / 1000).toFixed(2);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
data;
|
data;
|
||||||
break;
|
break;
|
||||||
@@ -412,6 +521,7 @@ export async function useGetMetricEntity(metric: string, metricType: any) {
|
|||||||
[
|
[
|
||||||
MetricQueryTypes.ReadSampledRecords,
|
MetricQueryTypes.ReadSampledRecords,
|
||||||
MetricQueryTypes.SortMetrics,
|
MetricQueryTypes.SortMetrics,
|
||||||
|
MetricQueryTypes.ReadRecords,
|
||||||
].includes(metricType)
|
].includes(metricType)
|
||||||
) {
|
) {
|
||||||
const res = await dashboardStore.fetchMetricList(metric);
|
const res = await dashboardStore.fetchMetricList(metric);
|
@@ -13,12 +13,12 @@ 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' }">
|
<div class="nav-bar flex-h">
|
||||||
<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>
|
||||||
<TimePicker
|
<TimePicker
|
||||||
:value="time"
|
:value="[appStore.durationRow.start, appStore.durationRow.end]"
|
||||||
position="bottom"
|
position="bottom"
|
||||||
format="YYYY-MM-DD HH:mm"
|
format="YYYY-MM-DD HH:mm"
|
||||||
@input="changeTimeRange"
|
@input="changeTimeRange"
|
||||||
@@ -49,7 +49,7 @@ limitations under the License. -->
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch, computed } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import timeFormat from "@/utils/timeFormat";
|
import timeFormat from "@/utils/timeFormat";
|
||||||
@@ -61,23 +61,20 @@ const appStore = useAppStoreWithOut();
|
|||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const pageName = ref<string>("");
|
const pageName = ref<string>("");
|
||||||
const timeRange = ref<number>(0);
|
const timeRange = ref<number>(0);
|
||||||
const theme = ref<string>("light");
|
|
||||||
|
|
||||||
|
resetDuration();
|
||||||
getVersion();
|
getVersion();
|
||||||
const setConfig = (value: string) => {
|
const setConfig = (value: string) => {
|
||||||
pageName.value = value || "";
|
pageName.value = value || "";
|
||||||
// theme.value = route.path.includes("/infrastructure/") ? "dark" : "light";
|
|
||||||
};
|
};
|
||||||
const time = computed(() => [
|
|
||||||
appStore.durationRow.start,
|
function handleReload() {
|
||||||
appStore.durationRow.end,
|
|
||||||
]);
|
|
||||||
const handleReload = () => {
|
|
||||||
const gap =
|
const gap =
|
||||||
appStore.duration.end.getTime() - appStore.duration.start.getTime();
|
appStore.duration.end.getTime() - appStore.duration.start.getTime();
|
||||||
const time: Date[] = [new Date(new Date().getTime() - gap), new Date()];
|
const dates: Date[] = [new Date(new Date().getTime() - gap), new Date()];
|
||||||
appStore.setDuration(timeFormat(time));
|
appStore.setDuration(timeFormat(dates));
|
||||||
};
|
}
|
||||||
|
|
||||||
function changeTimeRange(val: Date[] | any) {
|
function changeTimeRange(val: Date[] | any) {
|
||||||
timeRange.value =
|
timeRange.value =
|
||||||
val[1].getTime() - val[0].getTime() > 60 * 24 * 60 * 60 * 1000 ? 1 : 0;
|
val[1].getTime() - val[0].getTime() > 60 * 24 * 60 * 60 * 1000 ? 1 : 0;
|
||||||
@@ -99,6 +96,19 @@ async function getVersion() {
|
|||||||
ElMessage.error(res.errors);
|
ElMessage.error(res.errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function resetDuration() {
|
||||||
|
const { duration }: any = route.params;
|
||||||
|
if (duration) {
|
||||||
|
const d = JSON.parse(duration);
|
||||||
|
|
||||||
|
appStore.updateDurationRow({
|
||||||
|
start: new Date(d.start),
|
||||||
|
end: new Date(d.end),
|
||||||
|
step: d.step,
|
||||||
|
});
|
||||||
|
appStore.updateUTC(d.utc);
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.nav-bar {
|
.nav-bar {
|
||||||
|
@@ -33,11 +33,7 @@ limitations under the License. -->
|
|||||||
<template v-for="(menu, index) in routes" :key="index">
|
<template v-for="(menu, index) in routes" :key="index">
|
||||||
<el-sub-menu :index="String(menu.name)" v-if="menu.meta.hasGroup">
|
<el-sub-menu :index="String(menu.name)" v-if="menu.meta.hasGroup">
|
||||||
<template #title>
|
<template #title>
|
||||||
<router-link
|
<router-link class="items" :to="menu.path">
|
||||||
class="items"
|
|
||||||
:to="menu.path"
|
|
||||||
:exact="menu.meta.exact || false"
|
|
||||||
>
|
|
||||||
<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>
|
||||||
@@ -52,12 +48,8 @@ limitations under the License. -->
|
|||||||
:index="m.name"
|
:index="m.name"
|
||||||
:key="idx"
|
:key="idx"
|
||||||
>
|
>
|
||||||
<router-link
|
<router-link class="items" :to="m.path">
|
||||||
class="items"
|
<span class="title">{{ m.meta && t(m.meta.title) }}</span>
|
||||||
:to="m.path"
|
|
||||||
:exact="m.meta.exact || false"
|
|
||||||
>
|
|
||||||
<span class="title">{{ t(m.meta.title) }}</span>
|
|
||||||
</router-link>
|
</router-link>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</el-menu-item-group>
|
</el-menu-item-group>
|
||||||
@@ -68,20 +60,12 @@ limitations under the License. -->
|
|||||||
v-else
|
v-else
|
||||||
>
|
>
|
||||||
<el-icon class="menu-icons" :style="{ marginRight: '12px' }">
|
<el-icon class="menu-icons" :style="{ marginRight: '12px' }">
|
||||||
<router-link
|
<router-link class="items" :to="menu.children[0].path">
|
||||||
class="items"
|
|
||||||
:to="menu.children[0].path"
|
|
||||||
:exact="menu.meta.exact"
|
|
||||||
>
|
|
||||||
<Icon size="lg" :iconName="menu.meta.icon" />
|
<Icon size="lg" :iconName="menu.meta.icon" />
|
||||||
</router-link>
|
</router-link>
|
||||||
</el-icon>
|
</el-icon>
|
||||||
<template #title>
|
<template #title>
|
||||||
<router-link
|
<router-link class="items" :to="menu.children[0].path">
|
||||||
class="items"
|
|
||||||
:to="menu.children[0].path"
|
|
||||||
:exact="menu.meta.exact"
|
|
||||||
>
|
|
||||||
<span class="title">{{ t(menu.meta.title) }}</span>
|
<span class="title">{{ t(menu.meta.title) }}</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
@@ -123,7 +107,7 @@ if (/Android|webOS|iPhone|iPod|iPad|BlackBerry/i.test(navigator.userAgent)) {
|
|||||||
} else {
|
} else {
|
||||||
appStore.setIsMobile(false);
|
appStore.setIsMobile(false);
|
||||||
}
|
}
|
||||||
const isCollapse = ref(appStore.isMobile ? true : false);
|
const isCollapse = ref(false);
|
||||||
const controlMenu = () => {
|
const controlMenu = () => {
|
||||||
isCollapse.value = !isCollapse.value;
|
isCollapse.value = !isCollapse.value;
|
||||||
};
|
};
|
||||||
@@ -141,13 +125,13 @@ const filterMenus = (menus: any[]) => {
|
|||||||
.side-bar {
|
.side-bar {
|
||||||
background: #252a2f;
|
background: #252a2f;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 700px;
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 100px;
|
margin-bottom: 100px;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-menu-vertical:not(.el-menu--collapse) {
|
.el-menu-vertical:not(.el-menu--collapse) {
|
||||||
width: 200px;
|
width: 220px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +157,7 @@ span.collapse {
|
|||||||
.menu-control {
|
.menu-control {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 7px;
|
top: 7px;
|
||||||
left: 200px;
|
left: 220px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s linear;
|
transition: all 0.2s linear;
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
|
@@ -32,6 +32,7 @@ const msg = {
|
|||||||
dashboards: "Dashboards",
|
dashboards: "Dashboards",
|
||||||
profiles: "Profiles",
|
profiles: "Profiles",
|
||||||
database: "Database",
|
database: "Database",
|
||||||
|
mySQL: "MySQL",
|
||||||
serviceName: "Service Name",
|
serviceName: "Service Name",
|
||||||
technologies: "Technologies",
|
technologies: "Technologies",
|
||||||
generalServicePanel: "General Service Panel",
|
generalServicePanel: "General Service Panel",
|
||||||
@@ -51,17 +52,19 @@ const msg = {
|
|||||||
instance: "Instance",
|
instance: "Instance",
|
||||||
create: "Create",
|
create: "Create",
|
||||||
loading: "Loading",
|
loading: "Loading",
|
||||||
selectVisualization: "Visualize your metrics",
|
selectVisualization: "Visualize Metrics",
|
||||||
visualization: "Visualization",
|
visualization: "Visualization",
|
||||||
graphStyles: "Graph styles",
|
graphStyles: "Graph Styles",
|
||||||
widgetOptions: "Widget options",
|
widgetOptions: "Widget Options",
|
||||||
standardOptions: "Standard options",
|
standardOptions: "Standard Options",
|
||||||
max: "Max",
|
max: "Max",
|
||||||
min: "Min",
|
min: "Min",
|
||||||
plus: "Plus",
|
plus: "Plus",
|
||||||
|
mean: "Mean",
|
||||||
minus: "Minus",
|
minus: "Minus",
|
||||||
multiply: "Multiply",
|
multiply: "Multiply",
|
||||||
divide: "Divide",
|
divide: "Divide",
|
||||||
|
total: "Total",
|
||||||
convertToMilliseconds: "Convert Unix Timestamp(milliseconds)",
|
convertToMilliseconds: "Convert Unix Timestamp(milliseconds)",
|
||||||
convertToSeconds: "Convert Unix Timestamp(seconds)",
|
convertToSeconds: "Convert Unix Timestamp(seconds)",
|
||||||
smooth: "Smooth",
|
smooth: "Smooth",
|
||||||
@@ -107,6 +110,7 @@ const msg = {
|
|||||||
showXAxis: "Show X Axis",
|
showXAxis: "Show X Axis",
|
||||||
showYAxis: "Show Y Axis",
|
showYAxis: "Show Y Axis",
|
||||||
nameError: "The dashboard name cannot be duplicate",
|
nameError: "The dashboard name cannot be duplicate",
|
||||||
|
nameEmptyError: "The dashboard name cannot be empty",
|
||||||
showGroup: "Show Group",
|
showGroup: "Show Group",
|
||||||
noRoot: "Please set a root dashboard for",
|
noRoot: "Please set a root dashboard for",
|
||||||
noWidget: "Please add widgets.",
|
noWidget: "Please add widgets.",
|
||||||
@@ -122,6 +126,7 @@ const msg = {
|
|||||||
editWarning: "You are entering edit mode",
|
editWarning: "You are entering edit mode",
|
||||||
viewWarning: "You are entering view mode",
|
viewWarning: "You are entering view mode",
|
||||||
virtualDatabase: "Virtual Database",
|
virtualDatabase: "Virtual Database",
|
||||||
|
virtualCache: "Virtual Cache",
|
||||||
reloadDashboards: "Reload dashboards",
|
reloadDashboards: "Reload dashboards",
|
||||||
kubernetesService: "Service",
|
kubernetesService: "Service",
|
||||||
kubernetesCluster: "Cluster",
|
kubernetesCluster: "Cluster",
|
||||||
@@ -142,6 +147,40 @@ const msg = {
|
|||||||
interval: "Refresh Interval",
|
interval: "Refresh Interval",
|
||||||
pause: "Pause",
|
pause: "Pause",
|
||||||
begin: "Start",
|
begin: "Start",
|
||||||
|
associateOptions: "Association Options",
|
||||||
|
associateMetrics: "Association Metrics",
|
||||||
|
widget: "Widget",
|
||||||
|
nameTip:
|
||||||
|
"The name only supports Chinese and English, horizontal lines and underscores. The length of the name is limited to 300 characters",
|
||||||
|
duplicateName: "Duplicate name",
|
||||||
|
enableAssociate: "Enable association",
|
||||||
|
text: "Text",
|
||||||
|
query: "Query",
|
||||||
|
postgreSQL: "PostgreSQL",
|
||||||
|
endpointTips: "The table shows up to 20 pieces of endpoints.",
|
||||||
|
apisix: "APISIX",
|
||||||
|
viewTrace: "View Related Traces",
|
||||||
|
relatedTraceOptions: "Related Trace Options",
|
||||||
|
setLatencyDuration: "Latency Related Metrics",
|
||||||
|
queryOrder: "Query By Duration",
|
||||||
|
setOrder: "Query Order",
|
||||||
|
latency: "Latency",
|
||||||
|
metricValues: "Metric Values",
|
||||||
|
queryConditions: "Query Conditions",
|
||||||
|
enableRelatedTrace: "Enable Related Trace",
|
||||||
|
maxTraceDuration: "Maximum Duration",
|
||||||
|
minTraceDuration: "Minimum Duration",
|
||||||
|
legendOptions: "Legend Options",
|
||||||
|
showLegend: "Show Legend",
|
||||||
|
asTable: "As Table",
|
||||||
|
toTheRight: "To The Right",
|
||||||
|
legendValues: "Legend Values",
|
||||||
|
minDuration: "Minimal Request Duration",
|
||||||
|
when4xx:
|
||||||
|
"Sample HTTP requests and responses with tracing when response code between 400 and 499",
|
||||||
|
when5xx:
|
||||||
|
"Sample HTTP requests and responses with tracing when response code between 500 and 599",
|
||||||
|
taskTitle: "HTTP request and response collecting rules",
|
||||||
seconds: "Seconds",
|
seconds: "Seconds",
|
||||||
hourTip: "Select Hour",
|
hourTip: "Select Hour",
|
||||||
minuteTip: "Select Minute",
|
minuteTip: "Select Minute",
|
||||||
@@ -151,8 +190,6 @@ const msg = {
|
|||||||
monthsHead: "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec",
|
monthsHead: "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec",
|
||||||
months: "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec",
|
months: "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec",
|
||||||
weeks: "Mon_Tue_Wed_Thu_Fri_Sat_Sun",
|
weeks: "Mon_Tue_Wed_Thu_Fri_Sat_Sun",
|
||||||
hello: "Hello",
|
|
||||||
helloMessage: "Welcome Back, Apache SkyWalking APM System !",
|
|
||||||
username: "Username",
|
username: "Username",
|
||||||
password: "Password",
|
password: "Password",
|
||||||
title: "Title",
|
title: "Title",
|
||||||
@@ -161,7 +198,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",
|
||||||
@@ -236,7 +273,7 @@ const msg = {
|
|||||||
entityType: "Entity Type",
|
entityType: "Entity Type",
|
||||||
maxItemNum: "Max number of Item",
|
maxItemNum: "Max number of Item",
|
||||||
unknownMetrics: "Unknown Metrics",
|
unknownMetrics: "Unknown Metrics",
|
||||||
labels: "Labels",
|
labels: "Label",
|
||||||
aggregation: "Calculation",
|
aggregation: "Calculation",
|
||||||
unit: "Unit",
|
unit: "Unit",
|
||||||
labelsIndex: "Label Subscript",
|
labelsIndex: "Label Subscript",
|
||||||
@@ -297,6 +334,7 @@ const msg = {
|
|||||||
eventsParameters: "Event Parameters",
|
eventsParameters: "Event Parameters",
|
||||||
eventDetail: "Event Detail",
|
eventDetail: "Event Detail",
|
||||||
value: "Value",
|
value: "Value",
|
||||||
|
key: "Key",
|
||||||
show: "Show",
|
show: "Show",
|
||||||
hide: "Hide",
|
hide: "Hide",
|
||||||
statistics: "Statistics",
|
statistics: "Statistics",
|
||||||
@@ -335,5 +373,7 @@ const msg = {
|
|||||||
conditionNotice:
|
conditionNotice:
|
||||||
"Notice: Please press Enter after inputting a 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",
|
||||||
|
gateway: "Gateway",
|
||||||
|
virtualMQ: "Virtual MQ",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
@@ -32,6 +32,7 @@ const msg = {
|
|||||||
dashboards: "Paneles",
|
dashboards: "Paneles",
|
||||||
profiles: "Perfiles",
|
profiles: "Perfiles",
|
||||||
database: "Base de Datos",
|
database: "Base de Datos",
|
||||||
|
mySQL: "MySQL",
|
||||||
serviceName: "Nombre Servicio",
|
serviceName: "Nombre Servicio",
|
||||||
technologies: "Tecnologías",
|
technologies: "Tecnologías",
|
||||||
generalServicePanel: "Panel Servicio General",
|
generalServicePanel: "Panel Servicio General",
|
||||||
@@ -58,9 +59,11 @@ const msg = {
|
|||||||
standardOptions: "Opciones estandar",
|
standardOptions: "Opciones estandar",
|
||||||
max: "Máx",
|
max: "Máx",
|
||||||
min: "Mín",
|
min: "Mín",
|
||||||
|
mean: "Promedio",
|
||||||
plus: "Más",
|
plus: "Más",
|
||||||
minus: "Menoss",
|
minus: "Menoss",
|
||||||
multiply: "Multiplcar",
|
multiply: "Multiplcar",
|
||||||
|
total: "Todo",
|
||||||
divide: "Dividir",
|
divide: "Dividir",
|
||||||
convertToMilliseconds: "Convertir Unix Timestamp(milisegundos)",
|
convertToMilliseconds: "Convertir Unix Timestamp(milisegundos)",
|
||||||
convertToSeconds: "Convertir Unix Timestamp(segundos)",
|
convertToSeconds: "Convertir Unix Timestamp(segundos)",
|
||||||
@@ -109,6 +112,7 @@ const msg = {
|
|||||||
showXAxis: "Mostrar Eje X",
|
showXAxis: "Mostrar Eje X",
|
||||||
showYAxis: "Mostrar Eje Y",
|
showYAxis: "Mostrar Eje Y",
|
||||||
nameError: "El nombre del panel no puede ser duplicado",
|
nameError: "El nombre del panel no puede ser duplicado",
|
||||||
|
nameEmptyError: "El nombre del panel no puede estar vacío",
|
||||||
showGroup: "Mostrar Grupo",
|
showGroup: "Mostrar Grupo",
|
||||||
noRoot: "Por favor ponga la raíz del panel",
|
noRoot: "Por favor ponga la raíz del panel",
|
||||||
noWidget: "Por favor añada widgets.",
|
noWidget: "Por favor añada widgets.",
|
||||||
@@ -124,6 +128,7 @@ const msg = {
|
|||||||
editWarning: "Estás entrando en modo edición",
|
editWarning: "Estás entrando en modo edición",
|
||||||
viewWarning: "Estás entrando en modo visualización",
|
viewWarning: "Estás entrando en modo visualización",
|
||||||
virtualDatabase: "Base de Datos Virtual",
|
virtualDatabase: "Base de Datos Virtual",
|
||||||
|
virtualCache: "Caché virtual",
|
||||||
reloadDashboards: "Recargar Panel",
|
reloadDashboards: "Recargar Panel",
|
||||||
kubernetesService: "Servicio",
|
kubernetesService: "Servicio",
|
||||||
kubernetesCluster: "Cluster",
|
kubernetesCluster: "Cluster",
|
||||||
@@ -142,17 +147,49 @@ const msg = {
|
|||||||
interval: "Intervalo de actualización",
|
interval: "Intervalo de actualización",
|
||||||
pause: "Pausa",
|
pause: "Pausa",
|
||||||
begin: "Inicio",
|
begin: "Inicio",
|
||||||
|
associateOptions: "Opciones de asociación",
|
||||||
|
associateMetrics: "Índice de correlación",
|
||||||
|
widget: "Dispositivo pequeño",
|
||||||
|
text: "Texto",
|
||||||
|
duplicateName: "Nombre duplicado",
|
||||||
|
nameTip:
|
||||||
|
"El nombre sólo admite chino e inglés, líneas horizontales y subrayado, y la longitud del nombre no excederá de 300 caracteres",
|
||||||
|
enableAssociate: "Activar asociación",
|
||||||
|
query: "Consulta",
|
||||||
|
postgreSQL: "PostgreSQL",
|
||||||
|
endpointTips: "Aquí, la tabla muestra hasta 20 punto final.",
|
||||||
|
apisix: "APISIX",
|
||||||
|
queryOrder: "Consulta por duración",
|
||||||
|
setOrder: "Orden de consulta",
|
||||||
|
latency: "Retraso",
|
||||||
|
metricValues: "Valor métrico",
|
||||||
|
legendValues: "Valor de la leyenda",
|
||||||
seconds: "Segundos",
|
seconds: "Segundos",
|
||||||
hourTip: "Seleccione Hora",
|
hourTip: "Seleccione Hora",
|
||||||
minuteTip: "Seleccione Minuto",
|
minuteTip: "Seleccione Minuto",
|
||||||
secondTip: "Seleccione Segundo",
|
secondTip: "Seleccione Segundo",
|
||||||
|
viewTrace: "Ver trazas relacionadas",
|
||||||
|
relatedTraceOptions: "Opciones de seguimiento relacionadas",
|
||||||
|
setLatencyDuration: "Índice de correlación retardada",
|
||||||
|
enableRelatedTrace: "Activar trazas relacionadas",
|
||||||
|
queryConditions: "Condiciones de consulta",
|
||||||
|
maxTraceDuration: "Duración máxima",
|
||||||
|
minTraceDuration: "Duración mínima",
|
||||||
|
legendOptions: "Opciones de leyenda",
|
||||||
|
showLegend: "Mostrar leyenda",
|
||||||
|
asTable: "Como tabla",
|
||||||
|
toTheRight: "Derecha",
|
||||||
|
minDuration: "Duración mínima de la solicitud",
|
||||||
|
when4xx:
|
||||||
|
"Ejemplo de solicitud y respuesta http con seguimiento cuando el Código de respuesta está entre 400 y 499",
|
||||||
|
when5xx:
|
||||||
|
"Ejemplo de solicitud y respuesta http con seguimiento cuando el Código de respuesta está entre 500 y 599",
|
||||||
|
taskTitle: "Reglas de recolección de peticiones y respuestas HTTP",
|
||||||
second: "s",
|
second: "s",
|
||||||
yearSuffix: "Año",
|
yearSuffix: "Año",
|
||||||
monthsHead: "Ene_Feb_Mar_Abr_May_Jun_Jul_Ago_Set_Oct_Nov_Dic",
|
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",
|
months: "Ene_Feb_Mar_Abr_May_Jun_Jul_Ago_Set_Oct_Nov_Dic",
|
||||||
weeks: "Lun_Mar_Mier_Jue_Vie_Sáb_Dom",
|
weeks: "Lun_Mar_Mier_Jue_Vie_Sáb_Dom",
|
||||||
hello: "Hola",
|
|
||||||
helloMessage: "Bienvenido de vuelta, Apache SkyWalking APM System !",
|
|
||||||
username: "Usuario",
|
username: "Usuario",
|
||||||
password: "Contraseña",
|
password: "Contraseña",
|
||||||
title: "Título",
|
title: "Título",
|
||||||
@@ -161,7 +198,7 @@ const msg = {
|
|||||||
dashboard: "Panel",
|
dashboard: "Panel",
|
||||||
topology: "Topología",
|
topology: "Topología",
|
||||||
trace: "Traza",
|
trace: "Traza",
|
||||||
alarm: "Alarmas",
|
alarm: "Recordatorio en curso",
|
||||||
auto: "Auto",
|
auto: "Auto",
|
||||||
reload: "Recargar",
|
reload: "Recargar",
|
||||||
version: "Versión",
|
version: "Versión",
|
||||||
@@ -297,6 +334,7 @@ const msg = {
|
|||||||
eventsParameters: "Parámetro del Evento",
|
eventsParameters: "Parámetro del Evento",
|
||||||
eventDetail: "Detalle del Evento",
|
eventDetail: "Detalle del Evento",
|
||||||
value: "Valor",
|
value: "Valor",
|
||||||
|
key: "Clave",
|
||||||
show: "Mostrar",
|
show: "Mostrar",
|
||||||
hide: "Oculatr",
|
hide: "Oculatr",
|
||||||
statistics: "Estadísticas",
|
statistics: "Estadísticas",
|
||||||
@@ -338,5 +376,7 @@ const msg = {
|
|||||||
conditionNotice:
|
conditionNotice:
|
||||||
"Aviso: Por favor presione Intro después de introducir una clave de contenido, excluir clave de contenido(clave=valor).",
|
"Aviso: Por favor presione Intro después de introducir una clave de contenido, excluir clave de contenido(clave=valor).",
|
||||||
language: "Lenguaje",
|
language: "Lenguaje",
|
||||||
|
gateway: "Puerta",
|
||||||
|
virtualMQ: "MQ virtual",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
@@ -32,6 +32,7 @@ const msg = {
|
|||||||
dashboards: "仪表盘",
|
dashboards: "仪表盘",
|
||||||
profiles: "性能剖析",
|
profiles: "性能剖析",
|
||||||
database: "数据库",
|
database: "数据库",
|
||||||
|
mySQL: "MySQL",
|
||||||
serviceName: "服务名称",
|
serviceName: "服务名称",
|
||||||
technologies: "技术",
|
technologies: "技术",
|
||||||
health: "健康",
|
health: "健康",
|
||||||
@@ -55,10 +56,12 @@ const msg = {
|
|||||||
standardOptions: "标准选项",
|
standardOptions: "标准选项",
|
||||||
max: "最大值",
|
max: "最大值",
|
||||||
min: "最小值",
|
min: "最小值",
|
||||||
|
mean: "平均值",
|
||||||
plus: "加法",
|
plus: "加法",
|
||||||
minus: "减法",
|
minus: "减法",
|
||||||
multiply: "乘法",
|
multiply: "乘法",
|
||||||
divide: "除法",
|
divide: "除法",
|
||||||
|
total: "总计",
|
||||||
convertToMilliseconds: "转换Unix时间戳(毫秒)",
|
convertToMilliseconds: "转换Unix时间戳(毫秒)",
|
||||||
convertToSeconds: "转换Unix时间戳(秒)",
|
convertToSeconds: "转换Unix时间戳(秒)",
|
||||||
smooth: "光滑的",
|
smooth: "光滑的",
|
||||||
@@ -105,6 +108,7 @@ const msg = {
|
|||||||
showXAxis: "显示X轴",
|
showXAxis: "显示X轴",
|
||||||
showYAxis: "显示Y轴",
|
showYAxis: "显示Y轴",
|
||||||
nameError: "仪表板名称不能重复",
|
nameError: "仪表板名称不能重复",
|
||||||
|
nameEmptyError: "仪表板名称不能为空",
|
||||||
noRoot: "请设置根仪表板,为",
|
noRoot: "请设置根仪表板,为",
|
||||||
showGroup: "显示分组",
|
showGroup: "显示分组",
|
||||||
noWidget: "请添加组件",
|
noWidget: "请添加组件",
|
||||||
@@ -120,6 +124,7 @@ const msg = {
|
|||||||
editWarning: "你正在进入编辑模式",
|
editWarning: "你正在进入编辑模式",
|
||||||
viewWarning: "你正在进入预览模式",
|
viewWarning: "你正在进入预览模式",
|
||||||
virtualDatabase: "虚拟数据库",
|
virtualDatabase: "虚拟数据库",
|
||||||
|
virtualCache: "虚拟缓存",
|
||||||
reloadDashboards: "重新加载仪表盘",
|
reloadDashboards: "重新加载仪表盘",
|
||||||
kubernetesService: "服务",
|
kubernetesService: "服务",
|
||||||
kubernetesCluster: "集群",
|
kubernetesCluster: "集群",
|
||||||
@@ -140,6 +145,37 @@ const msg = {
|
|||||||
interval: "刷新间隔时间",
|
interval: "刷新间隔时间",
|
||||||
pause: "暂停",
|
pause: "暂停",
|
||||||
begin: "开始",
|
begin: "开始",
|
||||||
|
associateOptions: "关联选项",
|
||||||
|
associateMetrics: "关联指标",
|
||||||
|
widget: "部件",
|
||||||
|
enableAssociate: "启用关联",
|
||||||
|
nameTip: "该名称仅支持中文和英文、横线和下划线, 并且限制长度为300个字符",
|
||||||
|
duplicateName: "重复的名称",
|
||||||
|
text: "文本",
|
||||||
|
query: "查询",
|
||||||
|
postgreSQL: "PostgreSQL",
|
||||||
|
endpointTips: "这里最多展示20条endpoints。",
|
||||||
|
apisix: "APISIX",
|
||||||
|
viewTrace: "查看相关Trace",
|
||||||
|
relatedTraceOptions: "相关的Trace选项",
|
||||||
|
setLatencyDuration: "延迟相关指标",
|
||||||
|
queryOrder: "按持续时间查询",
|
||||||
|
setOrder: "查询顺序",
|
||||||
|
latency: "延迟",
|
||||||
|
metricValues: "指标值",
|
||||||
|
enableRelatedTrace: "启用相关Trace",
|
||||||
|
queryConditions: "查询条件",
|
||||||
|
maxTraceDuration: "最大持续时间",
|
||||||
|
minTraceDuration: "最小持续时间",
|
||||||
|
legendOptions: "图例选项",
|
||||||
|
showLegend: "显示图例",
|
||||||
|
asTable: "作为表格",
|
||||||
|
toTheRight: "在右边",
|
||||||
|
legendValues: "图例值",
|
||||||
|
minDuration: "最小请求持续时间",
|
||||||
|
when4xx: "当响应代码介于400和499之间时,带有跟踪的HTTP请求和响应示例",
|
||||||
|
when5xx: "当响应代码介于500和599之间时,带有跟踪的HTTP请求和响应示例",
|
||||||
|
taskTitle: "HTTP请求和响应收集规则",
|
||||||
seconds: "秒",
|
seconds: "秒",
|
||||||
hourTip: "选择小时",
|
hourTip: "选择小时",
|
||||||
minuteTip: "选择分钟",
|
minuteTip: "选择分钟",
|
||||||
@@ -149,8 +185,6 @@ const msg = {
|
|||||||
monthsHead: "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月",
|
monthsHead: "1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月",
|
||||||
months: "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月",
|
months: "一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月",
|
||||||
weeks: "一_二_三_四_五_六_日",
|
weeks: "一_二_三_四_五_六_日",
|
||||||
hello: "你好",
|
|
||||||
helloMessage: "欢迎来到, Apache SkyWalking APM 系统 !",
|
|
||||||
username: "用户名",
|
username: "用户名",
|
||||||
password: "密码",
|
password: "密码",
|
||||||
title: "标题",
|
title: "标题",
|
||||||
@@ -296,6 +330,7 @@ const msg = {
|
|||||||
eventsParameters: "事件参数",
|
eventsParameters: "事件参数",
|
||||||
eventDetail: "事件详情",
|
eventDetail: "事件详情",
|
||||||
value: "数值",
|
value: "数值",
|
||||||
|
key: "Key",
|
||||||
tableHeader: "表头名称",
|
tableHeader: "表头名称",
|
||||||
tableValues: "表值",
|
tableValues: "表值",
|
||||||
show: "展示",
|
show: "展示",
|
||||||
@@ -336,5 +371,7 @@ const msg = {
|
|||||||
conditionNotice:
|
conditionNotice:
|
||||||
"请输入一个内容关键词或者内容不包含的关键词(key=value)之后回车",
|
"请输入一个内容关键词或者内容不包含的关键词(key=value)之后回车",
|
||||||
language: "语言",
|
language: "语言",
|
||||||
|
gateway: "网关",
|
||||||
|
virtualMQ: "虚拟消息队列",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
@@ -25,18 +25,14 @@ export const routesAlarm: Array<RouteRecordRaw> = [
|
|||||||
title: "alarm",
|
title: "alarm",
|
||||||
icon: "spam",
|
icon: "spam",
|
||||||
hasGroup: false,
|
hasGroup: false,
|
||||||
exact: true,
|
|
||||||
},
|
},
|
||||||
component: Layout,
|
component: Layout,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/alarm",
|
path: "/alerting",
|
||||||
name: "Alarm",
|
name: "Alarm",
|
||||||
meta: {
|
|
||||||
exact: false,
|
|
||||||
},
|
|
||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "alarms" */ "@/views/Alarm.vue"),
|
import(/* webpackChunkName: "alerting" */ "@/views/Alarm.vue"),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@@ -26,7 +26,6 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
title: "dashboards",
|
title: "dashboards",
|
||||||
icon: "dashboard_customize",
|
icon: "dashboard_customize",
|
||||||
hasGroup: true,
|
hasGroup: true,
|
||||||
exact: true,
|
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
@@ -38,7 +37,6 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
name: "List",
|
name: "List",
|
||||||
meta: {
|
meta: {
|
||||||
title: "dashboardList",
|
title: "dashboardList",
|
||||||
exact: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -50,73 +48,198 @@ export const routesDashboard: Array<RouteRecordRaw> = [
|
|||||||
name: "New",
|
name: "New",
|
||||||
meta: {
|
meta: {
|
||||||
title: "dashboardNew",
|
title: "dashboardNew",
|
||||||
exact: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:name",
|
path: "",
|
||||||
|
redirect: "/dashboard/:layerId/:entity/:name",
|
||||||
|
name: "Create",
|
||||||
component: () =>
|
component: () =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
),
|
),
|
||||||
name: "Create",
|
|
||||||
meta: {
|
meta: {
|
||||||
title: "dashboardEdit",
|
|
||||||
exact: false,
|
|
||||||
notShow: true,
|
notShow: true,
|
||||||
},
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/dashboard/:layerId/:entity/:name",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "CreateChild",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/dashboard/:layerId/:entity/:name/tab/:activeTabIndex",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "CreateActiveTabIndex",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:serviceId/:name",
|
path: "",
|
||||||
component: () =>
|
component: () =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
),
|
),
|
||||||
name: "View",
|
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",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewChild",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/dashboard/:layerId/:entity/:serviceId/:name/tab/:activeTabIndex",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewActiveTabIndex",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name",
|
path: "",
|
||||||
|
redirect:
|
||||||
|
"/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name",
|
||||||
component: () =>
|
component: () =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
),
|
),
|
||||||
name: "ViewServiceRelation",
|
name: "ViewServiceRelation",
|
||||||
meta: {
|
meta: {
|
||||||
title: "dashboardEdit",
|
|
||||||
exact: false,
|
|
||||||
notShow: true,
|
notShow: true,
|
||||||
},
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewServiceRelation",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name/tab/:activeTabIndex",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewServiceRelationActiveTabIndex",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:name",
|
path: "",
|
||||||
|
redirect: "/dashboard/:layerId/:entity/:serviceId/:podId/:name",
|
||||||
component: () =>
|
component: () =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
),
|
),
|
||||||
name: "ViewPod",
|
name: "ViewPod",
|
||||||
meta: {
|
meta: {
|
||||||
title: "dashboardEdit",
|
|
||||||
exact: false,
|
|
||||||
notShow: true,
|
notShow: true,
|
||||||
},
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:name",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewPod",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:name/tab/:activeTabIndex",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewPodActiveTabIndex",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name",
|
path: "",
|
||||||
|
redirect:
|
||||||
|
"/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name",
|
||||||
component: () =>
|
component: () =>
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
),
|
),
|
||||||
name: "ViewPodRelation",
|
name: "PodRelation",
|
||||||
meta: {
|
meta: {
|
||||||
title: "dashboardEdit",
|
|
||||||
exact: true,
|
|
||||||
notShow: true,
|
notShow: true,
|
||||||
},
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewPodRelation",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name/tab/:activeTabIndex",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewPodRelationActiveTabIndex",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
redirect:
|
||||||
|
"/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ProcessRelation",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewProcessRelation",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name/tab/:activeTabIndex",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewProcessRelationActiveTabIndex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name/duration/:duration",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "dashboards" */ "@/views/dashboard/Edit.vue"
|
||||||
|
),
|
||||||
|
name: "ViewProcessRelationDuration",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@@ -14,10 +14,8 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
import { RouteRecordRaw } from "vue-router";
|
|
||||||
import Layout from "@/layout/Index.vue";
|
|
||||||
|
|
||||||
export const routesBrowser: Array<RouteRecordRaw> = [
|
export default [
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
name: "Browser",
|
name: "Browser",
|
||||||
@@ -26,18 +24,22 @@ export const routesBrowser: Array<RouteRecordRaw> = [
|
|||||||
icon: "language",
|
icon: "language",
|
||||||
},
|
},
|
||||||
redirect: "/browser",
|
redirect: "/browser",
|
||||||
component: Layout,
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/browser",
|
path: "/browser",
|
||||||
name: "Browser",
|
name: "Browser",
|
||||||
meta: {
|
meta: {
|
||||||
title: "browser",
|
title: "browser",
|
||||||
headPath: "/browser",
|
layer: "BROWSER",
|
||||||
exact: true,
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/browser/tab/:activeTabIndex",
|
||||||
|
name: "BrowserActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
layer: "BROWSER",
|
||||||
},
|
},
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
63
src/router/data/database.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* 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 default [
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
name: "Database",
|
||||||
|
meta: {
|
||||||
|
title: "database",
|
||||||
|
icon: "storage",
|
||||||
|
hasGroup: true,
|
||||||
|
},
|
||||||
|
redirect: "/mySQL",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/mySQL",
|
||||||
|
name: "MySQL",
|
||||||
|
meta: {
|
||||||
|
title: "mySQL",
|
||||||
|
layer: "MYSQL",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/mySQL/tab/:activeTabIndex",
|
||||||
|
name: "MySQLActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
layer: "MYSQL",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/postgreSQL",
|
||||||
|
name: "PostgreSQL",
|
||||||
|
meta: {
|
||||||
|
title: "postgreSQL",
|
||||||
|
layer: "POSTGRESQL",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/postgreSQL/tab/:activeTabIndex",
|
||||||
|
name: "PostgreSQLActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
layer: "POSTGRESQL",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
@@ -14,30 +14,25 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
import { RouteRecordRaw } from "vue-router";
|
|
||||||
import Layout from "@/layout/Index.vue";
|
|
||||||
|
|
||||||
export const routesFunctions: Array<RouteRecordRaw> = [
|
export default [
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
name: "Functions",
|
name: "Functions",
|
||||||
meta: {
|
meta: {
|
||||||
title: "functions",
|
title: "functions",
|
||||||
icon: "cloud_queue",
|
icon: "cloud_queue",
|
||||||
|
layer: "FAAS",
|
||||||
},
|
},
|
||||||
redirect: "/functions",
|
redirect: "/functions",
|
||||||
component: Layout,
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/functions",
|
path: "/functions",
|
||||||
name: "Functions",
|
name: "Functions",
|
||||||
meta: {
|
},
|
||||||
title: "functions",
|
{
|
||||||
headPath: "/functions",
|
path: "/functions/tab/:activeTabIndex",
|
||||||
exact: true,
|
name: "FunctionsActiveTabIndex",
|
||||||
},
|
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
@@ -14,29 +14,33 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
import { RouteRecordRaw } from "vue-router";
|
|
||||||
import Layout from "@/layout/Index.vue";
|
|
||||||
|
|
||||||
export const routesEvent: Array<RouteRecordRaw> = [
|
export default [
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
name: "Events",
|
name: "Gateway",
|
||||||
meta: {
|
meta: {
|
||||||
title: "events",
|
title: "gateway",
|
||||||
icon: "av_timer",
|
icon: "gateway",
|
||||||
hasGroup: false,
|
hasGroup: true,
|
||||||
exact: true,
|
|
||||||
},
|
},
|
||||||
component: Layout,
|
redirect: "/apisix",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/events",
|
path: "/apisix",
|
||||||
name: "Events",
|
name: "APISIX",
|
||||||
meta: {
|
meta: {
|
||||||
exact: false,
|
title: "apisix",
|
||||||
|
layer: "APISIX",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/apisix/tab/:activeTabIndex",
|
||||||
|
name: "APISIXActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
layer: "APISIX",
|
||||||
},
|
},
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "events" */ "@/views/Event.vue"),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
94
src/router/data/general.ts
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/**
|
||||||
|
* 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 default [
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
name: "General",
|
||||||
|
meta: {
|
||||||
|
title: "general",
|
||||||
|
icon: "chart",
|
||||||
|
hasGroup: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/general",
|
||||||
|
name: "GeneralServices",
|
||||||
|
meta: {
|
||||||
|
title: "services",
|
||||||
|
layer: "GENERAL",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/general/tab/:activeTabIndex",
|
||||||
|
name: "GeneralServicesActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
layer: "GENERAL",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/database",
|
||||||
|
name: "VirtualDatabase",
|
||||||
|
meta: {
|
||||||
|
title: "virtualDatabase",
|
||||||
|
layer: "VIRTUAL_DATABASE",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/database/tab/:activeTabIndex",
|
||||||
|
name: "VirtualDatabaseActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
layer: "VIRTUAL_DATABASE",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/cache",
|
||||||
|
name: "VirtualCache",
|
||||||
|
meta: {
|
||||||
|
title: "virtualCache",
|
||||||
|
layer: "VIRTUAL_CACHE",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/cache/tab/:activeTabIndex",
|
||||||
|
name: "VirtualCacheActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
layer: "VIRTUAL_CACHE",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/mq",
|
||||||
|
name: "VirtualMQ",
|
||||||
|
meta: {
|
||||||
|
title: "virtualMQ",
|
||||||
|
layer: "VIRTUAL_MQ",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/mq/tab/:activeTabIndex",
|
||||||
|
name: "VirtualMQActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
layer: "VIRTUAL_MQ",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
37
src/router/data/index.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.
|
||||||
|
*/
|
||||||
|
import general from "./general";
|
||||||
|
import serviceMesh from "./serviceMesh";
|
||||||
|
import database from "./database";
|
||||||
|
import infrastructure from "./infrastructure";
|
||||||
|
import selfObservability from "./selfObservability";
|
||||||
|
import functions from "./functions";
|
||||||
|
import browser from "./browser";
|
||||||
|
import k8s from "./k8s";
|
||||||
|
import gateway from "./gateway";
|
||||||
|
|
||||||
|
export default [
|
||||||
|
...general,
|
||||||
|
...serviceMesh,
|
||||||
|
...functions,
|
||||||
|
...k8s,
|
||||||
|
...infrastructure,
|
||||||
|
...browser,
|
||||||
|
...gateway,
|
||||||
|
...database,
|
||||||
|
...selfObservability,
|
||||||
|
];
|
@@ -14,31 +14,34 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
import { RouteRecordRaw } from "vue-router";
|
|
||||||
import Layout from "@/layout/Index.vue";
|
|
||||||
|
|
||||||
export const routesDatabase: Array<RouteRecordRaw> = [
|
export default [
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
name: "Database",
|
name: "Infrastructure",
|
||||||
meta: {
|
meta: {
|
||||||
title: "database",
|
title: "infrastructure",
|
||||||
icon: "storage",
|
icon: "scatter_plot",
|
||||||
hasGroup: true,
|
hasGroup: true,
|
||||||
},
|
},
|
||||||
redirect: "/database",
|
redirect: "/linux",
|
||||||
component: Layout,
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/database",
|
path: "/linux",
|
||||||
name: "Database",
|
name: "Linux",
|
||||||
meta: {
|
meta: {
|
||||||
title: "virtualDatabase",
|
title: "linux",
|
||||||
headPath: "/database",
|
layer: "OS_LINUX",
|
||||||
exact: true,
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/linux/tab/:activeTabIndex",
|
||||||
|
name: "LinuxActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
title: "linux",
|
||||||
|
notShow: true,
|
||||||
|
layer: "OS_LINUX",
|
||||||
},
|
},
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
@@ -14,10 +14,8 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
import { RouteRecordRaw } from "vue-router";
|
|
||||||
import Layout from "@/layout/Index.vue";
|
|
||||||
|
|
||||||
export const routesK8s: Array<RouteRecordRaw> = [
|
export default [
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
name: "Kubernetes",
|
name: "Kubernetes",
|
||||||
@@ -27,25 +25,42 @@ export const routesK8s: Array<RouteRecordRaw> = [
|
|||||||
hasGroup: true,
|
hasGroup: true,
|
||||||
},
|
},
|
||||||
redirect: "/kubernetes/cluster",
|
redirect: "/kubernetes/cluster",
|
||||||
component: Layout,
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/kubernetes/cluster",
|
path: "/kubernetes/cluster",
|
||||||
name: "KubernetesCluster",
|
name: "KubernetesCluster",
|
||||||
meta: {
|
meta: {
|
||||||
|
notShow: false,
|
||||||
title: "kubernetesCluster",
|
title: "kubernetesCluster",
|
||||||
|
layer: "K8S",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/kubernetes/cluster/tab/:activeTabIndex",
|
||||||
|
name: "KubernetesClusterActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
title: "kubernetesClusterActiveTabIndex",
|
||||||
|
layer: "K8S",
|
||||||
},
|
},
|
||||||
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",
|
||||||
|
layer: "K8S_SERVICE",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/kubernetes/service/tab/:activeTabIndex",
|
||||||
|
name: "KubernetesServiceActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
title: "kubernetesServiceActiveTabIndex",
|
||||||
|
layer: "K8S_SERVICE",
|
||||||
},
|
},
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
@@ -14,10 +14,8 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
import { RouteRecordRaw } from "vue-router";
|
|
||||||
import Layout from "@/layout/Index.vue";
|
|
||||||
|
|
||||||
export const routesSelf: Array<RouteRecordRaw> = [
|
export default [
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
name: "SelfObservability",
|
name: "SelfObservability",
|
||||||
@@ -27,27 +25,38 @@ export const routesSelf: Array<RouteRecordRaw> = [
|
|||||||
icon: "logo",
|
icon: "logo",
|
||||||
hasGroup: true,
|
hasGroup: true,
|
||||||
},
|
},
|
||||||
component: Layout,
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/self/skyWalkingServer",
|
path: "/self/skyWalkingServer",
|
||||||
name: "SkyWalkingServer",
|
name: "SkyWalkingServer",
|
||||||
meta: {
|
meta: {
|
||||||
title: "skyWalkingServer",
|
title: "skyWalkingServer",
|
||||||
headPath: "/mesh/services",
|
layer: "SO11Y_OAP",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/self/skyWalkingServer/tab/:activeTabIndex",
|
||||||
|
name: "SkyWalkingServerActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
layer: "SO11Y_OAP",
|
||||||
},
|
},
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/self/satellite",
|
path: "/self/satellite",
|
||||||
name: "Satellite",
|
name: "Satellite",
|
||||||
meta: {
|
meta: {
|
||||||
title: "satellite",
|
title: "satellite",
|
||||||
headPath: "/mesh/controlPanel",
|
layer: "SO11Y_SATELLITE",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/self/satellite/tab/:activeTabIndex",
|
||||||
|
name: "SatelliteActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
layer: "SO11Y_SATELLITE",
|
||||||
},
|
},
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
@@ -14,10 +14,8 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
import { RouteRecordRaw } from "vue-router";
|
|
||||||
import Layout from "@/layout/Index.vue";
|
|
||||||
|
|
||||||
export const routesMesh: Array<RouteRecordRaw> = [
|
export default [
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
name: "ServiceMesh",
|
name: "ServiceMesh",
|
||||||
@@ -27,36 +25,58 @@ export const routesMesh: Array<RouteRecordRaw> = [
|
|||||||
icon: "epic",
|
icon: "epic",
|
||||||
hasGroup: true,
|
hasGroup: true,
|
||||||
},
|
},
|
||||||
component: Layout,
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "/mesh/services",
|
path: "/mesh/services",
|
||||||
name: "MeshServices",
|
name: "MeshServices",
|
||||||
meta: {
|
meta: {
|
||||||
|
notShow: false,
|
||||||
title: "services",
|
title: "services",
|
||||||
headPath: "/mesh/services",
|
layer: "MESH",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/mesh/services/tab/:activeTabIndex",
|
||||||
|
name: "MeshServicesActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
layer: "MESH",
|
||||||
},
|
},
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/mesh/controlPanel",
|
path: "/mesh/controlPanel",
|
||||||
name: "ControlPanel",
|
name: "ControlPanel",
|
||||||
meta: {
|
meta: {
|
||||||
|
notShow: false,
|
||||||
title: "controlPanel",
|
title: "controlPanel",
|
||||||
headPath: "/mesh/controlPanel",
|
layer: "MESH_CP",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/mesh/controlPanel/tab/:activeTabIndex",
|
||||||
|
name: "ControlPanelActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
layer: "MESH_CP",
|
||||||
},
|
},
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/mesh/dataPanel",
|
path: "/mesh/dataPanel",
|
||||||
name: "DataPanel",
|
name: "DataPanel",
|
||||||
meta: {
|
meta: {
|
||||||
|
notShow: false,
|
||||||
title: "dataPanel",
|
title: "dataPanel",
|
||||||
headPath: "/mesh/dataPanel",
|
layer: "MESH_DP",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/mesh/dataPanel/tab/:activeTabIndex",
|
||||||
|
name: "DataPanelActiveTabIndex",
|
||||||
|
meta: {
|
||||||
|
notShow: true,
|
||||||
|
title: "dataPanelActiveTabIndex",
|
||||||
|
layer: "MESH_DP",
|
||||||
},
|
},
|
||||||
component: () => import("@/views/Layer.vue"),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
@@ -15,31 +15,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
|
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
|
||||||
import { routesGen } from "./general";
|
|
||||||
import { routesMesh } from "./serviceMesh";
|
|
||||||
import { routesDatabase } from "./database";
|
|
||||||
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 routesLayers from "./layer";
|
||||||
import { routesFunctions } from "./functions";
|
|
||||||
import { routesBrowser } from "./browser";
|
|
||||||
import { routesK8s } from "./k8s";
|
|
||||||
|
|
||||||
const routes: Array<RouteRecordRaw> = [
|
const routes: Array<RouteRecordRaw> = [
|
||||||
...routesGen,
|
...routesLayers,
|
||||||
...routesMesh,
|
|
||||||
...routesFunctions,
|
|
||||||
...routesK8s,
|
|
||||||
...routesInfra,
|
|
||||||
...routesBrowser,
|
|
||||||
...routesDatabase,
|
|
||||||
...routesSelf,
|
|
||||||
...routesDashboard,
|
...routesDashboard,
|
||||||
...routesAlarm,
|
...routesAlarm,
|
||||||
...routesEvent,
|
|
||||||
...routesSetting,
|
...routesSetting,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@@ -1,60 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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 { RouteRecordRaw } from "vue-router";
|
|
||||||
import Layout from "@/layout/Index.vue";
|
|
||||||
|
|
||||||
export const routesInfra: Array<RouteRecordRaw> = [
|
|
||||||
{
|
|
||||||
path: "",
|
|
||||||
name: "Infrastructure",
|
|
||||||
meta: {
|
|
||||||
title: "infrastructure",
|
|
||||||
icon: "scatter_plot",
|
|
||||||
exact: true,
|
|
||||||
hasGroup: true,
|
|
||||||
},
|
|
||||||
redirect: "/linux",
|
|
||||||
component: Layout,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: "/linux",
|
|
||||||
name: "Linux",
|
|
||||||
meta: {
|
|
||||||
title: "linux",
|
|
||||||
},
|
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue"),
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// path: "/infrastructure/vm",
|
|
||||||
// name: "VirtualMachine",
|
|
||||||
// meta: {
|
|
||||||
// title: "virtualMachine",
|
|
||||||
// },
|
|
||||||
// component: () => import("@/views/infrastructure/Infrastructure.vue"),
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// path: "/infrastructure/k8s",
|
|
||||||
// name: "Kubernetes",
|
|
||||||
// meta: {
|
|
||||||
// title: "kubernetes",
|
|
||||||
// },
|
|
||||||
// component: () => import("@/views/infrastructure/Infrastructure.vue"),
|
|
||||||
// },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
@@ -14,32 +14,22 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
import { RouteRecordRaw } from "vue-router";
|
import LayerJson from "./data";
|
||||||
import Layout from "@/layout/Index.vue";
|
import Layout from "@/layout/Index.vue";
|
||||||
|
|
||||||
export const routesGen: Array<RouteRecordRaw> = [
|
function layerDashboards() {
|
||||||
{
|
const routes = LayerJson.map((item: any) => {
|
||||||
path: "",
|
item.component = Layout;
|
||||||
name: "General",
|
if (item.children) {
|
||||||
meta: {
|
item.children = item.children.map((d: any) => {
|
||||||
title: "general",
|
d.component = () =>
|
||||||
icon: "chart",
|
import(/* webpackChunkName: "layer" */ "@/views/Layer.vue");
|
||||||
hasGroup: false,
|
return d;
|
||||||
exact: true,
|
});
|
||||||
},
|
}
|
||||||
component: Layout,
|
return item;
|
||||||
children: [
|
});
|
||||||
{
|
return routes;
|
||||||
path: "/general",
|
}
|
||||||
name: "GeneralServices",
|
|
||||||
meta: {
|
export default layerDashboards();
|
||||||
title: "services",
|
|
||||||
headPath: "/general/service",
|
|
||||||
exact: true,
|
|
||||||
},
|
|
||||||
component: () =>
|
|
||||||
import(/* webpackChunkName: "layers" */ "@/views/Layer.vue"),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
@@ -25,7 +25,6 @@ export const routesSetting: Array<RouteRecordRaw> = [
|
|||||||
title: "settings",
|
title: "settings",
|
||||||
icon: "settings",
|
icon: "settings",
|
||||||
hasGroup: false,
|
hasGroup: false,
|
||||||
exact: false,
|
|
||||||
},
|
},
|
||||||
component: Layout,
|
component: Layout,
|
||||||
children: [
|
children: [
|
||||||
@@ -36,7 +35,6 @@ export const routesSetting: Array<RouteRecordRaw> = [
|
|||||||
title: "settings",
|
title: "settings",
|
||||||
icon: "settings",
|
icon: "settings",
|
||||||
hasGroup: false,
|
hasGroup: false,
|
||||||
exact: false,
|
|
||||||
},
|
},
|
||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "settings" */ "@/views/Settings.vue"),
|
import(/* webpackChunkName: "settings" */ "@/views/Settings.vue"),
|
||||||
|
@@ -29,3 +29,11 @@ export const TextConfig = {
|
|||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
textAlign: "left",
|
textAlign: "left",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const TimeRangeConfig = {
|
||||||
|
fontColor: "black",
|
||||||
|
backgroundColor: "white",
|
||||||
|
fontSize: 14,
|
||||||
|
textAlign: "center",
|
||||||
|
text: "text",
|
||||||
|
};
|
||||||
|
@@ -34,6 +34,7 @@ interface AppState {
|
|||||||
pageTitle: string;
|
pageTitle: string;
|
||||||
version: string;
|
version: string;
|
||||||
isMobile: boolean;
|
isMobile: boolean;
|
||||||
|
reloadTimer: Nullable<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const appStore = defineStore({
|
export const appStore = defineStore({
|
||||||
@@ -53,6 +54,7 @@ export const appStore = defineStore({
|
|||||||
pageTitle: "",
|
pageTitle: "",
|
||||||
version: "",
|
version: "",
|
||||||
isMobile: false,
|
isMobile: false,
|
||||||
|
reloadTimer: null,
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
duration(): Duration {
|
duration(): Duration {
|
||||||
@@ -69,7 +71,7 @@ export const appStore = defineStore({
|
|||||||
step: this.duration.step,
|
step: this.duration.step,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
intervalTime(): string[] {
|
intervalUnix(): number[] {
|
||||||
let interval = 946080000000;
|
let interval = 946080000000;
|
||||||
switch (this.duration.step) {
|
switch (this.duration.step) {
|
||||||
case "MINUTE":
|
case "MINUTE":
|
||||||
@@ -95,12 +97,17 @@ export const appStore = defineStore({
|
|||||||
this.utcMin * 60000;
|
this.utcMin * 60000;
|
||||||
const startUnix: number = this.duration.start.getTime();
|
const startUnix: number = this.duration.start.getTime();
|
||||||
const endUnix: number = this.duration.end.getTime();
|
const endUnix: number = this.duration.end.getTime();
|
||||||
const timeIntervals: string[] = [];
|
const timeIntervals: number[] = [];
|
||||||
for (let i = 0; i <= endUnix - startUnix; i += interval) {
|
for (let i = 0; i <= endUnix - startUnix; i += interval) {
|
||||||
const temp: string = dateFormatTime(
|
timeIntervals.push(startUnix + i - utcSpace);
|
||||||
new Date(startUnix + i - utcSpace),
|
}
|
||||||
this.duration.step
|
return timeIntervals;
|
||||||
);
|
},
|
||||||
|
intervalTime(): string[] {
|
||||||
|
const arr = this.intervalUnix;
|
||||||
|
const timeIntervals: string[] = [];
|
||||||
|
for (const item of arr) {
|
||||||
|
const temp: string = dateFormatTime(new Date(item), this.duration.step);
|
||||||
timeIntervals.push(temp);
|
timeIntervals.push(temp);
|
||||||
}
|
}
|
||||||
return timeIntervals;
|
return timeIntervals;
|
||||||
@@ -117,12 +124,18 @@ export const appStore = defineStore({
|
|||||||
}
|
}
|
||||||
this.runEventStack();
|
this.runEventStack();
|
||||||
},
|
},
|
||||||
|
updateDurationRow(data: Duration) {
|
||||||
|
this.durationRow = data;
|
||||||
|
},
|
||||||
setUTC(utcHour: number, utcMin: number): void {
|
setUTC(utcHour: number, utcMin: number): void {
|
||||||
this.runEventStack();
|
this.runEventStack();
|
||||||
this.utcMin = utcMin;
|
this.utcMin = utcMin;
|
||||||
this.utcHour = utcHour;
|
this.utcHour = utcHour;
|
||||||
this.utc = `${utcHour}:${utcMin}`;
|
this.utc = `${utcHour}:${utcMin}`;
|
||||||
},
|
},
|
||||||
|
updateUTC(data: string) {
|
||||||
|
this.utc = data;
|
||||||
|
},
|
||||||
setIsMobile(mode: boolean) {
|
setIsMobile(mode: boolean) {
|
||||||
this.isMobile = mode;
|
this.isMobile = mode;
|
||||||
},
|
},
|
||||||
@@ -153,10 +166,9 @@ export const appStore = defineStore({
|
|||||||
.params({});
|
.params({});
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
this.utc = -(new Date().getTimezoneOffset() / 60) + ":0";
|
this.utc = -(new Date().getTimezoneOffset() / 60) + ":0";
|
||||||
return res.data;
|
} else {
|
||||||
|
this.utc = res.data.data.getTimeInfo.timezone / 100 + ":0";
|
||||||
}
|
}
|
||||||
this.utc = res.data.data.getTimeInfo.timezone / 100 + ":0";
|
|
||||||
|
|
||||||
const utcArr = this.utc.split(":");
|
const utcArr = this.utc.split(":");
|
||||||
this.utcHour = isNaN(Number(utcArr[0])) ? 0 : Number(utcArr[0]);
|
this.utcHour = isNaN(Number(utcArr[0])) ? 0 : Number(utcArr[0]);
|
||||||
this.utcMin = isNaN(Number(utcArr[1])) ? 0 : Number(utcArr[1]);
|
this.utcMin = isNaN(Number(utcArr[1])) ? 0 : Number(utcArr[1]);
|
||||||
@@ -173,6 +185,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 {
|
||||||
|
@@ -21,7 +21,7 @@ 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 { useSelectorStore } from "@/store/modules/selectors";
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
import { NewControl, TextConfig } from "../data";
|
import { NewControl, TextConfig, TimeRangeConfig } from "../data";
|
||||||
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";
|
||||||
@@ -39,6 +39,7 @@ interface DashboardState {
|
|||||||
dashboards: DashboardItem[];
|
dashboards: DashboardItem[];
|
||||||
currentDashboard: Nullable<DashboardItem>;
|
currentDashboard: Nullable<DashboardItem>;
|
||||||
editMode: boolean;
|
editMode: boolean;
|
||||||
|
currentTabIndex: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const dashboardStore = defineStore({
|
export const dashboardStore = defineStore({
|
||||||
@@ -56,6 +57,7 @@ export const dashboardStore = defineStore({
|
|||||||
dashboards: [],
|
dashboards: [],
|
||||||
currentDashboard: null,
|
currentDashboard: null,
|
||||||
editMode: false,
|
editMode: false,
|
||||||
|
currentTabIndex: 0,
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
setLayout(data: LayoutConfig[]) {
|
setLayout(data: LayoutConfig[]) {
|
||||||
@@ -80,6 +82,7 @@ export const dashboardStore = defineStore({
|
|||||||
const newItem: LayoutConfig = {
|
const newItem: LayoutConfig = {
|
||||||
...NewControl,
|
...NewControl,
|
||||||
i: index,
|
i: index,
|
||||||
|
id: index,
|
||||||
type,
|
type,
|
||||||
metricTypes: [""],
|
metricTypes: [""],
|
||||||
metrics: [""],
|
metrics: [""],
|
||||||
@@ -111,11 +114,14 @@ export const dashboardStore = defineStore({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
type === "Trace" ||
|
[
|
||||||
type === "Profile" ||
|
"Trace",
|
||||||
type === "Log" ||
|
"Profile",
|
||||||
type === "Ebpf" ||
|
"Log",
|
||||||
type === "DemandLog"
|
"DemandLog",
|
||||||
|
"Ebpf",
|
||||||
|
"NetworkProfiling",
|
||||||
|
].includes(type)
|
||||||
) {
|
) {
|
||||||
newItem.h = 36;
|
newItem.h = 36;
|
||||||
}
|
}
|
||||||
@@ -123,6 +129,11 @@ export const dashboardStore = defineStore({
|
|||||||
newItem.h = 6;
|
newItem.h = 6;
|
||||||
newItem.graph = TextConfig;
|
newItem.graph = TextConfig;
|
||||||
}
|
}
|
||||||
|
if (type === "TimeRange") {
|
||||||
|
newItem.w = 8;
|
||||||
|
newItem.h = 6;
|
||||||
|
newItem.graph = TimeRangeConfig;
|
||||||
|
}
|
||||||
this.activedGridItem = newItem.i;
|
this.activedGridItem = newItem.i;
|
||||||
this.selectedGrid = newItem;
|
this.selectedGrid = newItem;
|
||||||
this.layout = this.layout.map((d: LayoutConfig) => {
|
this.layout = this.layout.map((d: LayoutConfig) => {
|
||||||
@@ -158,9 +169,11 @@ export const dashboardStore = defineStore({
|
|||||||
if (!children.length) {
|
if (!children.length) {
|
||||||
index = "0";
|
index = "0";
|
||||||
}
|
}
|
||||||
|
const id = `${activedGridItem}-${tabIndex}-${index}`;
|
||||||
const newItem: LayoutConfig = {
|
const newItem: LayoutConfig = {
|
||||||
...NewControl,
|
...NewControl,
|
||||||
i: index,
|
i: index,
|
||||||
|
id,
|
||||||
type,
|
type,
|
||||||
metricTypes: [""],
|
metricTypes: [""],
|
||||||
metrics: [""],
|
metrics: [""],
|
||||||
@@ -172,11 +185,14 @@ export const dashboardStore = defineStore({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
type === "Trace" ||
|
[
|
||||||
type === "Profile" ||
|
"Trace",
|
||||||
type === "Log" ||
|
"Profile",
|
||||||
type === "DemandLog" ||
|
"Log",
|
||||||
type === "Ebpf"
|
"DemandLog",
|
||||||
|
"Ebpf",
|
||||||
|
"NetworkProfiling",
|
||||||
|
].includes(type)
|
||||||
) {
|
) {
|
||||||
newItem.h = 32;
|
newItem.h = 32;
|
||||||
}
|
}
|
||||||
@@ -184,6 +200,11 @@ export const dashboardStore = defineStore({
|
|||||||
newItem.h = 6;
|
newItem.h = 6;
|
||||||
newItem.graph = TextConfig;
|
newItem.graph = TextConfig;
|
||||||
}
|
}
|
||||||
|
if (type === "TimeRange") {
|
||||||
|
newItem.w = 8;
|
||||||
|
newItem.h = 6;
|
||||||
|
newItem.graph = TextConfig;
|
||||||
|
}
|
||||||
if (this.layout[idx].children) {
|
if (this.layout[idx].children) {
|
||||||
const items = children.map((d: LayoutConfig) => {
|
const items = children.map((d: LayoutConfig) => {
|
||||||
d.y = d.y + newItem.h;
|
d.y = d.y + newItem.h;
|
||||||
@@ -198,6 +219,7 @@ export const dashboardStore = defineStore({
|
|||||||
this.activedGridItem = index;
|
this.activedGridItem = index;
|
||||||
},
|
},
|
||||||
setActiveTabIndex(index: number, target?: number) {
|
setActiveTabIndex(index: number, target?: number) {
|
||||||
|
this.currentTabIndex = index;
|
||||||
const m = target || this.activedGridItem;
|
const m = target || this.activedGridItem;
|
||||||
const idx = this.layout.findIndex((d: LayoutConfig) => d.i === m);
|
const idx = this.layout.findIndex((d: LayoutConfig) => d.i === m);
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
@@ -287,6 +309,28 @@ export const dashboardStore = defineStore({
|
|||||||
};
|
};
|
||||||
this.selectedGrid = this.layout[index];
|
this.selectedGrid = this.layout[index];
|
||||||
},
|
},
|
||||||
|
setWidget(param: LayoutConfig) {
|
||||||
|
for (let i = 0; i < this.layout.length; i++) {
|
||||||
|
if (this.layout[i].type === "Tab") {
|
||||||
|
if (this.layout[i].children && this.layout[i].children.length) {
|
||||||
|
for (const child of this.layout[i].children) {
|
||||||
|
if (child.children && child.children.length) {
|
||||||
|
for (let c = 0; c < child.children.length; c++) {
|
||||||
|
if (child.children[c].id === param.id) {
|
||||||
|
child.children.splice(c, 1, param);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.layout[i].id === param.id) {
|
||||||
|
this.layout.splice(i, 1, param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
async fetchMetricType(item: string) {
|
async fetchMetricType(item: string) {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql
|
||||||
.query("queryTypeOfMetrics")
|
.query("queryTypeOfMetrics")
|
||||||
|
@@ -25,8 +25,7 @@ import {
|
|||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
import graphql from "@/graphql";
|
import graphql from "@/graphql";
|
||||||
import { AxiosResponse } from "axios";
|
import { AxiosResponse } from "axios";
|
||||||
|
interface EbpfState {
|
||||||
interface EbpfStore {
|
|
||||||
taskList: EBPFTaskList[];
|
taskList: EBPFTaskList[];
|
||||||
eBPFSchedules: EBPFProfilingSchedule[];
|
eBPFSchedules: EBPFProfilingSchedule[];
|
||||||
currentSchedule: EBPFProfilingSchedule | Record<string, never>;
|
currentSchedule: EBPFProfilingSchedule | Record<string, never>;
|
||||||
@@ -40,7 +39,7 @@ interface EbpfStore {
|
|||||||
|
|
||||||
export const ebpfStore = defineStore({
|
export const ebpfStore = defineStore({
|
||||||
id: "eBPF",
|
id: "eBPF",
|
||||||
state: (): EbpfStore => ({
|
state: (): EbpfState => ({
|
||||||
taskList: [],
|
taskList: [],
|
||||||
eBPFSchedules: [],
|
eBPFSchedules: [],
|
||||||
currentSchedule: {},
|
currentSchedule: {},
|
||||||
@@ -53,7 +52,7 @@ export const ebpfStore = defineStore({
|
|||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
setSelectedTask(task: EBPFTaskList) {
|
setSelectedTask(task: EBPFTaskList) {
|
||||||
this.selectedTask = task;
|
this.selectedTask = task || {};
|
||||||
},
|
},
|
||||||
setCurrentSchedule(s: EBPFProfilingSchedule) {
|
setCurrentSchedule(s: EBPFProfilingSchedule) {
|
||||||
this.currentSchedule = s;
|
this.currentSchedule = s;
|
||||||
@@ -84,22 +83,31 @@ export const ebpfStore = defineStore({
|
|||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.getTaskList(param.serviceId);
|
this.getTaskList({
|
||||||
|
serviceId: param.serviceId,
|
||||||
|
targets: ["ON_CPU", "OFF_CPU"],
|
||||||
|
});
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getTaskList(serviceId: string) {
|
async getTaskList(params: {
|
||||||
if (!serviceId) {
|
serviceId: string;
|
||||||
|
serviceInstanceId: string;
|
||||||
|
targets: string[];
|
||||||
|
}) {
|
||||||
|
if (!params.serviceId) {
|
||||||
return new Promise((resolve) => resolve({}));
|
return new Promise((resolve) => resolve({}));
|
||||||
}
|
}
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql
|
||||||
.query("getEBPFTasks")
|
.query("getEBPFTasks")
|
||||||
.params({ serviceId });
|
.params(params);
|
||||||
|
|
||||||
this.tip = "";
|
this.tip = "";
|
||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.taskList = res.data.data.queryEBPFTasks || [];
|
this.taskList = res.data.data.queryEBPFTasks || [];
|
||||||
|
this.selectedTask = this.taskList[0] || {};
|
||||||
|
this.setSelectedTask(this.selectedTask);
|
||||||
if (!this.taskList.length) {
|
if (!this.taskList.length) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
@@ -19,16 +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[];
|
||||||
services: Service[];
|
|
||||||
instances: Instance[];
|
instances: Instance[];
|
||||||
endpoints: Endpoint[];
|
endpoints: Endpoint[];
|
||||||
condition: QueryEventCondition | any;
|
condition: Nullable<QueryEventCondition>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const eventStore = defineStore({
|
export const eventStore = defineStore({
|
||||||
@@ -36,32 +36,18 @@ export const eventStore = defineStore({
|
|||||||
state: (): eventState => ({
|
state: (): eventState => ({
|
||||||
loading: false,
|
loading: false,
|
||||||
events: [],
|
events: [],
|
||||||
services: [{ value: "", label: "All" }],
|
|
||||||
instances: [{ value: "", label: "All" }],
|
instances: [{ value: "", label: "All" }],
|
||||||
endpoints: [{ value: "", label: "All" }],
|
endpoints: [{ value: "", label: "All" }],
|
||||||
condition: {
|
condition: null,
|
||||||
paging: { pageNum: 1, pageSize: 15 },
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
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,
|
||||||
@@ -75,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,
|
||||||
@@ -112,6 +104,9 @@ export const eventStore = defineStore({
|
|||||||
scope = "Endpoint";
|
scope = "Endpoint";
|
||||||
}
|
}
|
||||||
item.scope = scope;
|
item.scope = scope;
|
||||||
|
if (!item.endTime || item.endTime === item.startTime) {
|
||||||
|
item.endTime = Number(item.startTime) + 60000;
|
||||||
|
}
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@@ -53,6 +53,13 @@ export const logStore = defineStore({
|
|||||||
setLogCondition(data: any) {
|
setLogCondition(data: any) {
|
||||||
this.conditions = { ...this.conditions, ...data };
|
this.conditions = { ...this.conditions, ...data };
|
||||||
},
|
},
|
||||||
|
resetState() {
|
||||||
|
this.logs = [];
|
||||||
|
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,
|
||||||
|
203
src/store/modules/network-profiling.ts
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
/**
|
||||||
|
* 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 { EBPFTaskList, ProcessNode } from "@/types/ebpf";
|
||||||
|
import { store } from "@/store";
|
||||||
|
import graphql from "@/graphql";
|
||||||
|
import { AxiosResponse } from "axios";
|
||||||
|
import { Call } from "@/types/topology";
|
||||||
|
import { LayoutConfig } from "@/types/dashboard";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
|
||||||
|
interface NetworkProfilingState {
|
||||||
|
networkTasks: EBPFTaskList[];
|
||||||
|
networkTip: string;
|
||||||
|
selectedNetworkTask: Recordable<EBPFTaskList>;
|
||||||
|
nodes: ProcessNode[];
|
||||||
|
calls: Call[];
|
||||||
|
node: Nullable<ProcessNode>;
|
||||||
|
call: Nullable<Call>;
|
||||||
|
metricsLayout: LayoutConfig[];
|
||||||
|
selectedMetric: Nullable<LayoutConfig>;
|
||||||
|
activeMetricIndex: string;
|
||||||
|
aliveNetwork: boolean;
|
||||||
|
loadNodes: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const networkProfilingStore = defineStore({
|
||||||
|
id: "networkProfiling",
|
||||||
|
state: (): NetworkProfilingState => ({
|
||||||
|
networkTasks: [],
|
||||||
|
networkTip: "",
|
||||||
|
selectedNetworkTask: {},
|
||||||
|
nodes: [],
|
||||||
|
calls: [],
|
||||||
|
node: null,
|
||||||
|
call: null,
|
||||||
|
metricsLayout: [],
|
||||||
|
selectedMetric: null,
|
||||||
|
activeMetricIndex: "",
|
||||||
|
aliveNetwork: false,
|
||||||
|
loadNodes: false,
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
setSelectedNetworkTask(task: EBPFTaskList) {
|
||||||
|
this.selectedNetworkTask = task || {};
|
||||||
|
},
|
||||||
|
setNode(node: Node) {
|
||||||
|
this.node = node;
|
||||||
|
},
|
||||||
|
setLink(link: Call) {
|
||||||
|
this.call = link;
|
||||||
|
},
|
||||||
|
setMetricsLayout(layout: LayoutConfig[]) {
|
||||||
|
this.metricsLayout = layout;
|
||||||
|
},
|
||||||
|
setSelectedMetric(item: LayoutConfig) {
|
||||||
|
this.selectedMetric = item;
|
||||||
|
},
|
||||||
|
setActiveItem(index: string) {
|
||||||
|
this.activeMetricIndex = index;
|
||||||
|
},
|
||||||
|
setTopology(data: { nodes: ProcessNode[]; calls: Call[] }) {
|
||||||
|
const obj = {} as any;
|
||||||
|
let calls = (data.calls || []).reduce((prev: Call[], next: Call) => {
|
||||||
|
if (!obj[next.id]) {
|
||||||
|
obj[next.id] = true;
|
||||||
|
next.value = next.value || 1;
|
||||||
|
for (const node of data.nodes) {
|
||||||
|
if (next.source === node.id) {
|
||||||
|
next.sourceObj = node;
|
||||||
|
}
|
||||||
|
if (next.target === node.id) {
|
||||||
|
next.targetObj = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next.value = next.value || 1;
|
||||||
|
prev.push(next);
|
||||||
|
}
|
||||||
|
return prev;
|
||||||
|
}, []);
|
||||||
|
const param = {} as any;
|
||||||
|
calls = data.calls.reduce((prev: (Call | any)[], next: Call | any) => {
|
||||||
|
if (param[next.targetId + next.sourceId]) {
|
||||||
|
next.lowerArc = true;
|
||||||
|
}
|
||||||
|
param[next.sourceId + next.targetId] = true;
|
||||||
|
next.sourceId = next.source;
|
||||||
|
next.targetId = next.target;
|
||||||
|
next.source = next.sourceObj;
|
||||||
|
next.target = next.targetObj;
|
||||||
|
delete next.sourceObj;
|
||||||
|
delete next.targetObj;
|
||||||
|
prev.push(next);
|
||||||
|
return prev;
|
||||||
|
}, []);
|
||||||
|
this.calls = calls;
|
||||||
|
this.nodes = data.nodes;
|
||||||
|
},
|
||||||
|
async createNetworkTask(
|
||||||
|
instanceId: string,
|
||||||
|
params: {
|
||||||
|
uriRegex: string;
|
||||||
|
when4xx: string;
|
||||||
|
when5xx: string;
|
||||||
|
minDuration: number;
|
||||||
|
}[]
|
||||||
|
) {
|
||||||
|
const res: AxiosResponse = await graphql
|
||||||
|
.query("newNetworkProfiling")
|
||||||
|
.params({
|
||||||
|
request: {
|
||||||
|
instanceId,
|
||||||
|
samplings: params,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.data.errors) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
|
async getTaskList(params: {
|
||||||
|
serviceId: string;
|
||||||
|
serviceInstanceId: string;
|
||||||
|
targets: string[];
|
||||||
|
}) {
|
||||||
|
if (!params.serviceId) {
|
||||||
|
return new Promise((resolve) => resolve({}));
|
||||||
|
}
|
||||||
|
const res: AxiosResponse = await graphql
|
||||||
|
.query("getEBPFTasks")
|
||||||
|
.params(params);
|
||||||
|
|
||||||
|
this.networkTip = "";
|
||||||
|
if (res.data.errors) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
this.networkTasks = res.data.data.queryEBPFTasks || [];
|
||||||
|
this.selectedNetworkTask = this.networkTasks[0] || {};
|
||||||
|
this.setSelectedNetworkTask(this.selectedNetworkTask);
|
||||||
|
if (!this.networkTasks.length) {
|
||||||
|
this.nodes = [];
|
||||||
|
this.calls = [];
|
||||||
|
}
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
|
async keepNetworkProfiling(taskId: string) {
|
||||||
|
if (!taskId) {
|
||||||
|
return new Promise((resolve) => resolve({}));
|
||||||
|
}
|
||||||
|
const res: AxiosResponse = await graphql
|
||||||
|
.query("aliveNetworkProfiling")
|
||||||
|
.params({ taskId });
|
||||||
|
|
||||||
|
this.aliveMessage = "";
|
||||||
|
if (res.data.errors) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
this.aliveNetwork = res.data.data.keepEBPFNetworkProfiling.status;
|
||||||
|
if (!this.aliveNetwork) {
|
||||||
|
ElMessage.warning(res.data.data.keepEBPFNetworkProfiling.errorReason);
|
||||||
|
}
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
|
async getProcessTopology(params: {
|
||||||
|
duration: any;
|
||||||
|
serviceInstanceId: string;
|
||||||
|
}) {
|
||||||
|
this.loadNodes = true;
|
||||||
|
const res: AxiosResponse = await graphql
|
||||||
|
.query("getProcessTopology")
|
||||||
|
.params(params);
|
||||||
|
this.loadNodes = false;
|
||||||
|
if (res.data.errors) {
|
||||||
|
this.nodes = [];
|
||||||
|
this.calls = [];
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
const { topology } = res.data.data;
|
||||||
|
|
||||||
|
this.setTopology(topology);
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export function useNetworkProfilingStore(): any {
|
||||||
|
return networkProfilingStore(store);
|
||||||
|
}
|
@@ -83,7 +83,7 @@ export const profileStore = defineStore({
|
|||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.endpoints = [{ value: "", label: "All" }, ...res.data.data.pods];
|
this.endpoints = res.data.data.pods || [];
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getTaskEndpoints(serviceId: string, keyword?: string) {
|
async getTaskEndpoints(serviceId: string, keyword?: string) {
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { Service, Instance, Endpoint } from "@/types/selector";
|
import { Service, Instance, Endpoint, Process } 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";
|
||||||
@@ -24,11 +24,15 @@ interface SelectorState {
|
|||||||
services: Service[];
|
services: Service[];
|
||||||
destServices: Service[];
|
destServices: Service[];
|
||||||
pods: Array<Instance | Endpoint>;
|
pods: Array<Instance | Endpoint>;
|
||||||
|
processes: Process[];
|
||||||
|
destProcesses: Process[];
|
||||||
currentService: Nullable<Service>;
|
currentService: Nullable<Service>;
|
||||||
currentPod: Nullable<Instance | Endpoint>;
|
currentPod: Nullable<Instance | Endpoint>;
|
||||||
|
currentProcess: Nullable<Process>;
|
||||||
currentDestService: Nullable<Service>;
|
currentDestService: Nullable<Service>;
|
||||||
currentDestPod: Nullable<Instance | Endpoint>;
|
currentDestPod: Nullable<Instance | Endpoint>;
|
||||||
destPods: Array<Instance | Endpoint>;
|
destPods: Array<Instance | Endpoint>;
|
||||||
|
currentDestProcess: Nullable<Process>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const selectorStore = defineStore({
|
export const selectorStore = defineStore({
|
||||||
@@ -38,10 +42,14 @@ export const selectorStore = defineStore({
|
|||||||
destServices: [],
|
destServices: [],
|
||||||
pods: [],
|
pods: [],
|
||||||
destPods: [],
|
destPods: [],
|
||||||
|
processes: [],
|
||||||
|
destProcesses: [],
|
||||||
currentService: null,
|
currentService: null,
|
||||||
currentPod: null,
|
currentPod: null,
|
||||||
|
currentProcess: null,
|
||||||
currentDestService: null,
|
currentDestService: null,
|
||||||
currentDestPod: null,
|
currentDestPod: null,
|
||||||
|
currentDestProcess: null,
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
setCurrentService(service: Nullable<Service>) {
|
setCurrentService(service: Nullable<Service>) {
|
||||||
@@ -56,6 +64,18 @@ export const selectorStore = defineStore({
|
|||||||
setCurrentDestPod(pod: Nullable<Instance | Endpoint>) {
|
setCurrentDestPod(pod: Nullable<Instance | Endpoint>) {
|
||||||
this.currentDestPod = pod;
|
this.currentDestPod = pod;
|
||||||
},
|
},
|
||||||
|
setCurrentProcess(process: Nullable<Process>) {
|
||||||
|
this.currentProcess = process;
|
||||||
|
},
|
||||||
|
setCurrentDestProcess(process: Nullable<Process>) {
|
||||||
|
this.currentDestProcess = process;
|
||||||
|
},
|
||||||
|
setDestPods(pods: Array<Instance | Endpoint>) {
|
||||||
|
this.destPods = pods;
|
||||||
|
},
|
||||||
|
setDestProcesses(processes: Array<Process>) {
|
||||||
|
this.destProcesses = processes;
|
||||||
|
},
|
||||||
async fetchLayers(): Promise<AxiosResponse> {
|
async fetchLayers(): Promise<AxiosResponse> {
|
||||||
const res: AxiosResponse = await graphql.query("queryLayers").params({});
|
const res: AxiosResponse = await graphql.query("queryLayers").params({});
|
||||||
|
|
||||||
@@ -93,6 +113,27 @@ export const selectorStore = defineStore({
|
|||||||
}
|
}
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
|
async getProcesses(param?: {
|
||||||
|
instanceId: string;
|
||||||
|
isRelation: boolean;
|
||||||
|
}): Promise<Nullable<AxiosResponse>> {
|
||||||
|
const instanceId = param ? param.instanceId : this.currentPod?.id;
|
||||||
|
if (!instanceId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const res: AxiosResponse = await graphql.query("queryProcesses").params({
|
||||||
|
instanceId,
|
||||||
|
duration: useAppStoreWithOut().durationTime,
|
||||||
|
});
|
||||||
|
if (!res.data.errors) {
|
||||||
|
if (param && param.isRelation) {
|
||||||
|
this.destProcesses = res.data.data.processes || [];
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
this.processes = res.data.data.processes || [];
|
||||||
|
}
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
async getEndpoints(params: {
|
async getEndpoints(params: {
|
||||||
keyword?: string;
|
keyword?: string;
|
||||||
serviceId?: string;
|
serviceId?: string;
|
||||||
@@ -176,6 +217,25 @@ export const selectorStore = defineStore({
|
|||||||
this.pods = [res.data.data.endpoint];
|
this.pods = [res.data.data.endpoint];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
|
async getProcess(instanceId: string, isRelation?: boolean) {
|
||||||
|
if (!instanceId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const res: AxiosResponse = await graphql.query("queryProcess").params({
|
||||||
|
instanceId,
|
||||||
|
});
|
||||||
|
if (!res.data.errors) {
|
||||||
|
if (isRelation) {
|
||||||
|
this.currentDestProcess = res.data.data.process || null;
|
||||||
|
this.destProcesses = [res.data.data.process];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.currentProcess = res.data.data.process || null;
|
||||||
|
this.processes = [res.data.data.process];
|
||||||
|
}
|
||||||
|
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@@ -23,7 +23,7 @@ import { useSelectorStore } from "@/store/modules/selectors";
|
|||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { AxiosResponse } from "axios";
|
import { AxiosResponse } from "axios";
|
||||||
import query from "@/graphql/fetch";
|
import query from "@/graphql/fetch";
|
||||||
import { useQueryTopologyMetrics } from "@/hooks/useProcessor";
|
import { useQueryTopologyMetrics } from "@/hooks/useMetricsProcessor";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
|
|
||||||
interface MetricVal {
|
interface MetricVal {
|
||||||
|
@@ -22,6 +22,7 @@ import graphql from "@/graphql";
|
|||||||
import { AxiosResponse } from "axios";
|
import { AxiosResponse } from "axios";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { useSelectorStore } from "@/store/modules/selectors";
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
|
import { QueryOrders } from "@/views/dashboard/data";
|
||||||
|
|
||||||
interface TraceState {
|
interface TraceState {
|
||||||
services: Service[];
|
services: Service[];
|
||||||
@@ -47,7 +48,7 @@ export const traceStore = defineStore({
|
|||||||
conditions: {
|
conditions: {
|
||||||
queryDuration: useAppStoreWithOut().durationTime,
|
queryDuration: useAppStoreWithOut().durationTime,
|
||||||
traceState: "ALL",
|
traceState: "ALL",
|
||||||
queryOrder: "BY_START_TIME",
|
queryOrder: QueryOrders[0].value,
|
||||||
paging: { pageNum: 1, pageSize: 20 },
|
paging: { pageNum: 1, pageSize: 20 },
|
||||||
},
|
},
|
||||||
traceSpanLogs: [],
|
traceSpanLogs: [],
|
||||||
@@ -63,6 +64,17 @@ export const traceStore = defineStore({
|
|||||||
setTraceSpans(spans: Span) {
|
setTraceSpans(spans: Span) {
|
||||||
this.traceSpans = spans;
|
this.traceSpans = spans;
|
||||||
},
|
},
|
||||||
|
resetState() {
|
||||||
|
this.traceSpans = [];
|
||||||
|
this.traceList = [];
|
||||||
|
this.currentTrace = {};
|
||||||
|
this.conditions = {
|
||||||
|
queryDuration: useAppStoreWithOut().durationTime,
|
||||||
|
paging: { pageNum: 1, pageSize: 20 },
|
||||||
|
traceState: "ALL",
|
||||||
|
queryOrder: QueryOrders[0].value,
|
||||||
|
};
|
||||||
|
},
|
||||||
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,
|
||||||
@@ -73,6 +85,36 @@ export const traceStore = defineStore({
|
|||||||
this.services = res.data.data.services;
|
this.services = res.data.data.services;
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
|
async getService(serviceId: string) {
|
||||||
|
if (!serviceId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const res: AxiosResponse = await graphql.query("queryService").params({
|
||||||
|
serviceId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
|
async getInstance(instanceId: string) {
|
||||||
|
if (!instanceId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const res: AxiosResponse = await graphql.query("queryInstance").params({
|
||||||
|
instanceId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
|
async getEndpoint(endpointId: string) {
|
||||||
|
if (!endpointId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const res: AxiosResponse = await graphql.query("queryEndpoint").params({
|
||||||
|
endpointId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.data;
|
||||||
|
},
|
||||||
async getInstances(id: string) {
|
async getInstances(id: string) {
|
||||||
const serviceId = this.selectorStore.currentService
|
const serviceId = this.selectorStore.currentService
|
||||||
? this.selectorStore.currentService.id
|
? this.selectorStore.currentService.id
|
||||||
@@ -133,7 +175,8 @@ export const traceStore = defineStore({
|
|||||||
if (res.data.errors) {
|
if (res.data.errors) {
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
this.setTraceSpans(res.data.data.trace.spans || []);
|
const data = res.data.data.trace.spans;
|
||||||
|
this.setTraceSpans(data || []);
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getSpanLogs(params: any) {
|
async getSpanLogs(params: any) {
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
import "element-plus/es/components/message/style/css";
|
import "element-plus/es/components/message/style/css";
|
||||||
import "element-plus/es/components/message-box/style/css";
|
import "element-plus/es/components/message-box/style/css";
|
||||||
import "element-plus/es/components/notification/style/css";
|
import "element-plus/es/components/notification/style/css";
|
||||||
|
import "element-plus/es/components/drawer/style/css";
|
||||||
import "./grid.scss";
|
import "./grid.scss";
|
||||||
import "./lib.scss";
|
import "./lib.scss";
|
||||||
import "./reset.scss";
|
import "./reset.scss";
|
||||||
|
@@ -173,7 +173,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.scroll_bar_style::-webkit-scrollbar {
|
.scroll_bar_style::-webkit-scrollbar {
|
||||||
width: 9px;
|
width: 4px;
|
||||||
height: 4px;
|
height: 4px;
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
}
|
}
|
||||||
|
@@ -139,8 +139,10 @@ pre {
|
|||||||
padding-left: 56px !important;
|
padding-left: 56px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-icon.menu-icons {
|
.el-sub-menu__title {
|
||||||
margin-top: -3px !important;
|
.el-icon.menu-icons {
|
||||||
|
margin-top: -5px !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-switch__label--left {
|
.el-switch__label--left {
|
||||||
@@ -151,6 +153,55 @@ pre {
|
|||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-switch__label * {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-drawer__header {
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-left: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-drawer__body {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.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: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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 3px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vis-item.vis-selected.Error,
|
||||||
|
.vis-item.vis-selected.Normal {
|
||||||
|
color: #1a1a1a !important;
|
||||||
|
}
|
||||||
|
15
src/types/app.d.ts
vendored
@@ -32,3 +32,18 @@ export type Paging = {
|
|||||||
pageNum: number;
|
pageNum: number;
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type EventParams = {
|
||||||
|
componentType: string;
|
||||||
|
seriesType: string;
|
||||||
|
seriesIndex: number;
|
||||||
|
seriesName: string;
|
||||||
|
name: string;
|
||||||
|
dataIndex: number;
|
||||||
|
data: unknown;
|
||||||
|
dataType: string;
|
||||||
|
value: number | Array;
|
||||||
|
color: string;
|
||||||
|
event: any;
|
||||||
|
dataIndex: number;
|
||||||
|
};
|
||||||
|
2
src/types/components.d.ts
vendored
@@ -9,6 +9,7 @@ declare module '@vue/runtime-core' {
|
|||||||
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
||||||
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
||||||
ElDialog: typeof import('element-plus/es')['ElDialog']
|
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||||
|
ElDrawer: typeof import('element-plus/es')['ElDrawer']
|
||||||
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
||||||
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
||||||
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
|
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
|
||||||
@@ -24,6 +25,7 @@ declare module '@vue/runtime-core' {
|
|||||||
ElPopover: typeof import('element-plus/es')['ElPopover']
|
ElPopover: typeof import('element-plus/es')['ElPopover']
|
||||||
ElProgress: typeof import('element-plus/es')['ElProgress']
|
ElProgress: typeof import('element-plus/es')['ElProgress']
|
||||||
ElRadio: typeof import('element-plus/es')['ElRadio']
|
ElRadio: typeof import('element-plus/es')['ElRadio']
|
||||||
|
ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
|
||||||
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
||||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
ElSelect: typeof import('element-plus/es')['ElSelect']
|
||||||
ElSlider: typeof import('element-plus/es')['ElSlider']
|
ElSlider: typeof import('element-plus/es')['ElSlider']
|
||||||
|
55
src/types/dashboard.d.ts
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
import { DurationTime } from "@/types/app";
|
||||||
/**
|
/**
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
@@ -36,7 +37,35 @@ export interface LayoutConfig {
|
|||||||
children?: { name: string; children: LayoutConfig[] }[];
|
children?: { name: string; children: LayoutConfig[] }[];
|
||||||
activedTabIndex?: number;
|
activedTabIndex?: number;
|
||||||
metricConfig?: MetricConfigOpt[];
|
metricConfig?: MetricConfigOpt[];
|
||||||
|
id?: string;
|
||||||
|
associate?: { widgetId: string }[];
|
||||||
|
eventAssociate?: boolean;
|
||||||
|
filters?: Filters;
|
||||||
|
relatedTrace?: RelatedTrace;
|
||||||
}
|
}
|
||||||
|
export type RelatedTrace = {
|
||||||
|
duration: DurationTime;
|
||||||
|
status: string;
|
||||||
|
queryOrder: string;
|
||||||
|
latency: boolean;
|
||||||
|
enableRelate: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Filters = {
|
||||||
|
dataIndex: number;
|
||||||
|
sourceId: string;
|
||||||
|
isRange?: boolean;
|
||||||
|
duration?: {
|
||||||
|
startTime: string;
|
||||||
|
endTime: string;
|
||||||
|
};
|
||||||
|
traceId?: string;
|
||||||
|
spanId?: string;
|
||||||
|
segmentId?: string;
|
||||||
|
id?: string;
|
||||||
|
queryOrder?: string;
|
||||||
|
status?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type MetricConfigOpt = {
|
export type MetricConfigOpt = {
|
||||||
unit?: string;
|
unit?: string;
|
||||||
@@ -45,9 +74,11 @@ export type MetricConfigOpt = {
|
|||||||
labelsIndex: string;
|
labelsIndex: string;
|
||||||
sortOrder: string;
|
sortOrder: string;
|
||||||
topN?: number;
|
topN?: number;
|
||||||
|
index?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface WidgetConfig {
|
export interface WidgetConfig {
|
||||||
|
name?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
tips?: string;
|
tips?: string;
|
||||||
}
|
}
|
||||||
@@ -64,6 +95,7 @@ export type GraphConfig =
|
|||||||
export interface BarConfig {
|
export interface BarConfig {
|
||||||
type?: string;
|
type?: string;
|
||||||
showBackground?: boolean;
|
showBackground?: boolean;
|
||||||
|
legend?: LegendOptions;
|
||||||
}
|
}
|
||||||
export interface LineConfig extends AreaConfig {
|
export interface LineConfig extends AreaConfig {
|
||||||
type?: string;
|
type?: string;
|
||||||
@@ -79,6 +111,7 @@ export interface LineConfig extends AreaConfig {
|
|||||||
export interface AreaConfig {
|
export interface AreaConfig {
|
||||||
type?: string;
|
type?: string;
|
||||||
opacity?: number;
|
opacity?: number;
|
||||||
|
legend?: LegendOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CardConfig {
|
export interface CardConfig {
|
||||||
@@ -137,3 +170,25 @@ export interface TopologyConfig {
|
|||||||
depth?: number;
|
depth?: number;
|
||||||
showDepth?: boolean;
|
showDepth?: boolean;
|
||||||
}
|
}
|
||||||
|
export type EventParams = {
|
||||||
|
componentType: string;
|
||||||
|
seriesType: string;
|
||||||
|
seriesIndex: number;
|
||||||
|
seriesName: string;
|
||||||
|
name: string;
|
||||||
|
dataIndex: number;
|
||||||
|
data: Record<string, unknown>;
|
||||||
|
dataType: string;
|
||||||
|
value: number | number[];
|
||||||
|
color: string;
|
||||||
|
};
|
||||||
|
export type LegendOptions = {
|
||||||
|
show: boolean;
|
||||||
|
total: boolean;
|
||||||
|
min: boolean;
|
||||||
|
max: boolean;
|
||||||
|
mean: boolean;
|
||||||
|
asTable: boolean;
|
||||||
|
toTheRight: boolean;
|
||||||
|
width: number;
|
||||||
|
};
|
||||||
|
32
src/types/ebpf.d.ts
vendored
@@ -15,6 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Process } from "./selector";
|
||||||
export interface EBPFTaskCreationRequest {
|
export interface EBPFTaskCreationRequest {
|
||||||
serviceId: string;
|
serviceId: string;
|
||||||
processLabels: string[];
|
processLabels: string[];
|
||||||
@@ -43,18 +44,7 @@ export interface EBPFProfilingSchedule {
|
|||||||
startTime: number;
|
startTime: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Process = {
|
export type Process = Process;
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
serviceId: string;
|
|
||||||
serviceName: string;
|
|
||||||
instanceId: string;
|
|
||||||
instanceName: string;
|
|
||||||
agentId: string;
|
|
||||||
detectType: string;
|
|
||||||
attributes: { name: string; value: string }[];
|
|
||||||
labels: string[];
|
|
||||||
};
|
|
||||||
export type StackElement = {
|
export type StackElement = {
|
||||||
id: string;
|
id: string;
|
||||||
originId: string;
|
originId: string;
|
||||||
@@ -75,3 +65,21 @@ export type AnalyzationTrees = {
|
|||||||
dumpCount: number;
|
dumpCount: number;
|
||||||
stackType: string;
|
stackType: string;
|
||||||
};
|
};
|
||||||
|
export type ProcessNode = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
serviceId: string;
|
||||||
|
serviceName: string;
|
||||||
|
serviceInstanceId: string;
|
||||||
|
serviceInstanceName: string;
|
||||||
|
name: string;
|
||||||
|
isReal: boolean;
|
||||||
|
x?: number;
|
||||||
|
y?: number;
|
||||||
|
};
|
||||||
|
export interface NetworkProfilingRequest {
|
||||||
|
uriRegex: string;
|
||||||
|
when4xx: string;
|
||||||
|
when5xx: string;
|
||||||
|
minDuration: number;
|
||||||
|
}
|
||||||
|
13
src/types/selector.d.ts
vendored
@@ -46,3 +46,16 @@ export type Service = {
|
|||||||
layers: string[];
|
layers: string[];
|
||||||
shortName: string;
|
shortName: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type Process = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
serviceId: string;
|
||||||
|
serviceName: string;
|
||||||
|
instanceId: string;
|
||||||
|
instanceName: string;
|
||||||
|
agentId: string;
|
||||||
|
detectType: string;
|
||||||
|
attributes: { name: string; value: string }[];
|
||||||
|
labels: string[];
|
||||||
|
};
|
||||||
|
3
src/types/topology.d.ts
vendored
@@ -23,6 +23,9 @@ export interface Call {
|
|||||||
sourceObj?: any;
|
sourceObj?: any;
|
||||||
targetObj?: any;
|
targetObj?: any;
|
||||||
value?: number;
|
value?: number;
|
||||||
|
lowerArc?: boolean;
|
||||||
|
sourceComponents: string[];
|
||||||
|
targetComponents: string[];
|
||||||
}
|
}
|
||||||
export interface Node {
|
export interface Node {
|
||||||
id: string;
|
id: string;
|
||||||
|
17
src/types/trace.d.ts
vendored
@@ -14,7 +14,6 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export interface Trace {
|
export interface Trace {
|
||||||
duration: number;
|
duration: number;
|
||||||
isError: boolean;
|
isError: boolean;
|
||||||
@@ -85,3 +84,19 @@ export class TraceTreeRef {
|
|||||||
segmentMap: Map<string, Span>;
|
segmentMap: Map<string, Span>;
|
||||||
segmentIdGroup: string[];
|
segmentIdGroup: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Instant = {
|
||||||
|
seconds: number;
|
||||||
|
nanos: number;
|
||||||
|
};
|
||||||
|
type KeyValue = {
|
||||||
|
key: string;
|
||||||
|
value: string | number;
|
||||||
|
};
|
||||||
|
export interface SpanAttachedEvent {
|
||||||
|
startTime: Instant;
|
||||||
|
endTime: Instant;
|
||||||
|
event: string;
|
||||||
|
tags: KeyValue[];
|
||||||
|
summary: KeyValue[];
|
||||||
|
}
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
import dayjs from "dayjs";
|
||||||
export default function dateFormatStep(
|
export default function dateFormatStep(
|
||||||
date: Date,
|
date: Date,
|
||||||
step: string,
|
step: string,
|
||||||
@@ -99,3 +100,6 @@ export const dateFormatTime = (date: Date, step: string): string => {
|
|||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const dateFormat = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") =>
|
||||||
|
dayjs(new Date(date)).format(pattern);
|
||||||
|
@@ -16,13 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
import * as echarts from "echarts/core";
|
import * as echarts from "echarts/core";
|
||||||
|
|
||||||
import {
|
import { BarChart, LineChart, HeatmapChart, SankeyChart } from "echarts/charts";
|
||||||
BarChart,
|
|
||||||
LineChart,
|
|
||||||
PieChart,
|
|
||||||
HeatmapChart,
|
|
||||||
SankeyChart,
|
|
||||||
} from "echarts/charts";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
TitleComponent,
|
TitleComponent,
|
||||||
@@ -32,6 +26,7 @@ import {
|
|||||||
DataZoomComponent,
|
DataZoomComponent,
|
||||||
VisualMapComponent,
|
VisualMapComponent,
|
||||||
TimelineComponent,
|
TimelineComponent,
|
||||||
|
MarkAreaComponent,
|
||||||
} from "echarts/components";
|
} from "echarts/components";
|
||||||
|
|
||||||
import { SVGRenderer } from "echarts/renderers";
|
import { SVGRenderer } from "echarts/renderers";
|
||||||
@@ -43,13 +38,13 @@ echarts.use([
|
|||||||
GridComponent,
|
GridComponent,
|
||||||
BarChart,
|
BarChart,
|
||||||
LineChart,
|
LineChart,
|
||||||
PieChart,
|
|
||||||
HeatmapChart,
|
HeatmapChart,
|
||||||
SankeyChart,
|
SankeyChart,
|
||||||
SVGRenderer,
|
SVGRenderer,
|
||||||
DataZoomComponent,
|
DataZoomComponent,
|
||||||
VisualMapComponent,
|
VisualMapComponent,
|
||||||
TimelineComponent,
|
TimelineComponent,
|
||||||
|
MarkAreaComponent,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export default echarts;
|
export default echarts;
|
||||||
|
@@ -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 {
|
||||||
|
@@ -27,7 +27,6 @@ import { useDashboardStore } from "@/store/modules/dashboard";
|
|||||||
import Dashboard from "./dashboard/Edit.vue";
|
import Dashboard from "./dashboard/Edit.vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { RoutesMap } from "@/constants/data";
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
@@ -38,7 +37,7 @@ const layer = ref<string>("GENERAL");
|
|||||||
getDashboard();
|
getDashboard();
|
||||||
|
|
||||||
async function getDashboard() {
|
async function getDashboard() {
|
||||||
layer.value = RoutesMap[String(route.name)];
|
layer.value = String(route.meta.layer);
|
||||||
dashboardStore.setLayer(layer.value);
|
dashboardStore.setLayer(layer.value);
|
||||||
dashboardStore.setMode(false);
|
dashboardStore.setMode(false);
|
||||||
await dashboardStore.setDashboards();
|
await dashboardStore.setDashboards();
|
||||||
|
@@ -69,18 +69,16 @@ 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";
|
||||||
import { Languages } from "@/constants/data";
|
import { Languages } from "@/constants/data";
|
||||||
import Selector from "@/components/Selector.vue";
|
import Selector from "@/components/Selector.vue";
|
||||||
|
import getLocalTime from "@/utils/localtime";
|
||||||
|
|
||||||
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);
|
||||||
@@ -91,8 +89,11 @@ appStore.setPageTitle("Setting");
|
|||||||
const handleReload = () => {
|
const handleReload = () => {
|
||||||
const gap =
|
const gap =
|
||||||
appStore.duration.end.getTime() - appStore.duration.start.getTime();
|
appStore.duration.end.getTime() - appStore.duration.start.getTime();
|
||||||
const time: Date[] = [new Date(new Date().getTime() - gap), new Date()];
|
const dates: Date[] = [
|
||||||
appStore.setDuration(timeFormat(time));
|
getLocalTime(appStore.utc, new Date(new Date().getTime() - gap)),
|
||||||
|
getLocalTime(appStore.utc, new Date()),
|
||||||
|
];
|
||||||
|
appStore.setDuration(timeFormat(dates));
|
||||||
};
|
};
|
||||||
const handleAuto = () => {
|
const handleAuto = () => {
|
||||||
if (autoTime.value < 1) {
|
if (autoTime.value < 1) {
|
||||||
@@ -101,10 +102,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 +113,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 => {
|
||||||
|
@@ -145,16 +145,14 @@ limitations under the License. -->
|
|||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import dayjs from "dayjs";
|
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { Alarm, Event } from "@/types/alarm";
|
import { Alarm, Event } from "@/types/alarm";
|
||||||
import { useAlarmStore } from "@/store/modules/alarm";
|
import { useAlarmStore } from "@/store/modules/alarm";
|
||||||
import { EventsDetailHeaders, AlarmDetailCol, EventsDetailKeys } from "./data";
|
import { EventsDetailHeaders, AlarmDetailCol, EventsDetailKeys } from "./data";
|
||||||
|
import { dateFormat } from "@/utils/dateFormat";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const alarmStore = useAlarmStore();
|
const alarmStore = useAlarmStore();
|
||||||
const dateFormat = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") =>
|
|
||||||
dayjs(date).format(pattern);
|
|
||||||
const isShowDetails = ref<boolean>(false);
|
const isShowDetails = ref<boolean>(false);
|
||||||
const showEventDetails = ref<boolean>(false);
|
const showEventDetails = ref<boolean>(false);
|
||||||
const currentDetail = ref<Alarm | any>({});
|
const currentDetail = ref<Alarm | any>({});
|
||||||
|
@@ -15,11 +15,7 @@ limitations under the License. -->
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<span class="grey">{{ t("tags") }}: </span>
|
<span class="grey">{{ t("tags") }}: </span>
|
||||||
<span
|
<span v-if="tagsList.length" class="trace-tags">
|
||||||
v-if="tagsList.length"
|
|
||||||
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>
|
||||||
@@ -33,31 +29,29 @@ limitations under the License. -->
|
|||||||
@change="addLabels"
|
@change="addLabels"
|
||||||
:placeholder="t('addTags')"
|
:placeholder="t('addTags')"
|
||||||
/>
|
/>
|
||||||
<span v-else>
|
<el-popover v-else trigger="click" :visible="visible" width="300px">
|
||||||
<el-input
|
<template #reference>
|
||||||
size="small"
|
<el-input
|
||||||
v-model="tags"
|
size="small"
|
||||||
class="trace-new-tag"
|
v-model="tags"
|
||||||
@click="showClick"
|
class="trace-new-tag"
|
||||||
/>
|
@input="inputTags"
|
||||||
<el-dropdown
|
@blur="visible = false"
|
||||||
ref="dropdownTag"
|
@focus="visible = true"
|
||||||
trigger="contextmenu"
|
@change="addTags"
|
||||||
:hide-on-click="false"
|
/>
|
||||||
style="margin: 20px 0 0 -130px"
|
</template>
|
||||||
v-if="tagArr.length"
|
<div class="content">
|
||||||
>
|
<span
|
||||||
<template #dropdown>
|
v-for="(item, index) in tagList"
|
||||||
<el-dropdown-menu>
|
:key="index"
|
||||||
<el-dropdown-item v-for="(item, index) in tagArr" :key="index">
|
@click="selectTag(item)"
|
||||||
<span @click="selectTag(item)" class="tag-item">
|
class="tag-item"
|
||||||
{{ item }}
|
>
|
||||||
</span>
|
{{ item }}
|
||||||
</el-dropdown-item>
|
</span>
|
||||||
</el-dropdown-menu>
|
</div>
|
||||||
</template>
|
</el-popover>
|
||||||
</el-dropdown>
|
|
||||||
</span>
|
|
||||||
<span
|
<span
|
||||||
class="tags-tip"
|
class="tags-tip"
|
||||||
:class="type !== 'ALARM' && tagArr.length ? 'link-tips' : ''"
|
:class="type !== 'ALARM' && tagArr.length ? 'link-tips' : ''"
|
||||||
@@ -68,12 +62,12 @@ limitations under the License. -->
|
|||||||
>
|
>
|
||||||
{{ t("tagsLink") }}
|
{{ t("tagsLink") }}
|
||||||
</a>
|
</a>
|
||||||
<el-tooltip :content="t(tipsMap[type])">
|
<el-tooltip :content="t((tipsMap as any)[type])">
|
||||||
<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 === 'AL'">{{ t("noticeTag") }}</b>
|
<b v-if="type === 'ALARM'">{{ t("noticeTag") }}</b>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -85,7 +79,7 @@ import { useLogStore } from "@/store/modules/log";
|
|||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
|
|
||||||
/*global Nullable, defineEmits, defineProps */
|
/*global defineEmits, defineProps */
|
||||||
const emit = defineEmits(["update"]);
|
const emit = defineEmits(["update"]);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
type: { type: String, default: "TRACE" },
|
type: { type: String, default: "TRACE" },
|
||||||
@@ -97,13 +91,15 @@ const { t } = useI18n();
|
|||||||
const tags = ref<string>("");
|
const tags = ref<string>("");
|
||||||
const tagsList = ref<string[]>([]);
|
const tagsList = ref<string[]>([]);
|
||||||
const tagArr = ref<string[]>([]);
|
const tagArr = ref<string[]>([]);
|
||||||
|
const tagList = ref<string[]>([]);
|
||||||
const tagKeys = ref<string[]>([]);
|
const tagKeys = ref<string[]>([]);
|
||||||
|
const keysList = ref<string[]>([]);
|
||||||
|
const visible = ref<boolean>(false);
|
||||||
const tipsMap = {
|
const tipsMap = {
|
||||||
LOG: "logTagsTip",
|
LOG: "logTagsTip",
|
||||||
TRACE: "traceTagsTip",
|
TRACE: "traceTagsTip",
|
||||||
ALARM: "alarmTagsTip",
|
ALARM: "alarmTagsTip",
|
||||||
};
|
};
|
||||||
const dropdownTag = ref<Nullable<any>>(null);
|
|
||||||
|
|
||||||
fetchTagKeys();
|
fetchTagKeys();
|
||||||
|
|
||||||
@@ -143,6 +139,8 @@ async function fetchTagKeys() {
|
|||||||
}
|
}
|
||||||
tagArr.value = resp.data.tagKeys;
|
tagArr.value = resp.data.tagKeys;
|
||||||
tagKeys.value = resp.data.tagKeys;
|
tagKeys.value = resp.data.tagKeys;
|
||||||
|
keysList.value = resp.data.tagKeys;
|
||||||
|
searchTags();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchTagValues() {
|
async function fetchTagValues() {
|
||||||
@@ -159,25 +157,56 @@ async function fetchTagValues() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tagArr.value = resp.data.tagValues;
|
tagArr.value = resp.data.tagValues;
|
||||||
|
searchTags();
|
||||||
|
}
|
||||||
|
|
||||||
|
function inputTags() {
|
||||||
|
if (!tags.value) {
|
||||||
|
tagArr.value = keysList.value;
|
||||||
|
tagKeys.value = keysList.value;
|
||||||
|
tagList.value = tagArr.value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let search = "";
|
||||||
|
if (tags.value.includes("=")) {
|
||||||
|
search = tags.value.split("=")[1];
|
||||||
|
fetchTagValues();
|
||||||
|
} else {
|
||||||
|
search = tags.value;
|
||||||
|
}
|
||||||
|
tagList.value = tagArr.value.filter((d: string) => d.includes(search));
|
||||||
|
}
|
||||||
|
|
||||||
|
function addTags() {
|
||||||
|
if (!tags.value.includes("=")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addLabels();
|
||||||
|
tagArr.value = tagKeys.value;
|
||||||
|
searchTags();
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectTag(item: string) {
|
function selectTag(item: string) {
|
||||||
if (tags.value.includes("=")) {
|
if (tags.value.includes("=")) {
|
||||||
tags.value += item;
|
const key = tags.value.split("=")[0];
|
||||||
addLabels();
|
tags.value = key + "=" + item;
|
||||||
tagArr.value = tagKeys.value;
|
addTags();
|
||||||
dropdownTag.value.handleClose();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tags.value = item + "=";
|
tags.value = item + "=";
|
||||||
fetchTagValues();
|
fetchTagValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
function showClick() {
|
function searchTags() {
|
||||||
if (dropdownTag.value) {
|
let search = "";
|
||||||
dropdownTag.value.handleOpen();
|
if (tags.value.includes("=")) {
|
||||||
|
search = tags.value.split("=")[1];
|
||||||
|
} else {
|
||||||
|
search = tags.value;
|
||||||
}
|
}
|
||||||
|
tagList.value = tagArr.value.filter((d: string) => d.includes(search));
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => appStore.durationTime,
|
() => appStore.durationTime,
|
||||||
() => {
|
() => {
|
||||||
@@ -221,6 +250,12 @@ watch(
|
|||||||
.tag-item {
|
.tag-item {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
min-width: 210px;
|
min-width: 210px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-top: 10px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tags-tip {
|
.tags-tip {
|
||||||
@@ -229,7 +264,6 @@ watch(
|
|||||||
|
|
||||||
.link-tips {
|
.link-tips {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 130px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.light {
|
.light {
|
||||||
@@ -247,4 +281,10 @@ watch(
|
|||||||
.icon-help {
|
.icon-help {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
width: 300px;
|
||||||
|
max-height: 400px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -41,6 +41,7 @@ import Tool from "./panel/Tool.vue";
|
|||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import Configuration from "./configuration";
|
import Configuration from "./configuration";
|
||||||
|
import { LayoutConfig } from "@/types/dashboard";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "Dashboard",
|
name: "Dashboard",
|
||||||
@@ -66,7 +67,8 @@ export default defineComponent({
|
|||||||
sessionStorage.getItem(layoutKey.value) || "{}"
|
sessionStorage.getItem(layoutKey.value) || "{}"
|
||||||
);
|
);
|
||||||
const layout: any = c.configuration || {};
|
const layout: any = c.configuration || {};
|
||||||
dashboardStore.setLayout(layout.children || []);
|
|
||||||
|
dashboardStore.setLayout(setWidgetsID(layout.children || []));
|
||||||
appStore.setPageTitle(layout.name);
|
appStore.setPageTitle(layout.name);
|
||||||
if (p.entity) {
|
if (p.entity) {
|
||||||
dashboardStore.setCurrentDashboard({
|
dashboardStore.setCurrentDashboard({
|
||||||
@@ -78,6 +80,24 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function setWidgetsID(widgets: LayoutConfig[]) {
|
||||||
|
for (const item of widgets) {
|
||||||
|
item.id = item.i;
|
||||||
|
if (item.type === "Tab") {
|
||||||
|
if (item.children && item.children.length) {
|
||||||
|
for (const [index, child] of item.children.entries()) {
|
||||||
|
if (child.children && child.children.length) {
|
||||||
|
child.children.map((d: { i: string; index: string } | any) => {
|
||||||
|
d.id = `${item.i}-${index}-${d.i}`;
|
||||||
|
return d;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return widgets;
|
||||||
|
}
|
||||||
function handleClick(e: any) {
|
function handleClick(e: any) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (e.target.className === "ds-main") {
|
if (e.target.className === "ds-main") {
|
||||||
|
@@ -20,7 +20,7 @@ limitations under the License. -->
|
|||||||
placeholder="Please input name"
|
placeholder="Please input name"
|
||||||
class="input-with-search ml-10"
|
class="input-with-search ml-10"
|
||||||
size="small"
|
size="small"
|
||||||
@change="searchDashboards"
|
@change="searchDashboards(1)"
|
||||||
>
|
>
|
||||||
<template #append>
|
<template #append>
|
||||||
<el-button size="small">
|
<el-button size="small">
|
||||||
@@ -46,7 +46,7 @@ limitations under the License. -->
|
|||||||
ref="multipleTableRef"
|
ref="multipleTableRef"
|
||||||
:default-sort="{ prop: 'name', order: 'ascending' }"
|
:default-sort="{ prop: 'name', order: 'ascending' }"
|
||||||
@selection-change="handleSelectionChange"
|
@selection-change="handleSelectionChange"
|
||||||
height="637px"
|
height="calc(100% - 60px)"
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
<el-table-column type="selection" width="55" />
|
<el-table-column type="selection" width="55" />
|
||||||
@@ -129,7 +129,8 @@ limitations under the License. -->
|
|||||||
small
|
small
|
||||||
layout="prev, pager, next"
|
layout="prev, pager, next"
|
||||||
:page-size="pageSize"
|
:page-size="pageSize"
|
||||||
:total="dashboardStore.dashboards.length"
|
:total="total"
|
||||||
|
v-model="currentPage"
|
||||||
@current-change="changePage"
|
@current-change="changePage"
|
||||||
@prev-click="changePage"
|
@prev-click="changePage"
|
||||||
@next-click="changePage"
|
@next-click="changePage"
|
||||||
@@ -155,10 +156,12 @@ import { isEmptyObject } from "@/utils/is";
|
|||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const appStore = useAppStoreWithOut();
|
const appStore = useAppStoreWithOut();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const pageSize = 18;
|
const pageSize = 20;
|
||||||
const dashboards = ref<DashboardItem[]>([]);
|
const dashboards = ref<DashboardItem[]>([]);
|
||||||
const searchText = ref<string>("");
|
const searchText = ref<string>("");
|
||||||
const loading = ref<boolean>(false);
|
const loading = ref<boolean>(false);
|
||||||
|
const currentPage = ref<number>(1);
|
||||||
|
const total = ref<number>(0);
|
||||||
const multipleTableRef = ref<InstanceType<typeof ElTable>>();
|
const multipleTableRef = ref<InstanceType<typeof ElTable>>();
|
||||||
const multipleSelection = ref<DashboardItem[]>([]);
|
const multipleSelection = ref<DashboardItem[]>([]);
|
||||||
const dashboardFile = ref<Nullable<HTMLDivElement>>(null);
|
const dashboardFile = ref<Nullable<HTMLDivElement>>(null);
|
||||||
@@ -170,7 +173,7 @@ const handleSelectionChange = (val: DashboardItem[]) => {
|
|||||||
setList();
|
setList();
|
||||||
async function setList() {
|
async function setList() {
|
||||||
await dashboardStore.setDashboards();
|
await dashboardStore.setDashboards();
|
||||||
searchDashboards();
|
searchDashboards(1);
|
||||||
}
|
}
|
||||||
async function importTemplates(event: any) {
|
async function importTemplates(event: any) {
|
||||||
const arr: any = await readFile(event);
|
const arr: any = await readFile(event);
|
||||||
@@ -232,12 +235,20 @@ function exportTemplates() {
|
|||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
function optimizeTemplate(
|
function optimizeTemplate(
|
||||||
children: (LayoutConfig & { moved?: boolean; standard?: unknown })[]
|
children: (LayoutConfig & {
|
||||||
|
moved?: boolean;
|
||||||
|
standard?: unknown;
|
||||||
|
label?: string;
|
||||||
|
value?: string;
|
||||||
|
})[]
|
||||||
) {
|
) {
|
||||||
for (const child of children || []) {
|
for (const child of children || []) {
|
||||||
delete child.moved;
|
delete child.moved;
|
||||||
delete child.activedTabIndex;
|
delete child.activedTabIndex;
|
||||||
delete child.standard;
|
delete child.standard;
|
||||||
|
delete child.id;
|
||||||
|
delete child.label;
|
||||||
|
delete child.value;
|
||||||
if (isEmptyObject(child.graph)) {
|
if (isEmptyObject(child.graph)) {
|
||||||
delete child.graph;
|
delete child.graph;
|
||||||
}
|
}
|
||||||
@@ -370,7 +381,7 @@ async function setRoot(row: DashboardItem) {
|
|||||||
items.push(d);
|
items.push(d);
|
||||||
}
|
}
|
||||||
dashboardStore.resetDashboards(items);
|
dashboardStore.resetDashboards(items);
|
||||||
searchDashboards();
|
searchDashboards(1);
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
function handleRename(row: DashboardItem) {
|
function handleRename(row: DashboardItem) {
|
||||||
@@ -402,6 +413,7 @@ async function updateName(d: DashboardItem, value: string) {
|
|||||||
name: value,
|
name: value,
|
||||||
};
|
};
|
||||||
delete c.id;
|
delete c.id;
|
||||||
|
delete c.filters;
|
||||||
const setting = {
|
const setting = {
|
||||||
id: d.id,
|
id: d.id,
|
||||||
configuration: JSON.stringify(c),
|
configuration: JSON.stringify(c),
|
||||||
@@ -453,10 +465,13 @@ function searchDashboards(pageIndex?: any) {
|
|||||||
const arr = list.filter((d: { name: string }) =>
|
const arr = list.filter((d: { name: string }) =>
|
||||||
d.name.includes(searchText.value)
|
d.name.includes(searchText.value)
|
||||||
);
|
);
|
||||||
dashboards.value = arr.splice(
|
|
||||||
(pageIndex - 1 || 0) * pageSize,
|
total.value = arr.length;
|
||||||
pageSize * (pageIndex || 1)
|
dashboards.value = arr.filter(
|
||||||
|
(d: { name: string }, index: number) =>
|
||||||
|
index < pageIndex * pageSize && index >= (pageIndex - 1) * pageSize
|
||||||
);
|
);
|
||||||
|
currentPage.value = pageIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function reloadTemplates() {
|
async function reloadTemplates() {
|
||||||
@@ -465,6 +480,7 @@ async function reloadTemplates() {
|
|||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
function changePage(pageIndex: number) {
|
function changePage(pageIndex: number) {
|
||||||
|
currentPage.value = pageIndex;
|
||||||
searchDashboards(pageIndex);
|
searchDashboards(pageIndex);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -484,12 +500,13 @@ function changePage(pageIndex: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
padding: 20px;
|
padding: 20px 10px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
box-shadow: 0px 1px 4px 0px #00000029;
|
box-shadow: 0px 1px 4px 0px #00000029;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toggle-selection {
|
.toggle-selection {
|
||||||
|
@@ -81,6 +81,10 @@ const onCreate = () => {
|
|||||||
states.entity === d.entity &&
|
states.entity === d.entity &&
|
||||||
states.selectedLayer === d.layer
|
states.selectedLayer === d.layer
|
||||||
);
|
);
|
||||||
|
if (!states.name) {
|
||||||
|
ElMessage.error(t("nameEmptyError"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
ElMessage.error(t("nameError"));
|
ElMessage.error(t("nameError"));
|
||||||
return;
|
return;
|
||||||
|
82
src/views/dashboard/configuration/Event.vue
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<!-- 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>
|
||||||
|
<span class="label">{{ t("enableAssociate") }}</span>
|
||||||
|
<el-switch
|
||||||
|
v-model="eventAssociate"
|
||||||
|
active-text="Yes"
|
||||||
|
inactive-text="No"
|
||||||
|
@change="updateConfig"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
<el-button size="small" @click="cancelConfig">
|
||||||
|
{{ t("cancel") }}
|
||||||
|
</el-button>
|
||||||
|
<el-button size="small" type="primary" @click="applyConfig">
|
||||||
|
{{ t("apply") }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
const originConfig = dashboardStore.selectedGrid;
|
||||||
|
const eventAssociate = ref(dashboardStore.selectedGrid.eventAssociate || false);
|
||||||
|
|
||||||
|
function updateConfig() {
|
||||||
|
dashboardStore.selectedGrid = {
|
||||||
|
...dashboardStore.selectedGrid,
|
||||||
|
eventAssociate,
|
||||||
|
};
|
||||||
|
dashboardStore.selectWidget(dashboardStore.selectedGrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyConfig() {
|
||||||
|
dashboardStore.setConfigPanel(false);
|
||||||
|
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelConfig() {
|
||||||
|
dashboardStore.selectWidget(originConfig);
|
||||||
|
dashboardStore.setConfigPanel(false);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.label {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: right;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
161
src/views/dashboard/configuration/TimeRange.vue
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
<!-- 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="item">
|
||||||
|
<span class="label">{{ t("text") }}</span>
|
||||||
|
<el-input
|
||||||
|
class="input"
|
||||||
|
v-model="text"
|
||||||
|
size="small"
|
||||||
|
@change="changeConfig({ text })"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<span class="label">{{ t("textAlign") }}</span>
|
||||||
|
<Selector
|
||||||
|
:value="textAlign"
|
||||||
|
:options="AlignStyle"
|
||||||
|
size="small"
|
||||||
|
placeholder="Select a color"
|
||||||
|
class="input"
|
||||||
|
@change="changeConfig({ textAlign: $event[0].value })"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<span class="label">{{ t("backgroundColors") }}</span>
|
||||||
|
<Selector
|
||||||
|
:value="backgroundColor"
|
||||||
|
:options="Colors"
|
||||||
|
size="small"
|
||||||
|
placeholder="Select a color"
|
||||||
|
class="input"
|
||||||
|
@change="changeConfig({ backgroundColor: $event[0].value })"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<span class="label">{{ t("fontSize") }}</span>
|
||||||
|
<el-slider
|
||||||
|
class="slider"
|
||||||
|
v-model="fontSize"
|
||||||
|
show-input
|
||||||
|
input-size="small"
|
||||||
|
:min="12"
|
||||||
|
:max="30"
|
||||||
|
:step="1"
|
||||||
|
@change="changeConfig({ fontSize })"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<span class="label">{{ t("fontColors") }}</span>
|
||||||
|
<Selector
|
||||||
|
:value="fontColor"
|
||||||
|
:options="Colors"
|
||||||
|
size="small"
|
||||||
|
placeholder="Select a color"
|
||||||
|
class="input"
|
||||||
|
@change="changeConfig({ fontColor: $event[0].value })"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
<el-button size="small" @click="cancelConfig">
|
||||||
|
{{ t("cancel") }}
|
||||||
|
</el-button>
|
||||||
|
<el-button size="small" type="primary" @click="applyConfig">
|
||||||
|
{{ t("apply") }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
const originConfig = dashboardStore.selectedGrid;
|
||||||
|
const graph = originConfig.graph || {};
|
||||||
|
const backgroundColor = ref(graph.backgroundColor || "green");
|
||||||
|
const fontColor = ref(graph.fontColor || "white");
|
||||||
|
const fontSize = ref<number>(graph.fontSize || 12);
|
||||||
|
const textAlign = ref(graph.textAlign || "left");
|
||||||
|
const text = ref<string>(graph.text || "");
|
||||||
|
const Colors = [
|
||||||
|
{
|
||||||
|
label: "Green",
|
||||||
|
value: "green",
|
||||||
|
},
|
||||||
|
{ label: "Blue", value: "blue" },
|
||||||
|
{ label: "Red", value: "red" },
|
||||||
|
{ label: "Grey", value: "grey" },
|
||||||
|
{ label: "White", value: "white" },
|
||||||
|
{ label: "Black", value: "black" },
|
||||||
|
{ label: "Orange", value: "orange" },
|
||||||
|
];
|
||||||
|
const AlignStyle = [
|
||||||
|
{
|
||||||
|
label: "Left",
|
||||||
|
value: "left",
|
||||||
|
},
|
||||||
|
{ label: "Center", value: "center" },
|
||||||
|
{ label: "Right", value: "right" },
|
||||||
|
];
|
||||||
|
function changeConfig(param: { [key: string]: unknown }) {
|
||||||
|
const { selectedGrid } = dashboardStore;
|
||||||
|
const graph = {
|
||||||
|
...selectedGrid.graph,
|
||||||
|
...param,
|
||||||
|
};
|
||||||
|
dashboardStore.selectWidget({ ...selectedGrid, graph });
|
||||||
|
}
|
||||||
|
function applyConfig() {
|
||||||
|
dashboardStore.setConfigPanel(false);
|
||||||
|
dashboardStore.setConfigs(dashboardStore.selectedGrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelConfig() {
|
||||||
|
dashboardStore.selectWidget(originConfig);
|
||||||
|
dashboardStore.setConfigPanel(false);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.slider {
|
||||||
|
width: 500px;
|
||||||
|
margin-top: -3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: right;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
@@ -32,10 +32,12 @@ limitations under the License. -->
|
|||||||
:data="states.source"
|
:data="states.source"
|
||||||
:config="{
|
:config="{
|
||||||
...graph,
|
...graph,
|
||||||
|
legend: (dashboardStore.selectedGrid.graph || {}).legend,
|
||||||
i: dashboardStore.selectedGrid.i,
|
i: dashboardStore.selectedGrid.i,
|
||||||
metrics: dashboardStore.selectedGrid.metrics,
|
metrics: dashboardStore.selectedGrid.metrics,
|
||||||
metricTypes: dashboardStore.selectedGrid.metricTypes,
|
metricTypes: dashboardStore.selectedGrid.metricTypes,
|
||||||
metricConfig: dashboardStore.selectedGrid.metricConfig,
|
metricConfig: dashboardStore.selectedGrid.metricConfig,
|
||||||
|
relatedTrace: dashboardStore.selectedGrid.relatedTrace,
|
||||||
}"
|
}"
|
||||||
:needQuery="true"
|
:needQuery="true"
|
||||||
/>
|
/>
|
||||||
@@ -58,6 +60,20 @@ limitations under the License. -->
|
|||||||
<el-collapse-item :title="t('widgetOptions')" name="3">
|
<el-collapse-item :title="t('widgetOptions')" name="3">
|
||||||
<WidgetOptions />
|
<WidgetOptions />
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
|
<el-collapse-item
|
||||||
|
:title="t('associateOptions')"
|
||||||
|
name="4"
|
||||||
|
v-if="hasAssociate"
|
||||||
|
>
|
||||||
|
<AssociateOptions />
|
||||||
|
</el-collapse-item>
|
||||||
|
<el-collapse-item
|
||||||
|
:title="t('relatedTraceOptions')"
|
||||||
|
name="5"
|
||||||
|
v-if="hasAssociate"
|
||||||
|
>
|
||||||
|
<RelatedTraceOptions />
|
||||||
|
</el-collapse-item>
|
||||||
</el-collapse>
|
</el-collapse>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
@@ -77,20 +93,16 @@ import { useDashboardStore } from "@/store/modules/dashboard";
|
|||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { Option } from "@/types/app";
|
import { Option } from "@/types/app";
|
||||||
import graphs from "../graphs";
|
import graphs from "../graphs";
|
||||||
import configs from "./widget/graph-styles";
|
import CustomOptions from "./widget/index";
|
||||||
import WidgetOptions from "./widget/WidgetOptions.vue";
|
|
||||||
import MetricOptions from "./widget/metric/Index.vue";
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "WidgetEdit",
|
name: "WidgetEdit",
|
||||||
components: {
|
components: {
|
||||||
...graphs,
|
...graphs,
|
||||||
...configs,
|
...CustomOptions,
|
||||||
WidgetOptions,
|
|
||||||
MetricOptions,
|
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const configHeight = document.documentElement.clientHeight - 520;
|
const configHeight = document.documentElement.clientHeight - 540;
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const appStoreWithOut = useAppStoreWithOut();
|
const appStoreWithOut = useAppStoreWithOut();
|
||||||
@@ -111,6 +123,12 @@ export default defineComponent({
|
|||||||
const graph = computed(() => dashboardStore.selectedGrid.graph || {});
|
const graph = computed(() => dashboardStore.selectedGrid.graph || {});
|
||||||
const title = computed(() => encodeURIComponent(widget.value.title || ""));
|
const title = computed(() => encodeURIComponent(widget.value.title || ""));
|
||||||
const tips = computed(() => encodeURIComponent(widget.value.tips || ""));
|
const tips = computed(() => encodeURIComponent(widget.value.tips || ""));
|
||||||
|
const hasAssociate = computed(() =>
|
||||||
|
["Bar", "Line", "Area", "TopList"].includes(
|
||||||
|
dashboardStore.selectedGrid.graph &&
|
||||||
|
dashboardStore.selectedGrid.graph.type
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
function getSource(source: unknown) {
|
function getSource(source: unknown) {
|
||||||
states.source = source;
|
states.source = source;
|
||||||
@@ -145,6 +163,7 @@ export default defineComponent({
|
|||||||
graph,
|
graph,
|
||||||
title,
|
title,
|
||||||
tips,
|
tips,
|
||||||
|
hasAssociate,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -18,9 +18,13 @@
|
|||||||
import Text from "./Text.vue";
|
import Text from "./Text.vue";
|
||||||
import Widget from "./Widget.vue";
|
import Widget from "./Widget.vue";
|
||||||
import Topology from "./Topology.vue";
|
import Topology from "./Topology.vue";
|
||||||
|
import Event from "./Event.vue";
|
||||||
|
import TimeRange from "./TimeRange.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Text,
|
Text,
|
||||||
Widget,
|
Widget,
|
||||||
Topology,
|
Topology,
|
||||||
|
Event,
|
||||||
|
TimeRange,
|
||||||
};
|
};
|
||||||
|