Compare commits

..

No commits in common. "main" and "v9.7.0" have entirely different histories.
main ... v9.7.0

219 changed files with 11093 additions and 11592 deletions

View File

@ -37,7 +37,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
node-version: [18.x, 20.x, 22.x] node-version: [16.x, 18.x, 20.x]
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}

View File

@ -34,15 +34,14 @@ npm install
npm run dev npm run dev
``` ```
The default UI address is `http://localhost:3000`. The default UI address is `http://localhost:8080`.
# Contact Us # Contact Us
* Mail list: **dev@skywalking.apache.org**. Mail to `dev-subscribe@skywalking.apache.org`, follow the reply to subscribe to the mail list.
- Mail list: **dev@skywalking.apache.org**. Mail to `dev-subscribe@skywalking.apache.org`, follow the reply to subscribe to the mail list. * Send `Request to join SkyWalking slack` mail to the mail list(`dev@skywalking.apache.org`), we will invite you in.
- Send `Request to join SkyWalking slack` mail to the mail list(`dev@skywalking.apache.org`), we will invite you in. * For Chinese speaker, send `[CN] Request to join SkyWalking slack` mail to the mail list(`dev@skywalking.apache.org`), we will invite you in.
- For Chinese speaker, send `[CN] Request to join SkyWalking slack` mail to the mail list(`dev@skywalking.apache.org`), we will invite you in. * Twitter, [ASFSkyWalking](https://twitter.com/AsfSkyWalking)
- Twitter, [ASFSkyWalking](https://twitter.com/AsfSkyWalking) * [bilibili B站 视频](https://space.bilibili.com/390683219)
- [bilibili B 站 视频](https://space.bilibili.com/390683219)
# License # License

View File

@ -17,10 +17,35 @@
module.exports = { module.exports = {
ignores: [(commit) => commit.includes("init")], ignores: [(commit) => commit.includes("init")],
extends: ["@commitlint/config-conventional"],
rules: { rules: {
"body-leading-blank": [2, "always"], "body-leading-blank": [2, "always"],
"footer-leading-blank": [1, "always"], "footer-leading-blank": [1, "always"],
"header-max-length": [2, "always", 108], "header-max-length": [2, "always", 108],
"subject-empty": [2, "never"],
"type-empty": [2, "never"],
"subject-case": [0], "subject-case": [0],
"type-enum": [
2,
"always",
[
"feat",
"fix",
"perf",
"style",
"docs",
"test",
"refactor",
"build",
"ci",
"chore",
"revert",
"wip",
"workflow",
"types",
"release",
"merge",
],
],
}, },
}; };

10388
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "skywalking-booster-ui", "name": "skywalking-booster-ui",
"version": "10.2.0", "version": "9.4.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@ -18,17 +18,19 @@
"check-components-types": "if (! git diff --quiet -U0 ./src/types); then echo 'type files are not updated correctly'; git diff -U0 ./src/types; exit 1; fi" "check-components-types": "if (! git diff --quiet -U0 ./src/types); then echo 'type files are not updated correctly'; git diff -U0 ./src/types; exit 1; fi"
}, },
"dependencies": { "dependencies": {
"axios": "^1.6.0",
"d3": "^7.3.0", "d3": "^7.3.0",
"d3-flame-graph": "^4.1.3", "d3-flame-graph": "^4.1.3",
"d3-tip": "^0.9.1", "d3-tip": "^0.9.1",
"echarts": "^5.2.2", "echarts": "^5.2.2",
"element-plus": "^2.9.4", "element-plus": "^2.2.5",
"lodash": "^4.17.21",
"monaco-editor": "^0.34.1", "monaco-editor": "^0.34.1",
"pinia": "^2.0.28", "pinia": "^2.0.28",
"vis-timeline": "^7.5.1", "vis-timeline": "^7.5.1",
"vue": "^3.2.45", "vue": "^3.2.45",
"vue-grid-layout": "^3.0.0-beta1", "vue-grid-layout": "^3.0.0-beta1",
"vue-i18n": "^9.14.3", "vue-i18n": "^9.1.9",
"vue-router": "^4.1.6", "vue-router": "^4.1.6",
"vue-types": "^4.1.1" "vue-types": "^4.1.1"
}, },
@ -40,10 +42,11 @@
"@types/d3-tip": "^3.5.5", "@types/d3-tip": "^3.5.5",
"@types/echarts": "^4.9.12", "@types/echarts": "^4.9.12",
"@types/jsdom": "^20.0.1", "@types/jsdom": "^20.0.1",
"@types/lodash": "^4.14.179",
"@types/node": "^18.11.12", "@types/node": "^18.11.12",
"@types/three": "^0.131.0", "@types/three": "^0.131.0",
"@vitejs/plugin-vue": "^5.2.1", "@vitejs/plugin-vue": "^4.0.0",
"@vitejs/plugin-vue-jsx": "^4.1.1", "@vitejs/plugin-vue-jsx": "^3.0.0",
"@vue/eslint-config-prettier": "^7.0.0", "@vue/eslint-config-prettier": "^7.0.0",
"@vue/eslint-config-typescript": "^11.0.0", "@vue/eslint-config-typescript": "^11.0.0",
"@vue/test-utils": "^2.2.6", "@vue/test-utils": "^2.2.6",
@ -61,21 +64,21 @@
"postcss-html": "^1.3.0", "postcss-html": "^1.3.0",
"postcss-scss": "^4.0.2", "postcss-scss": "^4.0.2",
"prettier": "^2.7.1", "prettier": "^2.7.1",
"sass": "^1.85.0", "sass": "^1.56.1",
"start-server-and-test": "^2.0.5", "start-server-and-test": "^1.15.2",
"stylelint": "15.9.0", "stylelint": "15.9.0",
"stylelint-config-html": "^1.0.0", "stylelint-config-html": "^1.0.0",
"stylelint-config-prettier": "9.0.4", "stylelint-config-prettier": "9.0.4",
"stylelint-config-standard": "^33.0.0", "stylelint-config-standard": "^33.0.0",
"stylelint-order": "^6.0.3", "stylelint-order": "^6.0.3",
"typescript": "^5.7.3", "typescript": "~4.7.4",
"unplugin-auto-import": "^0.18.2", "unplugin-auto-import": "^0.7.0",
"unplugin-vue-components": "^0.27.3", "unplugin-vue-components": "^0.19.2",
"vite": "^6.3.4", "vite": "^4.0.5",
"vite-plugin-monaco-editor": "^1.1.0", "vite-plugin-monaco-editor": "^1.1.0",
"vite-plugin-svg-icons": "^2.0.1", "vite-plugin-svg-icons": "^2.0.1",
"vitest": "^3.0.5", "vitest": "^0.25.6",
"vue-tsc": "^2.2.2" "vue-tsc": "^1.0.12"
}, },
"browserslist": [ "browserslist": [
"> 1%", "> 1%",
@ -95,7 +98,10 @@
"{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [ "{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [
"prettier --write" "prettier --write"
], ],
"package.json, *.md": [ "package.json": [
"prettier --write"
],
"*.md": [
"prettier --write" "prettier --write"
] ]
} }

View File

@ -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 class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32"><path d="M856.32 428.064a32 32 0 0 0-32 32v163.328H372.48c-0.896 0-1.664 0.448-2.56 0.512v-177.696h244.48a32 32 0 1 0 0-64H130.56c-0.896 0-1.664 0.448-2.56 0.512V231.68h488.16a32 32 0 1 0 0-64H96a32 32 0 0 0-32 32v701.824a32 32 0 0 0 32 32h760.32a32 32 0 0 0 32-32V460.064a32 32 0 0 0-32-32zM128 445.728c0.896 0.064 1.664 0.512 2.56 0.512h175.36v423.264H128V445.728z m241.92 423.776v-182.624c0.896 0.064 1.664 0.512 2.56 0.512h451.84v182.08h-454.4zM960 174.656h-61.376V113.28a32 32 0 1 0-64 0v61.344H752.64a32 32 0 1 0 0 64h81.984v81.984a32 32 0 1 0 64 0V238.656H960a32 32 0 1 0 0-64z"></path></svg> <svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32"><path d="M856.32 428.064a32 32 0 0 0-32 32v163.328H372.48c-0.896 0-1.664 0.448-2.56 0.512v-177.696h244.48a32 32 0 1 0 0-64H130.56c-0.896 0-1.664 0.448-2.56 0.512V231.68h488.16a32 32 0 1 0 0-64H96a32 32 0 0 0-32 32v701.824a32 32 0 0 0 32 32h760.32a32 32 0 0 0 32-32V460.064a32 32 0 0 0-32-32zM128 445.728c0.896 0.064 1.664 0.512 2.56 0.512h175.36v423.264H128V445.728z m241.92 423.776v-182.624c0.896 0.064 1.664 0.512 2.56 0.512h451.84v182.08h-454.4zM960 174.656h-61.376V113.28a32 32 0 1 0-64 0v61.344H752.64a32 32 0 1 0 0 64h81.984v81.984a32 32 0 1 0 64 0V238.656H960a32 32 0 1 0 0-64z" fill="#2c2c2c"></path></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,18 +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. -->
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M512 992c-83.2 0-166.4-19.2-243.2-64-89.6-51.2-160-134.4-204.8-230.4C25.6 601.6 19.2 486.4 51.2 390.4c25.6-102.4 89.6-192 172.8-256C307.2 70.4 409.6 38.4 518.4 38.4c19.2 0 32 12.8 32 32s-19.2 25.6-38.4 25.6c-89.6 0-179.2 32-256 83.2S128 313.6 108.8 403.2s-12.8 185.6 19.2 268.8c32 83.2 96 153.6 179.2 198.4 76.8 44.8 172.8 64 262.4 51.2 89.6-12.8 172.8-51.2 236.8-115.2s108.8-147.2 115.2-236.8c12.8-89.6-6.4-185.6-51.2-262.4-6.4-12.8-6.4-32 12.8-44.8 12.8-12.8 38.4-6.4 44.8 12.8 51.2 89.6 76.8 198.4 57.6 300.8-12.8 102.4-64 204.8-134.4 275.2-76.8 76.8-172.8 121.6-275.2 134.4-19.2 6.4-44.8 6.4-64 6.4z" p-id="8538"></path><path d="M512 480c-19.2 0-32-12.8-32-32V64c0-19.2 12.8-32 32-32s32 12.8 32 32v384c0 19.2-12.8 32-32 32z" p-id="8539"></path><path d="M512 608c-12.8 0-25.6 0-38.4-6.4-12.8-6.4-19.2-12.8-32-19.2-6.4-12.8-12.8-19.2-19.2-32-6.4-12.8-6.4-25.6-6.4-38.4 0-25.6 12.8-51.2 25.6-70.4 38.4-38.4 102.4-38.4 134.4 0 19.2 19.2 32 44.8 32 70.4 0 25.6-12.8 51.2-25.6 70.4-19.2 12.8-44.8 25.6-70.4 25.6z m0-128c-6.4 0-19.2 6.4-25.6 6.4 0 6.4-6.4 19.2-6.4 25.6v12.8c0 6.4 6.4 6.4 6.4 12.8 0 0 6.4 6.4 12.8 6.4 12.8 6.4 25.6 0 32-6.4 6.4-6.4 12.8-19.2 12.8-25.6 0-6.4-6.4-19.2-6.4-25.6-6.4 0-19.2-6.4-25.6-6.4z" p-id="8540"></path><path d="M512 800c-51.2 0-102.4-12.8-147.2-38.4-57.6-32-96-83.2-121.6-140.8-19.2-57.6-25.6-121.6-6.4-185.6 19.2-64 51.2-115.2 102.4-153.6C384 243.2 448 224 512 224c19.2 0 32 12.8 32 32s-12.8 32-32 32c-51.2 0-96 19.2-134.4 44.8-38.4 32-70.4 76.8-83.2 121.6s-6.4 96 12.8 140.8c19.2 44.8 51.2 83.2 96 108.8 44.8 25.6 89.6 32 140.8 25.6 51.2-6.4 96-32 128-64s57.6-83.2 64-128c6.4-51.2-6.4-96-25.6-140.8-12.8-12.8-6.4-32 6.4-38.4 12.8-6.4 32-6.4 44.8 12.8 32 57.6 44.8 121.6 38.4 179.2-6.4 64-38.4 121.6-83.2 166.4-44.8 44.8-102.4 76.8-166.4 83.2H512z"></path>
</svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -1,16 +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. -->
<svg width="16" height="16" viewBox="20 0 70 72" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="m49.72 45.923-5.505-9.69 5.505-9.69h10.974l5.506 9.69-5.506 9.69H49.72ZM49.72 69.367l-5.505-9.69 5.505-9.689h10.974l5.506 9.69-5.506 9.69H49.72ZM49.72 22.477l-5.505-9.689 5.505-9.69h10.974l5.506 9.69-5.506 9.69H49.72ZM70.06 57.644l-5.506-9.69 5.506-9.69h10.974l5.506 9.69-5.506 9.69H70.06ZM70.06 34.2l-5.506-9.69 5.506-9.69h10.974l5.506 9.69-5.506 9.69H70.06ZM29.357 57.644l-5.506-9.69 5.506-9.69h10.974l5.506 9.69-5.506 9.69H29.357ZM29.357 34.2l-5.506-9.69 5.506-9.69h10.974l5.506 9.69-5.506 9.69H29.357Z" stroke="#141A1F" stroke-width="2.771"/><path d="M10.784 95.947c1.026.007 " fill="#141A1F"/></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,38 +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. -->
<svg width="2400" height="2400" viewBox="0 0 200 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="arrowhead" markerWidth="8" markerHeight="8" refX="2" refY="2.5" orient="auto">
<polygon points="0 0, 3 2.5, 0 5" fill="white" />
</marker>
</defs>
<line x1="0" y1="20" x2="42" y2="20" stroke="white" stroke-width="7" marker-end="url(#arrowhead)" />
<line x1="0" y1="50" x2="42" y2="50" stroke="white" stroke-width="7" marker-end="url(#arrowhead)" />
<line x1="0" y1="80" x2="42" y2="80" stroke="white" stroke-width="7" marker-end="url(#arrowhead)" />
<line x1="49" y1="10" x2="139" y2="10" stroke="white" stroke-width="7" />
<line x1="49" y1="90" x2="139" y2="90" stroke="white" stroke-width="7" />
<line x1="49" y1="10" x2="50" y2="90" stroke="white" stroke-width="7" />
<ellipse cx="140" cy="50" rx="10" ry="40" fill="none" stroke="white" stroke-width="7" />
<line x1="147" y1="20" x2="190" y2="20" stroke="white" stroke-width="7" marker-end="url(#arrowhead)" />
<line x1="149" y1="50" x2="190" y2="50" stroke="white" stroke-width="7" marker-end="url(#arrowhead)" />
<line x1="147" y1="80" x2="190" y2="80" stroke="white" stroke-width="7" marker-end="url(#arrowhead)" />
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -13,4 +13,4 @@ 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="1654161407133" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1721" width="16" height="16"><path d="M804.224 86.144c0-19.264-15.616-34.944-34.944-34.944l-734.336 0c-19.264 0-34.944 15.68-34.944 34.944l0 82.048 804.224 0 0-82.048zM738.88 602.432c0 47.072-38.176 85.248-85.248 85.248s-85.248-38.176-85.248-85.248c0-47.072 38.176-85.248 85.248-85.248s85.248 38.176 85.248 85.248zM804.992 264.64l0-62.976-804.224 0 0 665.408c0 18.56 14.656 33.472 32.96 34.56l402.24 0c61.12 44.544 136.192 71.168 217.664 71.168 204.544 0 370.368-165.824 370.368-370.368 0-150.592-89.984-279.936-219.008-337.792zM412.096 298.24l30.528 0c-10.624 7.36-20.8 15.36-30.528 23.744l0-23.744zM63.04 298.24l153.024 0 0 153.024-153.024 0 0-153.024zM216.064 805.056l-153.024 0 0-153.024 153.024 0 0 153.024zM219.136 631.232l-153.024 0 0-153.024 153.024 0 0 153.024zM237.568 805.056l0-153.024 49.408 0c7.488 55.936 27.264 107.904 56.832 153.024l-106.24 0zM284.672 631.232l-44.032 0 0-153.024 64.384 0c-13.824 38.848-21.824 80.576-21.824 124.224 0 9.728 0.768 19.264 1.472 28.8zM390.592 341.76c-31.168 31.424-56.512 68.544-74.88 109.44l-78.144 0 0-152.96 153.024 0 0 43.52zM899.136 638.4l-63.36 12.864c-4.288 16.064-10.688 31.296-18.816 45.376l35.712 53.888-50.944 50.944-53.888-35.712c-14.08 8.128-29.312 14.528-45.376 18.816l-12.864 63.36-72 0-12.864-63.36c-16.064-4.288-31.296-10.688-45.376-18.816l-53.888 35.712-50.944-50.944 35.712-53.888c-8.128-14.08-14.528-29.312-18.816-45.376l-63.36-12.864 0-72 63.36-12.864c4.352-16.064 10.688-31.296 18.816-45.312l-35.712-53.952 50.944-50.944 53.888 35.776c14.08-8.128 29.312-14.464 45.376-18.816l12.864-63.36 72 0 12.864 63.36c16.064 4.288 31.296 10.688 45.376 18.816l53.888-35.712 50.944 50.944-35.712 53.824c8.128 14.08 14.528 29.312 18.816 45.376l63.36 12.864 0 72z" p-id="1722"></path></svg> <svg t="1654161407133" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1721" width="16" height="16"><path d="M804.224 86.144c0-19.264-15.616-34.944-34.944-34.944l-734.336 0c-19.264 0-34.944 15.68-34.944 34.944l0 82.048 804.224 0 0-82.048zM738.88 602.432c0 47.072-38.176 85.248-85.248 85.248s-85.248-38.176-85.248-85.248c0-47.072 38.176-85.248 85.248-85.248s85.248 38.176 85.248 85.248zM804.992 264.64l0-62.976-804.224 0 0 665.408c0 18.56 14.656 33.472 32.96 34.56l402.24 0c61.12 44.544 136.192 71.168 217.664 71.168 204.544 0 370.368-165.824 370.368-370.368 0-150.592-89.984-279.936-219.008-337.792zM412.096 298.24l30.528 0c-10.624 7.36-20.8 15.36-30.528 23.744l0-23.744zM63.04 298.24l153.024 0 0 153.024-153.024 0 0-153.024zM216.064 805.056l-153.024 0 0-153.024 153.024 0 0 153.024zM219.136 631.232l-153.024 0 0-153.024 153.024 0 0 153.024zM237.568 805.056l0-153.024 49.408 0c7.488 55.936 27.264 107.904 56.832 153.024l-106.24 0zM284.672 631.232l-44.032 0 0-153.024 64.384 0c-13.824 38.848-21.824 80.576-21.824 124.224 0 9.728 0.768 19.264 1.472 28.8zM390.592 341.76c-31.168 31.424-56.512 68.544-74.88 109.44l-78.144 0 0-152.96 153.024 0 0 43.52zM899.136 638.4l-63.36 12.864c-4.288 16.064-10.688 31.296-18.816 45.376l35.712 53.888-50.944 50.944-53.888-35.712c-14.08 8.128-29.312 14.528-45.376 18.816l-12.864 63.36-72 0-12.864-63.36c-16.064-4.288-31.296-10.688-45.376-18.816l-53.888 35.712-50.944-50.944 35.712-53.888c-8.128-14.08-14.528-29.312-18.816-45.376l-63.36-12.864 0-72 63.36-12.864c4.352-16.064 10.688-31.296 18.816-45.312l-35.712-53.952 50.944-50.944 53.888 35.776c14.08-8.128 29.312-14.464 45.376-18.816l12.864-63.36 72 0 12.864 63.36c16.064 4.288 31.296 10.688 45.376 18.816l53.888-35.712 50.944 50.944-35.712 53.824c8.128 14.08 14.528 29.312 18.816 45.376l63.36 12.864 0 72z" p-id="1722" fill="#707070"></path></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -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="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"></path></svg> <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>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -1,18 +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. -->
<svg t="1704964118567" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5167">
<path d="M900.032 646.016h-56.064V502.976a16 16 0 0 0-16-16H544v-96h62.976c22.144 0 40-17.92 40-40V161.024a40 40 0 0 0-40-40H417.024a40 40 0 0 0-40 40v189.952c0 22.144 17.92 40 40 40H480v96H195.968a16 16 0 0 0-16 16v143.04h-55.936a38.016 38.016 0 0 0-38.016 38.016v176c0 20.928 17.024 37.952 37.952 37.952h176a38.016 38.016 0 0 0 38.016-38.016v-176a38.016 38.016 0 0 0-37.952-37.952h-56V550.976H480v95.04h-56a38.016 38.016 0 0 0-38.016 38.016v176c0 20.928 17.024 37.952 38.016 37.952h176a38.016 38.016 0 0 0 38.016-38.016v-176a38.016 38.016 0 0 0-38.016-37.952H544V550.976h236.032v95.04h-56.064a38.016 38.016 0 0 0-37.952 38.016v176c0 20.928 17.024 37.952 38.016 37.952h176a38.016 38.016 0 0 0 37.952-38.016v-176a38.016 38.016 0 0 0-38.016-37.952zM440.96 184.96h141.952v141.952H441.024V185.024zM278.016 838.016H145.92V705.92h132.032v132.032z m299.968 0H446.08V705.92H577.92v132.032z m300.032 0h-132.032V705.92h132.032v132.032z" p-id="5168"></path>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,138 +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. -->
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400.000000 400.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,400.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M1737 3725 c-379 -61 -696 -224 -968 -495 -249 -248 -403 -533 -481
-890 -20 -93 -22 -133 -22 -340 0 -207 2 -247 22 -339 48 -217 123 -407 231
-581 253 -406 658 -688 1141 -791 91 -20 135 -23 330 -24 172 0 246 4 315 17
361 69 669 231 926 487 271 272 438 604 494 983 23 154 16 448 -15 593 -147
694 -668 1214 -1366 1365 -130 29 -472 37 -607 15z m461 -131 c24 -3 52 -14
63 -25 23 -23 25 -76 3 -100 -15 -17 -15 -19 0 -34 25 -26 20 -82 -10 -112
-25 -25 -28 -25 -112 -19 -48 4 -88 8 -89 10 -1 1 4 60 12 131 8 72 15 137 15
145 0 17 14 17 118 4z m-359 -30 c30 -22 61 -89 61 -137 0 -48 -22 -102 -48
-116 -23 -12 -163 -43 -169 -38 -7 7 -53 280 -48 285 8 9 78 20 130 21 32 1
59 -5 74 -15z m564 -8 c7 -8 22 -44 31 -80 l18 -66 62 48 c48 38 66 47 85 43
23 -6 18 -12 -58 -71 -76 -61 -83 -69 -98 -122 -12 -43 -21 -58 -34 -58 -28 0
-30 14 -10 73 l19 56 -29 93 c-16 51 -29 94 -29 96 0 8 31 0 43 -12z m-858
-45 c0 -8 -30 -27 -69 -43 -38 -15 -71 -30 -74 -32 -4 -4 17 -76 22 -76 1 0
31 11 66 25 76 30 90 31 90 7 0 -13 -19 -24 -70 -42 -61 -21 -69 -27 -64 -45
15 -46 24 -65 32 -65 5 0 42 14 82 30 57 23 75 27 82 18 4 -7 8 -16 8 -19 0
-7 -180 -79 -197 -79 -6 0 -28 44 -49 98 -20 53 -43 112 -51 131 -7 19 -11 36
-9 38 10 11 173 71 186 70 8 -1 15 -9 15 -16z m-257 -157 c26 -29 28 -61 6
-92 -12 -17 -12 -22 -2 -22 7 0 42 -13 77 -29 62 -28 63 -29 41 -44 -21 -15
-26 -14 -59 2 -20 10 -53 24 -73 30 -37 12 -37 13 -96 -25 -2 -1 13 -27 32
-58 34 -52 35 -56 17 -65 -17 -10 -27 2 -92 101 -39 62 -74 119 -76 128 -2 9
14 26 44 44 119 73 138 76 181 30z m-292 -145 c3 -6 -19 -37 -52 -70 l-58 -59
29 -30 29 -30 56 55 c48 47 59 54 69 42 10 -12 2 -24 -44 -68 l-56 -52 32 -33
32 -33 64 59 c52 47 68 57 78 47 11 -10 -1 -27 -66 -92 l-80 -80 -99 105 c-55
58 -100 108 -100 111 0 10 139 139 150 139 5 0 12 -5 16 -11z m1197 -44 c494
-74 896 -467 982 -959 19 -113 19 -299 0 -410 -73 -416 -377 -773 -776 -910
-142 -48 -213 -59 -384 -59 -175 -1 -241 10 -400 65 -383 131 -680 481 -761
893 -22 115 -20 335 5 450 79 372 314 669 656 831 214 102 441 135 678 99z
m-1319 -258 c81 -91 95 -110 86 -126 -9 -18 -14 -18 -122 16 -62 19 -117 38
-123 41 -10 6 17 -27 109 -133 41 -46 48 -60 39 -73 -13 -20 0 -23 -160 28
-89 28 -133 47 -133 56 0 28 27 25 134 -15 73 -26 103 -34 94 -23 -7 9 -43 50
-80 91 -55 61 -65 78 -57 93 13 25 30 23 147 -15 l103 -33 -82 82 c-67 67 -80
85 -74 103 4 12 10 21 14 19 4 -2 51 -51 105 -111z m2502 -151 c38 -38 44 -77
19 -126 -19 -37 -43 -50 -95 -50 -61 0 -100 41 -100 105 0 40 5 52 31 76 46
42 99 41 145 -5z m-2677 -171 c16 -8 41 -29 56 -47 24 -29 27 -38 23 -91 -4
-54 -8 -63 -41 -93 -32 -30 -44 -34 -90 -34 -126 0 -200 102 -150 207 9 20 30
44 47 54 38 23 115 25 155 4z m-145 -306 c35 -16 50 -59 42 -124 l-6 -54 32
-5 c18 -3 44 -7 58 -8 19 -2 24 -8 22 -23 -2 -11 -5 -21 -6 -22 -5 -6 -272 30
-280 37 -5 5 -4 42 3 87 9 63 16 82 37 101 28 24 60 28 98 11z m2717 -590 c14
-7 18 -16 14 -27 -4 -9 -20 -52 -36 -95 l-29 -78 33 -13 c77 -32 72 -34 105
51 29 75 55 102 67 70 3 -7 -7 -48 -24 -90 l-29 -76 55 -21 c30 -11 58 -18 62
-15 5 2 23 45 41 95 31 87 41 99 68 82 10 -7 2 -36 -32 -126 -25 -65 -47 -120
-49 -123 -3 -2 -82 26 -177 62 -95 36 -175 65 -177 65 -9 0 1 33 39 137 24 62
44 113 46 113 2 0 12 -5 23 -11z m34 -411 c80 -57 145 -106 145 -109 0 -3 -6
-14 -14 -24 -13 -18 -17 -16 -79 28 -36 26 -69 47 -74 47 -10 0 -113 -145
-113 -158 0 -7 61 -53 122 -93 14 -9 -11 -52 -26 -46 -10 4 -288 198 -304 212
-6 5 18 45 26 45 5 0 36 -21 71 -46 34 -25 64 -44 65 -42 1 2 25 35 52 73 28
39 53 75 57 81 4 7 -18 29 -58 55 -35 24 -65 49 -65 55 0 16 23 35 38 29 7 -2
78 -51 157 -107z m-2350 -142 c35 -15 65 -59 65 -96 0 -54 -57 -110 -112 -110
-13 0 -37 9 -55 20 -69 41 -63 154 9 185 42 18 51 18 93 1z m2003 -75 c8 -5
12 -17 10 -27 -3 -14 -11 -18 -33 -17 -82 7 -145 -48 -145 -126 0 -89 73 -161
162 -161 43 0 54 4 84 34 27 27 34 42 34 74 0 32 4 41 22 45 29 8 38 1 38 -31
-1 -38 -32 -102 -66 -133 -75 -69 -196 -57 -276 28 -27 28 -58 99 -58 132 0
65 56 152 115 177 34 15 94 18 113 5z m-247 -340 c79 -74 145 -138 147 -142 2
-4 -7 -13 -19 -19 -19 -11 -26 -7 -65 31 l-43 42 -68 -31 -68 -32 -3 -64 c-2
-55 -6 -66 -23 -71 -11 -4 -23 -5 -25 -2 -3 2 -9 94 -14 203 -8 180 -7 200 8
212 9 7 19 11 23 10 4 -2 71 -63 150 -137z m-321 34 c58 -30 78 -120 40 -182
-19 -31 -48 -44 -151 -67 l-26 -6 14 -60 c15 -68 12 -80 -20 -80 -20 0 -24 12
-56 173 -19 94 -36 179 -38 188 -4 12 11 19 64 31 90 20 138 21 173 3z m-334
-207 c38 -105 71 -195 72 -200 2 -4 -10 -8 -26 -8 -28 0 -32 5 -49 58 l-20 57
-79 3 -79 3 -27 -54 c-24 -49 -29 -54 -53 -50 -14 3 -25 9 -23 13 2 3 41 88
87 188 112 243 106 244 197 -10z"/>
<path d="M2120 3537 c0 -14 -2 -32 -6 -40 -4 -11 6 -16 43 -20 54 -6 83 5 83
32 0 27 -24 43 -75 49 -43 4 -45 3 -45 -21z"/>
<path d="M2105 3399 c-4 -22 -5 -42 -2 -45 9 -10 77 -16 101 -10 52 13 44 70
-12 86 -68 19 -79 14 -87 -31z"/>
<path d="M1697 3533 c-13 -3 -17 -11 -14 -26 3 -12 11 -58 18 -102 7 -44 14
-81 15 -83 7 -10 96 13 113 29 39 36 21 165 -24 183 -18 7 -80 6 -108 -1z"/>
<path d="M1156 3310 l-47 -30 22 -33 c12 -17 24 -34 25 -36 6 -7 94 50 103 67
5 10 5 27 0 40 -12 31 -45 28 -103 -8z"/>
<path d="M1060 2137 c-20 -10 -25 -20 -25 -52 0 -37 4 -42 53 -75 79 -52 68
-97 -21 -88 -23 2 -32 -1 -32 -12 0 -11 14 -16 57 -18 48 -2 60 0 77 19 40 43
27 78 -46 125 -71 45 -70 68 5 72 35 2 52 7 52 16 0 26 -78 34 -120 13z"/>
<path d="M1230 2020 c0 -123 1 -130 20 -130 17 0 20 7 20 43 l1 42 20 -25 c12
-14 27 -33 34 -43 8 -11 22 -17 35 -15 21 3 20 4 -9 43 -38 50 -38 61 0 105
29 34 29 35 8 38 -12 2 -26 -4 -34 -15 -7 -10 -22 -29 -34 -43 l-20 -25 -1 78
c0 70 -2 77 -20 77 -19 0 -20 -7 -20 -130z"/>
<path d="M2030 1976 c0 -130 1 -136 20 -136 20 0 20 5 18 132 -3 117 -5 133
-20 136 -16 3 -18 -8 -18 -132z"/>
<path d="M2133 2103 c-10 -3 -13 -40 -13 -134 0 -121 1 -129 19 -129 16 0 20
8 23 43 l3 42 30 -42 c20 -28 38 -42 53 -43 12 0 22 3 22 6 0 3 -16 26 -35 51
l-35 46 35 43 c40 48 42 54 18 54 -10 0 -35 -19 -55 -42 l-37 -43 -1 78 c0 75
-2 81 -27 70z"/>
<path d="M2310 2090 c0 -13 7 -20 20 -20 13 0 20 7 20 20 0 13 -7 20 -20 20
-13 0 -20 -7 -20 -20z"/>
<path d="M1410 2073 c0 -5 7 -30 15 -58 9 -27 20 -67 26 -87 5 -22 16 -38 24
-38 8 0 15 -4 15 -8 0 -17 -25 -32 -52 -32 -18 0 -28 -5 -28 -15 0 -22 72 -20
92 3 9 9 28 60 42 112 15 52 29 103 32 113 5 15 1 18 -17 15 -17 -2 -25 -12
-32 -38 -23 -94 -29 -110 -36 -106 -5 3 -11 20 -15 38 -17 85 -27 108 -46 108
-11 0 -20 -3 -20 -7z"/>
<path d="M1766 2031 c-3 -4 -8 -35 -12 -67 -8 -75 -19 -96 -28 -58 -25 105
-26 105 -53 102 -23 -3 -29 -10 -41 -58 -15 -63 -32 -88 -32 -48 0 14 -3 40
-7 59 -5 28 -7 30 -14 14 -13 -35 -10 -112 6 -125 29 -24 49 -7 67 55 9 33 17
62 18 65 1 3 11 -24 23 -60 19 -57 25 -65 47 -65 22 0 27 7 37 50 7 28 16 71
19 98 5 39 4 47 -9 47 -9 0 -18 -4 -21 -9z"/>
<path d="M1853 2033 c-7 -2 -13 -12 -13 -20 0 -12 7 -14 31 -9 34 7 69 -8 69
-28 0 -8 -17 -16 -42 -20 -53 -9 -68 -21 -68 -57 0 -43 21 -57 90 -56 l60 0 0
68 c0 103 -19 130 -90 128 -14 0 -31 -3 -37 -6z m87 -128 c0 -18 -7 -26 -24
-31 -30 -7 -46 1 -46 25 0 24 9 31 42 31 23 0 28 -4 28 -25z"/>
<path d="M2317 2033 c-4 -3 -7 -48 -7 -100 0 -86 1 -93 20 -93 19 0 20 7 20
100 0 77 -3 100 -13 100 -8 0 -17 -3 -20 -7z"/>
<path d="M2400 1938 c0 -91 1 -98 20 -98 17 0 19 8 22 78 l3 77 35 0 35 0 3
-77 c3 -70 5 -78 22 -78 18 0 20 7 20 78 0 106 -9 117 -94 118 l-66 1 0 -99z"/>
<path d="M2642 2025 l-33 -14 4 -73 c2 -40 -1 -84 -7 -97 -9 -20 -6 -27 17
-47 51 -43 147 -23 147 30 0 31 -16 43 -78 57 -64 15 -67 29 -7 29 58 0 90 28
81 71 -3 15 -1 31 4 34 39 24 -74 32 -128 10z m74 -29 c27 -20 7 -51 -32 -51
-23 0 -30 5 -32 24 -6 38 29 52 64 27z m-8 -151 c14 -4 22 -13 20 -23 -4 -22
-60 -28 -77 -9 -15 19 -3 49 18 43 9 -2 26 -7 39 -11z"/>
<path d="M549 2531 c-50 -50 -35 -120 33 -151 52 -24 80 -25 117 -5 72 37 56
137 -26 171 -52 22 -91 18 -124 -15z"/>
<path d="M471 2222 c-10 -19 -18 -99 -11 -105 3 -2 24 -7 47 -10 l42 -5 7 54
c4 37 2 59 -6 69 -17 21 -67 19 -79 -3z"/>
<path d="M2571 750 c0 -25 4 -66 7 -91 l7 -46 57 27 57 27 -65 64 -64 63 1
-44z"/>
<path d="M2247 708 c-25 -7 -36 -15 -33 -23 2 -7 10 -41 17 -74 l12 -62 31 6
c84 17 103 26 114 50 17 37 15 59 -9 89 -23 29 -61 33 -132 14z"/>
<path d="M1927 590 l-36 -75 60 -9 c33 -5 62 -7 64 -4 4 4 -4 28 -47 148 -4 9
-19 -14 -41 -60z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.9 KiB

View File

@ -1,17 +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. -->
<svg t="1712402256302" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1578">
<path d="M640 885.589333a39.424 39.424 0 0 1-32.938667 46.634667A483.413333 483.413333 0 0 1 512 938.666667a295.68 295.68 0 0 1-92.117333-16.768 32.085333 32.085333 0 1 1 13.568-62.72 415.658667 415.658667 0 0 0 78.549333 15.36 295.722667 295.722667 0 0 0 75.434667-4.266667c20.181333-9.514667 47.317333-9.216 52.565333 15.36z m-397.824-307.968a160.597333 160.597333 0 0 1 156.842667 164.096 198.314667 198.314667 0 0 1-6.954667 48.426667 154.325333 154.325333 0 0 1-149.930667 115.712 164.266667 164.266667 0 0 1 0-328.192z m539.605333 0a164.266667 164.266667 0 1 1-156.842666 164.096 160.597333 160.597333 0 0 1 156.885333-164.096z m-30.122666-262.058666A344.917333 344.917333 0 0 1 853.333333 497.024c1.109333 16.768-1.749333 38.826667-30.08 41.258667a32.554667 32.554667 0 0 1-33.493333-26.325334 334.848 334.848 0 0 0-80.341333-146.304 34.517333 34.517333 0 0 1-4.992-54.613333 33.408 33.408 0 0 1 47.232 4.693333z m-417.706667-4.48c13.269333 16.64 4.821333 28.501333-8.789333 48.512A422.4 422.4 0 0 0 256 517.802667a33.152 33.152 0 0 1-36.821333 26.709333 31.573333 31.573333 0 0 1-27.52-32.512 89.6 89.6 0 0 1 3.797333-29.226667 402.773333 402.773333 0 0 1 93.312-177.536 30.592 30.592 0 0 1 45.184 5.845334zM512 85.333333a164.266667 164.266667 0 1 1-156.842667 164.096A160.597333 160.597333 0 0 1 512 85.333333z" p-id="1579"></path>
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

BIN
src/assets/img/technologies/ACTIVEMQ.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 471 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 471 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 B

View File

@ -451,7 +451,7 @@ limitations under the License. -->
} }
.calendar + .calendar { .calendar + .calendar {
border-left: solid 1px var(--sw-border-color-light); border-left: solid 1px #eaeaea;
margin-left: 5px; margin-left: 5px;
padding-left: 5px; padding-left: 5px;
} }
@ -464,7 +464,7 @@ limitations under the License. -->
} }
.calendar-head a { .calendar-head a {
color: var(--sw-topology-color); color: #666;
cursor: pointer; cursor: pointer;
display: inline-block; display: inline-block;
text-align: center; text-align: center;
@ -568,7 +568,7 @@ limitations under the License. -->
.calendar-hour { .calendar-hour {
display: inline-block; display: inline-block;
border: 1px solid var(--sw-border-color-light); border: 1px solid #e6e5e5;
color: #9e9e9e; color: #9e9e9e;
} }

View File

@ -13,13 +13,6 @@ 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>
<SelectorLegend
:data="option.legend.data"
:show="legendSelector.isSelector"
:isConfigPage="legendSelector.isConfigPage"
:colors="option.color"
@change="changeLegend"
/>
<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 <div
@ -60,8 +53,6 @@ limitations under the License. -->
import { addResizeListener, removeResizeListener } from "@/utils/event"; import { addResizeListener, removeResizeListener } from "@/utils/event";
import Trace from "@/views/dashboard/related/trace/Index.vue"; import Trace from "@/views/dashboard/related/trace/Index.vue";
import associateProcessor from "@/hooks/useAssociateProcessor"; import associateProcessor from "@/hooks/useAssociateProcessor";
import { WidgetType } from "@/views/dashboard/data";
import SelectorLegend from "./Legend.vue";
/*global Nullable, defineProps, defineEmits, Indexable*/ /*global Nullable, defineProps, defineEmits, Indexable*/
const emits = defineEmits(["select"]); const emits = defineEmits(["select"]);
@ -72,7 +63,7 @@ limitations under the License. -->
const currentParams = ref<Nullable<EventParams>>(null); const currentParams = ref<Nullable<EventParams>>(null);
const showTrace = ref<boolean>(false); const showTrace = ref<boolean>(false);
const traceOptions = ref<{ type: string; filters?: unknown }>({ const traceOptions = ref<{ type: string; filters?: unknown }>({
type: WidgetType.Trace, type: "Trace",
}); });
const menuPos = reactive<{ x: number; y: number }>({ x: NaN, y: NaN }); const menuPos = reactive<{ x: number; y: number }>({ x: NaN, y: NaN });
const props = defineProps({ const props = defineProps({
@ -92,10 +83,6 @@ limitations under the License. -->
type: Array as PropType<{ widgetId: string }[]>, type: Array as PropType<{ widgetId: string }[]>,
default: () => [], default: () => [],
}, },
legendSelector: {
type: Object as PropType<Indexable>,
default: () => ({ isConfigPage: false, isSelector: false }),
},
}); });
const available = computed( const available = computed(
() => () =>
@ -115,7 +102,6 @@ limitations under the License. -->
if (!instance) { if (!instance) {
return; return;
} }
instance.on("click", (params: EventParams) => { instance.on("click", (params: EventParams) => {
currentParams.value = params; currentParams.value = params;
if (props.option.series.type === "sankey") { if (props.option.series.type === "sankey") {
@ -216,23 +202,6 @@ limitations under the License. -->
}); });
} }
function changeLegend(names: string[]) {
const instance = getInstance();
for (const item of props.option.legend.data) {
if (names.includes(item.name)) {
instance.dispatchAction({
type: "legendSelect",
name: item.name,
});
} else {
instance.dispatchAction({
type: "legendUnSelect",
name: item.name,
});
}
}
}
watch( watch(
() => props.option, () => props.option,
(newVal, oldVal) => { (newVal, oldVal) => {
@ -265,10 +234,12 @@ limitations under the License. -->
.no-data { .no-data {
font-size: $font-size-smaller; font-size: $font-size-smaller;
height: 100%; height: 100%;
align-items: center; box-sizing: border-box;
justify-content: center; display: -webkit-box;
display: flex; -webkit-box-orient: horizontal;
color: var(--text-color-placeholder); -webkit-box-pack: center;
-webkit-box-align: center;
color: #666;
} }
.chart { .chart {

View File

@ -1,74 +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. -->
<template>
<Selector
class="mb-10"
multiple
:value="legend"
size="small"
:options="Options"
@change="changeLegend"
filterable
collapseTags
collapseTagsTooltip
v-if="show"
/>
</template>
<script lang="ts" setup>
import { computed, ref, watch } from "vue";
import type { PropType } from "vue";
import type { Option } from "@/types/app";
import Selector from "./Selector.vue";
const props = defineProps({
data: {
type: Array as PropType<{ name: string }[]>,
default: () => [],
},
colors: {
type: Array as PropType<string[]>,
default: () => [],
},
show: {
type: Boolean,
default: false,
},
isConfigPage: {
type: Boolean,
default: false,
},
});
const emits = defineEmits(["change"]);
const legend = ref<string[]>([]);
const Options = computed(() =>
props.data.map((d: { name: string }, index: number) => ({
label: d.name,
value: d.name,
color: props.colors[index % props.colors.length],
})),
);
function changeLegend(opt: Option[]) {
legend.value = opt.map((d: Option) => d.value);
emits("change", legend.value);
}
watch(
() => props.data,
() => {
legend.value = props.data.map((d) => d.name);
},
);
</script>

View File

@ -1,107 +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. -->
<template>
<el-select
:size="size"
v-model="selected"
:placeholder="placeholder"
@change="changeSelected"
:multiple="multiple"
:disabled="disabled"
:style="{ borderRadius }"
:clearable="clearable"
:remote="isRemote"
:reserve-keyword="isRemote"
:remote-method="remoteMethod"
:filterable="filterable"
:collapse-tags="collapseTags"
:collapse-tags-tooltip="collapseTagsTooltip"
>
<el-option
v-for="(item, index) in options"
:key="`${item.value}${index}`"
:label="item.label || ''"
:value="item.value || ''"
:disabled="item.disabled || false"
>
<div class="flex items-center">
<el-tag :color="item.color" class="mr-5" size="small" />
<span :style="{ color: item.color }">{{ item.label }}</span>
</div>
</el-option>
</el-select>
</template>
<script lang="ts" setup>
import { ref, watch } from "vue";
import type { PropType } from "vue";
/*global defineProps, defineEmits, Indexable*/
const emit = defineEmits(["change", "query"]);
const props = defineProps({
options: {
type: Array as PropType<
({
label: string | number;
value: string | number;
color: string;
} & { disabled?: boolean })[]
>,
default: () => [],
},
value: {
type: [Array, String, Number, undefined] as PropType<any>,
default: () => [],
},
size: { type: null, default: "default" },
placeholder: {
type: [String, undefined] as PropType<string>,
default: "Select a option",
},
borderRadius: { type: Number, default: 3 },
multiple: { type: Boolean, default: false },
disabled: { type: Boolean, default: false },
clearable: { type: Boolean, default: false },
isRemote: { type: Boolean, default: false },
filterable: { type: Boolean, default: true },
collapseTags: { type: Boolean, default: false },
collapseTagsTooltip: { type: Boolean, default: false },
});
const selected = ref<string[] | string>(props.value);
function changeSelected() {
const options = props.options.filter((d: Indexable) =>
props.multiple ? selected.value.includes(d.value) : selected.value === d.value,
);
emit("change", options);
}
function remoteMethod(query: string) {
if (props.isRemote) {
emit("query", query);
}
}
watch(
() => props.value,
(data) => {
selected.value = data;
},
);
</script>
<style lang="scss" scoped>
.el-input__inner {
border-radius: unset !important;
}
</style>

View File

@ -85,7 +85,7 @@ limitations under the License. -->
.bar-select { .bar-select {
position: relative; position: relative;
justify-content: space-between; justify-content: space-between;
border: 1px solid var(--el-border-color); border: 1px solid #ddd;
background: $theme-background; background: $theme-background;
border-radius: 3px; border-radius: 3px;
color: $font-color; color: $font-color;
@ -97,8 +97,8 @@ limitations under the License. -->
border-radius: 3px; border-radius: 3px;
margin: 3px; margin: 3px;
color: $active-color; color: $active-color;
background-color: var(--theme-background); background-color: #fafafa;
border: 1px solid var(--el-color-primary); border: 1px solid #e8e8e8;
text-align: center; text-align: center;
} }
} }
@ -139,7 +139,7 @@ limitations under the License. -->
left: 0; left: 0;
background-color: $theme-background; background-color: $theme-background;
box-shadow: 0 1px 6px rgb(99 99 99 / 20%); box-shadow: 0 1px 6px rgb(99 99 99 / 20%);
border: 1px solid var(--el-border-color); border: 1px solid #ddd;
width: 100%; width: 100%;
border-radius: 0 0 3px 3px; border-radius: 0 0 3px 3px;
border-right-width: 1px !important; border-right-width: 1px !important;
@ -169,7 +169,7 @@ limitations under the License. -->
} }
&:hover { &:hover {
background-color: var(--layout-background); background-color: #f5f5f5;
} }
} }
</style> </style>

View File

@ -26,12 +26,10 @@ limitations under the License. -->
:reserve-keyword="isRemote" :reserve-keyword="isRemote"
:remote-method="remoteMethod" :remote-method="remoteMethod"
:filterable="filterable" :filterable="filterable"
:collapse-tags="collapseTags"
:collapse-tags-tooltip="collapseTagsTooltip"
> >
<el-option <el-option
v-for="(item, index) in options" v-for="item in options"
:key="`${item.value}${index}`" :key="item.value || ''"
:label="item.label || ''" :label="item.label || ''"
:value="item.value || ''" :value="item.value || ''"
:disabled="item.disabled || false" :disabled="item.disabled || false"
@ -43,6 +41,11 @@ limitations under the License. -->
import { ref, watch } from "vue"; import { ref, watch } from "vue";
import type { PropType } from "vue"; import type { PropType } from "vue";
// interface Option {
// label: string | number;
// value: string | number;
// }
/*global defineProps, defineEmits, Indexable*/ /*global defineProps, defineEmits, Indexable*/
const emit = defineEmits(["change", "query"]); const emit = defineEmits(["change", "query"]);
const props = defineProps({ const props = defineProps({
@ -70,8 +73,6 @@ limitations under the License. -->
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 }, filterable: { type: Boolean, default: true },
collapseTags: { type: Boolean, default: false },
collapseTagsTooltip: { type: Boolean, default: false },
}); });
const selected = ref<string[] | string>(props.value); const selected = ref<string[] | string>(props.value);

View File

@ -31,7 +31,7 @@ limitations under the License. -->
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { nextTick, ref, watch } from "vue"; import { nextTick, ref } from "vue";
import type { PropType } from "vue"; import type { PropType } from "vue";
import { ElInput } from "element-plus"; import { ElInput } from "element-plus";
@ -69,17 +69,10 @@ limitations under the License. -->
inputValue.value = ""; inputValue.value = "";
emits("change", dynamicTags.value); emits("change", dynamicTags.value);
}; };
watch(
() => props.tags,
() => {
dynamicTags.value = props.tags || [];
},
);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.input-name { .input-name {
width: 250px; width: 300px;
} }
.vertical { .vertical {

View File

@ -447,7 +447,7 @@ limitations under the License. -->
width: 100px; width: 100px;
height: 100%; height: 100%;
padding: 5px; padding: 5px;
border-right: solid 1px var(--sw-border-color-light); border-right: solid 1px #eaeaea;
} }
&__shortcut { &__shortcut {
@ -457,7 +457,7 @@ limitations under the License. -->
background-color: transparent; background-color: transparent;
line-height: 34px; line-height: 34px;
font-size: $font-size-smaller; font-size: $font-size-smaller;
color: var(--sw-topology-color); color: #666;
text-align: left; text-align: left;
outline: none; outline: none;
cursor: pointer; cursor: pointer;
@ -532,6 +532,6 @@ limitations under the License. -->
} }
.datepicker__buttons .datepicker__button-cancel { .datepicker__buttons .datepicker__button-cancel {
background: var(--sw-topology-color); background: #666;
} }
</style> </style>

View File

@ -18,7 +18,7 @@ import type { App } from "vue";
import Icon from "./Icon.vue"; import Icon from "./Icon.vue";
import TimePicker from "./TimePicker.vue"; import TimePicker from "./TimePicker.vue";
import Selector from "./Selector.vue"; import Selector from "./Selector.vue";
import Graph from "./Graph/Graph.vue"; import Graph from "./Graph.vue";
import Radio from "./Radio.vue"; import Radio from "./Radio.vue";
import SelectSingle from "./SelectSingle.vue"; import SelectSingle from "./SelectSingle.vue";
import Tags from "./Tags.vue"; import Tags from "./Tags.vue";

View File

@ -1,75 +0,0 @@
/*
* Licensed to 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. Apache Software Foundation (ASF) licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
const Timeout = 2 * 60 * 1000;
export let globalAbortController = new AbortController();
export function abortRequestsAndUpdate() {
globalAbortController.abort(`Request timeout ${Timeout}ms`);
globalAbortController = new AbortController();
}
class HTTPError extends Error {
response;
constructor(response: Response, detailText = "") {
super(detailText || response.statusText);
this.name = "HTTPError";
this.response = response;
}
}
const BasePath = `/graphql`;
export async function httpQuery({
path = "",
method = "GET",
json,
headers = {},
}: {
path?: string;
method: string;
json: unknown;
headers: Recordable;
}) {
const timeoutId = setTimeout(() => {
abortRequestsAndUpdate();
}, Timeout);
const url = `${BasePath}${path}`;
const response: Response = await fetch(url, {
method,
headers: {
"Content-Type": "application/json",
accept: "application/json",
...headers,
},
body: JSON.stringify(json),
signal: globalAbortController.signal,
})
.catch((error) => {
throw new HTTPError(error);
})
.finally(() => {
clearTimeout(timeoutId);
});
if (response.ok) {
return response.json();
} else {
console.error(new HTTPError(response));
}
}

View File

@ -14,18 +14,20 @@
* 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 { httpQuery } from "./base"; import type { AxiosResponse } from "axios";
import axios from "axios";
import { cancelToken } from "@/utils/cancelToken";
async function fetchQuery(param: { queryStr: string; conditions: { [key: string]: unknown } }) { async function query(param: { queryStr: string; conditions: { [key: string]: unknown } }) {
const response = await httpQuery({ const res: AxiosResponse = await axios.post(
method: "post", "/graphql",
json: { query: param.queryStr, variables: { ...param.conditions } }, { query: param.queryStr, variables: { ...param.conditions } },
headers: {}, { cancelToken: cancelToken() },
}); );
if (response.errors) { if (res.data.errors) {
response.errors = response.errors.map((e: { message: string }) => e.message).join(" "); res.data.errors = res.data.errors.map((e: { message: string }) => e.message).join(" ");
} }
return response; return res;
} }
export default fetchQuery; export default query;

View File

@ -24,7 +24,6 @@ export const Alarm = {
message message
startTime startTime
scope scope
name
tags { tags {
key key
value value
@ -44,46 +43,6 @@ export const Alarm = {
startTime startTime
endTime endTime
} }
snapshot {
expression
metrics {
name
results {
metric {
labels {
key
value
}
}
values {
id
owner {
scope
serviceID
serviceName
normal
serviceInstanceID
serviceInstanceName
endpointID
endpointName
}
value
traceID
}
}
}
}
} }
}`, }`,
}; };
export const AlarmTagKeys = {
variable: "$duration: Duration!",
query: `
tagKeys: queryAlarmTagAutocompleteKeys(duration: $duration)`,
};
export const AlarmTagValues = {
variable: "$tagKey: String!, $duration: Duration!",
query: `
tagValues: queryAlarmTagAutocompleteValues(tagKey: $tagKey, duration: $duration)`,
};

View File

@ -1,80 +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.
*/
export const GetAsyncTaskList = {
variable: "$request: AsyncProfilerTaskListRequest!",
query: `
asyncTaskList: queryAsyncProfilerTaskList(request: $request) {
errorReason
tasks {
id
serviceId
serviceInstanceIds
createTime
events
duration
execArgs
}
}
`,
};
export const GetAsyncProfileTaskProcess = {
variable: "$taskId: String!",
query: `
taskProgress: queryAsyncProfilerTaskProgress(taskId: $taskId) {
logs {
id
instanceId
instanceName
operationType
operationTime
}
errorInstanceIds
successInstanceIds
}
`,
};
export const CreateAsyncProfileTask = {
variable: "$asyncProfilerTaskCreationRequest: AsyncProfilerTaskCreationRequest!",
query: `
task: createAsyncProfilerTask(asyncProfilerTaskCreationRequest: $asyncProfilerTaskCreationRequest) {
id
errorReason
code
}
`,
};
export const GetAsyncProfileAnalyze = {
variable: "$request: AsyncProfilerAnalyzationRequest!",
query: `
analysisResult: queryAsyncProfilerAnalyze(request: $request) {
tree {
type
elements {
id
parentId
symbol: codeSignature
dumpCount: total
self
}
}
}
`,
};

View File

@ -14,6 +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.
*/ */
export const TypeOfMetrics = {
variable: "$name: String!",
query: `typeOfMetrics(name: $name)`,
};
export const listMetrics = {
variable: "$regex: String",
query: `
metrics: listMetrics(regex: $regex) {
value: name
label: name
type
catalog
}
`,
};
export const getAllTemplates = { export const getAllTemplates = {
query: ` query: `

View File

@ -73,9 +73,9 @@ export const Processes = {
}; };
export const Endpoints = { export const Endpoints = {
variable: "$serviceId: ID!, $keyword: String!, $duration: Duration, $limit: Int!", variable: "$serviceId: ID!, $keyword: String!",
query: ` query: `
pods: findEndpoint(serviceId: $serviceId, keyword: $keyword, limit: $limit, duration: $duration) { pods: findEndpoint(serviceId: $serviceId, keyword: $keyword, limit: 20) {
id id
value: name value: name
label: name label: name

View File

@ -23,7 +23,6 @@ export const ServicesTopology = {
name name
type type
isReal isReal
layers
} }
calls { calls {
id id
@ -100,56 +99,3 @@ export const ProcessTopology = {
} }
`, `,
}; };
export const HierarchyServiceTopology = {
variable: "$serviceId: ID!, $layer: String!",
query: `
hierarchyServiceTopology: getServiceHierarchy(serviceId: $serviceId, layer: $layer) {
relations {
upperService {
id
name
layer
normal
}
lowerService {
id
name
layer
normal
}
}
}`,
};
export const HierarchyInstanceTopology = {
variable: "$instanceId: ID!, $layer: String!",
query: `
hierarchyInstanceTopology: getInstanceHierarchy(instanceId: $instanceId, layer: $layer) {
relations {
upperInstance {
id
name
layer
normal
serviceName
serviceId
}
lowerInstance {
id
name
layer
normal
serviceName
serviceId
}
}
}`,
};
export const ListLayerLevels = {
query: `
levels: listLayerLevels {
layer
level
}
`,
};

View File

@ -14,7 +14,9 @@
* 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 { httpQuery } from "./base"; import type { AxiosPromise, AxiosResponse } from "axios";
import axios from "axios";
import { cancelToken } from "@/utils/cancelToken";
import * as app from "./query/app"; import * as app from "./query/app";
import * as selector from "./query/selector"; import * as selector from "./query/selector";
import * as dashboard from "./query/dashboard"; import * as dashboard from "./query/dashboard";
@ -26,7 +28,6 @@ import * as alarm from "./query/alarm";
import * as event from "./query/event"; import * as event from "./query/event";
import * as ebpf from "./query/ebpf"; import * as ebpf from "./query/ebpf";
import * as demandLog from "./query/demand-log"; import * as demandLog from "./query/demand-log";
import * as asyncProfile from "./query/async-profile";
const query: { [key: string]: string } = { const query: { [key: string]: string } = {
...app, ...app,
@ -40,27 +41,32 @@ const query: { [key: string]: string } = {
...event, ...event,
...ebpf, ...ebpf,
...demandLog, ...demandLog,
...asyncProfile,
}; };
class Graphql { class Graphql {
queryData = ""; private queryData = "";
query(data: string) { public query(queryData: string) {
this.queryData = data; this.queryData = queryData;
return this; return this;
} }
async params(variables: unknown) { public params(variablesData: unknown): AxiosPromise<void> {
const response = await httpQuery({ return axios
method: "post", .post(
headers: {}, "/graphql",
json: { {
query: query[this.queryData], query: query[this.queryData],
variables, variables: variablesData,
}, },
}); { cancelToken: cancelToken() },
if (response.errors) { )
response.errors = response.errors.map((e: { message: string }) => e.message).join(" "); .then((res: AxiosResponse) => {
if (res.data.errors) {
res.data.errors = res.data.errors.map((e: { message: string }) => e.message).join(" ");
} }
return response; return res;
})
.catch((err: Error) => {
throw err;
});
} }
} }

View File

@ -15,8 +15,6 @@
* limitations under the License. * limitations under the License.
*/ */
import { Alarm, AlarmTagKeys, AlarmTagValues } from "../fragments/alarm"; import { Alarm } from "../fragments/alarm";
export const queryAlarms = `query queryAlarms(${Alarm.variable}) {${Alarm.query}}`; export const queryAlarms = `query queryAlarms(${Alarm.variable}) {${Alarm.query}}`;
export const queryAlarmTagValues = `query queryTagValues(${AlarmTagValues.variable}) {${AlarmTagValues.query}}`;
export const queryAlarmTagKeys = `query queryTagKeys(${AlarmTagKeys.variable}) {${AlarmTagKeys.query}}`;

View File

@ -1,31 +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 {
GetAsyncTaskList,
GetAsyncProfileTaskProcess,
CreateAsyncProfileTask,
GetAsyncProfileAnalyze,
} from "../fragments/async-profile";
export const getAsyncTaskList = `query getAsyncTaskList(${GetAsyncTaskList.variable}) {${GetAsyncTaskList.query}}`;
export const getAsyncProfileTaskProcess = `query getAsyncProfileTaskProcess(${GetAsyncProfileTaskProcess.variable}) {${GetAsyncProfileTaskProcess.query}}`;
export const saveAsyncProfileTask = `mutation createAsyncProfileTask(${CreateAsyncProfileTask.variable}) {${CreateAsyncProfileTask.query}}`;
export const getAsyncProfileAnalyze = `query getAsyncProfileAnalyze(${GetAsyncProfileAnalyze.variable}) {${GetAsyncProfileAnalyze.query}}`;

View File

@ -14,7 +14,18 @@
* 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 { getAllTemplates, addTemplate, changeTemplate, deleteTemplate } from "../fragments/dashboard"; import {
TypeOfMetrics,
listMetrics,
getAllTemplates,
addTemplate,
changeTemplate,
deleteTemplate,
} from "../fragments/dashboard";
export const queryTypeOfMetrics = `query typeOfMetrics(${TypeOfMetrics.variable}) {${TypeOfMetrics.query}}`;
export const queryMetrics = `query queryData(${listMetrics.variable}) {${listMetrics.query}}`;
export const addNewTemplate = `mutation template(${addTemplate.variable}) {${addTemplate.query}}`; export const addNewTemplate = `mutation template(${addTemplate.variable}) {${addTemplate.query}}`;

View File

@ -14,20 +14,9 @@
* 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 { import { InstanceTopology, EndpointTopology, ServicesTopology, ProcessTopology } from "../fragments/topology";
InstanceTopology,
EndpointTopology,
ServicesTopology,
ProcessTopology,
HierarchyServiceTopology,
HierarchyInstanceTopology,
ListLayerLevels,
} 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}}`; export const getProcessTopology = `query queryData(${ProcessTopology.variable}) {${ProcessTopology.query}}`;
export const getHierarchyInstanceTopology = `query queryData(${HierarchyInstanceTopology.variable}) {${HierarchyInstanceTopology.query}}`;
export const getHierarchyServiceTopology = `query queryData(${HierarchyServiceTopology.variable}) {${HierarchyServiceTopology.query}}`;
export const queryListLayerLevels = `query queryLayerLevels {${ListLayerLevels.query}}`;

View File

@ -14,8 +14,32 @@
* 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 const MaximumEntities = 20; export enum MetricQueryTypes {
ReadMetricsValue = "readMetricsValue",
ReadMetricsValues = "readMetricsValues",
SortMetrics = "sortMetrics",
ReadLabeledMetricsValues = "readLabeledMetricsValues",
READHEATMAP = "readHeatMap",
ReadSampledRecords = "readSampledRecords",
ReadRecords = "readRecords",
ReadNullableMetricsValue = "readNullableMetricsValue",
}
export enum Calculations {
Percentage = "percentage",
ByteToKB = "byteToKB",
ByteToMB = "byteToMB",
ByteToGB = "byteToGB",
Apdex = "apdex",
ConvertSeconds = "convertSeconds",
ConvertMilliseconds = "convertMilliseconds",
MsToS = "msTos",
Average = "average",
PercentageAvg = "percentageAvg",
ApdexAvg = "apdexAvg",
SecondToDay = "secondToDay",
NanosecondToMillisecond = "nanosecondToMillisecond",
}
export enum sizeEnum { export enum sizeEnum {
XS = "XS", XS = "XS",
SM = "SM", SM = "SM",
@ -44,6 +68,50 @@ screenMap.set(sizeEnum.XL, screenEnum.XL);
screenMap.set(sizeEnum.XXL, screenEnum.XXL); screenMap.set(sizeEnum.XXL, screenEnum.XXL);
export const RespFields: Indexable = { export const RespFields: Indexable = {
readMetricsValues: `{
label
values {
values {value isEmptyValue}
}
}`,
readMetricsValue: ``,
readNullableMetricsValue: `{
value
isEmptyValue
}`,
sortMetrics: `{
name
id
value
refId
}`,
readLabeledMetricsValues: `{
label
values {
values {value isEmptyValue}
}
}`,
readHeatMap: `{
values {
id
values
}
buckets {
min
max
}
}`,
readSampledRecords: `{
name
value
refId
}`,
readRecords: `{
id
name
value
refId
}`,
execExpression: `{ execExpression: `{
type type
results { results {
@ -57,16 +125,6 @@ export const RespFields: Indexable = {
name: id name: id
value value
refId: traceID refId: traceID
owner {
scope
serviceID
serviceName
normal
serviceInstanceID
serviceInstanceName
endpointID
endpointName
}
} }
} }
error error
@ -112,5 +170,3 @@ export const LightChartColors = [
"#546570", "#546570",
"#c4ccd3", "#c4ccd3",
]; ];
export const MaxQueryLength = 120;

View File

@ -47,11 +47,11 @@ export function createBreakpointListen(fn?: (opt: CreateCallbackParams) => void)
function getWindowWidth() { function getWindowWidth() {
const width = document.body.clientWidth; const width = document.body.clientWidth;
const xs = screenMap.get(sizeEnum.XS) || 0; const xs = screenMap.get(sizeEnum.XS) || "";
const sm = screenMap.get(sizeEnum.SM) || 0; const sm = screenMap.get(sizeEnum.SM) || "";
const md = screenMap.get(sizeEnum.MD) || 0; const md = screenMap.get(sizeEnum.MD) || "";
const lg = screenMap.get(sizeEnum.LG) || 0; const lg = screenMap.get(sizeEnum.LG) || "";
const xl = screenMap.get(sizeEnum.XL) || 0; const xl = screenMap.get(sizeEnum.XL) || "";
if (width < xs) { if (width < xs) {
screenRef.value = sizeEnum.XS; screenRef.value = sizeEnum.XS;
} else if (width < sm) { } else if (width < sm) {

View File

@ -17,25 +17,15 @@
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import type { LayoutConfig } from "@/types/dashboard"; import type { LayoutConfig } from "@/types/dashboard";
import { ConfigFieldTypes } from "@/views/dashboard/data";
export default function getDashboard(param?: { name?: string; layer: string; entity: string }, t?: string) { export default function getDashboard(param?: { name: string; layer: string; entity: string }) {
const type = t || ConfigFieldTypes.NAME; // "NAME" or "ISDEFAULT"
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const opt = param || dashboardStore.currentDashboard; const opt = param || dashboardStore.currentDashboard;
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]"); const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
let dashboard: Recordable; const dashboard = list.find(
if (type === ConfigFieldTypes.NAME) {
dashboard = list.find(
(d: { name: string; layer: string; entity: string }) => (d: { name: string; layer: string; entity: string }) =>
d.name === opt.name && d.entity === opt.entity && d.layer === opt.layer, d.name === opt.name && d.entity === opt.entity && d.layer === opt.layer,
); );
} else {
dashboard = list.find(
(d: { name: string; layer: string; entity: string; isDefault: boolean }) =>
d.isDefault && d.entity === opt.entity && d.layer === opt.layer,
);
}
const all = dashboardStore.layout; const all = dashboardStore.layout;
const widgets: LayoutConfig[] = []; const widgets: LayoutConfig[] = [];
for (const item of all) { for (const item of all) {
@ -62,9 +52,6 @@ export default function getDashboard(param?: { name?: string; layer: string; ent
filters, filters,
}; };
dashboardStore.setWidget(item); dashboardStore.setWidget(item);
if (widget.id === sourceId) {
return;
}
const targetTabIndex = (widget.id || "").split("-"); const targetTabIndex = (widget.id || "").split("-");
const sourceTabindex = (sourceId || "").split("-") || []; const sourceTabindex = (sourceId || "").split("-") || [];
let container: Nullable<Element>; let container: Nullable<Element>;

View File

@ -14,10 +14,9 @@
* 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 { RespFields, MaximumEntities, MaxQueryLength } from "./data"; import { RespFields } from "./data";
import { EntityType, ExpressionResultType } from "@/views/dashboard/data"; import { EntityType, ExpressionResultType } from "@/views/dashboard/data";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useTopologyStore } from "@/store/modules/topology";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { useSelectorStore } from "@/store/modules/selectors"; import { useSelectorStore } from "@/store/modules/selectors";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
@ -25,35 +24,31 @@ import type { MetricConfigOpt } from "@/types/dashboard";
import type { Instance, Endpoint, Service } from "@/types/selector"; import type { Instance, Endpoint, Service } from "@/types/selector";
import type { Node, Call } from "@/types/topology"; import type { Node, Call } from "@/types/topology";
function chunkArray(array: any[], chunkSize: number) { export async function useExpressionsQueryProcessor(config: Indexable) {
const result = []; function expressionsGraphqlPods() {
for (let i = 0; i < array.length; i += chunkSize) {
result.push(array.slice(i, i + chunkSize));
}
return result;
}
export async function useDashboardQueryProcessor(configList: Indexable[]) {
function expressionsGraphql(config: Indexable, idx: number) {
if (!(config.metrics && config.metrics[0])) { if (!(config.metrics && config.metrics[0])) {
return; return;
} }
const appStore = useAppStoreWithOut();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const selectorStore = useSelectorStore(); const selectorStore = useSelectorStore();
if (!selectorStore.currentService && dashboardStore.entity !== "All") { if (!selectorStore.currentService && dashboardStore.entity !== "All") {
return; return;
} }
const conditions: Recordable = {}; const conditions: Recordable = {
const variables: string[] = []; duration: appStore.durationTime,
};
const variables: string[] = [`$duration: Duration!`];
const isRelation = ["ServiceRelation", "ServiceInstanceRelation", "EndpointRelation", "ProcessRelation"].includes( const isRelation = ["ServiceRelation", "ServiceInstanceRelation", "EndpointRelation", "ProcessRelation"].includes(
dashboardStore.entity, dashboardStore.entity,
); );
if (isRelation && !selectorStore.currentDestService) { if (isRelation && !selectorStore.currentDestService) {
return; return;
} }
if (idx === 0) { const fragment = config.metrics.map((name: string, index: number) => {
variables.push(`$entity: Entity!`); variables.push(`$expression${index}: String!`, `$entity${index}: Entity!`);
conditions[`expression${index}`] = name;
const entity = { const entity = {
serviceName: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.value, serviceName: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.value,
normal: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.normal, normal: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.normal,
@ -81,21 +76,19 @@ export async function useDashboardQueryProcessor(configList: Indexable[]) {
? selectorStore.currentDestProcess && selectorStore.currentDestProcess.value ? selectorStore.currentDestProcess && selectorStore.currentDestProcess.value
: undefined, : undefined,
}; };
conditions[`entity`] = entity; conditions[`entity${index}`] = entity;
}
const fragment = config.metrics.map((name: string, index: number) => {
variables.push(`$expression${idx}${index}: String!`);
conditions[`expression${idx}${index}`] = name;
return `expression${idx}${index}: execExpression(expression: $expression${idx}${index}, entity: $entity, duration: $duration)${RespFields.execExpression}`; return `expression${index}: execExpression(expression: $expression${index}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}`;
}); });
const queryStr = `query queryData(${variables}) {${fragment}}`;
return { return {
variables, queryStr,
fragment,
conditions, conditions,
}; };
} }
function expressionsSource(config: Indexable, resp: { errors: string; data: Indexable | any }) {
function expressionsSource(resp: { errors: string; data: Indexable }) {
if (resp.errors) { if (resp.errors) {
ElMessage.error(resp.errors); ElMessage.error(resp.errors);
return { source: {}, tips: [], typesOfMQE: [] }; return { source: {}, tips: [], typesOfMQE: [] };
@ -104,17 +97,13 @@ export async function useDashboardQueryProcessor(configList: Indexable[]) {
ElMessage.error("The query is wrong"); ElMessage.error("The query is wrong");
return { source: {}, tips: [], typesOfMQE: [] }; return { source: {}, tips: [], typesOfMQE: [] };
} }
if (resp.data.error) {
ElMessage.error(resp.data.error);
return { source: {}, tips: [], typesOfMQE: [] };
}
const tips: string[] = []; const tips: string[] = [];
const source: Indexable<unknown> = {}; const source: { [key: string]: unknown } = {};
const keys = Object.keys(resp.data); const keys = Object.keys(resp.data);
const typesOfMQE: string[] = []; const typesOfMQE: string[] = [];
for (let i = 0; i < config.metrics.length; i++) { for (let i = 0; i < config.metrics.length; i++) {
const metricConfig: MetricConfigOpt = (config.metricConfig && config.metricConfig[i]) || {}; const c: MetricConfigOpt = (config.metricConfig && config.metricConfig[i]) || {};
const obj = resp.data[keys[i]] || {}; const obj = resp.data[keys[i]] || {};
const results = obj.results || []; const results = obj.results || [];
const name = config.metrics[i]; const name = config.metrics[i];
@ -123,19 +112,27 @@ export async function useDashboardQueryProcessor(configList: Indexable[]) {
tips.push(obj.error); tips.push(obj.error);
typesOfMQE.push(type); typesOfMQE.push(type);
if (!obj.error) { if (!obj.error) {
if ([ExpressionResultType.SINGLE_VALUE, ExpressionResultType.TIME_SERIES_VALUES].includes(type)) { if (type === ExpressionResultType.TIME_SERIES_VALUES) {
for (const item of results) {
let label =
item.metric &&
item.metric.labels.map((d: { key: string; value: string }) => `${d.key}=${d.value}`).join(",");
const values = item.values.map((d: { value: unknown }) => d.value) || [];
if (results.length === 1) { if (results.length === 1) {
// If the metrics label does not exist, use the configuration label or expression const label = results[0].metric && results[0].metric.labels[0] && results[0].metric.labels[0].value;
label = label ? `${metricConfig.label || name}, ${label}` : metricConfig.label || name; source[c.label || label || name] = results[0].values.map((d: { value: unknown }) => d.value) || [];
} else {
const labels = (c.label || "").split(",").map((item: string) => item.replace(/^\s*|\s*$/g, ""));
for (const item of results) {
const values = item.values.map((d: { value: unknown }) => d.value) || [];
const index = item.metric.labels[0].value;
const indexNum = labels.findIndex((_, i: number) => i === Number(index));
if (labels[indexNum] && indexNum > -1) {
source[labels[indexNum]] = values;
} else {
source[index] = values;
} }
source[label] = values;
} }
} }
}
if (type === ExpressionResultType.SINGLE_VALUE) {
source[c.label || name] = (results[0].values[0] || {}).value;
}
if (([ExpressionResultType.RECORD_LIST, ExpressionResultType.SORTED_LIST] as string[]).includes(type)) { if (([ExpressionResultType.RECORD_LIST, ExpressionResultType.SORTED_LIST] as string[]).includes(type)) {
source[name] = results[0].values; source[name] = results[0].values;
} }
@ -144,69 +141,24 @@ export async function useDashboardQueryProcessor(configList: Indexable[]) {
return { source, tips, typesOfMQE }; return { source, tips, typesOfMQE };
} }
async function fetchMetrics(configArr: any) { const params = await expressionsGraphqlPods();
const appStore = useAppStoreWithOut(); if (!params) {
const variables: string[] = [`$duration: Duration!`]; return { source: {}, tips: [], typesOfMQE: [] };
let fragments = "";
let conditions: Recordable<unknown> = {
duration: appStore.durationTime,
};
for (let i = 0; i < configArr.length; i++) {
const params = await expressionsGraphql(configArr[i], i);
if (params) {
fragments += params?.fragment;
conditions = { ...conditions, ...params.conditions };
variables.push(...params.variables);
} }
}
if (!fragments) {
return { 0: { source: {}, tips: [], typesOfMQE: [] } };
}
const queryStr = `query queryData(${variables}) {${fragments}}`;
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const json = await dashboardStore.fetchMetricValue({ const json = await dashboardStore.fetchMetricValue(params);
queryStr,
conditions,
});
if (json.errors) { if (json.errors) {
ElMessage.error(json.errors); ElMessage.error(json.errors);
return { 0: { source: {}, tips: [], typesOfMQE: [] } }; return { source: {}, tips: [], typesOfMQE: [] };
} }
try { const data = expressionsSource(json);
const pageData: Recordable = {};
for (let i = 0; i < configArr.length; i++) { return data;
const resp: any = {};
for (let m = 0; m < configArr[i].metrics.length; m++) {
resp[`expression${i}${m}`] = json.data[`expression${i}${m}`];
}
const data = expressionsSource(configArr[i], { ...json, data: resp });
const id = configArr[i].id;
pageData[id] = data;
}
return pageData;
} catch (error) {
console.error(error);
return { 0: { source: {}, tips: [], typesOfMQE: [] } };
}
}
const partArr = chunkArray(configList, 6);
const promiseArr = partArr.map((d: Array<Indexable>) => fetchMetrics(d));
const responseList = await Promise.all(promiseArr);
let resp = {};
for (const item of responseList) {
resp = {
...resp,
...item,
};
}
return resp;
} }
export async function useExpressionsQueryPodsMetrics( export async function useExpressionsQueryPodsMetrics(
allPods: Array<(Instance | Endpoint | Service) & Indexable>, pods: Array<(Instance | Endpoint | Service) & Indexable>,
config: { config: {
expressions: string[]; expressions: string[];
subExpressions: string[]; subExpressions: string[];
@ -214,7 +166,7 @@ export async function useExpressionsQueryPodsMetrics(
}, },
scope: string, scope: string,
) { ) {
function expressionsGraphqlPods(pods: Array<(Instance | Endpoint | Service) & Indexable>) { function expressionsGraphqlPods() {
const metrics: string[] = []; const metrics: string[] = [];
const subMetrics: string[] = []; const subMetrics: string[] = [];
config.expressions = config.expressions || []; config.expressions = config.expressions || [];
@ -246,22 +198,18 @@ export async function useExpressionsQueryPodsMetrics(
variables.push(`$entity${index}: Entity!`); variables.push(`$entity${index}: Entity!`);
conditions[`entity${index}`] = entity; conditions[`entity${index}`] = entity;
const f = metrics.map((name: string, idx: number) => { const f = metrics.map((name: string, idx: number) => {
if (index === 0) { variables.push(`$expression${index}${idx}: String!`);
variables.push(`$expression${idx}: String!`); conditions[`expression${index}${idx}`] = name;
conditions[`expression${idx}`] = name;
}
let str = ""; let str = "";
if (config.subExpressions[idx]) { if (config.subExpressions[idx]) {
if (index === 0) { variables.push(`$subExpression${index}${idx}: String!`);
variables.push(`$subExpression${idx}: String!`); conditions[`subExpression${index}${idx}`] = config.subExpressions[idx];
conditions[`subExpression${idx}`] = config.subExpressions[idx]; str = `subexpression${index}${idx}: execExpression(expression: $subExpression${index}${idx}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}`;
}
str = `subexpression${index}${idx}: execExpression(expression: $subExpression${idx}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}`;
} }
return ( return (
str + str +
`expression${index}${idx}: execExpression(expression: $expression${idx}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}` `expression${index}${idx}: execExpression(expression: $expression${index}${idx}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}`
); );
}); });
return f; return f;
@ -272,10 +220,7 @@ export async function useExpressionsQueryPodsMetrics(
return { queryStr, conditions }; return { queryStr, conditions };
} }
function expressionsPodsSource( function expressionsPodsSource(resp: { errors: string; data: Indexable }): Indexable {
resp: { errors: string; data: Indexable },
pods: Array<(Instance | Endpoint | Service) & Indexable>,
): Indexable {
if (resp.errors) { if (resp.errors) {
ElMessage.error(resp.errors); ElMessage.error(resp.errors);
return {}; return {};
@ -356,47 +301,24 @@ export async function useExpressionsQueryPodsMetrics(
return { data, names, subNames, metricConfigArr, metricTypesArr, expressionsTips, subExpressionsTips }; return { data, names, subNames, metricConfigArr, metricTypesArr, expressionsTips, subExpressionsTips };
} }
async function fetchPodsExpressionValues(pods: Array<(Instance | Endpoint | Service) & Indexable>) {
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
const params = await expressionsGraphqlPods(pods); const params = await expressionsGraphqlPods();
const json = await dashboardStore.fetchMetricValue(params); const json = await dashboardStore.fetchMetricValue(params);
if (json.errors) { if (json.errors) {
ElMessage.error(json.errors); ElMessage.error(json.errors);
return {}; return {};
} }
const expressionParams = expressionsPodsSource(json, pods); const expressionParams = expressionsPodsSource(json);
return expressionParams; return expressionParams;
}
const result = [];
for (let i = 0; i < allPods.length; i += MaximumEntities) {
result.push(allPods.slice(i, i + MaximumEntities));
}
const promiseArr = result.map((d: Array<(Instance | Endpoint | Service) & Indexable>) =>
fetchPodsExpressionValues(d),
);
const responseList = await Promise.all(promiseArr);
let resp: Indexable = { data: [], expressionsTips: [], subExpressionsTips: [] };
for (const item of responseList) {
resp = {
...item,
data: [...resp.data, ...item.data],
expressionsTips: [...resp.expressionsTips, ...item.expressionsTips],
subExpressionsTips: [...resp.subExpressionsTips, ...item.subExpressionsTips],
};
}
return resp;
} }
export function useQueryTopologyExpressionsProcessor(metrics: string[], instances: (Call | Node)[]) { export function useQueryTopologyExpressionsProcessor(metrics: string[], instances: (Call | Node)[]) {
const appStore = useAppStoreWithOut(); const appStore = useAppStoreWithOut();
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
function getExpressionQuery(partMetrics?: string[]) { function getExpressionQuery() {
const conditions: { [key: string]: unknown } = { const conditions: { [key: string]: unknown } = {
duration: appStore.durationTime, duration: appStore.durationTime,
}; };
@ -408,14 +330,10 @@ export function useQueryTopologyExpressionsProcessor(metrics: string[], instance
let serviceInstanceName; let serviceInstanceName;
let destServiceInstanceName; let destServiceInstanceName;
let destEndpointName; let destEndpointName;
let normal = false;
let destNormal;
if (d.sourceObj && d.targetObj) { if (d.sourceObj && d.targetObj) {
// instances = Calls // instances = Calls
serviceName = d.sourceObj.serviceName || d.sourceObj.name; serviceName = d.sourceObj.serviceName || d.sourceObj.name;
destServiceName = d.targetObj.serviceName || d.targetObj.name; destServiceName = d.targetObj.serviceName || d.targetObj.name;
normal = d.sourceObj.normal || d.sourceObj.isReal || false;
destNormal = d.targetObj.normal || d.targetObj.isReal || false;
if (EntityType[4].value === dashboardStore.entity) { if (EntityType[4].value === dashboardStore.entity) {
serviceInstanceName = d.sourceObj.name; serviceInstanceName = d.sourceObj.name;
destServiceInstanceName = d.targetObj.name; destServiceInstanceName = d.targetObj.name;
@ -427,10 +345,6 @@ export function useQueryTopologyExpressionsProcessor(metrics: string[], instance
} else { } else {
// instances = Nodes // instances = Nodes
serviceName = d.serviceName || d.name; serviceName = d.serviceName || d.name;
normal = d.normal || d.isReal || false;
if (EntityType[3].value === dashboardStore.entity) {
serviceInstanceName = d.name;
}
if (EntityType[4].value === dashboardStore.entity) { if (EntityType[4].value === dashboardStore.entity) {
serviceInstanceName = d.name; serviceInstanceName = d.name;
} }
@ -440,17 +354,17 @@ export function useQueryTopologyExpressionsProcessor(metrics: string[], instance
} }
const entity = { const entity = {
serviceName, serviceName,
normal, normal: true,
serviceInstanceName, serviceInstanceName,
endpointName, endpointName,
destServiceName, destServiceName,
destNormal: destServiceName ? destNormal : undefined, destNormal: destServiceName ? true : undefined,
destServiceInstanceName, destServiceInstanceName,
destEndpointName, destEndpointName,
}; };
variables.push(`$entity${index}: Entity!`); variables.push(`$entity${index}: Entity!`);
conditions[`entity${index}`] = entity; conditions[`entity${index}`] = entity;
const f = (partMetrics || metrics).map((name: string, idx: number) => { const f = metrics.map((name: string, idx: number) => {
if (index === 0) { if (index === 0) {
variables.push(`$expression${idx}: String!`); variables.push(`$expression${idx}: String!`);
conditions[`expression${idx}`] = name; conditions[`expression${idx}`] = name;
@ -464,19 +378,19 @@ export function useQueryTopologyExpressionsProcessor(metrics: string[], instance
return { queryStr, conditions }; return { queryStr, conditions };
} }
function handleExpressionValues(partMetrics: string[], resp: { [key: string]: any }) { function handleExpressionValues(resp: { [key: string]: any }) {
const obj: Indexable = {}; const obj: any = {};
for (let idx = 0; idx < instances.length; idx++) { for (let idx = 0; idx < instances.length; idx++) {
for (let index = 0; index < partMetrics.length; index++) { for (let index = 0; index < metrics.length; index++) {
const k = "expression" + idx + index; const k = "expression" + idx + index;
if (partMetrics[index]) { if (metrics[index]) {
if (!obj[partMetrics[index]]) { if (!obj[metrics[index]]) {
obj[partMetrics[index]] = { obj[metrics[index]] = {
values: [], values: [],
}; };
} }
obj[partMetrics[index]].values.push({ obj[metrics[index]].values.push({
value: resp[k] && resp[k].results[0] && resp[k].results[0].values[0].value, value: resp[k].results[0] && resp[k].results[0].values[0].value,
id: instances[idx].id, id: instances[idx].id,
}); });
} }
@ -484,31 +398,6 @@ export function useQueryTopologyExpressionsProcessor(metrics: string[], instance
} }
return obj; return obj;
} }
async function fetchMetrics(partMetrics: string[]) {
const topologyStore = useTopologyStore();
const param = getExpressionQuery(partMetrics);
const res = await topologyStore.getTopologyExpressionValue(param);
if (res.errors) {
ElMessage.error(res.errors);
return;
}
return handleExpressionValues(partMetrics, res.data);
}
async function getMetrics() { return { getExpressionQuery, handleExpressionValues };
const count = Math.floor(MaxQueryLength / instances.length);
const metricsArr = chunkArray(metrics, count);
const promiseArr = metricsArr.map((d: string[]) => fetchMetrics(d));
const responseList = await Promise.all(promiseArr);
let resp = {};
for (const item of responseList) {
resp = {
...resp,
...item,
};
}
return resp;
}
return { getMetrics, getExpressionQuery };
} }

View File

@ -35,7 +35,7 @@ export default function useLegendProcess(legend?: LegendOptions) {
if (keys.length === 1) { if (keys.length === 1) {
return false; return false;
} }
if (legend && (legend.asTable || legend.asSelector)) { if (legend && legend.asTable) {
return false; return false;
} }
return true; return true;

View File

@ -0,0 +1,41 @@
/**
* 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 { MetricQueryTypes, Calculations } from "./data";
import { MetricModes } from "@/views/dashboard/data";
export function useListConfig(config: Indexable, index: number) {
if (config.metricModes === MetricModes.Expression) {
return {
isLinear: false,
isAvg: true,
};
}
const i = Number(index);
const types = [Calculations.Average, Calculations.ApdexAvg, Calculations.PercentageAvg];
const calculation = config.metricConfig && config.metricConfig[i] && config.metricConfig[i].calculation;
const isLinear =
[MetricQueryTypes.ReadMetricsValues, MetricQueryTypes.ReadLabeledMetricsValues].includes(config.metricTypes[i]) &&
!types.includes(calculation);
const isAvg =
[MetricQueryTypes.ReadMetricsValues, MetricQueryTypes.ReadLabeledMetricsValues].includes(config.metricTypes[i]) &&
types.includes(calculation);
return {
isLinear,
isAvg,
};
}

View File

@ -0,0 +1,437 @@
/**
* 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 dayjs from "dayjs";
import { RespFields, MetricQueryTypes, Calculations } from "./data";
import { ElMessage } from "element-plus";
import { useDashboardStore } from "@/store/modules/dashboard";
import { useSelectorStore } from "@/store/modules/selectors";
import { useAppStoreWithOut } from "@/store/modules/app";
import type { Instance, Endpoint, Service } from "@/types/selector";
import type { MetricConfigOpt } from "@/types/dashboard";
export function useQueryProcessor(config: Indexable) {
if (!(config.metrics && config.metrics[0])) {
return;
}
if (!(config.metricTypes && config.metricTypes[0])) {
return;
}
const appStore = useAppStoreWithOut();
const dashboardStore = useDashboardStore();
const selectorStore = useSelectorStore();
if (!selectorStore.currentService && dashboardStore.entity !== "All") {
return;
}
const conditions: Recordable = {
duration: appStore.durationTime,
};
const variables: string[] = [`$duration: Duration!`];
const isRelation = ["ServiceRelation", "ServiceInstanceRelation", "EndpointRelation", "ProcessRelation"].includes(
dashboardStore.entity,
);
if (isRelation && !selectorStore.currentDestService) {
return;
}
const fragment = config.metrics.map((name: string, index: number) => {
const metricType = config.metricTypes[index] || "";
const c = (config.metricConfig && config.metricConfig[index]) || {};
if ([MetricQueryTypes.ReadSampledRecords, MetricQueryTypes.SortMetrics].includes(metricType)) {
variables.push(`$condition${index}: TopNCondition!`);
conditions[`condition${index}`] = {
name,
parentService: ["All"].includes(dashboardStore.entity) ? null : selectorStore.currentService.value,
normal: selectorStore.currentService ? selectorStore.currentService.normal : true,
topN: Number(c.topN) || 10,
order: c.sortOrder || "DES",
};
} else {
const entity = {
serviceName: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.value,
normal: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.normal,
serviceInstanceName: ["ServiceInstance", "ServiceInstanceRelation", "ProcessRelation"].includes(
dashboardStore.entity,
)
? selectorStore.currentPod && selectorStore.currentPod.value
: undefined,
endpointName: dashboardStore.entity.includes("Endpoint")
? selectorStore.currentPod && selectorStore.currentPod.value
: undefined,
processName: dashboardStore.entity.includes("Process")
? 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,
destProcessName: dashboardStore.entity.includes("ProcessRelation")
? selectorStore.currentDestProcess && selectorStore.currentDestProcess.value
: undefined,
};
if ([MetricQueryTypes.ReadRecords].includes(metricType)) {
variables.push(`$condition${index}: RecordCondition!`);
conditions[`condition${index}`] = {
name,
parentEntity: entity,
topN: Number(c.topN) || 10,
order: c.sortOrder || "DES",
};
} else {
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) {
return `${name}${index}: ${metricType}(condition: $condition${index}, labels: $labels${index}, duration: $duration)${RespFields[metricType]}`;
}
const t = metricType === MetricQueryTypes.ReadMetricsValue ? MetricQueryTypes.ReadNullableMetricsValue : metricType;
return `${name}${index}: ${t}(condition: $condition${index}, duration: $duration)${RespFields[t]}`;
});
const queryStr = `query queryData(${variables}) {${fragment}}`;
return {
queryStr,
conditions,
};
}
export function useSourceProcessor(
resp: { errors: string; data: Indexable },
config: {
metrics: string[];
metricTypes: string[];
metricConfig: MetricConfigOpt[];
},
) {
if (resp.errors) {
ElMessage.error(resp.errors);
return {};
}
if (!resp.data) {
ElMessage.error("The query is wrong");
return {};
}
const source: { [key: string]: unknown } = {};
const keys = Object.keys(resp.data);
config.metricTypes.forEach((type: string, index) => {
const m = config.metrics[index];
const c = (config.metricConfig && config.metricConfig[index]) || {};
if (type === MetricQueryTypes.ReadMetricsValues) {
source[c.label || m] = (resp.data[keys[index]] && calculateExp(resp.data[keys[index]].values.values, c)) || [];
}
if (type === MetricQueryTypes.ReadLabeledMetricsValues) {
const resVal = Object.values(resp.data)[0] || [];
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 (const item of resVal) {
const values = item.values.values.map((d: { value: number; isEmptyValue: boolean }) =>
d.isEmptyValue ? NaN : aggregation(Number(d.value), c),
);
const indexNum = labelsIdx.findIndex((d: string) => d === item.label);
if (labels[indexNum] && indexNum > -1) {
source[labels[indexNum]] = values;
} else {
source[item.label] = values;
}
}
}
if (type === MetricQueryTypes.ReadMetricsValue) {
const v = Object.values(resp.data)[0] || {};
source[m] = v.isEmptyValue ? NaN : aggregation(Number(v.value), c);
}
if (
(
[MetricQueryTypes.ReadRecords, MetricQueryTypes.ReadSampledRecords, MetricQueryTypes.SortMetrics] as string[]
).includes(type)
) {
source[m] = (Object.values(resp.data)[0] || []).map((d: { value: unknown; name: string }) => {
d.value = aggregation(Number(d.value), c);
return d;
});
}
if (type === MetricQueryTypes.READHEATMAP) {
const resVal = Object.values(resp.data)[0] || {};
const nodes = [] as Indexable[];
if (!(resVal && resVal.values)) {
source[m] = { nodes: [] };
return;
}
resVal.values.forEach((items: { values: number[] }, x: number) => {
const grids = items.values.map((val: number, y: number) => [x, y, val]);
nodes.push(...grids);
});
let buckets = [] as Indexable[];
if (resVal.buckets.length) {
buckets = [resVal.buckets[0].min, ...resVal.buckets.map((item: { min: string; max: string }) => item.max)];
}
source[m] = { nodes, buckets }; // nodes: number[][]
}
});
return source;
}
export function useQueryPodsMetrics(
pods: Array<(Instance | Endpoint | Service) & Indexable>,
config: {
metrics: string[];
metricTypes: string[];
metricConfig: MetricConfigOpt[];
},
scope: string,
) {
const metricTypes = (config.metricTypes || []).filter((m: string) => m);
if (!metricTypes.length) {
return;
}
const metrics = (config.metrics || []).filter((m: string) => m);
if (!metrics.length) {
return;
}
const appStore = useAppStoreWithOut();
const selectorStore = useSelectorStore();
const conditions: { [key: string]: unknown } = {
duration: appStore.durationTime,
};
const variables: string[] = [`$duration: Duration!`];
const currentService = selectorStore.currentService || {};
const fragmentList = pods.map((d: (Instance | Endpoint | Service) & Indexable, index: number) => {
const param = {
serviceName: scope === "Service" ? d.label : currentService.label,
serviceInstanceName: scope === "ServiceInstance" ? d.label : undefined,
endpointName: scope === "Endpoint" ? d.label : undefined,
normal: scope === "Service" ? d.normal : currentService.normal,
};
const f = metrics.map((name: string, idx: number) => {
const metricType = metricTypes[idx] || "";
variables.push(`$condition${index}${idx}: MetricsCondition!`);
conditions[`condition${index}${idx}`] = {
name,
entity: param,
};
let labelStr = "";
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;
}
const t =
metricType === MetricQueryTypes.ReadMetricsValue ? MetricQueryTypes.ReadNullableMetricsValue : metricType;
return `${name}${index}${idx}: ${t}(condition: $condition${index}${idx}, ${labelStr}duration: $duration)${RespFields[t]}`;
});
return f;
});
const fragment = fragmentList.flat(1).join(" ");
const queryStr = `query queryData(${variables}) {${fragment}}`;
return { queryStr, conditions };
}
export function usePodsSource(
pods: Array<Instance | Endpoint>,
resp: { errors: string; data: Indexable },
config: {
metrics: string[];
metricTypes: string[];
metricConfig: MetricConfigOpt[];
},
): Indexable {
if (resp.errors) {
ElMessage.error(resp.errors);
return {};
}
const names: string[] = [];
const metricConfigArr: MetricConfigOpt[] = [];
const metricTypesArr: string[] = [];
const data = pods.map((d: any, idx: number) => {
config.metrics.map((name: string, index: number) => {
const c: any = (config.metricConfig && config.metricConfig[index]) || {};
const key = name + idx + index;
if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValue) {
const v = resp.data[key];
d[name] = v.isEmptyValue ? NaN : aggregation(v.value, c);
if (idx === 0) {
names.push(name);
metricConfigArr.push(c);
metricTypesArr.push(config.metricTypes[index]);
}
}
if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValues) {
d[name] = {};
if ([Calculations.Average, Calculations.ApdexAvg, Calculations.PercentageAvg].includes(c.calculation)) {
d[name]["avg"] = calculateExp(resp.data[key].values.values, c);
}
d[name]["values"] = resp.data[key].values.values.map((val: { value: number; isEmptyValue: boolean }) =>
val.isEmptyValue ? NaN : 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; isEmptyValue: boolean }) =>
d.isEmptyValue ? NaN : 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 { data, names, metricConfigArr, metricTypesArr };
}
export function useQueryTopologyMetrics(metrics: string[], ids: string[]) {
const appStore = useAppStoreWithOut();
const conditions: { [key: string]: unknown } = {
duration: appStore.durationTime,
ids,
};
const variables: string[] = [`$duration: Duration!`, `$ids: [ID!]!`];
const fragmentList = metrics.map((d: string, index: number) => {
conditions[`m${index}`] = d;
variables.push(`$m${index}: String!`);
return `${d}: getValues(metric: {
name: $m${index}
ids: $ids
}, duration: $duration) {
values {
id
value
}
}`;
});
const queryStr = `query queryData(${variables}) {${fragmentList.join(" ")}}`;
return { queryStr, conditions };
}
export function calculateExp(
list: { value: number; isEmptyValue: boolean }[],
config: { calculation?: string },
): (number | string)[] {
const arr = list.filter((d: { value: number; isEmptyValue: boolean }) => !d.isEmptyValue);
const sum = arr.length ? arr.map((d: { value: number }) => Number(d.value)).reduce((a, b) => a + b) : 0;
let data: (number | string)[] = [];
switch (config.calculation) {
case Calculations.Average:
data = [(sum / arr.length).toFixed(2)];
break;
case Calculations.PercentageAvg:
data = [(sum / arr.length / 100).toFixed(2)];
break;
case Calculations.ApdexAvg:
data = [(sum / arr.length / 10000).toFixed(2)];
break;
default:
data = list.map((d: { value: number; isEmptyValue: boolean }) =>
d.isEmptyValue ? NaN : aggregation(d.value, config),
);
break;
}
return data;
}
export function aggregation(val: number, config: { calculation?: string }): number | string {
let data: number | string = Number(val);
switch (config.calculation) {
case Calculations.Percentage:
data = (val / 100).toFixed(2);
break;
case Calculations.PercentageAvg:
data = (val / 100).toFixed(2);
break;
case Calculations.ByteToKB:
data = (val / 1024).toFixed(2);
break;
case Calculations.ByteToMB:
data = (val / 1024 / 1024).toFixed(2);
break;
case Calculations.ByteToGB:
data = (val / 1024 / 1024 / 1024).toFixed(2);
break;
case Calculations.Apdex:
data = (val / 10000).toFixed(2);
break;
case Calculations.ConvertSeconds:
data = dayjs(val * 1000).format("YYYY-MM-DD HH:mm:ss");
break;
case Calculations.ConvertMilliseconds:
data = dayjs(val).format("YYYY-MM-DD HH:mm:ss");
break;
case Calculations.MsToS:
data = (val / 1000).toFixed(2);
break;
case Calculations.SecondToDay:
data = (val / 86400).toFixed(2);
break;
case Calculations.NanosecondToMillisecond:
data = (val / 1000 / 1000).toFixed(2);
break;
case Calculations.ApdexAvg:
data = (val / 10000).toFixed(2);
break;
default:
data;
break;
}
return data;
}

View File

@ -1,47 +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 type { MetricsResults } from "@/types/dashboard";
export function useSnapshot(metrics: { name: string; results: MetricsResults[] }[]) {
function processResults() {
const sources = metrics.map((metric: { name: string; results: MetricsResults[] }) => {
const values = metric.results.map(
(r: { values: { value: string }[]; metric: { labels: { key: string; value: string }[] } }) => {
const arr = r.values.map((v: { value: string }) => Number(v.value));
if (!r.metric.labels.length) {
return { values: arr };
}
const name = r.metric.labels
.map(
(label: { key: string; value: string }) =>
`${metric.name}${label ? "{" : ""}${label.key}=${label.value}${label ? "}" : ""}`,
)
.join(",");
return { name, values: arr };
},
);
return { name: metric.name, values };
});
return sources;
}
return {
processResults,
};
}

View File

@ -48,20 +48,14 @@ limitations under the License. -->
@input="changeTimeRange" @input="changeTimeRange"
/> />
<span> UTC{{ appStore.utcHour >= 0 ? "+" : "" }}{{ `${appStore.utcHour}:${appStore.utcMin}` }} </span> <span> UTC{{ appStore.utcHour >= 0 ? "+" : "" }}{{ `${appStore.utcHour}:${appStore.utcMin}` }} </span>
<span class="ml-5" ref="themeSwitchRef"> <span class="ml-5">
<el-switch <el-switch v-model="theme" :active-icon="Moon" :inactive-icon="Sunny" inline-prompt @change="changeTheme" />
v-model="theme"
:active-icon="Moon"
:inactive-icon="Sunny"
inline-prompt
@change="handleChangeTheme"
/>
</span> </span>
<span title="refresh" class="ghost ml-5 cp" @click="handleReload"> <span title="refresh" class="ghost ml-5 cp" @click="handleReload">
<Icon iconName="retry" :loading="appStore.autoRefresh" class="middle" /> <Icon iconName="retry" :loading="appStore.autoRefresh" class="middle" />
</span> </span>
<span class="version ml-5 cp"> <span class="version ml-5 cp">
<el-popover trigger="hover" :width="250" placement="bottom" :content="appStore.version"> <el-popover trigger="hover" width="250" placement="bottom" :content="appStore.version">
<template #reference> <template #reference>
<span> <span>
<Icon iconName="info_outline" size="middle" /> <Icon iconName="info_outline" size="middle" />
@ -73,18 +67,18 @@ limitations under the License. -->
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { Themes } from "@/constants/data"; import { ref, watch } from "vue";
import router from "@/router"; import { useRoute } from "vue-router";
import { useI18n } from "vue-i18n";
import timeFormat from "@/utils/timeFormat";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import type { DashboardItem } from "@/types/dashboard";
import timeFormat from "@/utils/timeFormat";
import { MetricCatalog } from "@/views/dashboard/data";
import { ArrowRight, Moon, Sunny } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { ref, watch } from "vue"; import { MetricCatalog } from "@/views/dashboard/data";
import { useI18n } from "vue-i18n"; import type { DashboardItem } from "@/types/dashboard";
import { useRoute } from "vue-router"; import router from "@/router";
import { ArrowRight, Moon, Sunny } from "@element-plus/icons-vue";
import { Themes } from "@/constants/data";
/*global Indexable */ /*global Indexable */
const { t, te } = useI18n(); const { t, te } = useI18n();
@ -95,13 +89,11 @@ limitations under the License. -->
const timeRange = ref<number>(0); const timeRange = ref<number>(0);
const pageTitle = ref<string>(""); const pageTitle = ref<string>("");
const theme = ref<boolean>(true); const theme = ref<boolean>(true);
const themeSwitchRef = ref<HTMLElement>();
const savedTheme = window.localStorage.getItem("theme-is-dark"); const savedTheme = window.localStorage.getItem("theme-is-dark");
if (savedTheme === "false") { if (savedTheme === "false") {
theme.value = false; theme.value = false;
} } else if (savedTheme === "") {
if (savedTheme === "") {
// read the theme preference from system setting if there is no user setting // read the theme preference from system setting if there is no user setting
theme.value = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; theme.value = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
} }
@ -126,35 +118,6 @@ limitations under the License. -->
window.localStorage.setItem("theme-is-dark", String(theme.value)); window.localStorage.setItem("theme-is-dark", String(theme.value));
} }
function handleChangeTheme() {
const x = themeSwitchRef.value?.offsetLeft ?? 0;
const y = themeSwitchRef.value?.offsetTop ?? 0;
const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y));
// compatibility handling
if (!document.startViewTransition) {
changeTheme();
return;
}
// api: https://developer.chrome.com/docs/web-platform/view-transitions
const transition = document.startViewTransition(() => {
changeTheme();
});
transition.ready.then(() => {
const clipPath = [`circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`];
document.documentElement.animate(
{
clipPath: !theme.value ? clipPath.reverse() : clipPath,
},
{
duration: 500,
easing: "ease-in",
pseudoElement: !theme.value ? "::view-transition-old(root)" : "::view-transition-new(root)",
},
);
});
}
function getName(list: any[]) { function getName(list: any[]) {
return list.find((d: any) => d.selected) || {}; return list.find((d: any) => d.selected) || {};
} }

View File

@ -50,7 +50,7 @@ limitations under the License. -->
</el-menu-item> </el-menu-item>
</el-menu-item-group> </el-menu-item-group>
</el-sub-menu> </el-sub-menu>
<el-menu-item :index="String(menu.name)" v-else> <el-menu-item :index="String(menu.name)" @click="changePage(menu)" v-else>
<el-icon class="menu-icons" :style="{ marginRight: '12px' }" @mouseover="setCollapse"> <el-icon class="menu-icons" :style="{ marginRight: '12px' }" @mouseover="setCollapse">
<router-link class="items menu-title" :to="menu.children[0].path"> <router-link class="items menu-title" :to="menu.children[0].path">
<Icon size="lg" :iconName="menu.meta.icon" /> <Icon size="lg" :iconName="menu.meta.icon" />
@ -83,6 +83,7 @@ limitations under the License. -->
const appStore = useAppStoreWithOut(); const appStore = useAppStoreWithOut();
const router = useRouter(); const router = useRouter();
const name = ref<string>(String(router.currentRoute.value.name)); const name = ref<string>(String(router.currentRoute.value.name));
const theme = ["VirtualMachine", "Kubernetes"].includes(name.value || "") ? ref("light") : ref("black");
const routes = ref<RouteRecordRaw[] | any>( const routes = ref<RouteRecordRaw[] | any>(
(router.options.routes || []).filter((d: any) => d.meta && d.meta.activate), (router.options.routes || []).filter((d: any) => d.meta && d.meta.activate),
); );
@ -99,7 +100,9 @@ limitations under the License. -->
if (route.name === "ViewWidget") { if (route.name === "ViewWidget") {
showMenu.value = false; showMenu.value = false;
} }
const changePage = (menu: RouteRecordRaw) => {
theme.value = ["VirtualMachine", "Kubernetes"].includes(String(menu.name)) ? "light" : "black";
};
const filterMenus = (menus: Recordable[]) => { const filterMenus = (menus: Recordable[]) => {
return menus.filter((d) => d.meta && !d.meta.notShow && d.meta.activate); return menus.filter((d) => d.meta && !d.meta.notShow && d.meta.activate);
}; };

View File

@ -94,13 +94,14 @@ const msg = {
editTab: "Enable editing tab names", editTab: "Enable editing tab names",
label: "Service Name", label: "Service Name",
id: "Service ID", id: "Service ID",
setRoot: "Set Normal to Root", setRoot: "Set this to root",
setNormal: "Set Root to Normal", setNormal: "Set this to normal",
export: "Export Dashboard Templates", export: "Export Dashboard Templates",
import: "Import Dashboard Templates", import: "Import Dashboard Templates",
yes: "Yes", yes: "Yes",
no: "No", no: "No",
tableHeaderCol2: "Name of the last column of the table", tableHeaderCol1: "Name of the first column of the table",
tableHeaderCol2: "Name of the second column of the table",
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",
@ -139,6 +140,7 @@ const msg = {
enableAssociate: "Enable association", enableAssociate: "Enable association",
text: "Text", text: "Text",
query: "Query", query: "Query",
endpointTips: "The table shows up to 20 pieces of endpoints.",
viewTrace: "View Related Traces", viewTrace: "View Related Traces",
relatedTraceOptions: "Related Trace Options", relatedTraceOptions: "Related Trace Options",
setLatencyDuration: "Latency Related Metrics", setLatencyDuration: "Latency Related Metrics",
@ -153,7 +155,6 @@ const msg = {
legendOptions: "Legend Options", legendOptions: "Legend Options",
showLegend: "Show Legend", showLegend: "Show Legend",
asTable: "As Table", asTable: "As Table",
asSelector: "As Selector",
toTheRight: "To The Right", toTheRight: "To The Right",
legendValues: "Legend Values", legendValues: "Legend Values",
minDuration: "Minimal Request Duration", minDuration: "Minimal Request Duration",
@ -284,8 +285,7 @@ const msg = {
errorInfo: "Error Info", errorInfo: "Error Info",
stack: "Stack", stack: "Stack",
serviceVersion: "Service Version", serviceVersion: "Service Version",
pagePath: "Page Path", errorPage: "Error Page",
errorUrl: "Error Url",
category: "Category", category: "Category",
grade: "Grade", grade: "Grade",
relatedTraceLogs: "Related Logs", relatedTraceLogs: "Related Logs",
@ -301,7 +301,7 @@ const msg = {
viewLogs: "View Logs", viewLogs: "View Logs",
logsTagsTip: `Only tags defined in the core/default/searchableLogsTags are searchable. logsTagsTip: `Only tags defined in the core/default/searchableLogsTags are searchable.
Check more details on the Configuration Vocabulary page`, Check more details on the Configuration Vocabulary page`,
keywordsOfContentLogTips: "Current storage of SkyWalking OAP server does not support this", keywordsOfContentLogTips: "Current storage of SkyWalking OAP server does not support this.",
setEvent: "Set Event", setEvent: "Set Event",
viewAttributes: "View", viewAttributes: "View",
attributes: "Attributes", attributes: "Attributes",
@ -356,7 +356,7 @@ const msg = {
addKeywordsOfContent: "Please input a keyword of content", addKeywordsOfContent: "Please input a keyword of content",
addExcludingKeywordsOfContent: "Please input a keyword of excluding content", addExcludingKeywordsOfContent: "Please input a keyword of excluding content",
noticeTag: "Please press Enter after inputting a tag(key=value).", noticeTag: "Please press Enter after inputting a tag(key=value).",
conditionNotice: "Notice: Please press Enter after inputting a key of content, exclude key of content(key=value)", conditionNotice: "Notice: Please press Enter after inputting a key of content, exclude key of content(key=value).",
language: "Language", language: "Language",
save: "Save", save: "Save",
editStrategy: "Edit Policies", editStrategy: "Edit Policies",
@ -378,24 +378,11 @@ const msg = {
menus: "Menus", menus: "Menus",
saveReload: "Save and reload the page", saveReload: "Save and reload the page",
document: "Documentation", document: "Documentation",
metricMode: "Metric Mode",
addExpressions: "Add Expressions", addExpressions: "Add Expressions",
expressions: "Expression", expressions: "Expression",
unhealthyExpression: "Unhealthy Expression", unhealthyExpression: "Unhealthy Expression",
traceDesc: traceDesc:
"The trace segment serves as a representation of a trace portion executed within one single OS process, such as a JVM. It comprises a collection of spans, typically associated with and collected from a single request or execution context.", "The trace segment serves as a representation of a trace portion executed within one single OS process, such as a JVM. It comprises a collection of spans, typically associated with and collected from a single request or execution context.",
tabExpressions: "Tab Expressions",
hierarchyNodeMetrics: "Metrics for Hierarchy Graph Node",
hierarchyNodeDashboard: "As dashboard for Hierarchy Graph Node",
valueMappings: "Value Mappings",
mappingTip: "Notice: The mapping key is a Regex string, e.g. ^([0-9])$",
valueDashboard: "Data Value Related Dashboard",
viewValueDashboard: "View Dashboard",
errorInstances: "Error Instances",
successInstances: "Success Instances",
profilingEvents: "Async Profiling Events",
execArgs: "Exec Args",
instances: "Instances",
snapshot: "Snapshot",
expression: "Expression",
}; };
export default msg; export default msg;

View File

@ -101,7 +101,8 @@ const msg = {
import: "Importar Plantilla Panel", import: "Importar Plantilla Panel",
yes: "Sí", yes: "Sí",
no: "No", no: "No",
tableHeaderCol2: "Nombre de la Último columna de la tabla", tableHeaderCol1: "Nombre de la primera columna de la tabla",
tableHeaderCol2: "Nombre de la segunda columna de la tabla",
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",
@ -138,6 +139,7 @@ const msg = {
"El nombre sólo admite chino e inglés, líneas horizontales y subrayado, y la longitud del nombre no excederá de 300 caracteres", "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", enableAssociate: "Activar asociación",
query: "Consulta", query: "Consulta",
endpointTips: "Aquí, la tabla muestra hasta 20 punto final.",
queryOrder: "Consulta por duración", queryOrder: "Consulta por duración",
setOrder: "Orden de consulta", setOrder: "Orden de consulta",
latency: "Retraso", latency: "Retraso",
@ -282,8 +284,7 @@ const msg = {
errorInfo: "Info Error", errorInfo: "Info Error",
stack: "Pila", stack: "Pila",
serviceVersion: "Versión Servicio", serviceVersion: "Versión Servicio",
pagePath: "Página de Error", errorPage: "Página de Error",
errorUrl: "Ruta de Error",
category: "Categoría", category: "Categoría",
grade: "Grado", grade: "Grado",
relatedTraceLogs: "Registro de Datos Relacionados", relatedTraceLogs: "Registro de Datos Relacionados",
@ -299,7 +300,7 @@ const msg = {
viewLogs: "Ver Registro de Datos", viewLogs: "Ver Registro de Datos",
logsTagsTip: `Solamente etiquetas definidas en core/default/searchableLogsTags pueden ser buscadas. logsTagsTip: `Solamente etiquetas definidas en core/default/searchableLogsTags pueden ser buscadas.
Más información en la página de Vocabulario de Configuración`, Más información en la página de Vocabulario de Configuración`,
keywordsOfContentLogTips: "El almacenamiento actual del servidor SkyWalking OAP no lo soporta", keywordsOfContentLogTips: "El almacenamiento actual del servidor SkyWalking OAP no lo soporta.",
setEvent: "Establecer Evento", setEvent: "Establecer Evento",
viewAttributes: "Ver", viewAttributes: "Ver",
serviceEvents: "Eventos Servico", serviceEvents: "Eventos Servico",
@ -377,25 +378,11 @@ const msg = {
menus: "Menus", menus: "Menus",
saveReload: "Save and reload the page", saveReload: "Save and reload the page",
document: "Documentation", document: "Documentation",
metricMode: "Metric Mode",
addExpressions: "Add Expressions", addExpressions: "Add Expressions",
expressions: "Expression", expressions: "Expression",
unhealthyExpression: "Unhealthy Expression", unhealthyExpression: "Unhealthy Expression",
traceDesc: traceDesc:
"The trace segment serves as a representation of a trace portion executed within one single OS process, such as a JVM. It comprises a collection of spans, typically associated with and collected from a single request or execution context.", "The trace segment serves as a representation of a trace portion executed within one single OS process, such as a JVM. It comprises a collection of spans, typically associated with and collected from a single request or execution context.",
tabExpressions: "Tab Expressions",
hierarchyNodeMetrics: "Metrics for Hierarchy Graph Node",
hierarchyNodeDashboard: "As dashboard for Hierarchy Graph Node",
valueMappings: "Value Mappings",
mappingTip: "Aviso: La clave de mapeo es una cadena Regex, p. ej. ^([0-9])$",
valueDashboard: "Data Value Related Dashboard",
viewValueDashboard: "View Dashboard",
errorInstances: "Error Instances",
successInstances: "Success Instances",
profilingEvents: "Async Profiling Events",
execArgs: "Exec Args",
instances: "Instances",
snapshot: "Snapshot",
expression: "Expression",
asSelector: "As Selector",
}; };
export default msg; export default msg;

View File

@ -30,11 +30,6 @@ const titles = {
general_service_virtual_mq: "Virtual MQ", general_service_virtual_mq: "Virtual MQ",
general_service_virtual_mq_desc: general_service_virtual_mq_desc:
"Observe the virtual message queue servers which are conjectured by language agents through various plugins.", "Observe the virtual message queue servers which are conjectured by language agents through various plugins.",
// Workflow Scheduler
workflow_scheduler: "Workflow Scheduler",
workflow_scheduler_desc: "Provide monitoring for workflow scheduling systems.",
workflow_scheduler_airflow: "Airflow",
workflow_scheduler_airflow_desc: "Observe tasks through telemetry data collected from Apache Airflow.",
// Service Mesh // Service Mesh
service_mesh: "Service Mesh", service_mesh: "Service Mesh",
service_mesh_desc: service_mesh_desc:
@ -113,8 +108,6 @@ const titles = {
mq_kafka_desc: "Provide Kafka monitoring through OpenTelemetry's Prometheus Receiver.", mq_kafka_desc: "Provide Kafka monitoring through OpenTelemetry's Prometheus Receiver.",
mq_pulsar: "Pulsar", mq_pulsar: "Pulsar",
mq_pulsar_desc: "Provide Pulsar monitoring through OpenTelemetry's Prometheus Receiver.", mq_pulsar_desc: "Provide Pulsar monitoring through OpenTelemetry's Prometheus Receiver.",
mq_rocketmq: "RocketMQ",
mq_rocketmq_desc: "Provide RocketMQ monitoring through OpenTelemetry's Prometheus Receiver.",
// self observability // self observability
self_observability: "Self Observability", self_observability: "Self Observability",
self_observability_desc: self_observability_desc:
@ -125,23 +118,6 @@ const titles = {
self_observability_satellite: "Satellite", self_observability_satellite: "Satellite",
self_observability_satellite_desc: self_observability_satellite_desc:
"Satellite: an open-source agent designed for the cloud-native infrastructures, which provides a low-cost, high-efficient, and more secure way to collect telemetry data. It is the recommended load balancer for telemetry collecting.", "Satellite: an open-source agent designed for the cloud-native infrastructures, which provides a low-cost, high-efficient, and more secure way to collect telemetry data. It is the recommended load balancer for telemetry collecting.",
self_observability_java_agent: "SkyWalking Java Agent",
self_observability_java_agent_desc:
"The self observability of SkyWalking Java Agent, which provides the abilities to measure the tracing performance and error statistics of plugins.",
self_observability_go_agent: "SkyWalking Go Agent",
self_observability_go_agent_desc:
"The self observability of SkyWalking Go Agent, which provides the abilities to measure the tracing performance and error statistics of plugins.",
cilium: "Cilium",
cilium_desc:
"Cilium is a CNI plugin for Kubernetes that provides eBPF-based networking, security, and load balancing.",
cilium_service: "Cilium Service",
cilium_service_desc: "Observe Service status and resources from Cilium Hubble.",
data_processing_engine: "Data Processing Engine",
data_processing_engine_desc:
"A data processing engine is a system designed to efficiently process, transform, and analyze large-scale data in real time or batch mode.",
data_processing_engine_flink: "Flink",
data_processing_engine_flink_desc:
"Apache Flink is a framework and distributed processing engine for stateful computations over unbounded and bounded data streams. Flink has been designed to run in all common cluster environments, perform computations at in-memory speed and at any scale.",
}; };
export default titles; export default titles;

View File

@ -30,12 +30,6 @@ const titles = {
general_service_virtual_mq: "MQ virtual", general_service_virtual_mq: "MQ virtual",
general_service_virtual_mq_desc: general_service_virtual_mq_desc:
"Observe the virtual message queue servers which are conjectured by language agents through various plugins.", "Observe the virtual message queue servers which are conjectured by language agents through various plugins.",
// Workflow Scheduler
workflow_scheduler: "Flujo de trabajo",
workflow_scheduler_desc: "Proporcionar monitoreo para sistemas de programación de flujos de trabajo.",
workflow_scheduler_airflow: "Airflow",
workflow_scheduler_airflow_desc:
"Observando tareas a través de los datos de telemetría recopilados desde Apache Airflow.",
// Service Mesh // Service Mesh
service_mesh: "Malla de Servicios", service_mesh: "Malla de Servicios",
service_mesh_desc: service_mesh_desc:
@ -114,8 +108,6 @@ const titles = {
mq_kafka_desc: "Provide Kafka monitoring through OpenTelemetry's Prometheus Receiver.", mq_kafka_desc: "Provide Kafka monitoring through OpenTelemetry's Prometheus Receiver.",
mq_pulsar: "Pulsar", mq_pulsar: "Pulsar",
mq_pulsar_desc: "Provide Pulsar monitoring through OpenTelemetry's Prometheus Receiver.", mq_pulsar_desc: "Provide Pulsar monitoring through OpenTelemetry's Prometheus Receiver.",
mq_rocketmq: "RocketMQ",
mq_rocketmq_desc: "Provide RocketMQ monitoring through OpenTelemetry's Prometheus Receiver.",
// self observability // self observability
self_observability: "Self Observability", self_observability: "Self Observability",
self_observability_desc: self_observability_desc:
@ -126,23 +118,6 @@ const titles = {
self_observability_satellite: "Satellite", self_observability_satellite: "Satellite",
self_observability_satellite_desc: self_observability_satellite_desc:
"Satellite: an open-source agent designed for the cloud-native infrastructures, which provides a low-cost, high-efficient, and more secure way to collect telemetry data. It is the recommended load balancer for telemetry collecting.", "Satellite: an open-source agent designed for the cloud-native infrastructures, which provides a low-cost, high-efficient, and more secure way to collect telemetry data. It is the recommended load balancer for telemetry collecting.",
self_observability_java_agent: "SkyWalking Java Agent",
self_observability_java_agent_desc:
"La auto-observabilidad de SkyWalking Java Agent, que proporciona la capacidad de medir el rendimiento del trazado y las estadísticas de errores de los plugins.",
self_observability_go_agent: "SkyWalking Go Agent",
self_observability_go_agent_desc:
"La auto-observabilidad de SkyWalking Go Agent, que proporciona la capacidad de medir el rendimiento del trazado y las estadísticas de errores de los plugins.",
cilium: "Cilium",
cilium_desc:
"Cilium es un complemento CNI para Kubernetes que proporciona redes, seguridad y equilibrio de carga basados en eBPF.",
cilium_service: "Cilium Service",
cilium_service_desc: "Observe el estado del servicio y los recursos de Cilium Hubble.",
data_processing_engine: "Data Processing Engine",
data_processing_engine_desc:
"A data processing engine is a system designed to efficiently process, transform, and analyze large-scale data in real time or batch mode.",
data_processing_engine_flink: "Flink",
data_processing_engine_flink_desc:
"Apache Flink is a framework and distributed processing engine for stateful computations over unbounded and bounded data streams. Flink has been designed to run in all common cluster environments, perform computations at in-memory speed and at any scale.",
}; };
export default titles; export default titles;

View File

@ -26,11 +26,6 @@ const titles = {
general_service_virtual_cache_desc: "观察语言代理通过各种插件推测的虚拟缓存服务器。", general_service_virtual_cache_desc: "观察语言代理通过各种插件推测的虚拟缓存服务器。",
general_service_virtual_mq: "虚拟消息队列", general_service_virtual_mq: "虚拟消息队列",
general_service_virtual_mq_desc: "观察语言代理通过各种插件推测的虚拟消息队列服务器。", general_service_virtual_mq_desc: "观察语言代理通过各种插件推测的虚拟消息队列服务器。",
// Workflow Scheduler
workflow_scheduler: "工作流调度",
workflow_scheduler_desc: "提供工作流调度系统监控。",
workflow_scheduler_airflow: "Airflow",
workflow_scheduler_airflow_desc: "通过从Apache Airflow收集的遥测数据观察任务。",
// Service Mesh // Service Mesh
service_mesh: "服务网格", service_mesh: "服务网格",
service_mesh_desc: "服务网格Istio通过分布式或微服务架构解决了开发人员和运营商面临的挑战。", service_mesh_desc: "服务网格Istio通过分布式或微服务架构解决了开发人员和运营商面临的挑战。",
@ -101,8 +96,6 @@ const titles = {
mq_Kafka_desc: "通过OpenTelemetry的Prometheus接收器提供Kafka监控。", mq_Kafka_desc: "通过OpenTelemetry的Prometheus接收器提供Kafka监控。",
mq_pulsar: "Pulsar", mq_pulsar: "Pulsar",
mq_Pulsar_desc: "通过OpenTelemetry的Prometheus接收器提供Pulsar监控。", mq_Pulsar_desc: "通过OpenTelemetry的Prometheus接收器提供Pulsar监控。",
mq_rocketmq: "RocketMQ",
mq_rocketmq_desc: "通过OpenTelemetry的Prometheus接收器提供RocketMQ监控。",
// self observability // self observability
self_observability: "自监控", self_observability: "自监控",
self_observability_desc: "自观察性为运行SkyWalking生态系统中的组件和服务器提供了可观察性。", self_observability_desc: "自观察性为运行SkyWalking生态系统中的组件和服务器提供了可观察性。",
@ -111,19 +104,6 @@ const titles = {
self_observability_satellite: "Satellite", self_observability_satellite: "Satellite",
self_observability_satellite_desc: self_observability_satellite_desc:
"Satellite为云原生基础设施设计的开源代理提供了一种低成本、高效、更安全的遥测数据收集方式。它是遥测采集的推荐负载均衡器。", "Satellite为云原生基础设施设计的开源代理提供了一种低成本、高效、更安全的遥测数据收集方式。它是遥测采集的推荐负载均衡器。",
self_observability_java_agent: "SkyWalking Java Agent",
self_observability_java_agent_desc: "SkyWalking Java Agent 自监控提供了对 agent 插件的性能追踪和错误统计。",
self_observability_go_agent: "SkyWalking Go Agent",
self_observability_go_agent_desc: "SkyWalking Go Agent 自监控提供了对 agent 插件的性能追踪和错误统计。",
cilium: "Cilium",
cilium_desc: "Cilium是Kubernetes上的CNI插件提供基于eBPF的网络、安全和负载均衡。",
cilium_service: "Cilium服务",
cilium_service_desc: "通过Cilium Hubble收集的遥测数据观察服务。",
data_processing_engine: "数据处理引擎",
data_processing_engine_desc: "数据处理引擎是一个用于高效地在实时或批处理模式下处理、转换和分析大规模数据的系统。",
data_processing_engine_flink: "Flink",
data_processing_engine_flink_desc:
"Apache Flink 是一个框架和分布式处理引擎用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算。",
}; };
export default titles; export default titles;

View File

@ -99,7 +99,8 @@ const msg = {
import: "导入仪表板模板", import: "导入仪表板模板",
yes: "是", yes: "是",
no: "否", no: "否",
tableHeaderCol2: "表格的最后一列的名称", tableHeaderCol1: "表格的第一列的名称",
tableHeaderCol2: "表格的第二列的名称",
showXAxis: "显示X轴", showXAxis: "显示X轴",
showYAxis: "显示Y轴", showYAxis: "显示Y轴",
nameError: "仪表板名称不能重复", nameError: "仪表板名称不能重复",
@ -137,6 +138,7 @@ const msg = {
duplicateName: "重复的名称", duplicateName: "重复的名称",
text: "文本", text: "文本",
query: "查询", query: "查询",
endpointTips: "这里最多展示20条endpoints。",
viewTrace: "查看相关Trace", viewTrace: "查看相关Trace",
relatedTraceOptions: "相关的Trace选项", relatedTraceOptions: "相关的Trace选项",
setLatencyDuration: "延迟相关指标", setLatencyDuration: "延迟相关指标",
@ -151,7 +153,6 @@ const msg = {
legendOptions: "图例选项", legendOptions: "图例选项",
showLegend: "显示图例", showLegend: "显示图例",
asTable: "作为表格", asTable: "作为表格",
asSelector: "作为选择器",
toTheRight: "在右边", toTheRight: "在右边",
legendValues: "图例值", legendValues: "图例值",
minDuration: "最小请求持续时间", minDuration: "最小请求持续时间",
@ -281,8 +282,7 @@ const msg = {
errorInfo: "错误信息", errorInfo: "错误信息",
stack: "堆栈", stack: "堆栈",
serviceVersion: "服务版本", serviceVersion: "服务版本",
pagePath: "错误页面", errorPage: "错误页面",
errorUrl: "错误路径",
category: "类别", category: "类别",
grade: "等级", grade: "等级",
relatedTraceLogs: "相关的日志", relatedTraceLogs: "相关的日志",
@ -376,24 +376,11 @@ const msg = {
menusManagement: "菜单", menusManagement: "菜单",
saveReload: "保存并重新加载页面", saveReload: "保存并重新加载页面",
document: "文档", document: "文档",
metricMode: "指标模式",
addExpressions: "添加表达式", addExpressions: "添加表达式",
expressions: "表达式", expressions: "表达式",
unhealthyExpression: "非健康表达式", unhealthyExpression: "非健康表达式",
traceDesc: traceDesc:
"Trace Segment代表在单一操作系统进程例如JVM中执行的追踪部分。它包含了一组跨度spans这些跨度通常与单一请求或执行上下文关联。", "Trace Segment代表在单一操作系统进程例如JVM中执行的追踪部分。它包含了一组跨度spans这些跨度通常与单一请求或执行上下文关联。",
tabExpressions: "Tab表达式",
hierarchyNodeMetrics: "层次图节点的指标",
hierarchyNodeDashboard: "作为层次图节点的dashboard",
valueMappings: "值映射",
mappingTip: "注意: 映射键是一个正则表达式字符串,比如 ^([0-9])$",
valueDashboard: "数据值相关的仪表板",
viewValueDashboard: "查看仪表板",
errorInstances: "错误的实例",
successInstances: "成功的实例",
profilingEvents: "异步分析事件",
execArgs: "String任务扩展",
instances: "实例",
snapshot: "快照",
expression: "表达式",
}; };
export default msg; export default msg;

View File

@ -15,7 +15,6 @@
* limitations under the License. * limitations under the License.
*/ */
import { createApp } from "vue"; import { createApp } from "vue";
import { ElLoading } from "element-plus";
import App from "./App.vue"; import App from "./App.vue";
import { store } from "./store"; import { store } from "./store";
import components from "@/components"; import components from "@/components";
@ -24,11 +23,6 @@ import { useAppStoreWithOut } from "@/store/modules/app";
import "./styles/index.ts"; import "./styles/index.ts";
import "virtual:svg-icons-register"; import "virtual:svg-icons-register";
const loading = ElLoading.service({
lock: true,
text: "Loading...",
background: "rgba(0, 0, 0, 0.8)",
});
const app = createApp(App); const app = createApp(App);
const appStore = useAppStoreWithOut(); const appStore = useAppStoreWithOut();
@ -40,7 +34,7 @@ mountApp();
async function mountApp() { async function mountApp() {
await appStore.getActivateMenus(); await appStore.getActivateMenus();
await appStore.queryOAPTimeInfo(); await appStore.queryOAPTimeInfo();
const router = await import("./router"); const router = await import("./router");
app.use(router.default).mount("#app"); app.use(router.default).mount("#app");
loading.close();
} }

View File

@ -33,7 +33,7 @@ export const routesAlarm: Array<RouteRecordRaw> = [
children: [ children: [
{ {
path: "/alerting", path: "/alerting",
name: "ViewAlarm", name: "Alarm",
component: Alarm, component: Alarm,
}, },
], ],

View File

@ -100,7 +100,7 @@ export const routesDashboard: Array<RouteRecordRaw> = [
path: "", path: "",
redirect: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name", redirect: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name",
component: Edit, component: Edit,
name: "ServiceRelations", name: "ViewServiceRelation",
meta: { meta: {
notShow: true, notShow: true,
}, },
@ -121,7 +121,7 @@ export const routesDashboard: Array<RouteRecordRaw> = [
path: "", path: "",
redirect: "/dashboard/:layerId/:entity/:serviceId/:podId/:name", redirect: "/dashboard/:layerId/:entity/:serviceId/:podId/:name",
component: Edit, component: Edit,
name: "Pods", name: "ViewPod",
meta: { meta: {
notShow: true, notShow: true,
}, },
@ -142,7 +142,7 @@ export const routesDashboard: Array<RouteRecordRaw> = [
path: "", path: "",
redirect: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:name", redirect: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:name",
component: Edit, component: Edit,
name: "Processes", name: "ViewProcess",
meta: { meta: {
notShow: true, notShow: true,
}, },
@ -163,7 +163,7 @@ export const routesDashboard: Array<RouteRecordRaw> = [
path: "", path: "",
redirect: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name", redirect: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name",
component: Edit, component: Edit,
name: "PodRelations", name: "PodRelation",
meta: { meta: {
notShow: true, notShow: true,
}, },
@ -185,7 +185,7 @@ export const routesDashboard: Array<RouteRecordRaw> = [
redirect: redirect:
"/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name", "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name",
component: Edit, component: Edit,
name: "ProcessRelations", name: "ProcessRelation",
meta: { meta: {
notShow: true, notShow: true,
}, },

View File

@ -21,7 +21,6 @@ import { routesMarketplace } from "./marketplace";
import { routesAlarm } from "./alarm"; import { routesAlarm } from "./alarm";
import routesLayers from "./layer"; import routesLayers from "./layer";
import { routesSettings } from "./settings"; import { routesSettings } from "./settings";
import { routesNotFound } from "./notFound";
const routes: RouteRecordRaw[] = [ const routes: RouteRecordRaw[] = [
...routesMarketplace, ...routesMarketplace,
@ -29,7 +28,6 @@ const routes: RouteRecordRaw[] = [
...routesAlarm, ...routesAlarm,
...routesDashboard, ...routesDashboard,
...routesSettings, ...routesSettings,
...routesNotFound,
]; ];
const router = createRouter({ const router = createRouter({
@ -37,27 +35,19 @@ const router = createRouter({
routes, routes,
}); });
router.beforeEach((to, _, next) => { (window as any).axiosCancel = [];
router.beforeEach((to, from, next) => {
// const token = window.localStorage.getItem("skywalking-authority"); // const token = window.localStorage.getItem("skywalking-authority");
if ((window as any).axiosCancel.length !== 0) {
for (const func of (window as any).axiosCancel) {
setTimeout(func(), 0);
}
(window as any).axiosCancel = [];
}
if (to.path === "/") { if (to.path === "/") {
let defaultPath = ""; const defaultPath = (routesLayers[0] && routesLayers[0].children[0].path) || "";
for (const route of routesLayers) {
for (const child of route.children) {
if (child.meta.activate) {
defaultPath = child.path;
break;
}
}
if (defaultPath) {
break;
}
}
if (!defaultPath) {
defaultPath = "/marketplace";
}
next({ path: defaultPath }); next({ path: defaultPath });
} else { } else {
next(); next();

View File

@ -1,26 +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 type { RouteRecordRaw } from "vue-router";
import NotFound from "@/views/NotFound.vue";
export const routesNotFound: Array<RouteRecordRaw> = [
{
path: "/:pathMatch(.*)*",
name: "NotFound",
component: NotFound,
},
];

View File

@ -33,7 +33,7 @@ export const routesSettings: Array<RouteRecordRaw> = [
children: [ children: [
{ {
path: "/settings", path: "/settings",
name: "ViewSettings", name: "Settings",
component: Settings, component: Settings,
}, },
], ],

View File

@ -14,15 +14,13 @@
* 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 { WidgetType } from "@/views/dashboard/data";
export const NewControl = { export const NewControl = {
x: 0, x: 0,
y: 0, y: 0,
w: 24, w: 24,
h: 12, h: 12,
i: "0", i: "0",
type: WidgetType.Widget, type: "Widget",
}; };
export const TextConfig = { export const TextConfig = {
fontColor: "white", fontColor: "white",
@ -41,20 +39,17 @@ export const TimeRangeConfig = {
}; };
export const ControlsTypes = [ export const ControlsTypes = [
WidgetType.Trace, "Trace",
WidgetType.Profile, "Profile",
WidgetType.Log, "Log",
WidgetType.DemandLog, "DemandLog",
WidgetType.Ebpf, "Ebpf",
WidgetType.NetworkProfiling, "NetworkProfiling",
WidgetType.AsyncProfiling, "ThirdPartyApp",
WidgetType.ThirdPartyApp, "ContinuousProfiling",
WidgetType.ContinuousProfiling, "TaskTimeline",
WidgetType.TaskTimeline,
]; ];
export enum EBPFProfilingTriggerType { export enum EBPFProfilingTriggerType {
FIXED_TIME = "FIXED_TIME", FIXED_TIME = "FIXED_TIME",
CONTINUOUS_PROFILING = "CONTINUOUS_PROFILING", CONTINUOUS_PROFILING = "CONTINUOUS_PROFILING",
} }
export const EndpointsTopNDefault = 20;

View File

@ -17,8 +17,8 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { store } from "@/store"; import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
import type { AxiosResponse } from "axios";
import type { Alarm } from "@/types/alarm"; import type { Alarm } from "@/types/alarm";
import { useAppStoreWithOut } from "@/store/modules/app";
interface AlarmState { interface AlarmState {
loading: boolean; loading: boolean;
@ -35,24 +35,16 @@ export const alarmStore = defineStore({
}), }),
actions: { actions: {
async getAlarms(params: Recordable) { async getAlarms(params: Recordable) {
this.loading = true; const res: AxiosResponse = await graphql.query("queryAlarms").params(params);
const res = await graphql.query("queryAlarms").params(params); if (res.data.errors) {
this.loading = false; return res.data;
if (res.errors) {
return res;
} }
if (res.data.getAlarm.items) { if (res.data.data.getAlarm.items) {
this.alarms = res.data.getAlarm.items; this.alarms = res.data.data.getAlarm.items;
this.total = res.data.getAlarm.total; this.total = res.data.data.getAlarm.total;
} }
return res.data; return res.data;
}, },
async getAlarmTagKeys() {
return await graphql.query("queryAlarmTagKeys").params({ duration: useAppStoreWithOut().durationTime });
},
async getAlarmTagValues(tagKey: string) {
return await graphql.query("queryAlarmTagValues").params({ tagKey, duration: useAppStoreWithOut().durationTime });
},
}, },
}); });

View File

@ -19,6 +19,7 @@ import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
import type { Duration, DurationTime } from "@/types/app"; import type { Duration, DurationTime } from "@/types/app";
import getLocalTime from "@/utils/localtime"; import getLocalTime from "@/utils/localtime";
import type { AxiosResponse } from "axios";
import dateFormatStep, { dateFormatTime } from "@/utils/dateFormat"; import dateFormatStep, { dateFormatTime } from "@/utils/dateFormat";
import { TimeType } from "@/constants/data"; import { TimeType } from "@/constants/data";
import type { MenuOptions, SubItem } from "@/types/app"; import type { MenuOptions, SubItem } from "@/types/app";
@ -117,6 +118,12 @@ export const appStore = defineStore({
actions: { actions: {
setDuration(data: Duration): void { setDuration(data: Duration): void {
this.durationRow = data; this.durationRow = data;
if ((window as any).axiosCancel.length !== 0) {
for (const event of (window as any).axiosCancel) {
setTimeout(event(), 0);
}
(window as any).axiosCancel = [];
}
this.runEventStack(); this.runEventStack();
}, },
updateDurationRow(data: Duration) { updateDurationRow(data: Duration) {
@ -178,11 +185,11 @@ export const appStore = defineStore({
}); });
}, },
async queryOAPTimeInfo() { async queryOAPTimeInfo() {
const res = await graphql.query("queryOAPTimeInfo").params({}); const res: AxiosResponse = await graphql.query("queryOAPTimeInfo").params({});
if (res.errors) { if (res.data.errors) {
this.utc = -(new Date().getTimezoneOffset() / 60) + ":0"; this.utc = -(new Date().getTimezoneOffset() / 60) + ":0";
} else { } else {
this.utc = res.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]);
@ -190,21 +197,21 @@ export const appStore = defineStore({
return res.data; return res.data;
}, },
async fetchVersion() { async fetchVersion(): Promise<void> {
const res = await graphql.query("queryOAPVersion").params({}); const res: AxiosResponse = await graphql.query("queryOAPVersion").params({});
if (res.errors) { if (res.data.errors) {
return res; return res.data;
} }
this.version = res.data.version; this.version = res.data.data.version;
return res.data; return res.data;
}, },
async queryMenuItems() { async queryMenuItems() {
const res = await graphql.query("queryMenuItems").params({}); const res: AxiosResponse = await graphql.query("queryMenuItems").params({});
if (res.errors) { if (res.data.errors) {
return res; return res.data;
} }
return res.data; return res.data.data;
}, },
setReloadTimer(timer: IntervalHandle) { setReloadTimer(timer: IntervalHandle) {
this.reloadTimer = timer; this.reloadTimer = timer;

View File

@ -1,138 +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 { defineStore } from "pinia";
import type {
AsyncProfilingTask,
AsyncProfileTaskCreationRequest,
AsyncProfilerStackElement,
AsyncProfilerTaskProgress,
} from "@/types/async-profiling";
import { store } from "@/store";
import graphql from "@/graphql";
import { useAppStoreWithOut } from "@/store/modules/app";
import { useSelectorStore } from "@/store/modules/selectors";
import type { Instance } from "@/types/selector";
interface AsyncProfilingState {
taskList: Array<Recordable<AsyncProfilingTask>>;
selectedTask: Recordable<AsyncProfilingTask>;
taskProgress: Recordable<AsyncProfilerTaskProgress>;
instances: Instance[];
analyzeTrees: AsyncProfilerStackElement[];
loadingTree: boolean;
loadingTasks: boolean;
}
export const asyncProfilingStore = defineStore({
id: "asyncProfiling",
state: (): AsyncProfilingState => ({
taskList: [],
selectedTask: {},
taskProgress: {},
instances: [],
analyzeTrees: [],
loadingTree: false,
loadingTasks: false,
}),
actions: {
setSelectedTask(task: Recordable<AsyncProfilingTask>) {
this.selectedTask = task || {};
},
setAnalyzeTrees(tree: AsyncProfilerStackElement[]) {
this.analyzeTrees = tree;
},
async getTaskList() {
const selectorStore = useSelectorStore();
this.loadingTasks = true;
const response = await graphql.query("getAsyncTaskList").params({
request: {
serviceId: selectorStore.currentService.id,
limit: 10000,
},
});
this.loadingTasks = false;
if (response.errors) {
return response;
}
this.taskList = response.data.asyncTaskList.tasks || [];
this.selectedTask = this.taskList[0] || {};
this.setAnalyzeTrees([]);
this.setSelectedTask(this.selectedTask);
if (!this.taskList.length) {
return response;
}
return response;
},
async getTaskLogs(param: { taskID: string }) {
const response = await graphql.query("getAsyncProfileTaskProcess").params(param);
if (response.errors) {
return response;
}
this.taskProgress = response.data.taskProgress;
return response;
},
async getServiceInstances(param: { serviceId: string; isRelation: boolean }) {
if (!param.serviceId) {
return null;
}
const response = await graphql.query("queryInstances").params({
serviceId: param.serviceId,
duration: useAppStoreWithOut().durationTime,
});
if (!response.errors) {
this.instances = (response.data.pods || []).map((d: Instance) => {
d.value = d.id || "";
return d;
});
}
return response;
},
async createTask(param: AsyncProfileTaskCreationRequest) {
const response = await graphql.query("saveAsyncProfileTask").params({ asyncProfilerTaskCreationRequest: param });
if (response.errors) {
return response;
}
this.getTaskList();
return response;
},
async getAsyncProfilingAnalyze(params: { taskId: string; instanceIds: Array<string>; eventType: string }) {
if (!params.instanceIds.length) {
return new Promise((resolve) => resolve({}));
}
this.loadingTree = true;
const response = await graphql.query("getAsyncProfileAnalyze").params({ request: params });
this.loadingTree = false;
if (response.errors) {
this.analyzeTrees = [];
return response;
}
const { analysisResult } = response.data;
if (!analysisResult) {
this.analyzeTrees = [];
return response;
}
this.analyzeTrees = [analysisResult.tree];
return response;
},
},
});
export function useAsyncProfilingStore(): Recordable {
return asyncProfilingStore(store);
}

View File

@ -21,6 +21,7 @@ import type { Instance } from "@/types/selector";
import { store } from "@/store"; import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
import type { MonitorInstance, MonitorProcess } from "@/types/continous-profiling"; import type { MonitorInstance, MonitorProcess } from "@/types/continous-profiling";
import type { AxiosResponse } from "axios";
import { dateFormat } from "@/utils/dateFormat"; import { dateFormat } from "@/utils/dateFormat";
interface ContinousProfilingState { interface ContinousProfilingState {
@ -83,37 +84,37 @@ export const continousProfilingStore = defineStore({
checkItems: CheckItems[]; checkItems: CheckItems[];
}[], }[],
) { ) {
const response = await graphql.query("editStrategy").params({ const res: AxiosResponse = await graphql.query("editStrategy").params({
request: { request: {
serviceId, serviceId,
targets, targets,
}, },
}); });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
return response; return res.data;
}, },
async getStrategyList(params: { serviceId: string }) { async getStrategyList(params: { serviceId: string }) {
if (!params.serviceId) { if (!params.serviceId) {
return new Promise((resolve) => resolve({})); return new Promise((resolve) => resolve({}));
} }
this.policyLoading = true; this.policyLoading = true;
const response = await graphql.query("getStrategyList").params(params); const res: AxiosResponse = await graphql.query("getStrategyList").params(params);
this.policyLoading = false; this.policyLoading = false;
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
const list = response.data.strategyList || []; const list = res.data.data.strategyList || [];
if (!list.length) { if (!list.length) {
this.taskList = []; this.taskList = [];
this.instances = []; this.instances = [];
this.instance = null; this.instance = null;
} }
const arr = list.length ? response.data.strategyList : [{ type: "", checkItems: [{ type: "" }] }]; const arr = list.length ? res.data.data.strategyList : [{ type: "", checkItems: [{ type: "" }] }];
this.strategyList = arr.map((d: StrategyItem, index: number) => { this.strategyList = arr.map((d: StrategyItem, index: number) => {
return { return {
...d, ...d,
@ -122,25 +123,25 @@ export const continousProfilingStore = defineStore({
}); });
this.setSelectedStrategy(this.strategyList[0]); this.setSelectedStrategy(this.strategyList[0]);
if (!this.selectedStrategy.type) { if (!this.selectedStrategy.type) {
return response; return res.data;
} }
this.getMonitoringInstances(params.serviceId); this.getMonitoringInstances(params.serviceId);
return response; return res.data;
}, },
async getMonitoringInstances(serviceId: string) { async getMonitoringInstances(serviceId: string): Promise<Nullable<AxiosResponse>> {
this.instancesLoading = true; this.instancesLoading = true;
if (!serviceId) { if (!serviceId) {
return null; return null;
} }
const response = await graphql.query("getMonitoringInstances").params({ const res: AxiosResponse = await graphql.query("getMonitoringInstances").params({
serviceId, serviceId,
target: this.selectedStrategy.type, target: this.selectedStrategy.type,
}); });
this.instancesLoading = false; this.instancesLoading = false;
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.instances = (response.data.instances || []) this.instances = (res.data.data.instances || [])
.map((d: MonitorInstance) => { .map((d: MonitorInstance) => {
const processes = (d.processes || []) const processes = (d.processes || [])
.sort((c: MonitorProcess, d: MonitorProcess) => d.lastTriggerTimestamp - c.lastTriggerTimestamp) .sort((c: MonitorProcess, d: MonitorProcess) => d.lastTriggerTimestamp - c.lastTriggerTimestamp)
@ -160,7 +161,7 @@ export const continousProfilingStore = defineStore({
}) })
.sort((a: MonitorInstance, b: MonitorInstance) => b.lastTriggerTimestamp - a.lastTriggerTimestamp); .sort((a: MonitorInstance, b: MonitorInstance) => b.lastTriggerTimestamp - a.lastTriggerTimestamp);
this.instance = this.instances[0] || null; this.instance = this.instances[0] || null;
return response; return res.data;
}, },
}, },
}); });

View File

@ -18,12 +18,14 @@ import { defineStore } from "pinia";
import { store } from "@/store"; import { store } from "@/store";
import type { LayoutConfig } from "@/types/dashboard"; import type { LayoutConfig } from "@/types/dashboard";
import graphql from "@/graphql"; import graphql from "@/graphql";
import fetchQuery from "@/graphql/fetch"; import query from "@/graphql/fetch";
import type { DashboardItem } from "@/types/dashboard"; import type { DashboardItem } from "@/types/dashboard";
import { useSelectorStore } from "@/store/modules/selectors"; import { useSelectorStore } from "@/store/modules/selectors";
import { NewControl, TextConfig, TimeRangeConfig, ControlsTypes } from "../data"; import { NewControl, TextConfig, TimeRangeConfig, ControlsTypes } from "../data";
import type { AxiosResponse } from "axios";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { EntityType, WidgetType } from "@/views/dashboard/data"; import { useI18n } from "vue-i18n";
import { EntityType, MetricModes } from "@/views/dashboard/data";
interface DashboardState { interface DashboardState {
showConfig: boolean; showConfig: boolean;
layout: LayoutConfig[]; layout: LayoutConfig[];
@ -76,7 +78,7 @@ export const dashboardStore = defineStore({
setCurrentDashboard(item: DashboardItem) { setCurrentDashboard(item: DashboardItem) {
this.currentDashboard = item; this.currentDashboard = item;
}, },
addControl(type: WidgetType) { addControl(type: string) {
const arr = this.layout.map((d: Recordable) => Number(d.i)); const arr = this.layout.map((d: Recordable) => Number(d.i));
let index = String(Math.max(...arr) + 1); let index = String(Math.max(...arr) + 1);
if (!this.layout.length) { if (!this.layout.length) {
@ -87,8 +89,14 @@ export const dashboardStore = defineStore({
i: index, i: index,
id: index, id: index,
type, type,
metricTypes: [""],
metrics: [""],
}; };
if (type === WidgetType.Tab) {
if (type === "Widget") {
newItem.metricMode = MetricModes.Expression;
}
if (type === "Tab") {
newItem.h = 36; newItem.h = 36;
newItem.activedTabIndex = 0; newItem.activedTabIndex = 0;
newItem.children = [ newItem.children = [
@ -102,7 +110,7 @@ export const dashboardStore = defineStore({
}, },
]; ];
} }
if (type === WidgetType.Topology) { if (type === "Topology") {
newItem.h = 36; newItem.h = 36;
newItem.graph = { newItem.graph = {
showDepth: true, showDepth: true,
@ -112,11 +120,11 @@ export const dashboardStore = defineStore({
if (ControlsTypes.includes(type)) { if (ControlsTypes.includes(type)) {
newItem.h = 36; newItem.h = 36;
} }
if (type === WidgetType.Text) { if (type === "Text") {
newItem.h = 6; newItem.h = 6;
newItem.graph = TextConfig; newItem.graph = TextConfig;
} }
if (type === WidgetType.TimeRange) { if (type === "TimeRange") {
newItem.w = 8; newItem.w = 8;
newItem.h = 6; newItem.h = 6;
newItem.graph = TimeRangeConfig; newItem.graph = TimeRangeConfig;
@ -141,7 +149,7 @@ export const dashboardStore = defineStore({
}; };
this.layout[idx].children?.push(i); this.layout[idx].children?.push(i);
}, },
addTabControls(type: WidgetType) { addTabControls(type: string) {
const activedGridItem = this.activedGridItem.split("-")[0]; const activedGridItem = this.activedGridItem.split("-")[0];
const idx = this.layout.findIndex((d: LayoutConfig) => d.i === activedGridItem); const idx = this.layout.findIndex((d: LayoutConfig) => d.i === activedGridItem);
if (idx < 0) { if (idx < 0) {
@ -160,21 +168,27 @@ export const dashboardStore = defineStore({
i: index, i: index,
id, id,
type, type,
metricTypes: [""],
metrics: [""],
}; };
if (type === WidgetType.Topology) { if (type === "Widget") {
newItem.metricMode = MetricModes.Expression;
}
if (type === "Topology") {
newItem.h = 32; newItem.h = 32;
newItem.graph = { newItem.graph = {
showDepth: true, showDepth: true,
}; };
newItem.metricMode = MetricModes.Expression;
} }
if (ControlsTypes.includes(type)) { if (ControlsTypes.includes(type)) {
newItem.h = 32; newItem.h = 32;
} }
if (type === WidgetType.Text) { if (type === "Text") {
newItem.h = 6; newItem.h = 6;
newItem.graph = TextConfig; newItem.graph = TextConfig;
} }
if (type === WidgetType.TimeRange) { if (type === "TimeRange") {
newItem.w = 8; newItem.w = 8;
newItem.h = 6; newItem.h = 6;
newItem.graph = TextConfig; newItem.graph = TextConfig;
@ -278,7 +292,7 @@ export const dashboardStore = defineStore({
}, },
setWidget(param: LayoutConfig) { setWidget(param: LayoutConfig) {
for (let i = 0; i < this.layout.length; i++) { for (let i = 0; i < this.layout.length; i++) {
if (this.layout[i].type === WidgetType.Tab) { if (this.layout[i].type === "Tab") {
if ((this.layout[i].children || []).length) { if ((this.layout[i].children || []).length) {
for (const child of this.layout[i].children || []) { for (const child of this.layout[i].children || []) {
if (child.children && child.children.length) { if (child.children && child.children.length) {
@ -298,24 +312,43 @@ export const dashboardStore = defineStore({
} }
} }
}, },
async fetchMetricType(item: string) {
const res: AxiosResponse = await graphql.query("queryTypeOfMetrics").params({ name: item });
return res.data;
},
async getTypeOfMQE(expression: string) {
const res: AxiosResponse = await graphql.query("getTypeOfMQE").params({ expression });
return res.data;
},
async fetchMetricList(regex: string) {
const res: AxiosResponse = await graphql.query("queryMetrics").params({ regex });
return res.data;
},
async fetchMetricValue(param: { queryStr: string; conditions: { [key: string]: unknown } }) { async fetchMetricValue(param: { queryStr: string; conditions: { [key: string]: unknown } }) {
return await fetchQuery(param); const res: AxiosResponse = await query(param);
return res.data;
}, },
async fetchTemplates() { async fetchTemplates() {
const res = await graphql.query("getTemplates").params({}); const res: AxiosResponse = await graphql.query("getTemplates").params({});
if (res.errors) { if (res.data.errors) {
return res; return res.data;
} }
const data = res.data.getAllTemplates; const data = res.data.data.getAllTemplates;
let list = []; let list = [];
for (const t of data) { for (const t of data) {
const c = JSON.parse(t.configuration); const c = JSON.parse(t.configuration);
const key = [c.layer, c.entity, c.name].join("_"); const key = [c.layer, c.entity, c.name].join("_");
list.push({ list.push({
...c,
id: t.id, id: t.id,
children: undefined, layer: c.layer,
entity: c.entity,
name: c.name,
isRoot: c.isRoot,
}); });
sessionStorage.setItem(key, JSON.stringify({ id: t.id, configuration: c })); sessionStorage.setItem(key, JSON.stringify({ id: t.id, configuration: c }));
} }
@ -354,20 +387,20 @@ export const dashboardStore = defineStore({
this.dashboards = JSON.parse(sessionStorage.getItem("dashboards") || "[]"); this.dashboards = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
}, },
async updateDashboard(setting: { id: string; configuration: string }) { async updateDashboard(setting: { id: string; configuration: string }) {
const resp = await graphql.query("updateTemplate").params({ const res: AxiosResponse = await graphql.query("updateTemplate").params({
setting, setting,
}); });
if (resp.errors) { if (res.data.errors) {
ElMessage.error(resp.errors); ElMessage.error(res.data.errors);
return resp; return res.data;
} }
const json = resp.data.changeTemplate; const json = res.data.data.changeTemplate;
if (!json.status) { if (!json.status) {
ElMessage.error(json.message); ElMessage.error(json.message);
return resp; return res.data;
} }
ElMessage.success("Saved successfully"); ElMessage.success("Saved successfully");
return resp; return res.data;
}, },
async saveDashboard() { async saveDashboard() {
if (!this.currentDashboard?.name) { if (!this.currentDashboard?.name) {
@ -396,19 +429,20 @@ export const dashboardStore = defineStore({
d.layer === this.currentDashboard?.layer, d.layer === this.currentDashboard?.layer,
); );
if (index > -1) { if (index > -1) {
ElMessage.error("The dashboard name cannot be duplicate"); const { t } = useI18n();
ElMessage.error(t("nameError"));
return; return;
} }
res = await graphql.query("addNewTemplate").params({ setting: { configuration: JSON.stringify(c) } }); res = await graphql.query("addNewTemplate").params({ setting: { configuration: JSON.stringify(c) } });
json = res.data.addTemplate; json = res.data.data.addTemplate;
if (!json.status) { if (!json.status) {
ElMessage.error(json.message); ElMessage.error(json.message);
} }
} }
if (res.errors) { if (res.data.errors || res.errors) {
ElMessage.error(res.errors); ElMessage.error(res.data.errors);
return res; return res.data;
} }
if (!json.status) { if (!json.status) {
return json; return json;
@ -430,16 +464,16 @@ export const dashboardStore = defineStore({
return json; return json;
}, },
async deleteDashboard() { async deleteDashboard() {
const res = await graphql.query("removeTemplate").params({ id: this.currentDashboard?.id }); const res: AxiosResponse = await graphql.query("removeTemplate").params({ id: this.currentDashboard?.id });
if (res.errors) { if (res.data.errors) {
ElMessage.error(res.errors); ElMessage.error(res.data.errors);
return res; return res.data;
} }
const json = res.data.disableTemplate; const json = res.data.data.disableTemplate;
if (!json.status) { if (!json.status) {
ElMessage.error(json.message); ElMessage.error(json.message);
return res; return res.data;
} }
this.dashboards = this.dashboards.filter((d: Recordable) => d.id !== this.currentDashboard?.id); this.dashboards = this.dashboards.filter((d: Recordable) => d.id !== this.currentDashboard?.id);
const key = [this.currentDashboard?.layer, this.currentDashboard?.entity, this.currentDashboard?.name].join("_"); const key = [this.currentDashboard?.layer, this.currentDashboard?.entity, this.currentDashboard?.name].join("_");

View File

@ -18,6 +18,7 @@ import { defineStore } from "pinia";
import type { Instance } from "@/types/selector"; import type { Instance } from "@/types/selector";
import { store } from "@/store"; import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
import type { 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 type { Conditions, Log } from "@/types/demand-log"; import type { Conditions, Log } from "@/types/demand-log";
@ -59,16 +60,16 @@ export const demandLogStore = defineStore({
}, },
async getInstances(id: string) { async getInstances(id: string) {
const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id; const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id;
const response = await graphql.query("queryInstances").params({ const res: AxiosResponse = await graphql.query("queryInstances").params({
serviceId, serviceId,
duration: useAppStoreWithOut().durationTime, duration: useAppStoreWithOut().durationTime,
}); });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.instances = response.data.pods || []; this.instances = res.data.data.pods || [];
return response; return res.data;
}, },
async getContainers(serviceInstanceId: string) { async getContainers(serviceInstanceId: string) {
if (!serviceInstanceId) { if (!serviceInstanceId) {
@ -77,35 +78,35 @@ export const demandLogStore = defineStore({
const condition = { const condition = {
serviceInstanceId, serviceInstanceId,
}; };
const response = await graphql.query("fetchContainers").params({ condition }); const res: AxiosResponse = await graphql.query("fetchContainers").params({ condition });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
if (response.data.containers.errorReason) { if (res.data.data.containers.errorReason) {
this.containers = [{ label: "", value: "" }]; this.containers = [{ label: "", value: "" }];
return response; return res.data;
} }
this.containers = response.data.containers.containers.map((d: string) => { this.containers = res.data.data.containers.containers.map((d: string) => {
return { label: d, value: d }; return { label: d, value: d };
}); });
return response; return res.data;
}, },
async getDemandLogs() { async getDemandLogs() {
this.loadLogs = true; this.loadLogs = true;
const response = await graphql.query("fetchDemandPodLogs").params({ condition: this.conditions }); const res: AxiosResponse = await graphql.query("fetchDemandPodLogs").params({ condition: this.conditions });
this.loadLogs = false; this.loadLogs = false;
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
if (response.data.logs.errorReason) { if (res.data.data.logs.errorReason) {
this.setLogs([], response.data.logs.errorReason); this.setLogs([], res.data.data.logs.errorReason);
return response; return res.data;
} }
this.total = response.data.logs.logs.length; this.total = res.data.data.logs.logs.length;
const logs = response.data.logs.logs.map((d: Log) => d.content).join("\n"); const logs = res.data.data.logs.logs.map((d: Log) => d.content).join("\n");
this.setLogs(logs); this.setLogs(logs);
return response; return res.data;
}, },
}, },
}); });

View File

@ -19,6 +19,7 @@ import type { Option } from "@/types/app";
import type { EBPFTaskCreationRequest, EBPFProfilingSchedule, EBPFTaskList, AnalyzationTrees } from "@/types/ebpf"; import type { EBPFTaskCreationRequest, EBPFProfilingSchedule, EBPFTaskList, AnalyzationTrees } from "@/types/ebpf";
import { store } from "@/store"; import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
import type { AxiosResponse } from "axios";
import { EBPFProfilingTriggerType } from "../data"; import { EBPFProfilingTriggerType } from "../data";
interface EbpfState { interface EbpfState {
taskList: Array<Recordable<EBPFTaskList>>; taskList: Array<Recordable<EBPFTaskList>>;
@ -56,70 +57,70 @@ export const ebpfStore = defineStore({
this.analyzeTrees = tree; this.analyzeTrees = tree;
}, },
async getCreateTaskData(serviceId: string) { async getCreateTaskData(serviceId: string) {
const response = await graphql.query("getCreateTaskData").params({ serviceId }); const res: AxiosResponse = await graphql.query("getCreateTaskData").params({ serviceId });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
const json = response.data.createTaskData; const json = res.data.data.createTaskData;
this.couldProfiling = json.couldProfiling || false; this.couldProfiling = json.couldProfiling || false;
this.labels = json.processLabels.map((d: string) => { this.labels = json.processLabels.map((d: string) => {
return { label: d, value: d }; return { label: d, value: d };
}); });
return response; return res.data;
}, },
async createTask(param: EBPFTaskCreationRequest) { async createTask(param: EBPFTaskCreationRequest) {
const response = await graphql.query("saveEBPFTask").params({ request: param }); const res: AxiosResponse = await graphql.query("saveEBPFTask").params({ request: param });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.getTaskList({ this.getTaskList({
serviceId: param.serviceId, serviceId: param.serviceId,
targets: ["ON_CPU", "OFF_CPU"], targets: ["ON_CPU", "OFF_CPU"],
triggerType: EBPFProfilingTriggerType.FIXED_TIME, triggerType: EBPFProfilingTriggerType.FIXED_TIME,
}); });
return response; return res.data;
}, },
async getTaskList(params: { serviceId: string; targets: string[] }) { async getTaskList(params: { serviceId: string; targets: string[] }) {
if (!params.serviceId) { if (!params.serviceId) {
return new Promise((resolve) => resolve({})); return new Promise((resolve) => resolve({}));
} }
const response = await graphql.query("getEBPFTasks").params(params); const res: AxiosResponse = await graphql.query("getEBPFTasks").params(params);
this.ebpfTips = ""; this.ebpfTips = "";
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.taskList = response.data.queryEBPFTasks || []; this.taskList = res.data.data.queryEBPFTasks || [];
this.selectedTask = this.taskList[0] || {}; this.selectedTask = this.taskList[0] || {};
this.setSelectedTask(this.selectedTask); this.setSelectedTask(this.selectedTask);
if (!this.taskList.length) { if (!this.taskList.length) {
return response; return res.data;
} }
this.getEBPFSchedules({ taskId: String(this.taskList[0].taskId) }); this.getEBPFSchedules({ taskId: String(this.taskList[0].taskId) });
return response; return res.data;
}, },
async getEBPFSchedules(params: { taskId: string }) { async getEBPFSchedules(params: { taskId: string }) {
if (!params.taskId) { if (!params.taskId) {
return new Promise((resolve) => resolve({})); return new Promise((resolve) => resolve({}));
} }
const response = await graphql.query("getEBPFSchedules").params({ ...params }); const res: AxiosResponse = await graphql.query("getEBPFSchedules").params({ ...params });
if (response.errors) { if (res.data.errors) {
this.eBPFSchedules = []; this.eBPFSchedules = [];
return response; return res.data;
} }
this.ebpfTips = ""; this.ebpfTips = "";
const { eBPFSchedules } = response.data; const { eBPFSchedules } = res.data.data;
this.eBPFSchedules = eBPFSchedules; this.eBPFSchedules = eBPFSchedules;
if (!eBPFSchedules.length) { if (!eBPFSchedules.length) {
this.eBPFSchedules = []; this.eBPFSchedules = [];
this.analyzeTrees = []; this.analyzeTrees = [];
} }
return response; return res.data;
}, },
async getEBPFAnalyze(params: { async getEBPFAnalyze(params: {
scheduleIdList: string[]; scheduleIdList: string[];
@ -133,24 +134,24 @@ export const ebpfStore = defineStore({
if (!params.timeRanges.length) { if (!params.timeRanges.length) {
return new Promise((resolve) => resolve({})); return new Promise((resolve) => resolve({}));
} }
const response = await graphql.query("getEBPFResult").params(params); const res: AxiosResponse = await graphql.query("getEBPFResult").params(params);
if (response.errors) { if (res.data.errors) {
this.analyzeTrees = []; this.analyzeTrees = [];
return response; return res.data;
} }
const { analysisEBPFResult } = response.data; const { analysisEBPFResult } = res.data.data;
this.ebpfTips = analysisEBPFResult.tip; this.ebpfTips = analysisEBPFResult.tip;
if (!analysisEBPFResult) { if (!analysisEBPFResult) {
this.analyzeTrees = []; this.analyzeTrees = [];
return response; return res.data;
} }
if (analysisEBPFResult.tip) { if (analysisEBPFResult.tip) {
this.analyzeTrees = []; this.analyzeTrees = [];
return response; return res.data;
} }
this.analyzeTrees = analysisEBPFResult.trees; this.analyzeTrees = analysisEBPFResult.trees;
return response; return res.data;
}, },
}, },
}); });

View File

@ -17,11 +17,11 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { store } from "@/store"; import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
import type { AxiosResponse } from "axios";
import type { Event, QueryEventCondition } from "@/types/events"; import type { Event, QueryEventCondition } from "@/types/events";
import type { Instance, Endpoint } from "@/types/selector"; import type { Instance, Endpoint } from "@/types/selector";
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 { EndpointsTopNDefault } from "../data";
interface eventState { interface eventState {
loading: boolean; loading: boolean;
@ -46,48 +46,47 @@ export const eventStore = defineStore({
}, },
async getInstances() { async getInstances() {
const serviceId = useSelectorStore().currentService ? useSelectorStore().currentService.id : ""; const serviceId = useSelectorStore().currentService ? useSelectorStore().currentService.id : "";
const response = await graphql.query("queryInstances").params({ const res: AxiosResponse = await graphql.query("queryInstances").params({
serviceId, serviceId,
duration: useAppStoreWithOut().durationTime, duration: useAppStoreWithOut().durationTime,
}); });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.instances = [{ value: "", label: "All" }, ...response.data.pods]; this.instances = [{ value: "", label: "All" }, ...res.data.data.pods] || [{ value: "", label: "All" }];
return response; return res.data;
}, },
async getEndpoints(keyword: string) { async getEndpoints(keyword: string) {
const serviceId = useSelectorStore().currentService ? useSelectorStore().currentService.id : ""; const serviceId = useSelectorStore().currentService ? useSelectorStore().currentService.id : "";
if (!serviceId) { if (!serviceId) {
return; return;
} }
const response = await graphql.query("queryEndpoints").params({ const res: AxiosResponse = await graphql.query("queryEndpoints").params({
serviceId, serviceId,
duration: useAppStoreWithOut().durationTime, duration: useAppStoreWithOut().durationTime,
keyword: keyword || "", keyword: keyword || "",
limit: EndpointsTopNDefault,
}); });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.endpoints = [{ value: "", label: "All" }, ...response.data.pods]; this.endpoints = [{ value: "", label: "All" }, ...res.data.data.pods] || [{ value: "", label: "All" }];
return response; return res.data;
}, },
async getEvents() { async getEvents() {
this.loading = true; this.loading = true;
const response = await graphql.query("queryEvents").params({ const res: AxiosResponse = await graphql.query("queryEvents").params({
condition: { condition: {
...this.condition, ...this.condition,
time: useAppStoreWithOut().durationTime, time: useAppStoreWithOut().durationTime,
}, },
}); });
this.loading = false; this.loading = false;
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
if (response.data.fetchEvents) { if (res.data.data.fetchEvents) {
this.events = (response.data.fetchEvents.events || []).map((item: Event) => { this.events = (res.data.data.fetchEvents.events || []).map((item: Event) => {
let scope = "Service"; let scope = "Service";
if (item.source.serviceInstance) { if (item.source.serviceInstance) {
scope = "ServiceInstance"; scope = "ServiceInstance";
@ -102,7 +101,7 @@ export const eventStore = defineStore({
return item; return item;
}); });
} }
return response; return res.data;
}, },
}, },
}); });

View File

@ -18,10 +18,10 @@ import { defineStore } from "pinia";
import type { Instance, Endpoint, Service } from "@/types/selector"; import type { Instance, Endpoint, Service } from "@/types/selector";
import { store } from "@/store"; import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
import type { 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 { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { EndpointsTopNDefault } from "../data";
interface LogState { interface LogState {
services: Service[]; services: Service[];
@ -61,51 +61,50 @@ export const logStore = defineStore({
}; };
}, },
async getServices(layer: string) { async getServices(layer: string) {
const response = await graphql.query("queryServices").params({ const res: AxiosResponse = await graphql.query("queryServices").params({
layer, layer,
}); });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.services = response.data.services; this.services = res.data.data.services;
return response; return res.data;
}, },
async getInstances(id: string) { async getInstances(id: string) {
const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id; const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id;
const response = await graphql.query("queryInstances").params({ const res: AxiosResponse = await graphql.query("queryInstances").params({
serviceId, serviceId,
duration: useAppStoreWithOut().durationTime, duration: useAppStoreWithOut().durationTime,
}); });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.instances = [{ value: "0", label: "All" }, ...response.data.pods]; this.instances = [{ value: "0", label: "All" }, ...res.data.data.pods] || [{ value: " 0", label: "All" }];
return response; return res.data;
}, },
async getEndpoints(id: string, keyword?: string) { async getEndpoints(id: string, keyword?: string) {
const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id; const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id;
const response = await graphql.query("queryEndpoints").params({ const res: AxiosResponse = await graphql.query("queryEndpoints").params({
serviceId, serviceId,
duration: useAppStoreWithOut().durationTime, duration: useAppStoreWithOut().durationTime,
keyword: keyword || "", keyword: keyword || "",
limit: EndpointsTopNDefault,
}); });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.endpoints = [{ value: "0", label: "All" }, ...response.data.pods]; this.endpoints = [{ value: "0", label: "All" }, ...res.data.data.pods] || [{ value: "0", label: "All" }];
return response; return res.data;
}, },
async getLogsByKeywords() { async getLogsByKeywords() {
const response = await graphql.query("queryLogsByKeywords").params({}); const res: AxiosResponse = await graphql.query("queryLogsByKeywords").params({});
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.supportQueryLogsByKeywords = response.data.support; this.supportQueryLogsByKeywords = res.data.data.support;
return response; return res.data;
}, },
async getLogs() { async getLogs() {
const dashboardStore = useDashboardStore(); const dashboardStore = useDashboardStore();
@ -116,31 +115,39 @@ export const logStore = defineStore({
}, },
async getServiceLogs() { async getServiceLogs() {
this.loadLogs = true; this.loadLogs = true;
const response = await graphql.query("queryServiceLogs").params({ condition: this.conditions }); const res: AxiosResponse = await graphql.query("queryServiceLogs").params({ condition: this.conditions });
this.loadLogs = false; this.loadLogs = false;
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.logs = response.data.queryLogs.logs; this.logs = res.data.data.queryLogs.logs;
return response; return res.data;
}, },
async getBrowserLogs() { async getBrowserLogs() {
this.loadLogs = true; this.loadLogs = true;
const response = await graphql.query("queryBrowserErrorLogs").params({ condition: this.conditions }); const res: AxiosResponse = await graphql.query("queryBrowserErrorLogs").params({ condition: this.conditions });
this.loadLogs = false; this.loadLogs = false;
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.logs = response.data.queryBrowserErrorLogs.logs; this.logs = res.data.data.queryBrowserErrorLogs.logs;
return response; return res.data;
}, },
async getLogTagKeys() { async getLogTagKeys() {
return await graphql.query("queryLogTagKeys").params({ duration: useAppStoreWithOut().durationTime }); const res: AxiosResponse = await graphql
.query("queryLogTagKeys")
.params({ duration: useAppStoreWithOut().durationTime });
return res.data;
}, },
async getLogTagValues(tagKey: string) { async getLogTagValues(tagKey: string) {
return await graphql.query("queryLogTagValues").params({ tagKey, duration: useAppStoreWithOut().durationTime }); const res: AxiosResponse = await graphql
.query("queryLogTagValues")
.params({ tagKey, duration: useAppStoreWithOut().durationTime });
return res.data;
}, },
}, },
}); });

View File

@ -18,6 +18,7 @@ import { defineStore } from "pinia";
import type { EBPFTaskList, ProcessNode } from "@/types/ebpf"; import type { EBPFTaskList, ProcessNode } from "@/types/ebpf";
import { store } from "@/store"; import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
import type { AxiosResponse } from "axios";
import type { Call } from "@/types/topology"; import type { Call } from "@/types/topology";
import type { LayoutConfig } from "@/types/dashboard"; import type { LayoutConfig } from "@/types/dashboard";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
@ -125,65 +126,65 @@ export const networkProfilingStore = defineStore({
minDuration: number; minDuration: number;
}[], }[],
) { ) {
const response = await graphql.query("newNetworkProfiling").params({ const res: AxiosResponse = await graphql.query("newNetworkProfiling").params({
request: { request: {
instanceId, instanceId,
samplings: params, samplings: params,
}, },
}); });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
return response; return res.data;
}, },
async getTaskList(params: { serviceId: string; serviceInstanceId: string; targets: string[] }) { async getTaskList(params: { serviceId: string; serviceInstanceId: string; targets: string[] }) {
if (!params.serviceId) { if (!params.serviceId) {
return new Promise((resolve) => resolve({})); return new Promise((resolve) => resolve({}));
} }
const response = await graphql.query("getEBPFTasks").params(params); const res: AxiosResponse = await graphql.query("getEBPFTasks").params(params);
this.networkTip = ""; this.networkTip = "";
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.networkTasks = response.data.queryEBPFTasks || []; this.networkTasks = res.data.data.queryEBPFTasks || [];
this.selectedNetworkTask = this.networkTasks[0] || {}; this.selectedNetworkTask = this.networkTasks[0] || {};
this.setSelectedNetworkTask(this.selectedNetworkTask); this.setSelectedNetworkTask(this.selectedNetworkTask);
if (!this.networkTasks.length) { if (!this.networkTasks.length) {
this.nodes = []; this.nodes = [];
this.calls = []; this.calls = [];
} }
return response; return res.data;
}, },
async keepNetworkProfiling(taskId: string) { async keepNetworkProfiling(taskId: string) {
if (!taskId) { if (!taskId) {
return new Promise((resolve) => resolve({})); return new Promise((resolve) => resolve({}));
} }
const response = await graphql.query("aliveNetworkProfiling").params({ taskId }); const res: AxiosResponse = await graphql.query("aliveNetworkProfiling").params({ taskId });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.aliveNetwork = response.data.keepEBPFNetworkProfiling.status; this.aliveNetwork = res.data.data.keepEBPFNetworkProfiling.status;
if (!this.aliveNetwork) { if (!this.aliveNetwork) {
ElMessage.warning(response.data.keepEBPFNetworkProfiling.errorReason); ElMessage.warning(res.data.data.keepEBPFNetworkProfiling.errorReason);
} }
return response; return res.data;
}, },
async getProcessTopology(params: { duration: DurationTime; serviceInstanceId: string }) { async getProcessTopology(params: { duration: DurationTime; serviceInstanceId: string }) {
this.loadNodes = true; this.loadNodes = true;
const response = await graphql.query("getProcessTopology").params(params); const res: AxiosResponse = await graphql.query("getProcessTopology").params(params);
this.loadNodes = false; this.loadNodes = false;
if (response.errors) { if (res.data.errors) {
this.nodes = []; this.nodes = [];
this.calls = []; this.calls = [];
return response; return res.data;
} }
const { topology } = response.data; const { topology } = res.data.data;
this.setTopology(topology); this.setTopology(topology);
return response; return res.data;
}, },
}, },
}); });

View File

@ -26,8 +26,8 @@ import type {
import type { Trace } from "@/types/trace"; import type { Trace } from "@/types/trace";
import { store } from "@/store"; import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
import type { AxiosResponse } from "axios";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
import { EndpointsTopNDefault } from "../data";
interface ProfileState { interface ProfileState {
endpoints: Endpoint[]; endpoints: Endpoint[];
@ -80,7 +80,7 @@ export const profileStore = defineStore({
this.analyzeTrees = []; this.analyzeTrees = [];
}, },
setCurrentSegment(segment: Trace) { setCurrentSegment(segment: Trace) {
this.currentSegment = segment || {}; this.currentSegment = segment;
this.segmentSpans = segment.spans || []; this.segmentSpans = segment.spans || [];
if (segment.spans) { if (segment.spans) {
this.currentSpan = segment.spans[0] || {}; this.currentSpan = segment.spans[0] || {};
@ -93,38 +93,36 @@ export const profileStore = defineStore({
this.highlightTop = !this.highlightTop; this.highlightTop = !this.highlightTop;
}, },
async getEndpoints(serviceId: string, keyword?: string) { async getEndpoints(serviceId: string, keyword?: string) {
const response = await graphql.query("queryEndpoints").params({ const res: AxiosResponse = await graphql.query("queryEndpoints").params({
serviceId, serviceId,
duration: useAppStoreWithOut().durationTime, duration: useAppStoreWithOut().durationTime,
keyword: keyword || "", keyword: keyword || "",
limit: EndpointsTopNDefault,
}); });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.endpoints = response.data.pods || []; this.endpoints = res.data.data.pods || [];
return response.data; return res.data;
}, },
async getTaskEndpoints(serviceId: string, keyword?: string) { async getTaskEndpoints(serviceId: string, keyword?: string) {
const response = await graphql.query("queryEndpoints").params({ const res: AxiosResponse = await graphql.query("queryEndpoints").params({
serviceId, serviceId,
duration: useAppStoreWithOut().durationTime, duration: useAppStoreWithOut().durationTime,
keyword: keyword || "", keyword: keyword || "",
limit: EndpointsTopNDefault,
}); });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.taskEndpoints = [{ value: "", label: "All" }, ...response.data.pods]; this.taskEndpoints = [{ value: "", label: "All" }, ...res.data.data.pods];
return response; return res.data;
}, },
async getTaskList() { async getTaskList() {
const response = await graphql.query("getProfileTaskList").params(this.condition); const res: AxiosResponse = await graphql.query("getProfileTaskList").params(this.condition);
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
const list = response.data.taskList || []; const list = res.data.data.taskList || [];
this.taskList = list; this.taskList = list;
this.currentTask = list[0] || {}; this.currentTask = list[0] || {};
if (!list.length) { if (!list.length) {
@ -132,52 +130,52 @@ export const profileStore = defineStore({
this.segmentSpans = []; this.segmentSpans = [];
this.analyzeTrees = []; this.analyzeTrees = [];
return response; return res.data;
} }
this.getSegmentList({ taskID: list[0].id }); this.getSegmentList({ taskID: list[0].id });
return response; return res.data;
}, },
async getSegmentList(params: { taskID: string }) { async getSegmentList(params: { taskID: string }) {
if (!params.taskID) { if (!params.taskID) {
return new Promise((resolve) => resolve({})); return new Promise((resolve) => resolve({}));
} }
const response = await graphql.query("getProfileTaskSegmentList").params(params); const res: AxiosResponse = await graphql.query("getProfileTaskSegmentList").params(params);
if (response.errors) { if (res.data.errors) {
this.segmentList = []; this.segmentList = [];
return response; return res.data;
} }
const { segmentList } = response.data; const { segmentList } = res.data.data;
this.segmentList = segmentList || []; this.segmentList = segmentList || [];
if (!segmentList.length) { if (!segmentList.length) {
this.segmentSpans = []; this.segmentSpans = [];
this.analyzeTrees = []; this.analyzeTrees = [];
return response; return res.data;
} }
if (segmentList[0]) { if (segmentList[0]) {
this.setCurrentSegment(segmentList[0]); this.currentSegment = segmentList[0];
this.getSegmentSpans(segmentList[0].segmentId); this.getSegmentSpans(segmentList[0].segmentId);
} else { } else {
this.setCurrentSegment({}); this.currentSegment = {};
} }
return response; return res.data;
}, },
async getSegmentSpans(params: { segmentId: string }) { async getSegmentSpans(params: { segmentId: string }) {
if (!(params && params.segmentId)) { if (!(params && params.segmentId)) {
return new Promise((resolve) => resolve({})); return new Promise((resolve) => resolve({}));
} }
const response = await graphql.query("queryProfileSegment").params(params); const res: AxiosResponse = await graphql.query("queryProfileSegment").params(params);
if (response.errors) { if (res.data.errors) {
this.segmentSpans = []; this.segmentSpans = [];
return response; return res.data;
} }
const { segment } = response.data; const { segment } = res.data.data;
if (!segment) { if (!segment) {
this.segmentSpans = []; this.segmentSpans = [];
this.analyzeTrees = []; this.analyzeTrees = [];
return response; return res.data;
} }
this.segmentSpans = segment.spans.map((d: SegmentSpan) => { this.segmentSpans = segment.spans.map((d: SegmentSpan) => {
return { return {
@ -188,52 +186,52 @@ export const profileStore = defineStore({
}); });
if (!(segment.spans && segment.spans.length)) { if (!(segment.spans && segment.spans.length)) {
this.analyzeTrees = []; this.analyzeTrees = [];
return response; return res.data;
} }
const index = segment.spans.length - 1 || 0; const index = segment.spans.length - 1 || 0;
this.currentSpan = segment.spans[index]; this.currentSpan = segment.spans[index];
return response; return res.data;
}, },
async getProfileAnalyze(params: Array<{ segmentId: string; timeRange: { start: number; end: number } }>) { async getProfileAnalyze(params: Array<{ segmentId: string; timeRange: { start: number; end: number } }>) {
if (!params.length) { if (!params.length) {
return new Promise((resolve) => resolve({})); return new Promise((resolve) => resolve({}));
} }
const response = await graphql.query("getProfileAnalyze").params({ queries: params }); const res: AxiosResponse = await graphql.query("getProfileAnalyze").params({ queries: params });
if (response.errors) { if (res.data.errors) {
this.analyzeTrees = []; this.analyzeTrees = [];
return response; return res.data;
} }
const { analyze, tip } = response.data; const { analyze, tip } = res.data.data;
if (tip) { if (tip) {
this.analyzeTrees = []; this.analyzeTrees = [];
return response; return res.data;
} }
if (!analyze) { if (!analyze) {
this.analyzeTrees = []; this.analyzeTrees = [];
return response; return res.data;
} }
this.analyzeTrees = analyze.trees; this.analyzeTrees = analyze.trees;
return response; return res.data;
}, },
async createTask(param: ProfileTaskCreationRequest) { async createTask(param: ProfileTaskCreationRequest) {
const response = await graphql.query("saveProfileTask").params({ creationRequest: param }); const res: AxiosResponse = await graphql.query("saveProfileTask").params({ creationRequest: param });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.getTaskList(); this.getTaskList();
return response; return res.data;
}, },
async getTaskLogs(param: { taskID: string }) { async getTaskLogs(param: { taskID: string }) {
const response = await graphql.query("getProfileTaskLogs").params(param); const res: AxiosResponse = await graphql.query("getProfileTaskLogs").params(param);
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.taskLogs = response.data.taskLogs; this.taskLogs = res.data.data.taskLogs;
return response; return res.data;
}, },
}, },
}); });

View File

@ -18,8 +18,8 @@ import { defineStore } from "pinia";
import type { Service, Instance, Endpoint, Process } from "@/types/selector"; import type { Service, Instance, Endpoint, Process } from "@/types/selector";
import { store } from "@/store"; import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
import type { AxiosResponse } from "axios";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
import { EndpointsTopNDefault } from "../data";
interface SelectorState { interface SelectorState {
services: Service[]; services: Service[];
destServices: Service[]; destServices: Service[];
@ -76,55 +76,62 @@ export const selectorStore = defineStore({
setDestProcesses(processes: Array<Process>) { setDestProcesses(processes: Array<Process>) {
this.destProcesses = processes; this.destProcesses = processes;
}, },
async fetchLayers() { async fetchLayers(): Promise<AxiosResponse> {
return await graphql.query("queryLayers").params({}); const res: AxiosResponse = await graphql.query("queryLayers").params({});
},
async fetchServices(layer: string) {
const res = await graphql.query("queryServices").params({ layer });
if (!res.errors) { return res.data || {};
this.services = res.data.services || []; },
this.destServices = res.data.services || []; async fetchServices(layer: string): Promise<AxiosResponse> {
const res: AxiosResponse = await graphql.query("queryServices").params({ layer });
if (!res.data.errors) {
this.services = res.data.data.services || [];
this.destServices = res.data.data.services || [];
} }
return res.data; return res.data;
}, },
async getServiceInstances(param?: { serviceId: string; isRelation: boolean }) { async getServiceInstances(param?: { serviceId: string; isRelation: boolean }): Promise<Nullable<AxiosResponse>> {
const serviceId = param ? param.serviceId : this.currentService?.id; const serviceId = param ? param.serviceId : this.currentService?.id;
if (!serviceId) { if (!serviceId) {
return null; return null;
} }
const resp = await graphql.query("queryInstances").params({ const res: AxiosResponse = await graphql.query("queryInstances").params({
serviceId, serviceId,
duration: useAppStoreWithOut().durationTime, duration: useAppStoreWithOut().durationTime,
}); });
if (!resp.errors) { if (!res.data.errors) {
if (param && param.isRelation) { if (param && param.isRelation) {
this.destPods = resp.data.pods || []; this.destPods = res.data.data.pods || [];
return resp; return res.data;
} }
this.pods = resp.data.pods || []; this.pods = res.data.data.pods || [];
} }
return resp; return res.data;
}, },
async getProcesses(param?: { instanceId: string; isRelation: boolean }) { async getProcesses(param?: { instanceId: string; isRelation: boolean }): Promise<Nullable<AxiosResponse>> {
const instanceId = param ? param.instanceId : this.currentPod?.id; const instanceId = param ? param.instanceId : this.currentPod?.id;
if (!instanceId) { if (!instanceId) {
return null; return null;
} }
const res = await graphql.query("queryProcesses").params({ const res: AxiosResponse = await graphql.query("queryProcesses").params({
instanceId, instanceId,
duration: useAppStoreWithOut().durationTime, duration: useAppStoreWithOut().durationTime,
}); });
if (!res.errors) { if (!res.data.errors) {
if (param && param.isRelation) { if (param && param.isRelation) {
this.destProcesses = res.data.processes || []; this.destProcesses = res.data.data.processes || [];
return res; return res.data;
} }
this.processes = res.data.processes || []; this.processes = res.data.data.processes || [];
} }
return res; return res.data;
}, },
async getEndpoints(params: { keyword?: string; serviceId?: string; isRelation?: boolean; limit?: number }) { async getEndpoints(params: {
keyword?: string;
serviceId?: string;
isRelation?: boolean;
limit?: number;
}): Promise<Nullable<AxiosResponse>> {
if (!params) { if (!params) {
params = {}; params = {};
} }
@ -132,96 +139,96 @@ export const selectorStore = defineStore({
if (!serviceId) { if (!serviceId) {
return null; return null;
} }
const res = await graphql.query("queryEndpoints").params({ const res: AxiosResponse = await graphql.query("queryEndpoints").params({
serviceId, serviceId,
duration: useAppStoreWithOut().durationTime, duration: useAppStoreWithOut().durationTime,
keyword: params.keyword || "", keyword: params.keyword || "",
limit: params.limit || EndpointsTopNDefault, limit: params.limit,
}); });
if (!res.errors) { if (!res.data.errors) {
if (params.isRelation) { if (params.isRelation) {
this.destPods = res.data.pods || []; this.destPods = res.data.data.pods || [];
return res; return res.data;
} }
this.pods = res.data.pods || []; this.pods = res.data.data.pods || [];
} }
return res; return res.data;
}, },
async getService(serviceId: string, isRelation: boolean) { async getService(serviceId: string, isRelation: boolean) {
if (!serviceId) { if (!serviceId) {
return; return;
} }
const res = await graphql.query("queryService").params({ const res: AxiosResponse = await graphql.query("queryService").params({
serviceId, serviceId,
}); });
if (!res.errors) { if (!res.data.errors) {
if (isRelation) { if (isRelation) {
this.setCurrentDestService(res.data.service); this.setCurrentDestService(res.data.data.service);
this.destServices = [res.data.service]; this.destServices = [res.data.data.service];
return res; return res.data;
} }
this.setCurrentService(res.data.service); this.setCurrentService(res.data.data.service);
this.services = [res.data.service]; this.services = [res.data.data.service];
} }
return res; return res.data;
}, },
async getInstance(instanceId: string, isRelation?: boolean) { async getInstance(instanceId: string, isRelation?: boolean) {
if (!instanceId) { if (!instanceId) {
return; return;
} }
const res = await graphql.query("queryInstance").params({ const res: AxiosResponse = await graphql.query("queryInstance").params({
instanceId, instanceId,
}); });
if (!res.errors) { if (!res.data.errors) {
if (isRelation) { if (isRelation) {
this.currentDestPod = res.data.instance || null; this.currentDestPod = res.data.data.instance || null;
this.destPods = [res.data.instance]; this.destPods = [res.data.data.instance];
return res; return res.data;
} }
this.currentPod = res.data.instance || null; this.currentPod = res.data.data.instance || null;
this.pods = [res.data.instance]; this.pods = [res.data.data.instance];
} }
return res; return res.data;
}, },
async getEndpoint(endpointId: string, isRelation?: string) { async getEndpoint(endpointId: string, isRelation?: string) {
if (!endpointId) { if (!endpointId) {
return; return;
} }
const res = await graphql.query("queryEndpoint").params({ const res: AxiosResponse = await graphql.query("queryEndpoint").params({
endpointId, endpointId,
}); });
if (res.errors) { if (res.data.errors) {
return res; return res.data;
} }
if (isRelation) { if (isRelation) {
this.currentDestPod = res.data.endpoint || null; this.currentDestPod = res.data.data.endpoint || null;
this.destPods = [res.data.endpoint]; this.destPods = [res.data.data.endpoint];
return res; return res.data;
} }
this.currentPod = res.data.endpoint || null; this.currentPod = res.data.data.endpoint || null;
this.pods = [res.data.endpoint]; this.pods = [res.data.data.endpoint];
return res; return res.data;
}, },
async getProcess(processId: string, isRelation?: boolean) { async getProcess(processId: string, isRelation?: boolean) {
if (!processId) { if (!processId) {
return; return;
} }
const res = await graphql.query("queryProcess").params({ const res: AxiosResponse = await graphql.query("queryProcess").params({
processId, processId,
}); });
if (!res.errors) { if (!res.data.errors) {
if (isRelation) { if (isRelation) {
this.currentDestProcess = res.data.process || null; this.currentDestProcess = res.data.data.process || null;
this.destProcesses = [res.data.process]; this.destProcesses = [res.data.data.process];
return res.data; return res.data;
} }
this.currentProcess = res.data.process || null; this.currentProcess = res.data.data.process || null;
this.processes = [res.data.process]; this.processes = [res.data.data.process];
} }
return res; return res.data;
}, },
}, },
}); });

View File

@ -18,6 +18,7 @@ import { defineStore } from "pinia";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { store } from "@/store"; import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
import type { AxiosResponse } from "axios";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
import type { EBPFTaskList } from "@/types/ebpf"; import type { EBPFTaskList } from "@/types/ebpf";
import { useNetworkProfilingStore } from "@/store/modules/network-profiling"; import { useNetworkProfilingStore } from "@/store/modules/network-profiling";
@ -56,18 +57,20 @@ export const taskTimelineStore = defineStore({
return new Promise((resolve) => resolve({})); return new Promise((resolve) => resolve({}));
} }
this.loading = true; this.loading = true;
const response = await graphql.query("getEBPFTasks").params(params); const res: AxiosResponse = await graphql.query("getEBPFTasks").params(params);
this.loading = false; this.loading = false;
this.errorTip = ""; this.errorTip = "";
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
const selectorStore = useSelectorStore(); const selectorStore = useSelectorStore();
this.taskList = (response.data.queryEBPFTasks || []).filter( this.taskList = (res.data.data.queryEBPFTasks || []).filter(
(d: EBPFTaskList) => selectorStore.currentProcess && d.processId === selectorStore.currentProcess.id, (d: EBPFTaskList) => selectorStore.currentProcess && d.processId === selectorStore.currentProcess.id,
); );
return response; // this.selectedTask = this.taskList[0] || {};
// await this.getGraphData();
return res.data;
}, },
async getGraphData() { async getGraphData() {
let res: any = {}; let res: any = {};

View File

@ -16,13 +16,16 @@
*/ */
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { store } from "@/store"; import { store } from "@/store";
import type { Node, Call, HierarchyNode, ServiceHierarchy, InstanceHierarchy } from "@/types/topology"; import type { Service } from "@/types/selector";
import type { Node, Call } from "@/types/topology";
import graphql from "@/graphql"; import graphql from "@/graphql";
import { useSelectorStore } from "@/store/modules/selectors"; import { useSelectorStore } from "@/store/modules/selectors";
import { useDashboardStore } from "@/store/modules/dashboard";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
import fetchQuery from "@/graphql/fetch"; import type { AxiosResponse } from "axios";
import query from "@/graphql/fetch";
import { useQueryTopologyMetrics } from "@/hooks/useMetricsProcessor";
import { useQueryTopologyExpressionsProcessor } from "@/hooks/useExpressionsProcessor"; import { useQueryTopologyExpressionsProcessor } from "@/hooks/useExpressionsProcessor";
import { ElMessage } from "element-plus";
interface MetricVal { interface MetricVal {
[key: string]: { values: { id: string; value: unknown }[] }; [key: string]: { values: { id: string; value: unknown }[] };
@ -32,15 +35,9 @@ interface TopologyState {
call: Nullable<Call>; call: Nullable<Call>;
calls: Call[]; calls: Call[];
nodes: Node[]; nodes: Node[];
hierarchyServiceCalls: Call[];
hierarchyServiceNodes: HierarchyNode[];
hierarchyInstanceCalls: Call[];
hierarchyInstanceNodes: HierarchyNode[];
nodeMetricValue: MetricVal; nodeMetricValue: MetricVal;
linkServerMetrics: MetricVal; linkServerMetrics: MetricVal;
linkClientMetrics: MetricVal; linkClientMetrics: MetricVal;
hierarchyNodeMetrics: { [key: string]: MetricVal };
hierarchyInstanceNodeMetrics: { [key: string]: MetricVal };
} }
export const topologyStore = defineStore({ export const topologyStore = defineStore({
@ -48,17 +45,11 @@ export const topologyStore = defineStore({
state: (): TopologyState => ({ state: (): TopologyState => ({
calls: [], calls: [],
nodes: [], nodes: [],
hierarchyServiceCalls: [],
hierarchyServiceNodes: [],
hierarchyInstanceCalls: [],
hierarchyInstanceNodes: [],
node: null, node: null,
call: null, call: null,
nodeMetricValue: {}, nodeMetricValue: {},
linkServerMetrics: {}, linkServerMetrics: {},
linkClientMetrics: {}, linkClientMetrics: {},
hierarchyNodeMetrics: {},
hierarchyInstanceNodeMetrics: {},
}), }),
actions: { actions: {
setNode(node: Node) { setNode(node: Node) {
@ -84,9 +75,12 @@ export const topologyStore = defineStore({
}, },
setTopology(data: { nodes: Node[]; calls: Call[] }) { setTopology(data: { nodes: Node[]; calls: Call[] }) {
const obj = {} as Recordable; const obj = {} as Recordable;
const services = useSelectorStore().services;
const nodes = (data.nodes || []).reduce((prev: Node[], next: Node) => { const nodes = (data.nodes || []).reduce((prev: Node[], next: Node) => {
if (!obj[next.id]) { if (!obj[next.id]) {
obj[next.id] = true; obj[next.id] = true;
const s = services.filter((d: Service) => d.id === next.id)[0] || {};
next.layer = s.layers ? s.layers[0] : null;
prev.push(next); prev.push(next);
} }
return prev; return prev;
@ -112,107 +106,8 @@ export const topologyStore = defineStore({
this.calls = calls; this.calls = calls;
this.nodes = nodes; this.nodes = nodes;
}, },
setHierarchyInstanceTopology(data: InstanceHierarchy, levels: { layer: string; level: number }[]) { setNodeMetricValue(m: MetricVal) {
const relations = data.relations || []; this.nodeMetricValue = m;
const nodesMap = new Map();
const callList = [];
for (const relation of relations) {
const upperId = relation.upperInstance.id;
const lowerId = relation.lowerInstance.id;
const lowerKey = `${lowerId}-${relation.lowerInstance.layer}`;
const upperKey = `${upperId}-${relation.upperInstance.layer}`;
const lowerLevel = levels.find(
(l: { layer: string; level: number }) => l.layer === relation.lowerInstance.layer,
) || { level: undefined };
const upperLevel = levels.find(
(l: { layer: string; level: number }) => l.layer === relation.upperInstance.layer,
) || { level: undefined };
const lowerObj = {
...relation.lowerInstance,
key: lowerId,
id: lowerKey,
l: lowerLevel.level,
};
const upperObj = {
...relation.upperInstance,
key: upperId,
id: upperKey,
l: upperLevel.level,
};
if (!nodesMap.get(upperKey)) {
nodesMap.set(upperKey, upperObj);
}
if (!nodesMap.get(lowerKey)) {
nodesMap.set(lowerKey, lowerObj);
}
callList.push({
target: lowerKey,
source: upperKey,
id: `${lowerKey}->${upperKey}`,
sourceObj: upperObj,
targetObj: lowerObj,
});
}
this.hierarchyInstanceCalls = callList;
this.hierarchyInstanceNodes = [];
for (const d of nodesMap.values()) {
this.hierarchyInstanceNodes.push(d);
}
},
setHierarchyServiceTopology(data: ServiceHierarchy, levels: { layer: string; level: number }[]) {
const relations = data.relations || [];
const nodesMap = new Map();
const callList = [];
for (const relation of relations) {
const upperId = relation.upperService.id;
const lowerId = relation.lowerService.id;
const lowerKey = `${lowerId}-${relation.lowerService.layer}`;
const upperKey = `${upperId}-${relation.upperService.layer}`;
const lowerLevel = levels.find(
(l: { layer: string; level: number }) => l.layer === relation.lowerService.layer,
) || { level: undefined };
const upperLevel = levels.find(
(l: { layer: string; level: number }) => l.layer === relation.upperService.layer,
) || { level: undefined };
const lowerObj = {
...relation.lowerService,
key: lowerId,
id: lowerKey,
l: lowerLevel.level,
};
const upperObj = {
...relation.upperService,
key: upperId,
id: upperKey,
l: upperLevel.level,
};
if (!nodesMap.get(upperKey)) {
nodesMap.set(upperKey, upperObj);
}
if (!nodesMap.get(lowerKey)) {
nodesMap.set(lowerKey, lowerObj);
}
callList.push({
target: lowerKey,
source: upperKey,
id: `${lowerKey}->${upperKey}`,
sourceObj: upperObj,
targetObj: lowerObj,
});
}
this.hierarchyServiceCalls = callList;
this.hierarchyServiceNodes = [];
for (const d of nodesMap.values()) {
this.hierarchyServiceNodes.push(d);
}
},
setHierarchyNodeMetricValue(m: MetricVal, layer: string) {
this.hierarchyNodeMetrics[layer] = m;
},
setHierarchyInstanceNodeMetricValue(m: MetricVal, layer: string) {
this.hierarchyInstanceNodeMetrics[layer] = m;
}, },
setLinkServerMetrics(m: MetricVal) { setLinkServerMetrics(m: MetricVal) {
this.linkServerMetrics = m; this.linkServerMetrics = m;
@ -220,16 +115,12 @@ export const topologyStore = defineStore({
setLinkClientMetrics(m: MetricVal) { setLinkClientMetrics(m: MetricVal) {
this.linkClientMetrics = m; this.linkClientMetrics = m;
}, },
setNodeMetricValue(m: MetricVal) {
this.nodeMetricValue = m;
},
setLegendValues(expressions: string, data: { [key: string]: any }) { setLegendValues(expressions: string, data: { [key: string]: any }) {
const nodeArr = this.nodes.filter((d: Node) => d.isReal); for (let idx = 0; idx < this.nodes.length; idx++) {
for (let idx = 0; idx < nodeArr.length; idx++) {
for (let index = 0; index < expressions.length; index++) { for (let index = 0; index < expressions.length; index++) {
const k = "expression" + idx + index; const k = "expression" + idx + index;
if (expressions[index]) { if (expressions[index]) {
nodeArr[idx][expressions[index]] = Number(data[k].results[0].values[0].value); this.nodes[idx][expressions[index]] = Number(data[k].results[0].values[0].value);
} }
} }
} }
@ -304,14 +195,14 @@ export const topologyStore = defineStore({
return new Promise((resolve) => resolve({})); return new Promise((resolve) => resolve({}));
} }
const duration = useAppStoreWithOut().durationTime; const duration = useAppStoreWithOut().durationTime;
const res = await graphql.query("getServicesTopology").params({ const res: AxiosResponse = await graphql.query("getServicesTopology").params({
serviceIds, serviceIds,
duration, duration,
}); });
if (res.errors) { if (res.data.errors) {
return res; return res.data;
} }
return res.data.topology; return res.data.data.topology;
}, },
async getInstanceTopology() { async getInstanceTopology() {
const { currentService, currentDestService } = useSelectorStore(); const { currentService, currentDestService } = useSelectorStore();
@ -321,15 +212,15 @@ export const topologyStore = defineStore({
if (!(serverServiceId && clientServiceId)) { if (!(serverServiceId && clientServiceId)) {
return new Promise((resolve) => resolve({})); return new Promise((resolve) => resolve({}));
} }
const res = await graphql.query("getInstanceTopology").params({ const res: AxiosResponse = await graphql.query("getInstanceTopology").params({
clientServiceId, clientServiceId,
serverServiceId, serverServiceId,
duration, duration,
}); });
if (!res.errors) { if (!res.data.errors) {
this.setInstanceTopology(res.data.topology); this.setInstanceTopology(res.data.data.topology);
} }
return res; return res.data;
}, },
async updateEndpointTopology(endpointIds: string[], depth: number) { async updateEndpointTopology(endpointIds: string[], depth: number) {
if (!endpointIds.length) { if (!endpointIds.length) {
@ -337,10 +228,7 @@ export const topologyStore = defineStore({
} }
const res = await this.getEndpointTopology(endpointIds); const res = await this.getEndpointTopology(endpointIds);
if (depth > 1) { if (depth > 1) {
const userNodeName = "User"; const ids = res.nodes.map((item: Node) => item.id).filter((d: string) => !endpointIds.includes(d));
const ids = res.nodes
.filter((d: Node) => !endpointIds.includes(d.id) && d.name !== userNodeName)
.map((item: Node) => item.id);
if (!ids.length) { if (!ids.length) {
this.setTopology(res); this.setTopology(res);
return; return;
@ -348,8 +236,8 @@ export const topologyStore = defineStore({
const json = await this.getEndpointTopology(ids); const json = await this.getEndpointTopology(ids);
if (depth > 2) { if (depth > 2) {
const pods = json.nodes const pods = json.nodes
.filter((d: Node) => ![...ids, ...endpointIds].includes(d.id) && d.name !== userNodeName) .map((item: Node) => item.id)
.map((item: Node) => item.id); .filter((d: string) => ![...ids, ...endpointIds].includes(d));
if (!pods.length) { if (!pods.length) {
const nodes = [...res.nodes, ...json.nodes]; const nodes = [...res.nodes, ...json.nodes];
const calls = [...res.calls, ...json.calls]; const calls = [...res.calls, ...json.calls];
@ -359,8 +247,8 @@ export const topologyStore = defineStore({
const topo = await this.getEndpointTopology(pods); const topo = await this.getEndpointTopology(pods);
if (depth > 3) { if (depth > 3) {
const endpoints = topo.nodes const endpoints = topo.nodes
.filter((d: Node) => ![...ids, ...pods, ...endpointIds].includes(d.id) && d.name !== userNodeName) .map((item: Node) => item.id)
.map((item: Node) => item.id); .filter((d: string) => ![...ids, ...pods, ...endpointIds].includes(d));
if (!endpoints.length) { if (!endpoints.length) {
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes]; const nodes = [...res.nodes, ...json.nodes, ...topo.nodes];
const calls = [...res.calls, ...json.calls, ...topo.calls]; const calls = [...res.calls, ...json.calls, ...topo.calls];
@ -370,11 +258,8 @@ export const topologyStore = defineStore({
const data = await this.getEndpointTopology(endpoints); const data = await this.getEndpointTopology(endpoints);
if (depth > 4) { if (depth > 4) {
const nodeIds = data.nodes const nodeIds = data.nodes
.filter( .map((item: Node) => item.id)
(d: Node) => .filter((d: string) => ![...endpoints, ...ids, ...pods, ...endpointIds].includes(d));
![...endpoints, ...ids, ...pods, ...endpointIds].includes(d.id) && d.name !== userNodeName,
)
.map((item: Node) => item.id);
if (!nodeIds.length) { if (!nodeIds.length) {
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes, ...data.nodes]; const nodes = [...res.nodes, ...json.nodes, ...topo.nodes, ...data.nodes];
const calls = [...res.calls, ...json.calls, ...topo.calls, ...data.calls]; const calls = [...res.calls, ...json.calls, ...topo.calls, ...data.calls];
@ -431,12 +316,12 @@ export const topologyStore = defineStore({
}); });
const queryStr = `query queryData(${variables}) {${fragment}}`; const queryStr = `query queryData(${variables}) {${fragment}}`;
const conditions = { duration }; const conditions = { duration };
const res = await fetchQuery({ queryStr, conditions }); const res: AxiosResponse = await query({ queryStr, conditions });
if (res.errors) { if (res.data.errors) {
return res; return res.data;
} }
const topo = res.data; const topo = res.data.data;
const calls = [] as Call[]; const calls = [] as Call[];
const nodes = [] as Node[]; const nodes = [] as Node[];
for (const key of Object.keys(topo)) { for (const key of Object.keys(topo)) {
@ -447,14 +332,55 @@ export const topologyStore = defineStore({
return { calls, nodes }; return { calls, nodes };
}, },
async getTopologyExpressionValue(param: { queryStr: string; conditions: { [key: string]: unknown } }) { async getNodeMetricValue(param: { queryStr: string; conditions: { [key: string]: unknown } }) {
const res = await fetchQuery(param); const res: AxiosResponse = await query(param);
if (res.errors) { if (res.data.errors) {
return res; return res.data;
}
this.setNodeMetricValue(res.data.data);
return res.data;
},
async getNodeExpressionValue(param: { queryStr: string; conditions: { [key: string]: unknown } }) {
const res: AxiosResponse = await query(param);
if (res.data.errors) {
return res.data;
} }
return res; return res.data;
},
async getLinkClientMetrics(linkClientMetrics: string[]) {
if (!linkClientMetrics.length) {
this.setLinkClientMetrics({});
return;
}
const idsC = this.calls.filter((i: Call) => i.detectPoints.includes("CLIENT")).map((b: Call) => b.id);
if (!idsC.length) {
return;
}
const param = await useQueryTopologyMetrics(linkClientMetrics, idsC);
const res = await this.getCallClientMetrics(param);
if (res.errors) {
ElMessage.error(res.errors);
}
},
async getLinkServerMetrics(linkServerMetrics: string[]) {
if (!linkServerMetrics.length) {
this.setLinkServerMetrics({});
return;
}
const idsS = this.calls.filter((i: Call) => i.detectPoints.includes("SERVER")).map((b: Call) => b.id);
if (!idsS.length) {
return;
}
const param = await useQueryTopologyMetrics(linkServerMetrics, idsS);
const res = await this.getCallServerMetrics(param);
if (res.errors) {
ElMessage.error(res.errors);
}
}, },
async getLinkExpressions(expressions: string[], type: string) { async getLinkExpressions(expressions: string[], type: string) {
if (!expressions.length) { if (!expressions.length) {
@ -465,14 +391,36 @@ export const topologyStore = defineStore({
if (!calls.length) { if (!calls.length) {
return; return;
} }
const { getMetrics } = useQueryTopologyExpressionsProcessor(expressions, calls); const { getExpressionQuery, handleExpressionValues } = useQueryTopologyExpressionsProcessor(expressions, calls);
const metrics = await getMetrics(); const param = getExpressionQuery();
const res = await this.getNodeExpressionValue(param);
if (res.errors) {
ElMessage.error(res.errors);
return;
}
const metrics = handleExpressionValues(res.data);
if (type === "SERVER") { if (type === "SERVER") {
this.setLinkServerMetrics(metrics); this.setLinkServerMetrics(metrics);
} else { } else {
this.setLinkClientMetrics(metrics); this.setLinkClientMetrics(metrics);
} }
}, },
async queryNodeMetrics(nodeMetrics: string[]) {
if (!nodeMetrics.length) {
this.setNodeMetricValue({});
return;
}
const ids = this.nodes.map((d: Node) => d.id);
if (!ids.length) {
return;
}
const param = await useQueryTopologyMetrics(nodeMetrics, ids);
const res = await this.getNodeMetricValue(param);
if (res.errors) {
ElMessage.error(res.errors);
}
},
async queryNodeExpressions(expressions: string[]) { async queryNodeExpressions(expressions: string[]) {
if (!expressions.length) { if (!expressions.length) {
this.setNodeMetricValue({}); this.setNodeMetricValue({});
@ -482,92 +430,56 @@ export const topologyStore = defineStore({
this.setNodeMetricValue({}); this.setNodeMetricValue({});
return; return;
} }
const { getMetrics } = useQueryTopologyExpressionsProcessor( const { getExpressionQuery, handleExpressionValues } = useQueryTopologyExpressionsProcessor(
expressions, expressions,
this.nodes.filter((d: Node) => d.isReal), this.nodes,
); );
const metrics = await getMetrics(); const param = getExpressionQuery();
const res = await this.getNodeExpressionValue(param);
if (res.errors) {
ElMessage.error(res.errors);
return;
}
const metrics = handleExpressionValues(res.data);
this.setNodeMetricValue(metrics); this.setNodeMetricValue(metrics);
}, },
async getHierarchyServiceTopology() { async getLegendMetrics(param: { queryStr: string; conditions: { [key: string]: unknown } }) {
const dashboardStore = useDashboardStore(); const res: AxiosResponse = await query(param);
const { currentService } = useSelectorStore();
const id = this.node ? this.node.id : (currentService || {}).id;
let layer = dashboardStore.layerId;
if (this.node) {
layer = this.node.layers.includes(dashboardStore.layerId)
? dashboardStore.layerId
: this.node.layers.filter((d: string) => d !== dashboardStore.layerId)[0];
}
if (!(id && layer)) {
return new Promise((resolve) => resolve({}));
}
const res = await graphql.query("getHierarchyServiceTopology").params({ serviceId: id, layer: layer });
if (res.errors) {
return res;
}
const resp = await this.getListLayerLevels();
if (resp.errors) {
return resp;
}
const levels = resp.levels || [];
this.setHierarchyServiceTopology(res.data.hierarchyServiceTopology || {}, levels);
return res;
},
async getListLayerLevels() {
const res = await graphql.query("queryListLayerLevels").params({});
if (res.data.errors) {
return res.data;
}
const data = res.data.data;
const metrics = Object.keys(data);
this.nodes = this.nodes.map((d: Node & Recordable) => {
for (const m of metrics) {
for (const val of data[m].values) {
if (d.id === val.id) {
d[m] = val.value;
}
}
}
return d;
});
return res.data; return res.data;
}, },
async getHierarchyInstanceTopology() { async getCallServerMetrics(param: { queryStr: string; conditions: { [key: string]: unknown } }) {
const { currentPod } = useSelectorStore(); const res: AxiosResponse = await query(param);
const dashboardStore = useDashboardStore();
if (!(currentPod && dashboardStore.layerId)) { if (res.data.errors) {
return new Promise((resolve) => resolve({})); return res.data;
} }
const res = await graphql this.setLinkServerMetrics(res.data.data);
.query("getHierarchyInstanceTopology") return res.data;
.params({ instanceId: currentPod.id, layer: dashboardStore.layerId });
if (res.errors) {
return res;
}
const resp = await this.getListLayerLevels();
if (resp.errors) {
return resp;
}
const levels = resp.levels || [];
this.setHierarchyInstanceTopology(res.data.hierarchyInstanceTopology || {}, levels);
return res;
}, },
async queryHierarchyNodeExpressions(expressions: string[], layer: string) { async getCallClientMetrics(param: { queryStr: string; conditions: { [key: string]: unknown } }) {
const nodes = this.hierarchyServiceNodes.filter((n: HierarchyNode) => n.layer === layer); const res: AxiosResponse = await query(param);
if (!nodes.length) {
this.setHierarchyNodeMetricValue({}, layer);
return;
}
if (!expressions.length) {
this.setHierarchyNodeMetricValue({}, layer);
return;
}
const { getMetrics } = useQueryTopologyExpressionsProcessor(expressions, nodes);
const metrics = await getMetrics();
this.setHierarchyNodeMetricValue(metrics, layer);
},
async queryHierarchyInstanceNodeExpressions(expressions: string[], layer: string) {
const nodes = this.hierarchyInstanceNodes.filter((n: HierarchyNode) => n.layer === layer);
if (!expressions.length) { if (res.data.errors) {
this.setHierarchyInstanceNodeMetricValue({}, layer); return res.data;
return;
} }
if (!nodes.length) { this.setLinkClientMetrics(res.data.data);
this.setHierarchyInstanceNodeMetricValue({}, layer); return res.data;
return;
}
const { getMetrics } = useQueryTopologyExpressionsProcessor(expressions, nodes);
const metrics = await getMetrics();
this.setHierarchyInstanceNodeMetricValue(metrics, layer);
}, },
}, },
}); });

View File

@ -19,10 +19,11 @@ import type { Instance, Endpoint, Service } from "@/types/selector";
import type { Trace, Span } from "@/types/trace"; import type { Trace, Span } from "@/types/trace";
import { store } from "@/store"; import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
import type { 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"; import { QueryOrders } from "@/views/dashboard/data";
import { EndpointsTopNDefault } from "../data";
interface TraceState { interface TraceState {
services: Service[]; services: Service[];
instances: Instance[]; instances: Instance[];
@ -33,7 +34,6 @@ interface TraceState {
conditions: Recordable; conditions: Recordable;
traceSpanLogs: Recordable[]; traceSpanLogs: Recordable[];
selectorStore: Recordable; selectorStore: Recordable;
selectedSpan: Recordable<Span>;
} }
export const traceStore = defineStore({ export const traceStore = defineStore({
@ -45,7 +45,6 @@ export const traceStore = defineStore({
traceList: [], traceList: [],
traceSpans: [], traceSpans: [],
currentTrace: {}, currentTrace: {},
selectedSpan: {},
conditions: { conditions: {
queryDuration: useAppStoreWithOut().durationTime, queryDuration: useAppStoreWithOut().durationTime,
traceState: "ALL", traceState: "ALL",
@ -65,9 +64,6 @@ export const traceStore = defineStore({
setTraceSpans(spans: Span[]) { setTraceSpans(spans: Span[]) {
this.traceSpans = spans; this.traceSpans = spans;
}, },
setSelectedSpan(span: Span) {
this.selectedSpan = span;
},
resetState() { resetState() {
this.traceSpans = []; this.traceSpans = [];
this.traceList = []; this.traceList = [];
@ -80,115 +76,123 @@ export const traceStore = defineStore({
}; };
}, },
async getServices(layer: string) { async getServices(layer: string) {
const response = await graphql.query("queryServices").params({ const res: AxiosResponse = await graphql.query("queryServices").params({
layer, layer,
}); });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.services = response.data.services; this.services = res.data.data.services;
return response; return res.data;
}, },
async getService(serviceId: string) { async getService(serviceId: string) {
if (!serviceId) { if (!serviceId) {
return; return;
} }
const response = await graphql.query("queryService").params({ const res: AxiosResponse = await graphql.query("queryService").params({
serviceId, serviceId,
}); });
return response; return res.data;
}, },
async getInstance(instanceId: string) { async getInstance(instanceId: string) {
if (!instanceId) { if (!instanceId) {
return; return;
} }
const response = await graphql.query("queryInstance").params({ const res: AxiosResponse = await graphql.query("queryInstance").params({
instanceId, instanceId,
}); });
return response; return res.data;
}, },
async getEndpoint(endpointId: string) { async getEndpoint(endpointId: string) {
if (!endpointId) { if (!endpointId) {
return; return;
} }
return await graphql.query("queryEndpoint").params({ const res: AxiosResponse = await graphql.query("queryEndpoint").params({
endpointId, endpointId,
}); });
return res.data;
}, },
async getInstances(id: string) { async getInstances(id: string) {
const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id; const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id;
const response = await graphql.query("queryInstances").params({ const res: AxiosResponse = await graphql.query("queryInstances").params({
serviceId: serviceId, serviceId: serviceId,
duration: useAppStoreWithOut().durationTime, duration: useAppStoreWithOut().durationTime,
}); });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.instances = [{ value: "0", label: "All" }, ...response.data.pods]; this.instances = [{ value: "0", label: "All" }, ...res.data.data.pods];
return response; return res.data;
}, },
async getEndpoints(id: string, keyword?: string) { async getEndpoints(id: string, keyword?: string) {
const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id; const serviceId = this.selectorStore.currentService ? this.selectorStore.currentService.id : id;
const response = await graphql.query("queryEndpoints").params({ const res: AxiosResponse = await graphql.query("queryEndpoints").params({
serviceId, serviceId,
duration: useAppStoreWithOut().durationTime, duration: useAppStoreWithOut().durationTime,
keyword: keyword || "", keyword: keyword || "",
limit: EndpointsTopNDefault,
}); });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
this.endpoints = [{ value: "0", label: "All" }, ...response.data.pods]; this.endpoints = [{ value: "0", label: "All" }, ...res.data.data.pods];
return response; return res.data;
}, },
async getTraces() { async getTraces() {
const response = await graphql.query("queryTraces").params({ condition: this.conditions }); const res: AxiosResponse = await graphql.query("queryTraces").params({ condition: this.conditions });
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
if (!response.data.data.traces.length) { if (!res.data.data.data.traces.length) {
this.traceList = []; this.traceList = [];
this.setCurrentTrace({}); this.setCurrentTrace({});
this.setTraceSpans([]); this.setTraceSpans([]);
return response; return res.data;
} }
this.getTraceSpans({ traceId: response.data.data.traces[0].traceIds[0] }); this.getTraceSpans({ traceId: res.data.data.data.traces[0].traceIds[0] });
this.traceList = response.data.data.traces.map((d: Trace) => { this.traceList = res.data.data.data.traces.map((d: Trace) => {
d.traceIds = d.traceIds.map((id: string) => { d.traceIds = d.traceIds.map((id: string) => {
return { value: id, label: id }; return { value: id, label: id };
}); });
return d; return d;
}); });
this.setCurrentTrace(response.data.data.traces[0] || {}); this.setCurrentTrace(res.data.data.data.traces[0] || {});
return response; return res.data;
}, },
async getTraceSpans(params: { traceId: string }) { async getTraceSpans(params: { traceId: string }) {
const response = await graphql.query("queryTrace").params(params); const res: AxiosResponse = await graphql.query("queryTrace").params(params);
if (response.errors) { if (res.data.errors) {
return response; return res.data;
} }
const data = response.data.trace.spans; const data = res.data.data.trace.spans;
this.setTraceSpans(data || []); this.setTraceSpans(data || []);
return response; return res.data;
}, },
async getSpanLogs(params: Recordable) { async getSpanLogs(params: Recordable) {
const response = await graphql.query("queryServiceLogs").params(params); const res: AxiosResponse = await graphql.query("queryServiceLogs").params(params);
if (response.errors) { if (res.data.errors) {
this.traceSpanLogs = []; this.traceSpanLogs = [];
return response; return res.data;
} }
this.traceSpanLogs = response.data.queryLogs.logs || []; this.traceSpanLogs = res.data.data.queryLogs.logs || [];
return response; return res.data;
}, },
async getTagKeys() { async getTagKeys() {
return await graphql.query("queryTraceTagKeys").params({ duration: useAppStoreWithOut().durationTime }); const res: AxiosResponse = await graphql
.query("queryTraceTagKeys")
.params({ duration: useAppStoreWithOut().durationTime });
return res.data;
}, },
async getTagValues(tagKey: string) { async getTagValues(tagKey: string) {
return await graphql.query("queryTraceTagValues").params({ tagKey, duration: useAppStoreWithOut().durationTime }); const res: AxiosResponse = await graphql
.query("queryTraceTagValues")
.params({ tagKey, duration: useAppStoreWithOut().durationTime });
return res.data;
}, },
}, },
}); });

View File

@ -139,10 +139,6 @@
margin-bottom: 10px; margin-bottom: 10px;
} }
.mb-20 {
margin-bottom: 20px;
}
.mr-5 { .mr-5 {
margin-right: 5px; margin-right: 5px;
} }

View File

@ -15,24 +15,13 @@
* limitations under the License. * limitations under the License.
*/ */
@use "element-plus/theme-chalk/src/dark/css-vars.scss" as *; @use "element-plus/theme-chalk/src/dark/css-vars.scss" as *;
@keyframes topo-dash {
from {
stroke-dashoffset: 10;
}
to {
stroke-dashoffset: 0;
}
}
:root { :root {
--sw-green: #70c877; --sw-green: #70c877;
--sw-orange: #e6a23c; --sw-orange: #e6a23c;
--sw-topo-animation: topo-dash 0.3s linear infinite;
} }
html { html {
--el-color-primary: #409eff; --el-color-primary: #409eff;
--el-color-info-light-9: #666;
--theme-background: #fff; --theme-background: #fff;
--font-color: #3d444f; --font-color: #3d444f;
--disabled-color: #ccc; --disabled-color: #ccc;
@ -69,16 +58,14 @@ html {
--sw-time-axis-text: #4d4d4d; --sw-time-axis-text: #4d4d4d;
--sw-drawer-header: #72767b; --sw-drawer-header: #72767b;
--sw-marketplace-border: #dedfe0; --sw-marketplace-border: #dedfe0;
--sw-grid-item-active: #d4d7de; --sw-grid-item-active: #79bbff;
--sw-trace-line: #999;
} }
html.dark { html.dark {
--el-color-primary: #409eff; --el-color-primary: #409eff;
--el-color-info-light-9: #333;
--theme-background: #212224; --theme-background: #212224;
--font-color: #fafbfc; --font-color: #fafbfc;
--disabled-color: #999; --disabled-color: #ccc;
--dashboard-tool-bg: #000; --dashboard-tool-bg: #000;
--text-color-placeholder: #ccc; --text-color-placeholder: #ccc;
--border-color: #262629; --border-color: #262629;
@ -95,7 +82,7 @@ html.dark {
--sw-config-header: #303133; --sw-config-header: #303133;
--sw-topology-color: #ccc; --sw-topology-color: #ccc;
--vis-tooltip-bg: #414243; --vis-tooltip-bg: #414243;
--sw-topology-switch-icon: #999; --sw-topology-switch-icon: #aaa;
--sw-topology-box-shadow: 0 0 2px 0 #444; --sw-topology-box-shadow: 0 0 2px 0 #444;
--sw-topology-setting-bg: #333; --sw-topology-setting-bg: #333;
--sw-topology-border: 1px solid #666; --sw-topology-border: 1px solid #666;
@ -113,16 +100,14 @@ html.dark {
--sw-drawer-header: #e9e9eb; --sw-drawer-header: #e9e9eb;
--sw-marketplace-border: #606266; --sw-marketplace-border: #606266;
--sw-grid-item-active: #73767a; --sw-grid-item-active: #73767a;
--sw-trace-line: #e8e8e8;
} }
.el-drawer__header { .el-drawer__header {
color: var(--sw-drawer-header); color: var(--sw-drawer-header);
} }
.el-table { .el-table tr {
--el-table-tr-bg-color: var(--theme-background); background-color: var(--el-table-tr-bg-color);
--el-table-header-bg-color: var(--theme-background);
} }
.el-popper.is-light { .el-popper.is-light {
@ -134,6 +119,27 @@ html.dark {
--el-switch-off-color: #aaa; --el-switch-off-color: #aaa;
} }
.el-table__body-wrapper tr td.el-table-fixed-column--left,
.el-table__body-wrapper tr td.el-table-fixed-column--right,
.el-table__body-wrapper tr th.el-table-fixed-column--left,
.el-table__body-wrapper tr th.el-table-fixed-column--right,
.el-table__footer-wrapper tr td.el-table-fixed-column--left,
.el-table__footer-wrapper tr td.el-table-fixed-column--right,
.el-table__footer-wrapper tr th.el-table-fixed-column--left,
.el-table__footer-wrapper tr th.el-table-fixed-column--right,
.el-table__header-wrapper tr td.el-table-fixed-column--left,
.el-table__header-wrapper tr td.el-table-fixed-column--right,
.el-table__header-wrapper tr th.el-table-fixed-column--left,
.el-table__header-wrapper tr th.el-table-fixed-column--right {
background-color: var(--sw-table-col);
}
.el-table.is-scrolling-none th.el-table-fixed-column--left,
.el-table.is-scrolling-none th.el-table-fixed-column--right,
.el-table th.el-table__cell {
background-color: var(--sw-table-col);
}
$tool-icon-btn-bg: var(--sw-icon-btn-bg); $tool-icon-btn-bg: var(--sw-icon-btn-bg);
$tool-icon-btn-color: var(--sw-icon-btn-color); $tool-icon-btn-color: var(--sw-icon-btn-color);
$popper-hover-bg-color: var(--popper-hover-bg); $popper-hover-bg-color: var(--popper-hover-bg);
@ -244,31 +250,3 @@ div:has(> a.menu-title) {
.el-input-number .el-input__inner { .el-input-number .el-input__inner {
text-align: left !important; text-align: left !important;
} }
.el-input--small .el-input__inner {
--el-input-inner-height: calc(var(--el-input-height, 24px));
}
html {
&::view-transition-old(root),
&::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
&.dark {
&::view-transition-old(root) {
z-index: 1;
}
&::view-transition-new(root) {
z-index: 999;
}
}
&::view-transition-old(root) {
z-index: 999;
}
&::view-transition-new(root) {
z-index: 1;
}
}

View File

@ -27,7 +27,6 @@ export interface Alarm {
scope: string; scope: string;
tags: Array<{ key: string; value: string }>; tags: Array<{ key: string; value: string }>;
events: Event[]; events: Event[];
snapshot: Indexable;
} }
export interface Event { export interface Event {

2
src/types/app.d.ts vendored
View File

@ -59,7 +59,7 @@ export interface SubItem {
icon: string; icon: string;
title: string; title: string;
activate: boolean; activate: boolean;
name: string; name?: string;
path?: string; path?: string;
notShow?: boolean; notShow?: boolean;
id?: string; id?: string;

View File

@ -1,68 +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.
*/
export type AsyncProfilingTask = {
id: string;
serviceId: string;
serviceInstanceIds: string[];
createTime: number;
events: string;
duration: number;
execArgs: string;
};
export type AsyncProfileTaskCreationRequest = {
serviceId: string;
serviceInstanceIds: string[];
duration: number;
events: string[];
execArgs: string;
};
export type AsyncProfilerStackElement = {
id: string;
parentId: string;
codeSignature: string;
total: number;
self: number;
};
export type AsyncProfilerTaskProgress = {
errorInstanceIds: string[];
successInstanceIds: string[];
logs: AsyncProfilerTaskLog[];
};
type AsyncProfilerTaskLog = {
id: string;
instanceId: string;
instanceName: string;
operationType: string;
operationTime: number;
};
export type StackElement = {
id: string;
originId: string;
name: string;
parentId: string;
codeSignature: string;
total: number;
self: number;
value: number;
children?: StackElement[];
};

View File

@ -1,9 +1,52 @@
/* eslint-disable */ // Generated by 'unplugin-auto-import'
/* prettier-ignore */ // We suggest you to commit this file into source control
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
export {}
declare global { declare global {
const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp']
const customRef: typeof import('vue')['customRef']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const effectScope: typeof import('vue')['effectScope']
const EffectScope: typeof import('vue')['EffectScope']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const inject: typeof import('vue')['inject']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const provide: typeof import('vue')['provide']
const reactive: typeof import('vue')['reactive']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const resolveComponent: typeof import('vue')['resolveComponent']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const toRaw: typeof import('vue')['toRaw']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const triggerRef: typeof import('vue')['triggerRef']
const unref: typeof import('vue')['unref']
const useAttrs: typeof import('vue')['useAttrs']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVars: typeof import('vue')['useCssVars']
const useSlots: typeof import('vue')['useSlots']
const watch: typeof import('vue')['watch']
const watchEffect: typeof import('vue')['watchEffect']
} }
export {}

Some files were not shown because too many files have changed in this diff Show More