Compare commits

..

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

258 changed files with 11651 additions and 12578 deletions

View File

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

View File

@ -34,15 +34,14 @@ npm install
npm run dev
```
The default UI address is `http://localhost:3000`.
The default UI address is `http://localhost:8080`.
# Contact Us
- 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.
- 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)
- [bilibili B 站 视频](https://space.bilibili.com/390683219)
- Submit an [issue](https://github.com/apache/skywalking/issues) if you face some issues. Submit a [discussion](https://github.com/apache/skywalking/discussions) if you want to propose new feature or have any question.
- Mailing list: **dev@skywalking.apache.org**. Mail to `dev-subscribe@skywalking.apache.org`, follow the reply to subscribe the mailing list.
- Join Slack. Send `Request to join SkyWalking slack` mail to the mail list(`dev@skywalking.apache.org`), we will invite you in.
- QQ Group: 392443393, 901167865
# License

View File

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

10672
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "skywalking-booster-ui",
"version": "10.2.0",
"version": "9.4.0",
"private": true,
"scripts": {
"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"
},
"dependencies": {
"axios": "^0.24.0",
"d3": "^7.3.0",
"d3-flame-graph": "^4.1.3",
"d3-tip": "^0.9.1",
"echarts": "^5.2.2",
"element-plus": "^2.9.4",
"element-plus": "^2.1.0",
"lodash": "^4.17.21",
"monaco-editor": "^0.34.1",
"pinia": "^2.0.28",
"vis-timeline": "^7.5.1",
"vue": "^3.2.45",
"vue-grid-layout": "^3.0.0-beta1",
"vue-i18n": "^9.14.3",
"vue-i18n": "^9.1.9",
"vue-router": "^4.1.6",
"vue-types": "^4.1.1"
},
@ -40,16 +42,17 @@
"@types/d3-tip": "^3.5.5",
"@types/echarts": "^4.9.12",
"@types/jsdom": "^20.0.1",
"@types/lodash": "^4.14.179",
"@types/node": "^18.11.12",
"@types/three": "^0.131.0",
"@vitejs/plugin-vue": "^5.2.1",
"@vitejs/plugin-vue-jsx": "^4.1.1",
"@vitejs/plugin-vue": "^4.0.0",
"@vitejs/plugin-vue-jsx": "^3.0.0",
"@vue/eslint-config-prettier": "^7.0.0",
"@vue/eslint-config-typescript": "^11.0.0",
"@vue/test-utils": "^2.2.6",
"@vue/tsconfig": "^0.1.3",
"@vueuse/core": "^9.6.0",
"cypress": "^13.3.2",
"cypress": "^12.0.2",
"eslint": "^8.22.0",
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-vue": "^9.3.0",
@ -61,21 +64,21 @@
"postcss-html": "^1.3.0",
"postcss-scss": "^4.0.2",
"prettier": "^2.7.1",
"sass": "^1.85.0",
"start-server-and-test": "^2.0.5",
"sass": "^1.56.1",
"start-server-and-test": "^1.15.2",
"stylelint": "15.9.0",
"stylelint-config-html": "^1.0.0",
"stylelint-config-prettier": "9.0.4",
"stylelint-config-standard": "^33.0.0",
"stylelint-order": "^6.0.3",
"typescript": "^5.7.3",
"unplugin-auto-import": "^0.18.2",
"unplugin-vue-components": "^0.27.3",
"vite": "^6.3.4",
"typescript": "~4.7.4",
"unplugin-auto-import": "^0.7.0",
"unplugin-vue-components": "^0.19.2",
"vite": "^4.0.5",
"vite-plugin-monaco-editor": "^1.1.0",
"vite-plugin-svg-icons": "^2.0.1",
"vitest": "^3.0.5",
"vue-tsc": "^2.2.2"
"vitest": "^0.25.6",
"vue-tsc": "^1.0.12"
},
"browserslist": [
"> 1%",
@ -95,7 +98,10 @@
"{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [
"prettier --write"
],
"package.json, *.md": [
"package.json": [
"prettier --write"
],
"*.md": [
"prettier --write"
]
}

View File

@ -27,11 +27,10 @@ limitations under the License. -->
}
}, 500);
</script>
<style lang="scss">
<style>
#app {
color: $font-color;
color: #2c3e50;
height: 100%;
overflow: hidden;
background-color: $layout-background;
}
</style>

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.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg t="1655799536378" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9286" width="48" height="48"><path d="M563.2 614.4v51.2c0 30.72-20.48 51.2-51.2 51.2s-51.2-20.48-51.2-51.2v-51.2H409.6c-30.72 0-51.2-20.48-51.2-51.2s20.48-51.2 51.2-51.2h51.2V460.8c0-30.72 20.48-51.2 51.2-51.2s51.2 20.48 51.2 51.2v51.2h51.2c30.72 0 51.2 20.48 51.2 51.2s-20.48 51.2-51.2 51.2h-51.2z m51.2-563.2c158.72 15.36 281.6 143.36 281.6 307.2v512c0 56.32-46.08 102.4-102.4 102.4h-563.2c-56.32 0-102.4-46.08-102.4-102.4V153.6c0-56.32 46.08-102.4 102.4-102.4H614.4z m163.84 230.4c-25.6-61.44-76.8-107.52-138.24-122.88v71.68c0 30.72 20.48 51.2 51.2 51.2h87.04zM537.6 153.6h-256c-30.72 0-51.2 20.48-51.2 51.2v614.4c0 30.72 20.48 51.2 51.2 51.2h460.8c30.72 0 51.2-20.48 51.2-51.2V384h-153.6c-56.32 0-102.4-46.08-102.4-102.4V153.6z" p-id="9287"></path></svg>
<svg t="1655799536378" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9286" width="48" height="48"><path d="M563.2 614.4v51.2c0 30.72-20.48 51.2-51.2 51.2s-51.2-20.48-51.2-51.2v-51.2H409.6c-30.72 0-51.2-20.48-51.2-51.2s20.48-51.2 51.2-51.2h51.2V460.8c0-30.72 20.48-51.2 51.2-51.2s51.2 20.48 51.2 51.2v51.2h51.2c30.72 0 51.2 20.48 51.2 51.2s-20.48 51.2-51.2 51.2h-51.2z m51.2-563.2c158.72 15.36 281.6 143.36 281.6 307.2v512c0 56.32-46.08 102.4-102.4 102.4h-563.2c-56.32 0-102.4-46.08-102.4-102.4V153.6c0-56.32 46.08-102.4 102.4-102.4H614.4z m163.84 230.4c-25.6-61.44-76.8-107.52-138.24-122.88v71.68c0 30.72 20.48 51.2 51.2 51.2h87.04zM537.6 153.6h-256c-30.72 0-51.2 20.48-51.2 51.2v614.4c0 30.72 20.48 51.2 51.2 51.2h460.8c30.72 0 51.2-20.48 51.2-51.2V384h-153.6c-56.32 0-102.4-46.08-102.4-102.4V153.6z" fill="#707070" p-id="9287"></path></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.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.
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" 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
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.
See the License for the specific language governing permissions and
limitations under the License. -->
<svg t="1655695739627" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2218" width="48" height="48"><path d="M173.292308 177.230769C86.646154 265.846154 39.384615 382.030769 39.384615 504.123077 39.384615 531.692308 61.046154 551.384615 86.646154 551.384615s47.261538-21.661538 47.261538-47.261538c-1.969231-96.492308 37.415385-189.046154 106.338462-257.969231s163.446154-106.338462 257.969231-106.338461c27.569231 0 47.261538-21.661538 47.261538-47.261539 0-27.569231-21.661538-47.261538-47.261538-47.261538C378.092308 43.323077 259.938462 90.584615 173.292308 177.230769z m57.107692 326.892308c0 27.569231 19.692308 47.261538 47.261538 47.261538s47.261538-21.661538 47.261539-47.261538c0-45.292308 17.723077-90.584615 51.2-122.092308 33.476923-33.476923 76.8-49.230769 122.092308-51.2 27.569231 0 47.261538-21.661538 47.261538-47.261538 0-27.569231-19.692308-47.261538-47.261538-47.261539-70.892308 0-139.815385 27.569231-191.015385 76.8-7.876923 9.846154-80.738462 82.707692-76.8 191.015385z m665.6-204.8c-17.723077-23.630769-41.353846-51.2-45.292308-55.138462-5.907692-3.938462-13.784615-7.876923-21.661538-7.876923-7.876923 0-15.753846 1.969231-19.692308 7.876923L610.461538 441.107692c-47.261538-39.384615-118.153846-37.415385-163.446153 7.876923-45.292308 45.292308-47.261538 116.184615-7.876923 163.446154l-191.015385 191.015385c-5.907692 5.907692-9.846154 13.784615-9.846154 21.661538 0 9.846154 3.938462 19.692308 11.815385 25.6l53.16923 39.384616c72.861538 57.107692 163.446154 88.615385 259.938462 88.615384 232.369231 0 421.415385-189.046154 421.415385-421.415384 0-94.523077-33.476923-185.107692-88.615385-257.969231z" p-id="2219"></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: 4.3 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: 259 B

After

Width:  |  Height:  |  Size: 269 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 {
border-left: solid 1px var(--sw-border-color-light);
border-left: solid 1px #eaeaea;
margin-left: 5px;
padding-left: 5px;
}
@ -464,7 +464,7 @@ limitations under the License. -->
}
.calendar-head a {
color: var(--sw-topology-color);
color: #666;
cursor: pointer;
display: inline-block;
text-align: center;
@ -568,7 +568,7 @@ limitations under the License. -->
.calendar-hour {
display: inline-block;
border: 1px solid var(--sw-border-color-light);
border: 1px solid #e6e5e5;
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
limitations under the License. -->
<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 v-if="!available" class="no-data">No Data</div>
<div
@ -60,8 +53,6 @@ limitations under the License. -->
import { addResizeListener, removeResizeListener } from "@/utils/event";
import Trace from "@/views/dashboard/related/trace/Index.vue";
import associateProcessor from "@/hooks/useAssociateProcessor";
import { WidgetType } from "@/views/dashboard/data";
import SelectorLegend from "./Legend.vue";
/*global Nullable, defineProps, defineEmits, Indexable*/
const emits = defineEmits(["select"]);
@ -72,7 +63,7 @@ limitations under the License. -->
const currentParams = ref<Nullable<EventParams>>(null);
const showTrace = ref<boolean>(false);
const traceOptions = ref<{ type: string; filters?: unknown }>({
type: WidgetType.Trace,
type: "Trace",
});
const menuPos = reactive<{ x: number; y: number }>({ x: NaN, y: NaN });
const props = defineProps({
@ -92,10 +83,6 @@ limitations under the License. -->
type: Array as PropType<{ widgetId: string }[]>,
default: () => [],
},
legendSelector: {
type: Object as PropType<Indexable>,
default: () => ({ isConfigPage: false, isSelector: false }),
},
});
const available = computed(
() =>
@ -115,7 +102,6 @@ limitations under the License. -->
if (!instance) {
return;
}
instance.on("click", (params: EventParams) => {
currentParams.value = params;
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(
() => props.option,
(newVal, oldVal) => {
@ -265,10 +234,12 @@ limitations under the License. -->
.no-data {
font-size: $font-size-smaller;
height: 100%;
align-items: center;
justify-content: center;
display: flex;
color: var(--text-color-placeholder);
box-sizing: border-box;
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-pack: center;
-webkit-box-align: center;
color: #666;
}
.chart {
@ -281,11 +252,11 @@ limitations under the License. -->
display: block;
white-space: nowrap;
z-index: 9999999;
box-shadow: var(--sw-topology-box-shadow);
box-shadow: #ddd 1px 2px 10px;
transition: all cubic-bezier(0.075, 0.82, 0.165, 1) linear;
background-color: var(--sw-bg-color-overlay);
background-color: rgb(255 255 255);
border-radius: 4px;
color: $font-color;
color: rgb(51 51 51);
padding: 5px;
}
@ -296,7 +267,7 @@ limitations under the License. -->
&:hover {
color: $active-color;
background-color: $popper-hover-bg-color;
background-color: #eee;
}
}
</style>

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,10 +85,10 @@ limitations under the License. -->
.bar-select {
position: relative;
justify-content: space-between;
border: 1px solid var(--el-border-color);
border: 1px solid #ddd;
background: $theme-background;
border-radius: 3px;
color: $font-color;
color: #000;
font-size: $font-size-smaller;
height: 24px;
@ -97,8 +97,8 @@ limitations under the License. -->
border-radius: 3px;
margin: 3px;
color: $active-color;
background-color: var(--theme-background);
border: 1px solid var(--el-color-primary);
background-color: #fafafa;
border: 1px solid #e8e8e8;
text-align: center;
}
}
@ -112,7 +112,7 @@ limitations under the License. -->
width: 100%;
padding: 2px 10px;
overflow: auto;
color: var(--sw-setting-color);
color: #606266;
position: relative;
&:hover {
@ -133,13 +133,13 @@ limitations under the License. -->
}
.opt-wrapper {
color: var(--sw-setting-color);
color: #606266;
position: absolute;
top: 26px;
left: 0;
background-color: $theme-background;
box-shadow: 0 1px 6px rgb(99 99 99 / 20%);
border: 1px solid var(--el-border-color);
border: 1px solid #ddd;
width: 100%;
border-radius: 0 0 3px 3px;
border-right-width: 1px !important;
@ -169,7 +169,7 @@ limitations under the License. -->
}
&:hover {
background-color: var(--layout-background);
background-color: #f5f5f5;
}
}
</style>

View File

@ -26,12 +26,10 @@ limitations under the License. -->
: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}`"
v-for="item in options"
:key="item.value || ''"
:label="item.label || ''"
:value="item.value || ''"
:disabled="item.disabled || false"
@ -43,6 +41,11 @@ limitations under the License. -->
import { ref, watch } from "vue";
import type { PropType } from "vue";
// interface Option {
// label: string | number;
// value: string | number;
// }
/*global defineProps, defineEmits, Indexable*/
const emit = defineEmits(["change", "query"]);
const props = defineProps({
@ -70,8 +73,6 @@ limitations under the License. -->
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);

View File

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

View File

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

View File

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

View File

@ -26,8 +26,3 @@ export const Languages = [
{ label: "Chinese", value: "zh" },
{ label: "Spanish", value: "es" },
];
export enum Themes {
Dark = "dark",
Light = "light",
}

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
* 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 } }) {
const response = await httpQuery({
method: "post",
json: { query: param.queryStr, variables: { ...param.conditions } },
headers: {},
});
if (response.errors) {
response.errors = response.errors.map((e: { message: string }) => e.message).join(" ");
async function query(param: { queryStr: string; conditions: { [key: string]: unknown } }) {
const res: AxiosResponse = await axios.post(
"/graphql",
{ query: param.queryStr, variables: { ...param.conditions } },
{ cancelToken: cancelToken() },
);
if (res.data.errors) {
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
startTime
scope
name
tags {
key
value
@ -44,46 +43,6 @@ export const Alarm = {
startTime
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
* 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 = {
query: `

View File

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

View File

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

View File

@ -15,8 +15,6 @@
* 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 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
* 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}}`;

View File

@ -14,20 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
InstanceTopology,
EndpointTopology,
ServicesTopology,
ProcessTopology,
HierarchyServiceTopology,
HierarchyInstanceTopology,
ListLayerLevels,
} from "../fragments/topology";
import { InstanceTopology, EndpointTopology, ServicesTopology, ProcessTopology } from "../fragments/topology";
export const getInstanceTopology = `query queryData(${InstanceTopology.variable}) {${InstanceTopology.query}}`;
export const getEndpointTopology = `query queryData(${EndpointTopology.variable}) {${EndpointTopology.query}}`;
export const getServicesTopology = `query queryData(${ServicesTopology.variable}) {${ServicesTopology.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
* 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 {
XS = "XS",
SM = "SM",
@ -44,6 +68,50 @@ screenMap.set(sizeEnum.XL, screenEnum.XL);
screenMap.set(sizeEnum.XXL, screenEnum.XXL);
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: `{
type
results {
@ -57,60 +125,8 @@ export const RespFields: Indexable = {
name: id
value
refId: traceID
owner {
scope
serviceID
serviceName
normal
serviceInstanceID
serviceInstanceName
endpointID
endpointName
}
}
}
error
}`,
};
export const DarkChartColors = [
"#79bbff",
"#a0a7e6",
"#30A4EB",
"#45BFC0",
"#ebbf93",
"#884dde",
"#1bbf93",
"#7289ab",
"#f56c6c",
"#81feb7",
"#4094fa",
"#ff894d",
"#884dde",
"#ebbf93",
"#fedc6d",
"#da7cfa",
"#b88230",
"#a0cfff",
];
export const LightChartColors = [
"#3f96e3",
"#a0a7e6",
"#45BFC0",
"#FFCC55",
"#FF6A84",
"#c23531",
"#2f4554",
"#61a0a8",
"#d48265",
"#91c7ae",
"#749f83",
"#ca8622",
"#bda29a",
"#6e7074",
"#546570",
"#c4ccd3",
];
export const MaxQueryLength = 120;

View File

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

View File

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

View File

@ -30,8 +30,6 @@ import { useDebounceFn } from "@vueuse/core";
import { useEventListener } from "./useEventListener";
import { useBreakpoint } from "./useBreakpoint";
import echarts from "@/utils/echarts";
import { useAppStoreWithOut } from "@/store/modules/app";
import { Themes } from "@/constants/data";
export type ECOption = echarts.ComposeOption<
| BarSeriesOption
@ -46,9 +44,8 @@ export type ECOption = echarts.ComposeOption<
>;
export function useECharts(elRef: Ref<HTMLDivElement>, theme: "light" | "dark" | "default" = "default"): Indexable {
const appStore = useAppStoreWithOut();
const getDarkMode = computed(() => {
return appStore.theme === "default" ? Themes.Light : theme;
return theme === "default" ? "light" : theme;
});
let chartInstance: Nullable<echarts.ECharts> = null;
let resizeFn: Fn = resize;
@ -58,7 +55,7 @@ export function useECharts(elRef: Ref<HTMLDivElement>, theme: "light" | "dark" |
resizeFn = useDebounceFn(resize, 200);
const getOptions = computed(() => {
if (getDarkMode.value !== Themes.Dark) {
if (getDarkMode.value !== "dark") {
return cacheOptions.value as ECOption;
}
return {

View File

@ -14,10 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { RespFields, MaximumEntities, MaxQueryLength } from "./data";
import { RespFields } from "./data";
import { EntityType, ExpressionResultType } from "@/views/dashboard/data";
import { ElMessage } from "element-plus";
import { useTopologyStore } from "@/store/modules/topology";
import { useDashboardStore } from "@/store/modules/dashboard";
import { useSelectorStore } from "@/store/modules/selectors";
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 { Node, Call } from "@/types/topology";
function chunkArray(array: any[], chunkSize: number) {
const result = [];
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) {
export async function useExpressionsQueryProcessor(config: Indexable) {
function expressionsGraphqlPods() {
if (!(config.metrics && config.metrics[0])) {
return;
}
const appStore = useAppStoreWithOut();
const dashboardStore = useDashboardStore();
const selectorStore = useSelectorStore();
if (!selectorStore.currentService && dashboardStore.entity !== "All") {
return;
}
const conditions: Recordable = {};
const variables: string[] = [];
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;
}
if (idx === 0) {
variables.push(`$entity: Entity!`);
const fragment = config.metrics.map((name: string, index: number) => {
variables.push(`$expression${index}: String!`, `$entity${index}: Entity!`);
conditions[`expression${index}`] = name;
const entity = {
serviceName: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.value,
normal: dashboardStore.entity === "All" ? undefined : selectorStore.currentService.normal,
@ -81,21 +76,19 @@ export async function useDashboardQueryProcessor(configList: Indexable[]) {
? selectorStore.currentDestProcess && selectorStore.currentDestProcess.value
: undefined,
};
conditions[`entity`] = entity;
}
const fragment = config.metrics.map((name: string, index: number) => {
variables.push(`$expression${idx}${index}: String!`);
conditions[`expression${idx}${index}`] = name;
conditions[`entity${index}`] = entity;
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 {
variables,
fragment,
queryStr,
conditions,
};
}
function expressionsSource(config: Indexable, resp: { errors: string; data: Indexable | any }) {
function expressionsSource(resp: { errors: string; data: Indexable }) {
if (resp.errors) {
ElMessage.error(resp.errors);
return { source: {}, tips: [], typesOfMQE: [] };
@ -104,17 +97,13 @@ export async function useDashboardQueryProcessor(configList: Indexable[]) {
ElMessage.error("The query is wrong");
return { source: {}, tips: [], typesOfMQE: [] };
}
if (resp.data.error) {
ElMessage.error(resp.data.error);
return { source: {}, tips: [], typesOfMQE: [] };
}
const tips: string[] = [];
const source: Indexable<unknown> = {};
const source: { [key: string]: unknown } = {};
const keys = Object.keys(resp.data);
const typesOfMQE: string[] = [];
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 results = obj.results || [];
const name = config.metrics[i];
@ -123,19 +112,27 @@ export async function useDashboardQueryProcessor(configList: Indexable[]) {
tips.push(obj.error);
typesOfMQE.push(type);
if (!obj.error) {
if ([ExpressionResultType.SINGLE_VALUE, ExpressionResultType.TIME_SERIES_VALUES].includes(type)) {
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 the metrics label does not exist, use the configuration label or expression
label = label ? `${metricConfig.label || name}, ${label}` : metricConfig.label || name;
if (type === ExpressionResultType.TIME_SERIES_VALUES) {
if (results.length === 1) {
const label = results[0].metric && results[0].metric.labels[0] && results[0].metric.labels[0].value;
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)) {
source[name] = results[0].values;
}
@ -144,69 +141,24 @@ export async function useDashboardQueryProcessor(configList: Indexable[]) {
return { source, tips, typesOfMQE };
}
async function fetchMetrics(configArr: any) {
const appStore = useAppStoreWithOut();
const variables: string[] = [`$duration: Duration!`];
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 json = await dashboardStore.fetchMetricValue({
queryStr,
conditions,
});
if (json.errors) {
ElMessage.error(json.errors);
return { 0: { source: {}, tips: [], typesOfMQE: [] } };
}
try {
const pageData: Recordable = {};
for (let i = 0; i < configArr.length; i++) {
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 params = await expressionsGraphqlPods();
if (!params) {
return { 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,
};
const dashboardStore = useDashboardStore();
const json = await dashboardStore.fetchMetricValue(params);
if (json.errors) {
ElMessage.error(json.errors);
return { source: {}, tips: [], typesOfMQE: [] };
}
const data = expressionsSource(json);
return resp;
return data;
}
export async function useExpressionsQueryPodsMetrics(
allPods: Array<(Instance | Endpoint | Service) & Indexable>,
pods: Array<(Instance | Endpoint | Service) & Indexable>,
config: {
expressions: string[];
subExpressions: string[];
@ -214,7 +166,7 @@ export async function useExpressionsQueryPodsMetrics(
},
scope: string,
) {
function expressionsGraphqlPods(pods: Array<(Instance | Endpoint | Service) & Indexable>) {
function expressionsGraphqlPods() {
const metrics: string[] = [];
const subMetrics: string[] = [];
config.expressions = config.expressions || [];
@ -246,22 +198,18 @@ export async function useExpressionsQueryPodsMetrics(
variables.push(`$entity${index}: Entity!`);
conditions[`entity${index}`] = entity;
const f = metrics.map((name: string, idx: number) => {
if (index === 0) {
variables.push(`$expression${idx}: String!`);
conditions[`expression${idx}`] = name;
}
variables.push(`$expression${index}${idx}: String!`);
conditions[`expression${index}${idx}`] = name;
let str = "";
if (config.subExpressions[idx]) {
if (index === 0) {
variables.push(`$subExpression${idx}: String!`);
conditions[`subExpression${idx}`] = config.subExpressions[idx];
}
str = `subexpression${index}${idx}: execExpression(expression: $subExpression${idx}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}`;
variables.push(`$subExpression${index}${idx}: String!`);
conditions[`subExpression${index}${idx}`] = config.subExpressions[idx];
str = `subexpression${index}${idx}: execExpression(expression: $subExpression${index}${idx}, entity: $entity${index}, duration: $duration)${RespFields.execExpression}`;
}
return (
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;
@ -272,10 +220,7 @@ export async function useExpressionsQueryPodsMetrics(
return { queryStr, conditions };
}
function expressionsPodsSource(
resp: { errors: string; data: Indexable },
pods: Array<(Instance | Endpoint | Service) & Indexable>,
): Indexable {
function expressionsPodsSource(resp: { errors: string; data: Indexable }): Indexable {
if (resp.errors) {
ElMessage.error(resp.errors);
return {};
@ -356,47 +301,24 @@ export async function useExpressionsQueryPodsMetrics(
return { data, names, subNames, metricConfigArr, metricTypesArr, expressionsTips, subExpressionsTips };
}
const dashboardStore = useDashboardStore();
const params = await expressionsGraphqlPods();
const json = await dashboardStore.fetchMetricValue(params);
async function fetchPodsExpressionValues(pods: Array<(Instance | Endpoint | Service) & Indexable>) {
const dashboardStore = useDashboardStore();
const params = await expressionsGraphqlPods(pods);
const json = await dashboardStore.fetchMetricValue(params);
if (json.errors) {
ElMessage.error(json.errors);
return {};
}
const expressionParams = expressionsPodsSource(json, pods);
return expressionParams;
if (json.errors) {
ElMessage.error(json.errors);
return {};
}
const expressionParams = expressionsPodsSource(json);
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;
return expressionParams;
}
export function useQueryTopologyExpressionsProcessor(metrics: string[], instances: (Call | Node)[]) {
const appStore = useAppStoreWithOut();
const dashboardStore = useDashboardStore();
function getExpressionQuery(partMetrics?: string[]) {
function getExpressionQuery() {
const conditions: { [key: string]: unknown } = {
duration: appStore.durationTime,
};
@ -408,14 +330,10 @@ export function useQueryTopologyExpressionsProcessor(metrics: string[], instance
let serviceInstanceName;
let destServiceInstanceName;
let destEndpointName;
let normal = false;
let destNormal;
if (d.sourceObj && d.targetObj) {
// instances = Calls
serviceName = d.sourceObj.serviceName || d.sourceObj.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) {
serviceInstanceName = d.sourceObj.name;
destServiceInstanceName = d.targetObj.name;
@ -427,10 +345,6 @@ export function useQueryTopologyExpressionsProcessor(metrics: string[], instance
} else {
// instances = Nodes
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) {
serviceInstanceName = d.name;
}
@ -440,17 +354,17 @@ export function useQueryTopologyExpressionsProcessor(metrics: string[], instance
}
const entity = {
serviceName,
normal,
normal: true,
serviceInstanceName,
endpointName,
destServiceName,
destNormal: destServiceName ? destNormal : undefined,
destNormal: destServiceName ? true : undefined,
destServiceInstanceName,
destEndpointName,
};
variables.push(`$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) {
variables.push(`$expression${idx}: String!`);
conditions[`expression${idx}`] = name;
@ -464,51 +378,23 @@ export function useQueryTopologyExpressionsProcessor(metrics: string[], instance
return { queryStr, conditions };
}
function handleExpressionValues(partMetrics: string[], resp: { [key: string]: any }) {
const obj: Indexable = {};
function handleExpressionValues(resp: { [key: string]: any }) {
const obj: any = {};
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;
if (partMetrics[index]) {
if (!obj[partMetrics[index]]) {
obj[partMetrics[index]] = {
if (metrics[index]) {
if (!obj[metrics[index]]) {
obj[metrics[index]] = {
values: [],
};
}
obj[partMetrics[index]].values.push({
value: resp[k] && resp[k].results[0] && resp[k].results[0].values[0].value,
id: instances[idx].id,
});
obj[metrics[index]].values.push({ value: resp[k].results[0].values[0].value, id: instances[idx].id });
}
}
}
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() {
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 };
return { getExpressionQuery, handleExpressionValues };
}

View File

@ -16,9 +16,6 @@
*/
import type { LegendOptions } from "@/types/dashboard";
import { isDef } from "@/utils/is";
import { DarkChartColors, LightChartColors } from "./data";
import { useAppStoreWithOut } from "@/store/modules/app";
import { Themes } from "@/constants/data";
export default function useLegendProcess(legend?: LegendOptions) {
let isRight = false;
@ -35,7 +32,7 @@ export default function useLegendProcess(legend?: LegendOptions) {
if (keys.length === 1) {
return false;
}
if (legend && (legend.asTable || legend.asSelector)) {
if (legend && legend.asTable) {
return false;
}
return true;
@ -99,11 +96,37 @@ export default function useLegendProcess(legend?: LegendOptions) {
return { source, headers };
}
function chartColors() {
const appStore = useAppStoreWithOut();
const list = appStore.theme === Themes.Dark ? DarkChartColors : LightChartColors;
return list;
function chartColors(keys: string[]) {
let color: string[] = [];
switch (keys.length) {
case 2:
color = ["#FF6A84", "#a0b1e6"];
break;
case 1:
color = ["#3f96e3"];
break;
default:
color = [
"#30A4EB",
"#45BFC0",
"#FFCC55",
"#FF6A84",
"#a0a7e6",
"#c23531",
"#2f4554",
"#61a0a8",
"#d48265",
"#91c7ae",
"#749f83",
"#ca8622",
"#bda29a",
"#6e7074",
"#546570",
"#c4ccd3",
];
break;
}
return color;
}
return { showEchartsLegend, isRight, aggregations, chartColors };
}

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

@ -24,7 +24,7 @@ limitations under the License. -->
<style lang="scss" scoped>
.app-main {
height: calc(100% - 40px);
background: $layout-background;
background: #f7f9fa;
overflow: auto;
}
</style>

View File

@ -48,20 +48,11 @@ limitations under the License. -->
@input="changeTimeRange"
/>
<span> UTC{{ appStore.utcHour >= 0 ? "+" : "" }}{{ `${appStore.utcHour}:${appStore.utcMin}` }} </span>
<span class="ml-5" ref="themeSwitchRef">
<el-switch
v-model="theme"
:active-icon="Moon"
:inactive-icon="Sunny"
inline-prompt
@change="handleChangeTheme"
/>
</span>
<span title="refresh" class="ghost ml-5 cp" @click="handleReload">
<Icon iconName="retry" :loading="appStore.autoRefresh" class="middle" />
</span>
<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" effect="light" :content="appStore.version">
<template #reference>
<span>
<Icon iconName="info_outline" size="middle" />
@ -73,18 +64,17 @@ limitations under the License. -->
</div>
</template>
<script lang="ts" setup>
import { Themes } from "@/constants/data";
import router from "@/router";
import { ref, watch } from "vue";
import { useRoute } from "vue-router";
import { useI18n } from "vue-i18n";
import timeFormat from "@/utils/timeFormat";
import { useAppStoreWithOut } from "@/store/modules/app";
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 { ref, watch } from "vue";
import { useI18n } from "vue-i18n";
import { useRoute } from "vue-router";
import { MetricCatalog } from "@/views/dashboard/data";
import type { DashboardItem } from "@/types/dashboard";
import router from "@/router";
import { ArrowRight } from "@element-plus/icons-vue";
/*global Indexable */
const { t, te } = useI18n();
@ -94,67 +84,11 @@ limitations under the License. -->
const pathNames = ref<{ path?: string; name: string; selected: boolean }[][]>([]);
const timeRange = ref<number>(0);
const pageTitle = ref<string>("");
const theme = ref<boolean>(true);
const themeSwitchRef = ref<HTMLElement>();
const savedTheme = window.localStorage.getItem("theme-is-dark");
if (savedTheme === "false") {
theme.value = false;
}
if (savedTheme === "") {
// read the theme preference from system setting if there is no user setting
theme.value = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
}
changeTheme();
resetDuration();
getVersion();
getNavPaths();
function changeTheme() {
const root = document.documentElement;
if (theme.value) {
root.classList.add(Themes.Dark);
root.classList.remove(Themes.Light);
appStore.setTheme(Themes.Dark);
} else {
root.classList.add(Themes.Light);
root.classList.remove(Themes.Dark);
appStore.setTheme(Themes.Light);
}
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[]) {
return list.find((d: any) => d.selected) || {};
}
@ -353,16 +287,21 @@ limitations under the License. -->
padding: 5px;
text-align: left;
justify-content: space-between;
background-color: $theme-background;
border-bottom: 1px solid $border-color;
color: $font-color;
background-color: #fafbfc;
border-bottom: 1px solid #dfe4e8;
color: #222;
font-size: $font-size-smaller;
}
.nav-bar.dark {
background-color: #333840;
border-bottom: 1px solid #252a2f;
color: #fafbfc;
}
.title {
font-size: $font-size-normal;
font-weight: 500;
padding-top: 5px;
}
.nav-tabs {

View File

@ -50,7 +50,7 @@ limitations under the License. -->
</el-menu-item>
</el-menu-item-group>
</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">
<router-link class="items menu-title" :to="menu.children[0].path">
<Icon size="lg" :iconName="menu.meta.icon" />
@ -83,6 +83,7 @@ limitations under the License. -->
const appStore = useAppStoreWithOut();
const router = useRouter();
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>(
(router.options.routes || []).filter((d: any) => d.meta && d.meta.activate),
);
@ -99,7 +100,9 @@ limitations under the License. -->
if (route.name === "ViewWidget") {
showMenu.value = false;
}
const changePage = (menu: RouteRecordRaw) => {
theme.value = ["VirtualMachine", "Kubernetes"].includes(String(menu.name)) ? "light" : "black";
};
const filterMenus = (menus: Recordable[]) => {
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",
label: "Service Name",
id: "Service ID",
setRoot: "Set Normal to Root",
setNormal: "Set Root to Normal",
setRoot: "Set this to root",
setNormal: "Set this to normal",
export: "Export Dashboard Templates",
import: "Import Dashboard Templates",
yes: "Yes",
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",
showYAxis: "Show Y Axis",
nameError: "The dashboard name cannot be duplicate",
@ -139,6 +140,7 @@ const msg = {
enableAssociate: "Enable association",
text: "Text",
query: "Query",
endpointTips: "The table shows up to 20 pieces of endpoints.",
viewTrace: "View Related Traces",
relatedTraceOptions: "Related Trace Options",
setLatencyDuration: "Latency Related Metrics",
@ -153,7 +155,6 @@ const msg = {
legendOptions: "Legend Options",
showLegend: "Show Legend",
asTable: "As Table",
asSelector: "As Selector",
toTheRight: "To The Right",
legendValues: "Legend Values",
minDuration: "Minimal Request Duration",
@ -164,6 +165,7 @@ const msg = {
iframeSrc: "Iframe Link",
generateLink: "Generate Link",
setDuration: "Lock Query Duration",
openFunction: "OpenFunction",
period: "Period",
windows: "Windows",
seconds: "Seconds",
@ -284,8 +286,7 @@ const msg = {
errorInfo: "Error Info",
stack: "Stack",
serviceVersion: "Service Version",
pagePath: "Page Path",
errorUrl: "Error Url",
errorPage: "Error Page",
category: "Category",
grade: "Grade",
relatedTraceLogs: "Related Logs",
@ -296,12 +297,11 @@ const msg = {
return: "Return",
isError: "Error",
contentType: "Content Type",
content: "Timestamp - Content",
level: "Level",
content: "Content",
viewLogs: "View Logs",
logsTagsTip: `Only tags defined in the core/default/searchableLogsTags are searchable.
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",
viewAttributes: "View",
attributes: "Attributes",
@ -356,7 +356,7 @@ const msg = {
addKeywordsOfContent: "Please input a keyword of content",
addExcludingKeywordsOfContent: "Please input a keyword of excluding content",
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",
save: "Save",
editStrategy: "Edit Policies",
@ -378,24 +378,9 @@ const msg = {
menus: "Menus",
saveReload: "Save and reload the page",
document: "Documentation",
metricMode: "Metric Mode",
addExpressions: "Add Expressions",
expressions: "Expression",
unhealthyExpression: "Unhealthy Expression",
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.",
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;

View File

@ -101,7 +101,8 @@ const msg = {
import: "Importar Plantilla Panel",
yes: "Sí",
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",
showYAxis: "Mostrar Eje Y",
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",
enableAssociate: "Activar asociación",
query: "Consulta",
endpointTips: "Aquí, la tabla muestra hasta 20 punto final.",
queryOrder: "Consulta por duración",
setOrder: "Orden de consulta",
latency: "Retraso",
@ -147,6 +149,7 @@ const msg = {
iframeSrc: "Enlace Iframe",
generateLink: "Generar enlaces",
setDuration: "Duración de la consulta de bloqueo",
openFunction: "OpenFunction",
seconds: "Segundos",
hourTip: "Seleccione Hora",
minuteTip: "Seleccione Minuto",
@ -282,8 +285,7 @@ const msg = {
errorInfo: "Info Error",
stack: "Pila",
serviceVersion: "Versión Servicio",
pagePath: "Página de Error",
errorUrl: "Ruta de Error",
errorPage: "Página de Error",
category: "Categoría",
grade: "Grado",
relatedTraceLogs: "Registro de Datos Relacionados",
@ -295,11 +297,10 @@ const msg = {
isError: "Error",
contentType: "Tipo de Contenido",
content: "Contenido",
level: "Level",
viewLogs: "Ver Registro de Datos",
logsTagsTip: `Solamente etiquetas definidas en core/default/searchableLogsTags pueden ser buscadas.
Más información en la página de Vocabulario de Configuración`,
keywordsOfContentLogTips: "El almacenamiento actual del servidor SkyWalking OAP no lo soporta",
keywordsOfContentLogTips: "El almacenamiento actual del servidor SkyWalking OAP no lo soporta.",
setEvent: "Establecer Evento",
viewAttributes: "Ver",
serviceEvents: "Eventos Servico",
@ -377,25 +378,9 @@ const msg = {
menus: "Menus",
saveReload: "Save and reload the page",
document: "Documentation",
metricMode: "Metric Mode",
addExpressions: "Add Expressions",
expressions: "Expression",
unhealthyExpression: "Unhealthy Expression",
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.",
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;

View File

@ -30,11 +30,6 @@ const titles = {
general_service_virtual_mq: "Virtual MQ",
general_service_virtual_mq_desc:
"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_desc:
@ -46,6 +41,13 @@ const titles = {
service_mesh_control_plane_desc: "Provide monitoring of the behavior of Istio through its self-monitoring metrics.",
service_mesh_data_plane: "Data Plane",
service_mesh_data_plane_desc: "Observe Envoy Proxy through Envoy Metrics Service.",
// Functions
functions: "Functions",
functions_desc:
"FaaS (Function-as-a-Service) is a type of cloud-computing service that allows you to execute code in response to events without the complex infrastructure typically associated with building and launching microservices applications.",
functions_openfunction: "OpenFunction",
functions_openfunction_desc:
"OpenFunction as a FaaS platform, provides out-of-box observability with SkyWalking integration.",
// Kubernetes
kubernetes: "Kubernetes",
kubernetes_desc:
@ -80,8 +82,6 @@ const titles = {
gateway: "Gateway",
gateway_desc:
"API gateway is an API management tool that sits between a client and a collection of backend services.",
gateway_nginx: "Nginx",
gateway_nginx_desc: "Provide Nginx monitoring through OpenTelemetry's Prometheus Receiver.",
gateway_apisix: "APISIX",
gateway_apisix_desc: "Provide APISIX monitoring through OpenTelemetry's Prometheus Receiver.",
gateway_aws_api_gateway: "AWS API Gateway",
@ -109,12 +109,6 @@ const titles = {
"A message queue is a form of asynchronous service-to-service communication used in serverless and microservices architectures.",
mq_rabbitmq: "RabbitMQ",
mq_rabbitmq_desc: "Provide RabbitMQ monitoring through OpenTelemetry's Prometheus Receiver.",
mq_kafka: "Kafka",
mq_kafka_desc: "Provide Kafka monitoring through OpenTelemetry's Prometheus Receiver.",
mq_pulsar: "Pulsar",
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_desc:
@ -125,23 +119,6 @@ const titles = {
self_observability_satellite: "Satellite",
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.",
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;

View File

@ -30,12 +30,6 @@ const titles = {
general_service_virtual_mq: "MQ virtual",
general_service_virtual_mq_desc:
"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: "Malla de Servicios",
service_mesh_desc:
@ -47,6 +41,13 @@ const titles = {
service_mesh_control_plane_desc: "Provide monitoring of the behavior of Istio through its self-monitoring metrics.",
service_mesh_data_plane: "Plano de Datos",
service_mesh_data_plane_desc: "Observe Envoy Proxy through Envoy Metrics Service.",
// Functions
functions: "Funciones",
functions_desc:
"FaaS (Function-as-a-Service) is a type of cloud-computing service that allows you to execute code in response to events without the complex infrastructure typically associated with building and launching microservices applications.",
functions_openfunction: "OpenFunction",
functions_openfunction_desc:
"OpenFunction as a FaaS platform, provides out-of-box observability with SkyWalking integration.",
// Kubernetes
kubernetes: "Kubernetes",
kubernetes_desc:
@ -81,8 +82,6 @@ const titles = {
gateway: "Puerta",
gateway_desc:
"API gateway is an API management tool that sits between a client and a collection of backend services.",
gateway_nginx: "Nginx",
gateway_nginx_desc: "Provide Nginx monitoring through OpenTelemetry's Prometheus Receiver.",
gateway_apisix: "APISIX",
gateway_apisix_desc: "Provide APISIX monitoring through OpenTelemetry's Prometheus Receiver.",
gateway_aws_api_gateway: "AWS API Gateway",
@ -110,12 +109,6 @@ const titles = {
"A message queue is a form of asynchronous service-to-service communication used in serverless and microservices architectures.",
mq_rabbitmq: "RabbitMQ",
mq_rabbitmq_desc: "Provide RabbitMQ monitoring through OpenTelemetry's Prometheus Receiver.",
mq_kafka: "Kafka",
mq_kafka_desc: "Provide Kafka monitoring through OpenTelemetry's Prometheus Receiver.",
mq_pulsar: "Pulsar",
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_desc:
@ -126,23 +119,6 @@ const titles = {
self_observability_satellite: "Satellite",
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.",
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;

View File

@ -26,11 +26,6 @@ const titles = {
general_service_virtual_cache_desc: "观察语言代理通过各种插件推测的虚拟缓存服务器。",
general_service_virtual_mq: "虚拟消息队列",
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_desc: "服务网格Istio通过分布式或微服务架构解决了开发人员和运营商面临的挑战。",
@ -40,6 +35,12 @@ const titles = {
service_mesh_control_plane_desc: "通过Istio的自我监控指标提供对其行为的监控。",
service_mesh_data_plane: "数据平面",
service_mesh_data_plane_desc: "通过Envoy Metrics Service观察Envoy Proxy。",
// Functions
functions: "Functions",
functions_desc:
"FaaS功能即服务是一种云计算服务允许您在没有通常与构建和启动微服务应用程序相关的复杂基础设施的情况下执行代码以响应事件。",
functions_openfunction: "OpenFunction",
functions_openfunction_desc: "OpenFunction作为一个FaaS平台通过SkyWalking集成提供开箱即用的可观察性。",
// Kubernetes
kubernetes: "Kubernetes",
kubernetes_desc: "Kubernetes是一个开源的容器编排系统用于自动化软件部署、扩展和管理。",
@ -71,8 +72,6 @@ const titles = {
// Gateway
gateway: "网关",
gateway_desc: "API网关是位于客户端和后端服务集合之间的API管理工具。",
gateway_nginx: "Nginx",
gateway_nginx_desc: "通过OpenTelemetry的Prometheus接收器提供Nginx监控。",
gateway_apisix: "APISIX",
gateway_apisix_desc: "通过OpenTelemetry的Prometheus接收器提供APISIX监控。",
gateway_aws_api_gateway: "AWS API Gateway",
@ -97,12 +96,6 @@ const titles = {
mq_desc: "消息队列是无服务器和微服务架构中使用的异步服务对服务通信的一种形式。",
mq_rabbitmq: "RabbitMQ",
mq_rabbitmq_desc: "通过OpenTelemetry的Prometheus接收器提供RabbitMQ监控。",
mq_kafka: "Kafka",
mq_Kafka_desc: "通过OpenTelemetry的Prometheus接收器提供Kafka监控。",
mq_pulsar: "Pulsar",
mq_Pulsar_desc: "通过OpenTelemetry的Prometheus接收器提供Pulsar监控。",
mq_rocketmq: "RocketMQ",
mq_rocketmq_desc: "通过OpenTelemetry的Prometheus接收器提供RocketMQ监控。",
// self observability
self_observability: "自监控",
self_observability_desc: "自观察性为运行SkyWalking生态系统中的组件和服务器提供了可观察性。",
@ -111,19 +104,6 @@ const titles = {
self_observability_satellite: "Satellite",
self_observability_satellite_desc:
"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;

View File

@ -99,7 +99,8 @@ const msg = {
import: "导入仪表板模板",
yes: "是",
no: "否",
tableHeaderCol2: "表格的最后一列的名称",
tableHeaderCol1: "表格的第一列的名称",
tableHeaderCol2: "表格的第二列的名称",
showXAxis: "显示X轴",
showYAxis: "显示Y轴",
nameError: "仪表板名称不能重复",
@ -137,6 +138,7 @@ const msg = {
duplicateName: "重复的名称",
text: "文本",
query: "查询",
endpointTips: "这里最多展示20条endpoints。",
viewTrace: "查看相关Trace",
relatedTraceOptions: "相关的Trace选项",
setLatencyDuration: "延迟相关指标",
@ -151,7 +153,6 @@ const msg = {
legendOptions: "图例选项",
showLegend: "显示图例",
asTable: "作为表格",
asSelector: "作为选择器",
toTheRight: "在右边",
legendValues: "图例值",
minDuration: "最小请求持续时间",
@ -162,6 +163,7 @@ const msg = {
iframeSrc: "Iframe链接",
generateLink: "生成链接",
setDuration: "锁定查询持续时间",
openFunction: "OpenFunction",
period: "周期",
windows: "Windows",
seconds: "秒",
@ -281,8 +283,7 @@ const msg = {
errorInfo: "错误信息",
stack: "堆栈",
serviceVersion: "服务版本",
pagePath: "错误页面",
errorUrl: "错误路径",
errorPage: "错误页面",
category: "类别",
grade: "等级",
relatedTraceLogs: "相关的日志",
@ -293,8 +294,7 @@ const msg = {
return: "返回",
isError: "错误",
contentType: "内容类型",
content: "时间戳 - 内容",
level: "Level",
content: "内容",
viewLogs: "查看日志",
logsTagsTip: "只有core/default/searchableLogsTags中定义的标记才可搜索。查看配置词汇表页面上的更多详细信息。",
keywordsOfContentLogTips: "SkyWalking OAP服务器的当前存储不支持此操作",
@ -376,24 +376,9 @@ const msg = {
menusManagement: "菜单",
saveReload: "保存并重新加载页面",
document: "文档",
metricMode: "指标模式",
addExpressions: "添加表达式",
expressions: "表达式",
unhealthyExpression: "非健康表达式",
traceDesc:
"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;

View File

@ -15,7 +15,6 @@
* limitations under the License.
*/
import { createApp } from "vue";
import { ElLoading } from "element-plus";
import App from "./App.vue";
import { store } from "./store";
import components from "@/components";
@ -24,11 +23,6 @@ import { useAppStoreWithOut } from "@/store/modules/app";
import "./styles/index.ts";
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 appStore = useAppStoreWithOut();
@ -40,7 +34,7 @@ mountApp();
async function mountApp() {
await appStore.getActivateMenus();
await appStore.queryOAPTimeInfo();
const router = await import("./router");
app.use(router.default).mount("#app");
loading.close();
}

View File

@ -16,7 +16,6 @@
*/
import type { RouteRecordRaw } from "vue-router";
import Layout from "@/layout/Index.vue";
import Alarm from "@/views/Alarm.vue";
export const routesAlarm: Array<RouteRecordRaw> = [
{
@ -33,8 +32,8 @@ export const routesAlarm: Array<RouteRecordRaw> = [
children: [
{
path: "/alerting",
name: "ViewAlarm",
component: Alarm,
name: "Alarm",
component: () => import("@/views/Alarm.vue"),
},
],
},

View File

@ -16,10 +16,6 @@
*/
import type { RouteRecordRaw } from "vue-router";
import Layout from "@/layout/Index.vue";
import List from "@/views/dashboard/List.vue";
import New from "@/views/dashboard/New.vue";
import Edit from "@/views/dashboard/Edit.vue";
import Widget from "@/views/dashboard/Widget.vue";
export const routesDashboard: Array<RouteRecordRaw> = [
{
@ -36,7 +32,7 @@ export const routesDashboard: Array<RouteRecordRaw> = [
children: [
{
path: "/dashboard/list",
component: List,
component: () => import("@/views/dashboard/List.vue"),
name: "List",
meta: {
i18nKey: "dashboardList",
@ -46,7 +42,7 @@ export const routesDashboard: Array<RouteRecordRaw> = [
},
{
path: "/dashboard/new",
component: New,
component: () => import("@/views/dashboard/New.vue"),
name: "New",
meta: {
i18nKey: "dashboardNew",
@ -58,26 +54,26 @@ export const routesDashboard: Array<RouteRecordRaw> = [
path: "",
redirect: "/dashboard/:layerId/:entity/:name",
name: "Create",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
meta: {
notShow: true,
},
children: [
{
path: "/dashboard/:layerId/:entity/:name",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "CreateChild",
},
{
path: "/dashboard/:layerId/:entity/:name/tab/:activeTabIndex",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "CreateActiveTabIndex",
},
],
},
{
path: "",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "View",
redirect: "/dashboard/:layerId/:entity/:serviceId/:name",
meta: {
@ -86,12 +82,12 @@ export const routesDashboard: Array<RouteRecordRaw> = [
children: [
{
path: "/dashboard/:layerId/:entity/:serviceId/:name",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewChild",
},
{
path: "/dashboard/:layerId/:entity/:serviceId/:name/tab/:activeTabIndex",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewActiveTabIndex",
},
],
@ -99,20 +95,20 @@ export const routesDashboard: Array<RouteRecordRaw> = [
{
path: "",
redirect: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name",
component: Edit,
name: "ServiceRelations",
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewServiceRelation",
meta: {
notShow: true,
},
children: [
{
path: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewServiceRelation",
},
{
path: "/dashboard/related/:layerId/:entity/:serviceId/:destServiceId/:name/tab/:activeTabIndex",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewServiceRelationActiveTabIndex",
},
],
@ -120,20 +116,20 @@ export const routesDashboard: Array<RouteRecordRaw> = [
{
path: "",
redirect: "/dashboard/:layerId/:entity/:serviceId/:podId/:name",
component: Edit,
name: "Pods",
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewPod",
meta: {
notShow: true,
},
children: [
{
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:name",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewPod",
},
{
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:name/tab/:activeTabIndex",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewPodActiveTabIndex",
},
],
@ -141,20 +137,20 @@ export const routesDashboard: Array<RouteRecordRaw> = [
{
path: "",
redirect: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:name",
component: Edit,
name: "Processes",
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewProcess",
meta: {
notShow: true,
},
children: [
{
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:name",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewProcess",
},
{
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:name/tab/:activeTabIndex",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewProcessActiveTabIndex",
},
],
@ -162,20 +158,20 @@ export const routesDashboard: Array<RouteRecordRaw> = [
{
path: "",
redirect: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name",
component: Edit,
name: "PodRelations",
component: () => import("@/views/dashboard/Edit.vue"),
name: "PodRelation",
meta: {
notShow: true,
},
children: [
{
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewPodRelation",
},
{
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:destServiceId/:destPodId/:name/tab/:activeTabIndex",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewPodRelationActiveTabIndex",
},
],
@ -184,25 +180,25 @@ export const routesDashboard: Array<RouteRecordRaw> = [
path: "",
redirect:
"/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name",
component: Edit,
name: "ProcessRelations",
component: () => import("@/views/dashboard/Edit.vue"),
name: "ProcessRelation",
meta: {
notShow: true,
},
children: [
{
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewProcessRelation",
},
{
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name/tab/:activeTabIndex",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewProcessRelationActiveTabIndex",
},
{
path: "/dashboard/:layerId/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:name/duration/:duration",
component: Edit,
component: () => import("@/views/dashboard/Edit.vue"),
name: "ViewProcessRelationDuration",
},
],
@ -210,14 +206,14 @@ export const routesDashboard: Array<RouteRecordRaw> = [
{
path: "",
name: "Widget",
component: Widget,
component: () => import("@/views/dashboard/Widget.vue"),
meta: {
notShow: true,
},
children: [
{
path: "/page/:layer/:entity/:serviceId/:podId/:processId/:destServiceId/:destPodId/:destProcessId/:config/:duration?",
component: Widget,
component: () => import("@/views/dashboard/Widget.vue"),
name: "ViewWidget",
},
],

View File

@ -21,7 +21,6 @@ import { routesMarketplace } from "./marketplace";
import { routesAlarm } from "./alarm";
import routesLayers from "./layer";
import { routesSettings } from "./settings";
import { routesNotFound } from "./notFound";
const routes: RouteRecordRaw[] = [
...routesMarketplace,
@ -29,7 +28,6 @@ const routes: RouteRecordRaw[] = [
...routesAlarm,
...routesDashboard,
...routesSettings,
...routesNotFound,
];
const router = createRouter({
@ -37,27 +35,19 @@ const router = createRouter({
routes,
});
router.beforeEach((to, _, next) => {
(window as any).axiosCancel = [];
router.beforeEach((to, from, next) => {
// 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 === "/") {
let defaultPath = "";
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";
}
const defaultPath = (routesLayers[0] && routesLayers[0].children[0].path) || "";
next({ path: defaultPath });
} else {
next();

View File

@ -17,7 +17,6 @@
import Layout from "@/layout/Index.vue";
import { useAppStoreWithOut } from "@/store/modules/app";
import type { MenuOptions } from "@/types/app";
import Layer from "@/views/Layer.vue";
function layerDashboards() {
const appStore = useAppStoreWithOut();
@ -48,13 +47,13 @@ function layerDashboards() {
descKey: child.descKey,
i18nKey: child.i18nKey,
},
component: Layer,
component: () => import("@/views/Layer.vue"),
};
route.children.push(d);
const tab = {
name: `${child.name}ActiveTabIndex`,
path: `/${child.path}/tab/:activeTabIndex`,
component: Layer,
path: `/${child.name}/tab/:activeTabIndex`,
component: () => import("@/views/Layer.vue"),
meta: {
notShow: true,
layer: child.layer,
@ -75,7 +74,7 @@ function layerDashboards() {
descKey: item.descKey,
i18nKey: item.i18nKey,
},
component: Layer,
component: () => import("@/views/Layer.vue"),
},
];
}

View File

@ -16,7 +16,6 @@
*/
import type { RouteRecordRaw } from "vue-router";
import Layout from "@/layout/Index.vue";
import Marketplace from "@/views/Marketplace.vue";
export const routesMarketplace: Array<RouteRecordRaw> = [
{
@ -34,7 +33,7 @@ export const routesMarketplace: Array<RouteRecordRaw> = [
{
path: "/marketplace",
name: "MenusManagement",
component: Marketplace,
component: () => import("@/views/Marketplace.vue"),
},
],
},

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

@ -16,7 +16,6 @@
*/
import type { RouteRecordRaw } from "vue-router";
import Layout from "@/layout/Index.vue";
import Settings from "@/views/Settings.vue";
export const routesSettings: Array<RouteRecordRaw> = [
{
@ -33,8 +32,8 @@ export const routesSettings: Array<RouteRecordRaw> = [
children: [
{
path: "/settings",
name: "ViewSettings",
component: Settings,
name: "Settings",
component: () => import("@/views/Settings.vue"),
},
],
},

View File

@ -14,15 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { WidgetType } from "@/views/dashboard/data";
export const NewControl = {
x: 0,
y: 0,
w: 24,
h: 12,
i: "0",
type: WidgetType.Widget,
type: "Widget",
};
export const TextConfig = {
fontColor: "white",
@ -41,20 +39,17 @@ export const TimeRangeConfig = {
};
export const ControlsTypes = [
WidgetType.Trace,
WidgetType.Profile,
WidgetType.Log,
WidgetType.DemandLog,
WidgetType.Ebpf,
WidgetType.NetworkProfiling,
WidgetType.AsyncProfiling,
WidgetType.ThirdPartyApp,
WidgetType.ContinuousProfiling,
WidgetType.TaskTimeline,
"Trace",
"Profile",
"Log",
"DemandLog",
"Ebpf",
"NetworkProfiling",
"ThirdPartyApp",
"ContinuousProfiling",
"TaskTimeline",
];
export enum EBPFProfilingTriggerType {
FIXED_TIME = "FIXED_TIME",
CONTINUOUS_PROFILING = "CONTINUOUS_PROFILING",
}
export const EndpointsTopNDefault = 20;

View File

@ -17,8 +17,8 @@
import { defineStore } from "pinia";
import { store } from "@/store";
import graphql from "@/graphql";
import type { AxiosResponse } from "axios";
import type { Alarm } from "@/types/alarm";
import { useAppStoreWithOut } from "@/store/modules/app";
interface AlarmState {
loading: boolean;
@ -35,24 +35,16 @@ export const alarmStore = defineStore({
}),
actions: {
async getAlarms(params: Recordable) {
this.loading = true;
const res = await graphql.query("queryAlarms").params(params);
this.loading = false;
if (res.errors) {
return res;
const res: AxiosResponse = await graphql.query("queryAlarms").params(params);
if (res.data.errors) {
return res.data;
}
if (res.data.getAlarm.items) {
this.alarms = res.data.getAlarm.items;
this.total = res.data.getAlarm.total;
if (res.data.data.getAlarm.items) {
this.alarms = res.data.data.getAlarm.items;
this.total = res.data.data.getAlarm.total;
}
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,10 +19,10 @@ import { store } from "@/store";
import graphql from "@/graphql";
import type { Duration, DurationTime } from "@/types/app";
import getLocalTime from "@/utils/localtime";
import type { AxiosResponse } from "axios";
import dateFormatStep, { dateFormatTime } from "@/utils/dateFormat";
import { TimeType } from "@/constants/data";
import type { MenuOptions, SubItem } from "@/types/app";
import { Themes } from "@/constants/data";
/*global Nullable*/
interface AppState {
durationRow: Recordable;
@ -36,7 +36,6 @@ interface AppState {
isMobile: boolean;
reloadTimer: Nullable<IntervalHandle>;
allMenus: MenuOptions[];
theme: string;
}
export const appStore = defineStore({
@ -57,7 +56,6 @@ export const appStore = defineStore({
isMobile: false,
reloadTimer: null,
allMenus: [],
theme: Themes.Dark,
}),
getters: {
duration(): Duration {
@ -117,14 +115,17 @@ export const appStore = defineStore({
actions: {
setDuration(data: Duration): void {
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();
},
updateDurationRow(data: Duration) {
this.durationRow = data;
},
setTheme(data: string) {
this.theme = data;
},
setUTC(utcHour: number, utcMin: number): void {
this.runEventStack();
this.utcMin = utcMin;
@ -178,11 +179,11 @@ export const appStore = defineStore({
});
},
async queryOAPTimeInfo() {
const res = await graphql.query("queryOAPTimeInfo").params({});
if (res.errors) {
const res: AxiosResponse = await graphql.query("queryOAPTimeInfo").params({});
if (res.data.errors) {
this.utc = -(new Date().getTimezoneOffset() / 60) + ":0";
} else {
this.utc = res.data.getTimeInfo.timezone / 100 + ":0";
this.utc = res.data.data.getTimeInfo.timezone / 100 + ":0";
}
const utcArr = this.utc.split(":");
this.utcHour = isNaN(Number(utcArr[0])) ? 0 : Number(utcArr[0]);
@ -190,21 +191,21 @@ export const appStore = defineStore({
return res.data;
},
async fetchVersion() {
const res = await graphql.query("queryOAPVersion").params({});
if (res.errors) {
return res;
async fetchVersion(): Promise<void> {
const res: AxiosResponse = await graphql.query("queryOAPVersion").params({});
if (res.data.errors) {
return res.data;
}
this.version = res.data.version;
this.version = res.data.data.version;
return res.data;
},
async queryMenuItems() {
const res = await graphql.query("queryMenuItems").params({});
if (res.errors) {
return res;
const res: AxiosResponse = await graphql.query("queryMenuItems").params({});
if (res.data.errors) {
return res.data;
}
return res.data;
return res.data.data;
},
setReloadTimer(timer: IntervalHandle) {
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 graphql from "@/graphql";
import type { MonitorInstance, MonitorProcess } from "@/types/continous-profiling";
import type { AxiosResponse } from "axios";
import { dateFormat } from "@/utils/dateFormat";
interface ContinousProfilingState {
@ -83,37 +84,37 @@ export const continousProfilingStore = defineStore({
checkItems: CheckItems[];
}[],
) {
const response = await graphql.query("editStrategy").params({
const res: AxiosResponse = await graphql.query("editStrategy").params({
request: {
serviceId,
targets,
},
});
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
return response;
return res.data;
},
async getStrategyList(params: { serviceId: string }) {
if (!params.serviceId) {
return new Promise((resolve) => resolve({}));
}
this.policyLoading = true;
const response = await graphql.query("getStrategyList").params(params);
const res: AxiosResponse = await graphql.query("getStrategyList").params(params);
this.policyLoading = false;
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
const list = response.data.strategyList || [];
const list = res.data.data.strategyList || [];
if (!list.length) {
this.taskList = [];
this.instances = [];
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) => {
return {
...d,
@ -122,25 +123,25 @@ export const continousProfilingStore = defineStore({
});
this.setSelectedStrategy(this.strategyList[0]);
if (!this.selectedStrategy.type) {
return response;
return res.data;
}
this.getMonitoringInstances(params.serviceId);
return response;
return res.data;
},
async getMonitoringInstances(serviceId: string) {
async getMonitoringInstances(serviceId: string): Promise<Nullable<AxiosResponse>> {
this.instancesLoading = true;
if (!serviceId) {
return null;
}
const response = await graphql.query("getMonitoringInstances").params({
const res: AxiosResponse = await graphql.query("getMonitoringInstances").params({
serviceId,
target: this.selectedStrategy.type,
});
this.instancesLoading = false;
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
this.instances = (response.data.instances || [])
this.instances = (res.data.data.instances || [])
.map((d: MonitorInstance) => {
const processes = (d.processes || [])
.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);
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 type { LayoutConfig } from "@/types/dashboard";
import graphql from "@/graphql";
import fetchQuery from "@/graphql/fetch";
import query from "@/graphql/fetch";
import type { DashboardItem } from "@/types/dashboard";
import { useSelectorStore } from "@/store/modules/selectors";
import { NewControl, TextConfig, TimeRangeConfig, ControlsTypes } from "../data";
import type { AxiosResponse } from "axios";
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 {
showConfig: boolean;
layout: LayoutConfig[];
@ -76,7 +78,7 @@ export const dashboardStore = defineStore({
setCurrentDashboard(item: DashboardItem) {
this.currentDashboard = item;
},
addControl(type: WidgetType) {
addControl(type: string) {
const arr = this.layout.map((d: Recordable) => Number(d.i));
let index = String(Math.max(...arr) + 1);
if (!this.layout.length) {
@ -87,8 +89,14 @@ export const dashboardStore = defineStore({
i: index,
id: index,
type,
metricTypes: [""],
metrics: [""],
};
if (type === WidgetType.Tab) {
if (type === "Widget") {
newItem.metricMode = MetricModes.Expression;
}
if (type === "Tab") {
newItem.h = 36;
newItem.activedTabIndex = 0;
newItem.children = [
@ -102,7 +110,7 @@ export const dashboardStore = defineStore({
},
];
}
if (type === WidgetType.Topology) {
if (type === "Topology") {
newItem.h = 36;
newItem.graph = {
showDepth: true,
@ -112,11 +120,11 @@ export const dashboardStore = defineStore({
if (ControlsTypes.includes(type)) {
newItem.h = 36;
}
if (type === WidgetType.Text) {
if (type === "Text") {
newItem.h = 6;
newItem.graph = TextConfig;
}
if (type === WidgetType.TimeRange) {
if (type === "TimeRange") {
newItem.w = 8;
newItem.h = 6;
newItem.graph = TimeRangeConfig;
@ -141,7 +149,7 @@ export const dashboardStore = defineStore({
};
this.layout[idx].children?.push(i);
},
addTabControls(type: WidgetType) {
addTabControls(type: string) {
const activedGridItem = this.activedGridItem.split("-")[0];
const idx = this.layout.findIndex((d: LayoutConfig) => d.i === activedGridItem);
if (idx < 0) {
@ -160,8 +168,13 @@ export const dashboardStore = defineStore({
i: index,
id,
type,
metricTypes: [""],
metrics: [""],
};
if (type === WidgetType.Topology) {
if (type === "Widget") {
newItem.metricMode = MetricModes.Expression;
}
if (type === "Topology") {
newItem.h = 32;
newItem.graph = {
showDepth: true,
@ -170,11 +183,11 @@ export const dashboardStore = defineStore({
if (ControlsTypes.includes(type)) {
newItem.h = 32;
}
if (type === WidgetType.Text) {
if (type === "Text") {
newItem.h = 6;
newItem.graph = TextConfig;
}
if (type === WidgetType.TimeRange) {
if (type === "TimeRange") {
newItem.w = 8;
newItem.h = 6;
newItem.graph = TextConfig;
@ -278,7 +291,7 @@ export const dashboardStore = defineStore({
},
setWidget(param: LayoutConfig) {
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) {
for (const child of this.layout[i].children || []) {
if (child.children && child.children.length) {
@ -298,24 +311,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 } }) {
return await fetchQuery(param);
const res: AxiosResponse = await query(param);
return res.data;
},
async fetchTemplates() {
const res = await graphql.query("getTemplates").params({});
const res: AxiosResponse = await graphql.query("getTemplates").params({});
if (res.errors) {
return res;
if (res.data.errors) {
return res.data;
}
const data = res.data.getAllTemplates;
const data = res.data.data.getAllTemplates;
let list = [];
for (const t of data) {
const c = JSON.parse(t.configuration);
const key = [c.layer, c.entity, c.name].join("_");
list.push({
...c,
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 }));
}
@ -354,20 +386,20 @@ export const dashboardStore = defineStore({
this.dashboards = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
},
async updateDashboard(setting: { id: string; configuration: string }) {
const resp = await graphql.query("updateTemplate").params({
const res: AxiosResponse = await graphql.query("updateTemplate").params({
setting,
});
if (resp.errors) {
ElMessage.error(resp.errors);
return resp;
if (res.data.errors) {
ElMessage.error(res.data.errors);
return res.data;
}
const json = resp.data.changeTemplate;
const json = res.data.data.changeTemplate;
if (!json.status) {
ElMessage.error(json.message);
return resp;
return res.data;
}
ElMessage.success("Saved successfully");
return resp;
return res.data;
},
async saveDashboard() {
if (!this.currentDashboard?.name) {
@ -396,19 +428,20 @@ export const dashboardStore = defineStore({
d.layer === this.currentDashboard?.layer,
);
if (index > -1) {
ElMessage.error("The dashboard name cannot be duplicate");
const { t } = useI18n();
ElMessage.error(t("nameError"));
return;
}
res = await graphql.query("addNewTemplate").params({ setting: { configuration: JSON.stringify(c) } });
json = res.data.addTemplate;
json = res.data.data.addTemplate;
if (!json.status) {
ElMessage.error(json.message);
}
}
if (res.errors) {
ElMessage.error(res.errors);
return res;
if (res.data.errors || res.errors) {
ElMessage.error(res.data.errors);
return res.data;
}
if (!json.status) {
return json;
@ -430,16 +463,16 @@ export const dashboardStore = defineStore({
return json;
},
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) {
ElMessage.error(res.errors);
return res;
if (res.data.errors) {
ElMessage.error(res.data.errors);
return res.data;
}
const json = res.data.disableTemplate;
const json = res.data.data.disableTemplate;
if (!json.status) {
ElMessage.error(json.message);
return res;
return res.data;
}
this.dashboards = this.dashboards.filter((d: Recordable) => d.id !== this.currentDashboard?.id);
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 { store } from "@/store";
import graphql from "@/graphql";
import type { AxiosResponse } from "axios";
import { useAppStoreWithOut } from "@/store/modules/app";
import { useSelectorStore } from "@/store/modules/selectors";
import type { Conditions, Log } from "@/types/demand-log";
@ -59,16 +60,16 @@ export const demandLogStore = defineStore({
},
async getInstances(id: string) {
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,
duration: useAppStoreWithOut().durationTime,
});
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
this.instances = response.data.pods || [];
return response;
this.instances = res.data.data.pods || [];
return res.data;
},
async getContainers(serviceInstanceId: string) {
if (!serviceInstanceId) {
@ -77,35 +78,35 @@ export const demandLogStore = defineStore({
const condition = {
serviceInstanceId,
};
const response = await graphql.query("fetchContainers").params({ condition });
const res: AxiosResponse = await graphql.query("fetchContainers").params({ condition });
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
if (response.data.containers.errorReason) {
if (res.data.data.containers.errorReason) {
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 response;
return res.data;
},
async getDemandLogs() {
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;
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
if (response.data.logs.errorReason) {
this.setLogs([], response.data.logs.errorReason);
return response;
if (res.data.data.logs.errorReason) {
this.setLogs([], res.data.data.logs.errorReason);
return res.data;
}
this.total = response.data.logs.logs.length;
const logs = response.data.logs.logs.map((d: Log) => d.content).join("\n");
this.total = res.data.data.logs.logs.length;
const logs = res.data.data.logs.logs.map((d: Log) => d.content).join("\n");
this.setLogs(logs);
return 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 { store } from "@/store";
import graphql from "@/graphql";
import type { AxiosResponse } from "axios";
import { EBPFProfilingTriggerType } from "../data";
interface EbpfState {
taskList: Array<Recordable<EBPFTaskList>>;
@ -56,70 +57,70 @@ export const ebpfStore = defineStore({
this.analyzeTrees = tree;
},
async getCreateTaskData(serviceId: string) {
const response = await graphql.query("getCreateTaskData").params({ serviceId });
const res: AxiosResponse = await graphql.query("getCreateTaskData").params({ serviceId });
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
const json = response.data.createTaskData;
const json = res.data.data.createTaskData;
this.couldProfiling = json.couldProfiling || false;
this.labels = json.processLabels.map((d: string) => {
return { label: d, value: d };
});
return response;
return res.data;
},
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) {
return response;
if (res.data.errors) {
return res.data;
}
this.getTaskList({
serviceId: param.serviceId,
targets: ["ON_CPU", "OFF_CPU"],
triggerType: EBPFProfilingTriggerType.FIXED_TIME,
});
return response;
return res.data;
},
async getTaskList(params: { serviceId: string; targets: string[] }) {
if (!params.serviceId) {
return new Promise((resolve) => resolve({}));
}
const response = await graphql.query("getEBPFTasks").params(params);
const res: AxiosResponse = await graphql.query("getEBPFTasks").params(params);
this.ebpfTips = "";
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
this.taskList = response.data.queryEBPFTasks || [];
this.taskList = res.data.data.queryEBPFTasks || [];
this.selectedTask = this.taskList[0] || {};
this.setSelectedTask(this.selectedTask);
if (!this.taskList.length) {
return response;
return res.data;
}
this.getEBPFSchedules({ taskId: String(this.taskList[0].taskId) });
return response;
return res.data;
},
async getEBPFSchedules(params: { taskId: string }) {
if (!params.taskId) {
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 = [];
return response;
return res.data;
}
this.ebpfTips = "";
const { eBPFSchedules } = response.data;
const { eBPFSchedules } = res.data.data;
this.eBPFSchedules = eBPFSchedules;
if (!eBPFSchedules.length) {
this.eBPFSchedules = [];
this.analyzeTrees = [];
}
return response;
return res.data;
},
async getEBPFAnalyze(params: {
scheduleIdList: string[];
@ -133,24 +134,24 @@ export const ebpfStore = defineStore({
if (!params.timeRanges.length) {
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 = [];
return response;
return res.data;
}
const { analysisEBPFResult } = response.data;
const { analysisEBPFResult } = res.data.data;
this.ebpfTips = analysisEBPFResult.tip;
if (!analysisEBPFResult) {
this.analyzeTrees = [];
return response;
return res.data;
}
if (analysisEBPFResult.tip) {
this.analyzeTrees = [];
return response;
return res.data;
}
this.analyzeTrees = analysisEBPFResult.trees;
return response;
return res.data;
},
},
});

View File

@ -17,11 +17,11 @@
import { defineStore } from "pinia";
import { store } from "@/store";
import graphql from "@/graphql";
import type { AxiosResponse } from "axios";
import type { Event, QueryEventCondition } from "@/types/events";
import type { Instance, Endpoint } from "@/types/selector";
import { useAppStoreWithOut } from "@/store/modules/app";
import { useSelectorStore } from "@/store/modules/selectors";
import { EndpointsTopNDefault } from "../data";
interface eventState {
loading: boolean;
@ -46,48 +46,47 @@ export const eventStore = defineStore({
},
async getInstances() {
const serviceId = useSelectorStore().currentService ? useSelectorStore().currentService.id : "";
const response = await graphql.query("queryInstances").params({
const res: AxiosResponse = await graphql.query("queryInstances").params({
serviceId,
duration: useAppStoreWithOut().durationTime,
});
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
this.instances = [{ value: "", label: "All" }, ...response.data.pods];
return response;
this.instances = [{ value: "", label: "All" }, ...res.data.data.pods] || [{ value: "", label: "All" }];
return res.data;
},
async getEndpoints(keyword: string) {
const serviceId = useSelectorStore().currentService ? useSelectorStore().currentService.id : "";
if (!serviceId) {
return;
}
const response = await graphql.query("queryEndpoints").params({
const res: AxiosResponse = await graphql.query("queryEndpoints").params({
serviceId,
duration: useAppStoreWithOut().durationTime,
keyword: keyword || "",
limit: EndpointsTopNDefault,
});
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
this.endpoints = [{ value: "", label: "All" }, ...response.data.pods];
return response;
this.endpoints = [{ value: "", label: "All" }, ...res.data.data.pods] || [{ value: "", label: "All" }];
return res.data;
},
async getEvents() {
this.loading = true;
const response = await graphql.query("queryEvents").params({
const res: AxiosResponse = await graphql.query("queryEvents").params({
condition: {
...this.condition,
time: useAppStoreWithOut().durationTime,
},
});
this.loading = false;
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
if (response.data.fetchEvents) {
this.events = (response.data.fetchEvents.events || []).map((item: Event) => {
if (res.data.data.fetchEvents) {
this.events = (res.data.data.fetchEvents.events || []).map((item: Event) => {
let scope = "Service";
if (item.source.serviceInstance) {
scope = "ServiceInstance";
@ -102,7 +101,7 @@ export const eventStore = defineStore({
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 { store } from "@/store";
import graphql from "@/graphql";
import type { AxiosResponse } from "axios";
import { useAppStoreWithOut } from "@/store/modules/app";
import { useSelectorStore } from "@/store/modules/selectors";
import { useDashboardStore } from "@/store/modules/dashboard";
import { EndpointsTopNDefault } from "../data";
interface LogState {
services: Service[];
@ -61,51 +61,50 @@ export const logStore = defineStore({
};
},
async getServices(layer: string) {
const response = await graphql.query("queryServices").params({
const res: AxiosResponse = await graphql.query("queryServices").params({
layer,
});
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
this.services = response.data.services;
return response;
this.services = res.data.data.services;
return res.data;
},
async getInstances(id: string) {
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,
duration: useAppStoreWithOut().durationTime,
});
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
this.instances = [{ value: "0", label: "All" }, ...response.data.pods];
return response;
this.instances = [{ value: "0", label: "All" }, ...res.data.data.pods] || [{ value: " 0", label: "All" }];
return res.data;
},
async getEndpoints(id: string, keyword?: string) {
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,
duration: useAppStoreWithOut().durationTime,
keyword: keyword || "",
limit: EndpointsTopNDefault,
});
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
this.endpoints = [{ value: "0", label: "All" }, ...response.data.pods];
return response;
this.endpoints = [{ value: "0", label: "All" }, ...res.data.data.pods] || [{ value: "0", label: "All" }];
return res.data;
},
async getLogsByKeywords() {
const response = await graphql.query("queryLogsByKeywords").params({});
const res: AxiosResponse = await graphql.query("queryLogsByKeywords").params({});
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
this.supportQueryLogsByKeywords = response.data.support;
return response;
this.supportQueryLogsByKeywords = res.data.data.support;
return res.data;
},
async getLogs() {
const dashboardStore = useDashboardStore();
@ -116,31 +115,39 @@ export const logStore = defineStore({
},
async getServiceLogs() {
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;
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
this.logs = response.data.queryLogs.logs;
return response;
this.logs = res.data.data.queryLogs.logs;
return res.data;
},
async getBrowserLogs() {
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;
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
this.logs = response.data.queryBrowserErrorLogs.logs;
return response;
this.logs = res.data.data.queryBrowserErrorLogs.logs;
return res.data;
},
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) {
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 { store } from "@/store";
import graphql from "@/graphql";
import type { AxiosResponse } from "axios";
import type { Call } from "@/types/topology";
import type { LayoutConfig } from "@/types/dashboard";
import { ElMessage } from "element-plus";
@ -125,65 +126,65 @@ export const networkProfilingStore = defineStore({
minDuration: number;
}[],
) {
const response = await graphql.query("newNetworkProfiling").params({
const res: AxiosResponse = await graphql.query("newNetworkProfiling").params({
request: {
instanceId,
samplings: params,
},
});
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
return response;
return res.data;
},
async getTaskList(params: { serviceId: string; serviceInstanceId: string; targets: string[] }) {
if (!params.serviceId) {
return new Promise((resolve) => resolve({}));
}
const response = await graphql.query("getEBPFTasks").params(params);
const res: AxiosResponse = await graphql.query("getEBPFTasks").params(params);
this.networkTip = "";
if (response.errors) {
return response;
if (res.data.errors) {
return res.data;
}
this.networkTasks = response.data.queryEBPFTasks || [];
this.networkTasks = res.data.data.queryEBPFTasks || [];
this.selectedNetworkTask = this.networkTasks[0] || {};
this.setSelectedNetworkTask(this.selectedNetworkTask);
if (!this.networkTasks.length) {
this.nodes = [];
this.calls = [];
}
return response;
return res.data;
},
async keepNetworkProfiling(taskId: string) {
if (!taskId) {
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) {
return response;
if (res.data.errors) {
return res.data;
}
this.aliveNetwork = response.data.keepEBPFNetworkProfiling.status;
this.aliveNetwork = res.data.data.keepEBPFNetworkProfiling.status;
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 }) {
this.loadNodes = true;
const response = await graphql.query("getProcessTopology").params(params);
const res: AxiosResponse = await graphql.query("getProcessTopology").params(params);
this.loadNodes = false;
if (response.errors) {
if (res.data.errors) {
this.nodes = [];
this.calls = [];
return response;
return res.data;
}
const { topology } = response.data;
const { topology } = res.data.data;
this.setTopology(topology);
return response;
return res.data;
},
},
});

View File

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

View File

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

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