Merge branch 'apache:main' into main

This commit is contained in:
Brandon Fergerson 2022-05-18 19:56:14 +04:00 committed by GitHub
commit cfab1a5ab5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 509 additions and 452 deletions

201
package-lock.json generated
View File

@ -16,7 +16,6 @@
"element-plus": "^2.0.2", "element-plus": "^2.0.2",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"pinia": "^2.0.5", "pinia": "^2.0.5",
"vis-timeline": "^7.5.1",
"vue": "^3.0.0", "vue": "^3.0.0",
"vue-grid-layout": "^3.0.0-beta1", "vue-grid-layout": "^3.0.0-beta1",
"vue-i18n": "^9.1.9", "vue-i18n": "^9.1.9",
@ -1812,18 +1811,6 @@
"ms": "^2.1.1" "ms": "^2.1.1"
} }
}, },
"node_modules/@egjs/hammerjs": {
"version": "2.0.17",
"resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
"integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==",
"peer": true,
"dependencies": {
"@types/hammerjs": "^2.0.36"
},
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/@element-plus/icons-vue": { "node_modules/@element-plus/icons-vue": {
"version": "0.2.7", "version": "0.2.7",
"resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-0.2.7.tgz", "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-0.2.7.tgz",
@ -3313,12 +3300,6 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/hammerjs": {
"version": "2.0.41",
"resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.41.tgz",
"integrity": "sha512-ewXv/ceBaJprikMcxCmWU1FKyMAQ2X7a9Gtmzw8fcg2kIePI1crERDM818W+XYrxqdBBOdlf2rm137bU+BltCA==",
"peer": true
},
"node_modules/@types/http-proxy": { "node_modules/@types/http-proxy": {
"version": "1.17.8", "version": "1.17.8",
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz",
@ -7901,7 +7882,8 @@
"node_modules/component-emitter": { "node_modules/component-emitter": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
"dev": true
}, },
"node_modules/compressible": { "node_modules/compressible": {
"version": "2.0.18", "version": "2.0.18",
@ -8713,12 +8695,6 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/cssfilter": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz",
"integrity": "sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=",
"peer": true
},
"node_modules/cssnano": { "node_modules/cssnano": {
"version": "4.1.11", "version": "4.1.11",
"resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.11.tgz", "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.11.tgz",
@ -16462,12 +16438,6 @@
"node": ">=0.6.0" "node": ">=0.6.0"
} }
}, },
"node_modules/keycharm": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/keycharm/-/keycharm-0.4.0.tgz",
"integrity": "sha512-TyQTtsabOVv3MeOpR92sIKk/br9wxS+zGj4BG7CR8YbK4jM3tyIBaF0zhzeBUMx36/Q/iQLOKKOT+3jOQtemRQ==",
"peer": true
},
"node_modules/killable": { "node_modules/killable": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
@ -18259,6 +18229,7 @@
"version": "2.24.0", "version": "2.24.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==", "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==",
"dev": true,
"engines": { "engines": {
"node": "*" "node": "*"
} }
@ -21727,15 +21698,6 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/propagating-hammerjs": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/propagating-hammerjs/-/propagating-hammerjs-2.0.1.tgz",
"integrity": "sha512-PH3zG5whbSxMocphXJzVtvKr+vWAgfkqVvtuwjSJ/apmEACUoiw6auBAT5HYXpZOR0eGcTAfYG5Yl8h91O5Elg==",
"peer": true,
"peerDependencies": {
"@egjs/hammerjs": "^2.0.17"
}
},
"node_modules/proto-list": { "node_modules/proto-list": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
@ -26875,6 +26837,7 @@
"version": "8.3.2", "version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true,
"bin": { "bin": {
"uuid": "dist/bin/uuid" "uuid": "dist/bin/uuid"
} }
@ -26934,59 +26897,6 @@
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"dev": true "dev": true
}, },
"node_modules/vis-data": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/vis-data/-/vis-data-7.1.4.tgz",
"integrity": "sha512-usy+ePX1XnArNvJ5BavQod7YRuGQE1pjFl+pu7IS6rCom2EBoG0o1ZzCqf3l5US6MW51kYkLR+efxRbnjxNl7w==",
"hasInstallScript": true,
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/visjs"
},
"peerDependencies": {
"uuid": "^7.0.0 || ^8.0.0",
"vis-util": "^4.0.0 || ^5.0.0"
}
},
"node_modules/vis-timeline": {
"version": "7.5.1",
"resolved": "https://registry.npmjs.org/vis-timeline/-/vis-timeline-7.5.1.tgz",
"integrity": "sha512-XZMHHbA8xm9/Y/iu3mE9MT7J5tfWgbdsW+PmqrgINU2QRX24AiqifNHZHV4YYzeJstiTSOg9Gs5qRkxQ0BvZJw==",
"hasInstallScript": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/visjs"
},
"peerDependencies": {
"@egjs/hammerjs": "^2.0.0",
"component-emitter": "^1.3.0",
"keycharm": "^0.3.0 || ^0.4.0",
"moment": "^2.24.0",
"propagating-hammerjs": "^1.4.0 || ^2.0.0",
"uuid": "^3.4.0 || ^7.0.0 || ^8.0.0",
"vis-data": "^6.3.0 || ^7.0.0",
"vis-util": "^3.0.0 || ^4.0.0 || ^5.0.0",
"xss": "^1.0.0"
}
},
"node_modules/vis-util": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/vis-util/-/vis-util-5.0.3.tgz",
"integrity": "sha512-Wf9STUcFrDzK4/Zr7B6epW2Kvm3ORNWF+WiwEz2dpf5RdWkLUXFSbLcuB88n1W6tCdFwVN+v3V4/Xmn9PeL39g==",
"peer": true,
"engines": {
"node": ">=8"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/visjs"
},
"peerDependencies": {
"@egjs/hammerjs": "^2.0.0",
"component-emitter": "^1.3.0"
}
},
"node_modules/vm-browserify": { "node_modules/vm-browserify": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
@ -28835,28 +28745,6 @@
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
"dev": true "dev": true
}, },
"node_modules/xss": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/xss/-/xss-1.0.11.tgz",
"integrity": "sha512-EimjrjThZeK2MO7WKR9mN5ZC1CSqivSl55wvUK5EtU6acf0rzEE1pN+9ZDrFXJ82BRp3JL38pPE6S4o/rpp1zQ==",
"peer": true,
"dependencies": {
"commander": "^2.20.3",
"cssfilter": "0.0.10"
},
"bin": {
"xss": "bin/xss"
},
"engines": {
"node": ">= 0.10.0"
}
},
"node_modules/xss/node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"peer": true
},
"node_modules/xtend": { "node_modules/xtend": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@ -30311,15 +30199,6 @@
} }
} }
}, },
"@egjs/hammerjs": {
"version": "2.0.17",
"resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
"integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==",
"peer": true,
"requires": {
"@types/hammerjs": "^2.0.36"
}
},
"@element-plus/icons-vue": { "@element-plus/icons-vue": {
"version": "0.2.7", "version": "0.2.7",
"resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-0.2.7.tgz", "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-0.2.7.tgz",
@ -31583,12 +31462,6 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/hammerjs": {
"version": "2.0.41",
"resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.41.tgz",
"integrity": "sha512-ewXv/ceBaJprikMcxCmWU1FKyMAQ2X7a9Gtmzw8fcg2kIePI1crERDM818W+XYrxqdBBOdlf2rm137bU+BltCA==",
"peer": true
},
"@types/http-proxy": { "@types/http-proxy": {
"version": "1.17.8", "version": "1.17.8",
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz",
@ -35280,7 +35153,8 @@
"component-emitter": { "component-emitter": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
"dev": true
}, },
"compressible": { "compressible": {
"version": "2.0.18", "version": "2.0.18",
@ -35921,12 +35795,6 @@
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
"dev": true "dev": true
}, },
"cssfilter": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz",
"integrity": "sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=",
"peer": true
},
"cssnano": { "cssnano": {
"version": "4.1.11", "version": "4.1.11",
"resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.11.tgz", "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.11.tgz",
@ -42014,12 +41882,6 @@
"verror": "1.10.0" "verror": "1.10.0"
} }
}, },
"keycharm": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/keycharm/-/keycharm-0.4.0.tgz",
"integrity": "sha512-TyQTtsabOVv3MeOpR92sIKk/br9wxS+zGj4BG7CR8YbK4jM3tyIBaF0zhzeBUMx36/Q/iQLOKKOT+3jOQtemRQ==",
"peer": true
},
"killable": { "killable": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
@ -43406,7 +43268,8 @@
"moment": { "moment": {
"version": "2.24.0", "version": "2.24.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==",
"dev": true
}, },
"move-concurrently": { "move-concurrently": {
"version": "1.0.1", "version": "1.0.1",
@ -46071,13 +45934,6 @@
"sisteransi": "^1.0.5" "sisteransi": "^1.0.5"
} }
}, },
"propagating-hammerjs": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/propagating-hammerjs/-/propagating-hammerjs-2.0.1.tgz",
"integrity": "sha512-PH3zG5whbSxMocphXJzVtvKr+vWAgfkqVvtuwjSJ/apmEACUoiw6auBAT5HYXpZOR0eGcTAfYG5Yl8h91O5Elg==",
"peer": true,
"requires": {}
},
"proto-list": { "proto-list": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
@ -50179,7 +50035,8 @@
"uuid": { "uuid": {
"version": "8.3.2", "version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true
}, },
"v8-compile-cache": { "v8-compile-cache": {
"version": "2.3.0", "version": "2.3.0",
@ -50228,26 +50085,6 @@
} }
} }
}, },
"vis-data": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/vis-data/-/vis-data-7.1.4.tgz",
"integrity": "sha512-usy+ePX1XnArNvJ5BavQod7YRuGQE1pjFl+pu7IS6rCom2EBoG0o1ZzCqf3l5US6MW51kYkLR+efxRbnjxNl7w==",
"peer": true,
"requires": {}
},
"vis-timeline": {
"version": "7.5.1",
"resolved": "https://registry.npmjs.org/vis-timeline/-/vis-timeline-7.5.1.tgz",
"integrity": "sha512-XZMHHbA8xm9/Y/iu3mE9MT7J5tfWgbdsW+PmqrgINU2QRX24AiqifNHZHV4YYzeJstiTSOg9Gs5qRkxQ0BvZJw==",
"requires": {}
},
"vis-util": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/vis-util/-/vis-util-5.0.3.tgz",
"integrity": "sha512-Wf9STUcFrDzK4/Zr7B6epW2Kvm3ORNWF+WiwEz2dpf5RdWkLUXFSbLcuB88n1W6tCdFwVN+v3V4/Xmn9PeL39g==",
"peer": true,
"requires": {}
},
"vm-browserify": { "vm-browserify": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
@ -51759,24 +51596,6 @@
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
"dev": true "dev": true
}, },
"xss": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/xss/-/xss-1.0.11.tgz",
"integrity": "sha512-EimjrjThZeK2MO7WKR9mN5ZC1CSqivSl55wvUK5EtU6acf0rzEE1pN+9ZDrFXJ82BRp3JL38pPE6S4o/rpp1zQ==",
"peer": true,
"requires": {
"commander": "^2.20.3",
"cssfilter": "0.0.10"
},
"dependencies": {
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"peer": true
}
}
},
"xtend": { "xtend": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",

View File

@ -18,7 +18,6 @@
"element-plus": "^2.0.2", "element-plus": "^2.0.2",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"pinia": "^2.0.5", "pinia": "^2.0.5",
"vis-timeline": "^7.5.1",
"vue": "^3.0.0", "vue": "^3.0.0",
"vue-grid-layout": "^3.0.0-beta1", "vue-grid-layout": "^3.0.0-beta1",
"vue-i18n": "^9.1.9", "vue-i18n": "^9.1.9",

View File

@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. --> limitations under the License. -->
<template> <template>
<router-view :key="$route.fullPath" /> <router-view />
</template> </template>
<style> <style>
#app { #app {

View File

@ -247,7 +247,7 @@ limitations under the License. -->
(state.showMinutes = state.showSeconds = false) (state.showMinutes = state.showSeconds = false)
" "
:class="{ on: state.showHours }" :class="{ on: state.showHours }"
>{{ state.hour || dd }}</a >{{ dd(state.hour) }}</a
> >
<span>:</span> <span>:</span>
<a <a
@ -257,7 +257,7 @@ limitations under the License. -->
(state.showHours = state.showSeconds = false) (state.showHours = state.showSeconds = false)
" "
:class="{ on: state.showMinutes }" :class="{ on: state.showMinutes }"
>{{ state.minute || dd }}</a >{{ dd(state.minute) }}</a
> >
<span v-show="state.m !== 'D'"> <span v-show="state.m !== 'D'">
<span>:</span> <span>:</span>
@ -268,7 +268,7 @@ limitations under the License. -->
(state.showHours = state.showMinutes = false) (state.showHours = state.showMinutes = false)
" "
:class="{ on: state.showSeconds }" :class="{ on: state.showSeconds }"
>{{ state.second || dd }}</a >{{ dd(state.second) }}</a
> >
</span> </span>
</div> </div>
@ -464,7 +464,6 @@ const status = (
const minutes = time.getMinutes(); const minutes = time.getMinutes();
const seconds = time.getSeconds(); const seconds = time.getSeconds();
const milliseconds = time.getMilliseconds(); const milliseconds = time.getMilliseconds();
const dd = (t: number) => `0${t}`.slice(-2);
const map: { [key: string]: string | number } = { const map: { [key: string]: string | number } = {
YYYY: year, YYYY: year,
MM: dd(month + 1), MM: dd(month + 1),

View File

@ -48,9 +48,9 @@ export const queryEBPFTasks = {
}`, }`,
}; };
export const queryEBPFSchedules = { export const queryEBPFSchedules = {
variable: "$taskId: ID!, $duration: Duration!", variable: "$taskId: ID!",
query: ` query: `
eBPFSchedules: queryEBPFProfilingSchedules(taskId: $taskId, duration: $duration) { eBPFSchedules: queryEBPFProfilingSchedules(taskId: $taskId) {
scheduleId scheduleId
taskId taskId
process { process {
@ -60,7 +60,6 @@ export const queryEBPFSchedules = {
serviceName serviceName
instanceId instanceId
instanceName instanceName
layer
agentId agentId
detectType detectType
attributes { attributes {

View File

@ -63,3 +63,15 @@ export const QueryLogsByKeywords = {
query: ` query: `
support: supportQueryLogsByKeywords`, support: supportQueryLogsByKeywords`,
}; };
export const LogTagKeys = {
variable: "$duration: Duration!",
query: `
tagKeys: queryLogTagAutocompleteKeys(duration: $duration)`,
};
export const LogTagValues = {
variable: "$tagKey: String!, $duration: Duration!",
query: `
tagValues: queryLogTagAutocompleteValues(tagKey: $tagKey, duration: $duration)`,
};

View File

@ -20,10 +20,10 @@ export const Services = {
services: listServices(layer: $layer) { services: listServices(layer: $layer) {
id id
value: name value: name
label: name label: name
group group
layers layers
normal normal
} }
`, `,
}; };
@ -36,17 +36,16 @@ export const Instances = {
variable: "$serviceId: ID!, $duration: Duration!", variable: "$serviceId: ID!, $duration: Duration!",
query: ` query: `
pods: listInstances(duration: $duration, serviceId: $serviceId) { pods: listInstances(duration: $duration, serviceId: $serviceId) {
id id
value: name value: name
label: name label: name
language language
instanceUUID instanceUUID
layer attributes {
attributes { name
name value
value
}
} }
}
`, `,
}; };
export const Endpoints = { export const Endpoints = {
@ -66,10 +65,10 @@ export const getService = {
service: getService(serviceId: $serviceId) { service: getService(serviceId: $serviceId) {
id id
value: name value: name
label: name label: name
group group
layers layers
normal normal
} }
`, `,
}; };
@ -79,16 +78,15 @@ export const getInstance = {
query: ` query: `
instance: getInstance(instanceId: $instanceId) { instance: getInstance(instanceId: $instanceId) {
id id
value: name value: name
label: name label: name
language language
instanceUUID instanceUUID
layer attributes {
attributes { name
name value
value
}
} }
}
`, `,
}; };
@ -97,10 +95,10 @@ export const getEndpoint = {
query: ` query: `
endpoint: getEndpointInfo(endpointId: $endpointId) { endpoint: getEndpointInfo(endpointId: $endpointId) {
id id
value: name value: name
label: name label: name
serviceId serviceId
serviceName serviceName
} }
`, `,
}; };

View File

@ -74,3 +74,14 @@ export const TraceSpans = {
} }
`, `,
}; };
export const TraceTagKeys = {
variable: "$duration: Duration!",
query: `
tagKeys: queryTraceTagAutocompleteKeys(duration: $duration)`,
};
export const TraceTagValues = {
variable: "$tagKey: String!, $duration: Duration!",
query: `
tagValues: queryTraceTagAutocompleteValues(tagKey: $tagKey, duration: $duration)`,
};

View File

@ -19,9 +19,13 @@ import {
QueryBrowserErrorLogs, QueryBrowserErrorLogs,
QueryServiceLogs, QueryServiceLogs,
QueryLogsByKeywords, QueryLogsByKeywords,
LogTagValues,
LogTagKeys,
} from "../fragments/log"; } from "../fragments/log";
export const queryBrowserErrorLogs = `query queryBrowserErrorLogs(${QueryBrowserErrorLogs.variable}) { export const queryBrowserErrorLogs = `query queryBrowserErrorLogs(${QueryBrowserErrorLogs.variable}) {
${QueryBrowserErrorLogs.query}}`; ${QueryBrowserErrorLogs.query}}`;
export const queryServiceLogs = `query queryLogs(${QueryServiceLogs.variable}) {${QueryServiceLogs.query}}`; export const queryServiceLogs = `query queryLogs(${QueryServiceLogs.variable}) {${QueryServiceLogs.query}}`;
export const queryLogsByKeywords = `query queryLogsByKeywords {${QueryLogsByKeywords.query}}`; export const queryLogsByKeywords = `query queryLogsByKeywords {${QueryLogsByKeywords.query}}`;
export const queryLogTagValues = `query queryTagValues(${LogTagValues.variable}) {${LogTagValues.query}}`;
export const queryLogTagKeys = `query queryTagKeys(${LogTagKeys.variable}) {${LogTagKeys.query}}`;

View File

@ -15,8 +15,17 @@
* limitations under the License. * limitations under the License.
*/ */
import { Traces, TraceSpans } from "../fragments/trace"; import {
Traces,
TraceSpans,
TraceTagKeys,
TraceTagValues,
} from "../fragments/trace";
export const queryTraces = `query queryTraces(${Traces.variable}) {${Traces.query}}`; export const queryTraces = `query queryTraces(${Traces.variable}) {${Traces.query}}`;
export const queryTrace = `query queryTrace(${TraceSpans.variable}) {${TraceSpans.query}}`; export const queryTrace = `query queryTrace(${TraceSpans.variable}) {${TraceSpans.query}}`;
export const queryTraceTagKeys = `query queryTraceTagKeys(${TraceTagKeys.variable}) {${TraceTagKeys.query}}`;
export const queryTraceTagValues = `query queryTraceTagValues(${TraceTagValues.variable}) {${TraceTagValues.query}}`;

View File

@ -331,7 +331,7 @@ export function useQueryTopologyMetrics(metrics: string[], ids: string[]) {
} }
function calculateExp( function calculateExp(
arr: { value: number }[], arr: { value: number }[],
config: { calculation: string } config: { calculation?: string }
): (number | string)[] { ): (number | string)[] {
const sum = arr const sum = arr
.map((d: { value: number }) => d.value) .map((d: { value: number }) => d.value)
@ -356,7 +356,7 @@ function calculateExp(
export function aggregation( export function aggregation(
val: number, val: number,
config: { calculation: string } config: { calculation?: string }
): number | string { ): number | string {
let data: number | string = Number(val); let data: number | string = Number(val);

View File

@ -21,19 +21,6 @@ limitations under the License. -->
</router-view> </router-view>
</section> </section>
</template> </template>
<script lang="ts" setup>
import { ElMessage } from "element-plus";
import { useAppStoreWithOut } from "@/store/modules/app";
const appStore = useAppStoreWithOut();
if (!appStore.utc) {
const res = appStore.queryOAPTimeInfo();
if (res.errors) {
ElMessage.error(res.errors);
}
}
</script>
<style lang="scss" scoped> <style lang="scss" scoped>
.app-main { .app-main {
height: calc(100% - 40px); height: calc(100% - 40px);

View File

@ -94,9 +94,6 @@ watch(
} }
); );
async function getVersion() { async function getVersion() {
if (appStore.version) {
return;
}
const res = await appStore.fetchVersion(); const res = await appStore.fetchVersion();
if (res.errors) { if (res.errors) {
ElMessage.error(res.errors); ElMessage.error(res.errors);

View File

@ -113,11 +113,11 @@ import { useAppStoreWithOut } from "@/store/modules/app";
const appStore = useAppStoreWithOut(); const appStore = useAppStoreWithOut();
const { t } = useI18n(); const { t } = useI18n();
const name = ref<any>(String(useRouter().currentRoute.value.name)); const name = ref<string>(String(useRouter().currentRoute.value.name));
const theme = ["VirtualMachine", "Kubernetes"].includes(name.value || "") const theme = ["VirtualMachine", "Kubernetes"].includes(name.value || "")
? ref("light") ? ref("light")
: ref("black"); : ref("black");
const routes = ref<any>(useRouter().options.routes); const routes = ref<RouteRecordRaw[] | any>(useRouter().options.routes);
if (/Android|webOS|iPhone|iPod|iPad|BlackBerry/i.test(navigator.userAgent)) { if (/Android|webOS|iPhone|iPod|iPad|BlackBerry/i.test(navigator.userAgent)) {
appStore.setIsMobile(true); appStore.setIsMobile(true);
} else { } else {

View File

@ -134,7 +134,7 @@ const msg = {
taskId: "Task ID", taskId: "Task ID",
triggerType: "Trigger Type", triggerType: "Trigger Type",
targetType: "Target Type", targetType: "Target Type",
ebpfTip: "Don't have process could profiling", ebpfTip: "Don't have a process for profiling",
processSelect: "Click to select processes", processSelect: "Click to select processes",
hourTip: "Select Hour", hourTip: "Select Hour",
minuteTip: "Select Minute", minuteTip: "Select Minute",
@ -326,7 +326,7 @@ const msg = {
addExcludingKeywordsOfContent: "Please input a keyword of excluding content", addExcludingKeywordsOfContent: "Please input a keyword of excluding content",
noticeTag: "Please press Enter after inputting a tag(key=value).", noticeTag: "Please press Enter after inputting a tag(key=value).",
conditionNotice: conditionNotice:
"Notice: Please press Enter after inputting a tag, key of content, exclude key of content(key=value).", "Notice: Please press Enter after inputting a key of content, exclude key of content(key=value).",
language: "Language", language: "Language",
}; };
export default msg; export default msg;

View File

@ -327,7 +327,7 @@ const msg = {
addExcludingKeywordsOfContent: "请输入一个内容不包含的关键词", addExcludingKeywordsOfContent: "请输入一个内容不包含的关键词",
noticeTag: "请输入一个标签(key=value)之后回车", noticeTag: "请输入一个标签(key=value)之后回车",
conditionNotice: conditionNotice:
"请输入一个标签、内容关键词或者内容不包含的关键词(key=value)之后回车", "请输入一个内容关键词或者内容不包含的关键词(key=value)之后回车",
language: "语言", language: "语言",
}; };
export default msg; export default msg;

View File

@ -20,11 +20,18 @@ import router from "./router";
import { store } from "./store"; import { store } from "./store";
import components from "@/components"; import components from "@/components";
import i18n from "./locales"; import i18n from "./locales";
import { useAppStoreWithOut } from "@/store/modules/app";
import "./styles/index.ts"; import "./styles/index.ts";
const app = createApp(App); const app = createApp(App);
const appStore = useAppStoreWithOut();
app.use(components); app.use(components);
app.use(i18n); app.use(i18n);
app.use(store); app.use(store);
app.use(router).mount("#app"); mountApp();
async function mountApp() {
await appStore.queryOAPTimeInfo();
app.use(router).mount("#app");
}

View File

@ -20,10 +20,8 @@ import { LayoutConfig } from "@/types/dashboard";
import graphql from "@/graphql"; import graphql from "@/graphql";
import query from "@/graphql/fetch"; import query from "@/graphql/fetch";
import { DashboardItem } from "@/types/dashboard"; import { DashboardItem } from "@/types/dashboard";
import { useAppStoreWithOut } from "@/store/modules/app";
import { useSelectorStore } from "@/store/modules/selectors"; import { useSelectorStore } from "@/store/modules/selectors";
import { NewControl, TextConfig } from "../data"; import { NewControl, TextConfig } from "../data";
import { Duration } from "@/types/app";
import { AxiosResponse } from "axios"; import { AxiosResponse } from "axios";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
@ -35,7 +33,6 @@ interface DashboardState {
entity: string; entity: string;
layerId: string; layerId: string;
activedGridItem: string; activedGridItem: string;
durationTime: Duration;
selectorStore: any; selectorStore: any;
showTopology: boolean; showTopology: boolean;
currentTabItems: LayoutConfig[]; currentTabItems: LayoutConfig[];
@ -53,7 +50,6 @@ export const dashboardStore = defineStore({
entity: "", entity: "",
layerId: "", layerId: "",
activedGridItem: "", activedGridItem: "",
durationTime: useAppStoreWithOut().durationTime,
selectorStore: useSelectorStore(), selectorStore: useSelectorStore(),
showTopology: false, showTopology: false,
currentTabItems: [], currentTabItems: [],

View File

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { Duration, Option } from "@/types/app"; import { Option } from "@/types/app";
import { import {
EBPFTaskCreationRequest, EBPFTaskCreationRequest,
EBPFProfilingSchedule, EBPFProfilingSchedule,
@ -26,10 +26,8 @@ import { Trace, Span } from "@/types/trace";
import { store } from "@/store"; import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
import { AxiosResponse } from "axios"; import { AxiosResponse } from "axios";
import { useAppStoreWithOut } from "@/store/modules/app";
interface EbpfStore { interface EbpfStore {
durationTime: Duration;
taskList: EBPFTaskList[]; taskList: EBPFTaskList[];
eBPFSchedules: EBPFProfilingSchedule[]; eBPFSchedules: EBPFProfilingSchedule[];
currentSchedule: EBPFProfilingSchedule | Record<string, never>; currentSchedule: EBPFProfilingSchedule | Record<string, never>;
@ -42,7 +40,6 @@ interface EbpfStore {
export const ebpfStore = defineStore({ export const ebpfStore = defineStore({
id: "eBPF", id: "eBPF",
state: (): EbpfStore => ({ state: (): EbpfStore => ({
durationTime: useAppStoreWithOut().durationTime,
taskList: [], taskList: [],
eBPFSchedules: [], eBPFSchedules: [],
currentSchedule: {}, currentSchedule: {},
@ -103,14 +100,13 @@ export const ebpfStore = defineStore({
this.getEBPFSchedules({ taskId: this.taskList[0].taskId }); this.getEBPFSchedules({ taskId: this.taskList[0].taskId });
return res.data; return res.data;
}, },
async getEBPFSchedules(params: { taskId: string; duration?: Duration }) { async getEBPFSchedules(params: { taskId: string }) {
if (!params.taskId) { if (!params.taskId) {
return new Promise((resolve) => resolve({})); return new Promise((resolve) => resolve({}));
} }
const duration = useAppStoreWithOut().durationTime;
const res: AxiosResponse = await graphql const res: AxiosResponse = await graphql
.query("getEBPFSchedules") .query("getEBPFSchedules")
.params({ ...params, duration }); .params({ ...params });
if (res.data.errors) { if (res.data.errors) {
this.eBPFSchedules = []; this.eBPFSchedules = [];
@ -154,7 +150,7 @@ export const ebpfStore = defineStore({
this.analyzeTrees = []; this.analyzeTrees = [];
return res.data; return res.data;
} }
this.analyzeTrees = analysisEBPFResult.trees[0].elements; this.analyzeTrees = analysisEBPFResult.trees;
return res.data; return res.data;
}, },
}, },

View File

@ -42,7 +42,6 @@ export const eventStore = defineStore({
instances: [{ value: "", label: "All" }], instances: [{ value: "", label: "All" }],
endpoints: [{ value: "", label: "All" }], endpoints: [{ value: "", label: "All" }],
condition: { condition: {
time: useAppStoreWithOut().durationTime,
paging: { pageNum: 1, pageSize: 15, needTotal: true }, paging: { pageNum: 1, pageSize: 15, needTotal: true },
}, },
}), }),
@ -94,9 +93,12 @@ export const eventStore = defineStore({
}, },
async getEvents() { async getEvents() {
this.loading = true; this.loading = true;
const res: AxiosResponse = await graphql const res: AxiosResponse = await graphql.query("queryEvents").params({
.query("queryEvents") condition: {
.params({ condition: this.condition }); ...this.condition,
time: useAppStoreWithOut().durationTime,
},
});
this.loading = false; this.loading = false;
if (res.data.errors) { if (res.data.errors) {
return res.data; return res.data;

View File

@ -15,7 +15,6 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { Duration } from "@/types/app";
import { Instance, Endpoint, Service } from "@/types/selector"; import { Instance, Endpoint, Service } from "@/types/selector";
import { store } from "@/store"; import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
@ -29,7 +28,6 @@ interface LogState {
instances: Instance[]; instances: Instance[];
endpoints: Endpoint[]; endpoints: Endpoint[];
conditions: any; conditions: any;
durationTime: Duration;
selectorStore: any; selectorStore: any;
supportQueryLogsByKeywords: boolean; supportQueryLogsByKeywords: boolean;
logs: any[]; logs: any[];
@ -48,7 +46,6 @@ export const logStore = defineStore({
paging: { pageNum: 1, pageSize: 15, needTotal: true }, paging: { pageNum: 1, pageSize: 15, needTotal: true },
}, },
supportQueryLogsByKeywords: true, supportQueryLogsByKeywords: true,
durationTime: useAppStoreWithOut().durationTime,
selectorStore: useSelectorStore(), selectorStore: useSelectorStore(),
logs: [], logs: [],
logsTotal: 0, logsTotal: 0,
@ -74,7 +71,7 @@ export const logStore = defineStore({
: id; : id;
const res: AxiosResponse = await graphql.query("queryInstances").params({ const res: AxiosResponse = await graphql.query("queryInstances").params({
serviceId, serviceId,
duration: this.durationTime, duration: useAppStoreWithOut().durationTime,
}); });
if (res.data.errors) { if (res.data.errors) {
@ -92,7 +89,7 @@ export const logStore = defineStore({
: id; : id;
const res: AxiosResponse = await graphql.query("queryEndpoints").params({ const res: AxiosResponse = await graphql.query("queryEndpoints").params({
serviceId, serviceId,
duration: this.durationTime, duration: useAppStoreWithOut().durationTime,
keyword: keyword || "", keyword: keyword || "",
}); });
if (res.data.errors) { if (res.data.errors) {
@ -151,6 +148,20 @@ export const logStore = defineStore({
this.logsTotal = res.data.data.queryBrowserErrorLogs.total; this.logsTotal = res.data.data.queryBrowserErrorLogs.total;
return res.data; return res.data;
}, },
async getLogTagKeys() {
const res: AxiosResponse = await graphql
.query("queryLogTagKeys")
.params({ duration: useAppStoreWithOut().durationTime });
return res.data;
},
async getLogTagValues(tagKey: string) {
const res: AxiosResponse = await graphql
.query("queryLogTagValues")
.params({ tagKey, duration: useAppStoreWithOut().durationTime });
return res.data;
},
}, },
}); });

View File

@ -15,7 +15,6 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { Duration } from "@/types/app";
import { Endpoint } from "@/types/selector"; import { Endpoint } from "@/types/selector";
import { import {
TaskListItem, TaskListItem,
@ -33,7 +32,6 @@ import { useAppStoreWithOut } from "@/store/modules/app";
interface ProfileState { interface ProfileState {
endpoints: Endpoint[]; endpoints: Endpoint[];
taskEndpoints: Endpoint[]; taskEndpoints: Endpoint[];
durationTime: Duration;
condition: { serviceId: string; endpointName: string }; condition: { serviceId: string; endpointName: string };
taskList: TaskListItem[]; taskList: TaskListItem[];
segmentList: Trace[]; segmentList: Trace[];
@ -50,7 +48,6 @@ export const profileStore = defineStore({
state: (): ProfileState => ({ state: (): ProfileState => ({
endpoints: [{ value: "", label: "All" }], endpoints: [{ value: "", label: "All" }],
taskEndpoints: [{ value: "", label: "All" }], taskEndpoints: [{ value: "", label: "All" }],
durationTime: useAppStoreWithOut().durationTime,
condition: { serviceId: "", endpointName: "" }, condition: { serviceId: "", endpointName: "" },
taskList: [], taskList: [],
segmentList: [], segmentList: [],
@ -80,7 +77,7 @@ export const profileStore = defineStore({
async getEndpoints(serviceId: string, keyword?: string) { async getEndpoints(serviceId: string, keyword?: string) {
const res: AxiosResponse = await graphql.query("queryEndpoints").params({ const res: AxiosResponse = await graphql.query("queryEndpoints").params({
serviceId, serviceId,
duration: this.durationTime, duration: useAppStoreWithOut().durationTime,
keyword: keyword || "", keyword: keyword || "",
}); });
if (res.data.errors) { if (res.data.errors) {
@ -92,7 +89,7 @@ export const profileStore = defineStore({
async getTaskEndpoints(serviceId: string, keyword?: string) { async getTaskEndpoints(serviceId: string, keyword?: string) {
const res: AxiosResponse = await graphql.query("queryEndpoints").params({ const res: AxiosResponse = await graphql.query("queryEndpoints").params({
serviceId, serviceId,
duration: this.durationTime, duration: useAppStoreWithOut().durationTime,
keyword: keyword || "", keyword: keyword || "",
}); });
if (res.data.errors) { if (res.data.errors) {

View File

@ -15,13 +15,11 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { Duration } from "@/types/app";
import { Service, Instance, Endpoint } from "@/types/selector"; import { Service, Instance, Endpoint } from "@/types/selector";
import { store } from "@/store"; import { store } from "@/store";
import graphql from "@/graphql"; import graphql from "@/graphql";
import { AxiosResponse } from "axios"; import { AxiosResponse } from "axios";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
interface SelectorState { interface SelectorState {
services: Service[]; services: Service[];
destServices: Service[]; destServices: Service[];
@ -31,7 +29,6 @@ interface SelectorState {
currentDestService: Nullable<Service>; currentDestService: Nullable<Service>;
currentDestPod: Nullable<Instance | Endpoint>; currentDestPod: Nullable<Instance | Endpoint>;
destPods: Array<Instance | Endpoint>; destPods: Array<Instance | Endpoint>;
durationTime: Duration;
} }
export const selectorStore = defineStore({ export const selectorStore = defineStore({
@ -45,7 +42,6 @@ export const selectorStore = defineStore({
currentPod: null, currentPod: null,
currentDestService: null, currentDestService: null,
currentDestPod: null, currentDestPod: null,
durationTime: useAppStoreWithOut().durationTime,
}), }),
actions: { actions: {
setCurrentService(service: Nullable<Service>) { setCurrentService(service: Nullable<Service>) {
@ -86,7 +82,7 @@ export const selectorStore = defineStore({
} }
const res: AxiosResponse = await graphql.query("queryInstances").params({ const res: AxiosResponse = await graphql.query("queryInstances").params({
serviceId, serviceId,
duration: this.durationTime, duration: useAppStoreWithOut().durationTime,
}); });
if (!res.data.errors) { if (!res.data.errors) {
if (param && param.isRelation) { if (param && param.isRelation) {
@ -112,7 +108,7 @@ export const selectorStore = defineStore({
} }
const res: AxiosResponse = await graphql.query("queryEndpoints").params({ const res: AxiosResponse = await graphql.query("queryEndpoints").params({
serviceId, serviceId,
duration: this.durationTime, duration: useAppStoreWithOut().durationTime,
keyword: params.keyword || "", keyword: params.keyword || "",
limit: params.limit, limit: params.limit,
}); });

View File

@ -15,7 +15,6 @@
* limitations under the License. * limitations under the License.
*/ */
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { Duration } from "@/types/app";
import { Instance, Endpoint, Service } from "@/types/selector"; import { Instance, Endpoint, Service } from "@/types/selector";
import { Trace, Span } from "@/types/trace"; import { Trace, Span } from "@/types/trace";
import { store } from "@/store"; import { store } from "@/store";
@ -35,10 +34,6 @@ interface TraceState {
conditions: any; conditions: any;
traceSpanLogs: any[]; traceSpanLogs: any[];
traceSpanLogsTotal: number; traceSpanLogsTotal: number;
// traceListErrors: string;
// traceSpanErrors: string;
// traceSpanLogErrors: string;
durationTime: Duration;
selectorStore: any; selectorStore: any;
} }
@ -60,12 +55,11 @@ export const traceStore = defineStore({
}, },
traceSpanLogs: [], traceSpanLogs: [],
traceSpanLogsTotal: 0, traceSpanLogsTotal: 0,
durationTime: useAppStoreWithOut().durationTime,
selectorStore: useSelectorStore(), selectorStore: useSelectorStore(),
}), }),
actions: { actions: {
setTraceCondition(data: any) { setTraceCondition(data: any) {
this.condition = { ...this.condition, ...data }; this.conditions = { ...this.conditions, ...data };
}, },
setCurrentTrace(trace: Trace) { setCurrentTrace(trace: Trace) {
this.currentTrace = trace; this.currentTrace = trace;
@ -89,7 +83,7 @@ export const traceStore = defineStore({
: id; : id;
const res: AxiosResponse = await graphql.query("queryInstances").params({ const res: AxiosResponse = await graphql.query("queryInstances").params({
serviceId: serviceId, serviceId: serviceId,
duration: this.durationTime, duration: useAppStoreWithOut().durationTime,
}); });
if (res.data.errors) { if (res.data.errors) {
@ -104,7 +98,7 @@ export const traceStore = defineStore({
: id; : id;
const res: AxiosResponse = await graphql.query("queryEndpoints").params({ const res: AxiosResponse = await graphql.query("queryEndpoints").params({
serviceId, serviceId,
duration: this.durationTime, duration: useAppStoreWithOut().durationTime,
keyword: keyword || "", keyword: keyword || "",
}); });
if (res.data.errors) { if (res.data.errors) {
@ -116,7 +110,7 @@ export const traceStore = defineStore({
async getTraces() { async getTraces() {
const res: AxiosResponse = await graphql const res: AxiosResponse = await graphql
.query("queryTraces") .query("queryTraces")
.params({ condition: this.condition }); .params({ condition: this.conditions });
if (res.data.errors) { if (res.data.errors) {
return res.data; return res.data;
} }
@ -161,6 +155,20 @@ export const traceStore = defineStore({
this.traceSpanLogsTotal = res.data.data.queryLogs.total; this.traceSpanLogsTotal = res.data.data.queryLogs.total;
return res.data; return res.data;
}, },
async getTagKeys() {
const res: AxiosResponse = await graphql
.query("queryTraceTagKeys")
.params({ duration: useAppStoreWithOut().durationTime });
return res.data;
},
async getTagValues(tagKey: string) {
const res: AxiosResponse = await graphql
.query("queryTraceTagValues")
.params({ tagKey, duration: useAppStoreWithOut().durationTime });
return res.data;
},
}, },
}); });

View File

@ -39,9 +39,9 @@ export interface LayoutConfig {
} }
export type MetricConfigOpt = { export type MetricConfigOpt = {
unit: string; unit?: string;
label: string; label?: string;
calculation: string; calculation?: string;
labelsIndex: string; labelsIndex: string;
sortOrder: string; sortOrder: string;
topN?: number; topN?: number;

3
src/types/ebpf.d.ts vendored
View File

@ -50,10 +50,9 @@ export type Process = {
serviceName: string; serviceName: string;
instanceId: string; instanceId: string;
instanceName: string; instanceName: string;
layer: string;
agentId: string; agentId: string;
detectType: string; detectType: string;
attributes: { name: string; value: string }; attributes: { name: string; value: string }[];
labels: string[]; labels: string[];
}; };
export type StackElement = { export type StackElement = {

View File

@ -26,7 +26,6 @@ export type Service = {
export type Instance = { export type Instance = {
value: string; value: string;
label: string; label: string;
layer?: string;
language?: string; language?: string;
instanceUUID?: string; instanceUUID?: string;
attributes?: { name: string; value: string }[]; attributes?: { name: string; value: string }[];

View File

@ -13,65 +13,99 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. --> limitations under the License. -->
<template> <template>
<div class="flex-h" :class="{ light: theme === 'light' }"> <div>
<div class="mr-5"> <span class="grey">{{ t("tags") }}: </span>
<span class="sm grey" v-show="theme === 'dark'">{{ t("tags") }}: </span> <span
<span v-if="tagsList.length"
class="trace-tags" class="trace-tags"
:style="type === 'LOG' ? `min-width: 122px;` : ''" :style="type === 'LOG' ? `min-width: 122px;` : ''"
> >
<span class="selected" v-for="(item, index) in tagsList" :key="index"> <span class="selected" v-for="(item, index) in tagsList" :key="index">
<span>{{ item }}</span> <span>{{ item }}</span>
<span class="remove-icon" @click="removeTags(index)">×</span> <span class="remove-icon" @click="removeTags(index)">×</span>
</span>
</span> </span>
</span>
<el-input
v-if="type === 'ALARM'"
size="small"
v-model="tags"
class="trace-new-tag"
@change="addLabels"
:placeholder="t('addTags')"
/>
<span v-else>
<el-input <el-input
size="small" size="small"
v-model="tags" v-model="tags"
class="trace-new-tag" class="trace-new-tag"
@change="addLabels" @click="showClick"
:placeholder="t('addTags')"
/> />
<span class="tags-tip"> <el-dropdown
<a ref="dropdownTag"
target="blank" trigger="contextmenu"
href="https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/configuration-vocabulary.md" :hide-on-click="false"
> style="margin: 20px 0 0 -130px"
{{ t("tagsLink") }} v-if="tagArr.length"
</a> >
<el-tooltip <template #dropdown>
:content=" <el-dropdown-menu>
t( <el-dropdown-item v-for="(item, index) in tagArr" :key="index">
type === 'LOG' <span @click="selectTag(item)" class="tag-item">
? 'logTagsTip' {{ item }}
: type === 'TRACE' </span>
? 'traceTagsTip' </el-dropdown-item>
: 'alarmTagsTip' </el-dropdown-menu>
) </template>
" </el-dropdown>
> </span>
<span> <span
<Icon class="icon-help mr-5" iconName="help" size="middle" /> class="tags-tip"
</span> :class="type !== 'ALARM' && tagArr.length ? 'link-tips' : ''"
</el-tooltip> >
<b v-if="type !== 'LOG'">{{ t("noticeTag") }}</b> <a
</span> target="blank"
</div> href="https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/configuration-vocabulary.md"
>
{{ t("tagsLink") }}
</a>
<el-tooltip :content="t(tipsMap[type])">
<span>
<Icon class="icon-help mr-5" iconName="help" size="middle" />
</span>
</el-tooltip>
<b v-if="type === 'AL'">{{ t("noticeTag") }}</b>
</span>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from "vue"; import { ref, watch } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useTraceStore } from "@/store/modules/trace";
import { useLogStore } from "@/store/modules/log";
import { ElMessage } from "element-plus";
import { useAppStoreWithOut } from "@/store/modules/app";
/*global defineEmits, defineProps */ /*global Nullable, defineEmits, defineProps */
const emit = defineEmits(["update"]); const emit = defineEmits(["update"]);
defineProps({ const props = defineProps({
type: { type: String, default: "TRACE" }, type: { type: String, default: "TRACE" },
}); });
const traceStore = useTraceStore();
const logStore = useLogStore();
const appStore = useAppStoreWithOut();
const { t } = useI18n(); const { t } = useI18n();
const theme = ref<string>("dark");
const tags = ref<string>(""); const tags = ref<string>("");
const tagsList = ref<string[]>([]); const tagsList = ref<string[]>([]);
const tagArr = ref<string[]>([]);
const tagKeys = ref<string[]>([]);
const tipsMap = {
LOG: "logTagsTip",
TRACE: "traceTagsTip",
ALARM: "alarmTagsTip",
};
const dropdownTag = ref<Nullable<any>>(null);
fetchTagKeys();
function removeTags(index: number) { function removeTags(index: number) {
tagsList.value.splice(index, 1); tagsList.value.splice(index, 1);
@ -95,6 +129,61 @@ function updateTags() {
}); });
emit("update", { tagsMap, tagsList: tagsList.value }); emit("update", { tagsMap, tagsList: tagsList.value });
} }
async function fetchTagKeys() {
let resp: any = {};
if (props.type === "TRACE") {
resp = await traceStore.getTagKeys();
} else {
resp = await logStore.getLogTagKeys();
}
if (resp.errors) {
ElMessage.error(resp.errors);
return;
}
tagArr.value = resp.data.tagKeys;
tagKeys.value = resp.data.tagKeys;
}
async function fetchTagValues() {
const param = tags.value.split("=")[0];
let resp: any = {};
if (props.type === "TRACE") {
resp = await traceStore.getTagValues(param);
} else {
resp = await logStore.getLogTagValues(param);
}
if (resp.errors) {
ElMessage.error(resp.errors);
return;
}
tagArr.value = resp.data.tagValues;
}
function selectTag(item: string) {
if (tags.value.includes("=")) {
tags.value += item;
addLabels();
tagArr.value = tagKeys.value;
dropdownTag.value.handleClose();
return;
}
tags.value = item + "=";
fetchTagValues();
}
function showClick() {
if (dropdownTag.value) {
dropdownTag.value.handleOpen();
}
}
watch(
() => appStore.durationTime,
() => {
fetchTagKeys();
}
);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.trace-tags { .trace-tags {
@ -121,7 +210,6 @@ function updateTags() {
padding: 2px 5px; padding: 2px 5px;
border-radius: 3px; border-radius: 3px;
width: 250px; width: 250px;
margin-right: 3px;
} }
.remove-icon { .remove-icon {
@ -130,10 +218,20 @@ function updateTags() {
cursor: pointer; cursor: pointer;
} }
.tag-item {
display: inline-block;
min-width: 210px;
}
.tags-tip { .tags-tip {
color: #a7aebb; color: #a7aebb;
} }
.link-tips {
display: inline-block;
margin-left: 130px;
}
.light { .light {
color: #3d444f; color: #3d444f;

View File

@ -146,9 +146,10 @@ import type { ElTable } from "element-plus";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import router from "@/router"; import router from "@/router";
import { DashboardItem } from "@/types/dashboard"; import { DashboardItem, LayoutConfig } from "@/types/dashboard";
import { saveFile, readFile } from "@/utils/file"; import { saveFile, readFile } from "@/utils/file";
import { EntityType } from "./data"; import { EntityType } from "./data";
import { isEmptyObject } from "@/utils/is";
/*global Nullable*/ /*global Nullable*/
const { t } = useI18n(); const { t } = useI18n();
@ -221,12 +222,77 @@ function exportTemplates() {
const layout = JSON.parse(sessionStorage.getItem(key) || "{}"); const layout = JSON.parse(sessionStorage.getItem(key) || "{}");
return layout; return layout;
}); });
for (const item of templates) {
optimizeTemplate(item.configuration.children);
}
const name = `dashboards.json`; const name = `dashboards.json`;
saveFile(templates, name); saveFile(templates, name);
setTimeout(() => { setTimeout(() => {
multipleTableRef.value!.clearSelection(); multipleTableRef.value!.clearSelection();
}, 2000); }, 2000);
} }
function optimizeTemplate(
children: (LayoutConfig & { moved?: boolean; standard?: unknown })[]
) {
for (const child of children || []) {
delete child.moved;
delete child.activedTabIndex;
delete child.standard;
if (isEmptyObject(child.graph)) {
delete child.graph;
}
if (child.widget) {
if (child.widget.title === "") {
delete child.widget.title;
}
if (child.widget.tips === "") {
delete child.widget.tips;
}
}
if (isEmptyObject(child.widget)) {
delete child.widget;
}
if (!(child.metrics && child.metrics.length && child.metrics[0])) {
delete child.metrics;
}
if (
!(child.metricTypes && child.metricTypes.length && child.metricTypes[0])
) {
delete child.metricTypes;
}
if (child.metricConfig && child.metricConfig.length) {
child.metricConfig.forEach((c, index) => {
if (!c.calculation) {
delete c.calculation;
}
if (!c.unit) {
delete c.unit;
}
if (!c.label) {
delete c.label;
}
if (isEmptyObject(c)) {
(child.metricConfig || []).splice(index, 1);
}
});
}
if (!(child.metricConfig && child.metricConfig.length)) {
delete child.metricConfig;
}
if (child.type === "Tab") {
for (const item of child.children || []) {
optimizeTemplate(item.children);
}
}
if (
["Trace", "Topology", "Tab", "Profile", "Ebpf", "Log"].includes(
child.type
)
) {
delete child.widget;
}
}
}
function handleEdit(row: DashboardItem) { function handleEdit(row: DashboardItem) {
dashboardStore.setMode(true); dashboardStore.setMode(true);
dashboardStore.setEntity(row.entity); dashboardStore.setEntity(row.entity);

View File

@ -16,7 +16,7 @@ limitations under the License. -->
<div class="flex-h content"> <div class="flex-h content">
<TaskList /> <TaskList />
<div class="vis-graph ml-5"> <div class="vis-graph ml-5">
<div class="item"> <div class="schedules">
<EBPFSchedules /> <EBPFSchedules />
</div> </div>
<div class="item"> <div class="item">
@ -39,12 +39,18 @@ import EBPFStack from "./components/EBPFStack.vue";
.vis-graph { .vis-graph {
height: 100%; height: 100%;
width: calc(100% - 300px); width: calc(100% - 300px);
min-width: 700px;
overflow: auto;
} }
.item { .item {
width: 100%; width: 100%;
overflow: auto; overflow: auto;
height: calc(50% - 10px); height: calc(100% - 70px);
padding-bottom: 10px; padding-bottom: 10px;
} }
.schedules {
height: 60px;
}
</style> </style>

View File

@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. --> limitations under the License. -->
<template> <template>
<div class="filters"> <div class="filters flex-h">
<Selector <Selector
:value="selectedLabels" :value="selectedLabels"
:options="labels" :options="labels"
@ -23,6 +23,11 @@ limitations under the License. -->
class="inputs mr-10" class="inputs mr-10"
:multiple="true" :multiple="true"
/> />
<el-button type="primary" size="small">
<span>{{ duration[0] }}</span>
<span> ~ </span>
<span>{{ duration[1] }}</span>
</el-button>
<el-popover placement="bottom" :width="680" trigger="click"> <el-popover placement="bottom" :width="680" trigger="click">
<template #reference> <template #reference>
<el-button type="primary" size="small"> <el-button type="primary" size="small">
@ -34,7 +39,7 @@ limitations under the License. -->
placeholder="Please input name" placeholder="Please input name"
class="input-with-search" class="input-with-search"
size="small" size="small"
@change="searchProcesses" @change="searchProcesses(0)"
> >
<template #append> <template #append>
<el-button size="small"> <el-button size="small">
@ -77,7 +82,6 @@ limitations under the License. -->
{{ t("analyze") }} {{ t("analyze") }}
</el-button> </el-button>
</div> </div>
<div ref="timeline" class="schedules"></div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, watch } from "vue"; import { ref, watch } from "vue";
@ -87,25 +91,21 @@ import { Option } from "@/types/app";
import { TableHeader } from "./data"; import { TableHeader } from "./data";
import { useEbpfStore } from "@/store/modules/ebpf"; import { useEbpfStore } from "@/store/modules/ebpf";
import { EBPFProfilingSchedule, Process } from "@/types/ebpf"; import { EBPFProfilingSchedule, Process } from "@/types/ebpf";
import { DataSet, Timeline } from "vis-timeline/standalone";
import "vis-timeline/styles/vis-timeline-graph2d.css";
import { ElMessage, ElTable } from "element-plus"; import { ElMessage, ElTable } from "element-plus";
const { t } = useI18n(); const { t } = useI18n();
const ebpfStore = useEbpfStore(); const ebpfStore = useEbpfStore();
const pageSize = 5; const pageSize = 5;
/*global Nullable */
const multipleTableRef = ref<InstanceType<typeof ElTable>>(); const multipleTableRef = ref<InstanceType<typeof ElTable>>();
const selectedProcesses = ref<string[]>([]); const selectedProcesses = ref<string[]>([]);
const timeline = ref<Nullable<HTMLDivElement>>(null);
const visGraph = ref<Nullable<any>>(null);
const labels = ref<Option[]>([{ label: "All", value: "0" }]); const labels = ref<Option[]>([{ label: "All", value: "0" }]);
const processes = ref<Process[]>([]); const processes = ref<Process[]>([]);
const currentProcesses = ref<Process[]>([]); const currentProcesses = ref<Process[]>([]);
const selectedLabels = ref<string[]>(["0"]); const selectedLabels = ref<string[]>(["0"]);
const searchText = ref<string>(""); const searchText = ref<string>("");
const duration = ref<string[]>([]);
const dateFormat = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") => const dateFormat = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") =>
new Date(dayjs(date).format(pattern)); dayjs(date).format(pattern);
function changeLabels(opt: any[]) { function changeLabels(opt: any[]) {
const arr = opt.map((d) => d.value); const arr = opt.map((d) => d.value);
@ -160,56 +160,59 @@ async function analyzeEBPF() {
} }
function visTimeline() { function visTimeline() {
if (visGraph.value) {
visGraph.value.destroy();
}
labels.value = [{ label: "All", value: "0" }]; labels.value = [{ label: "All", value: "0" }];
selectedLabels.value = ["0"]; selectedLabels.value = ["0"];
processes.value = []; processes.value = [];
const schedules = ebpfStore.eBPFSchedules.map( const ranges = ebpfStore.eBPFSchedules.map((d: EBPFProfilingSchedule) => {
(d: EBPFProfilingSchedule, index: number) => { for (const l of d.process.labels) {
for (const l of d.process.labels) { labels.value.push({ label: l, value: l });
labels.value.push({ label: l, value: l });
}
processes.value.push(d.process);
return {
id: index + 1,
content: d.process.name,
start: dateFormat(d.startTime),
end: dateFormat(d.endTime),
};
} }
); processes.value.push(d.process);
searchProcesses(); return [d.startTime / 10000, d.endTime / 10000];
if (!timeline.value) { });
return; const arr = ranges.flat(1);
} const min = Math.min(...arr);
const h = timeline.value.getBoundingClientRect().height; const max = Math.max(...arr);
const items: any = new DataSet(schedules); duration.value = [dateFormat(min * 10000), dateFormat(max * 10000)];
const options = { searchProcesses(0);
height: h,
width: "100%",
locale: "en",
};
visGraph.value = new Timeline(timeline.value, items, options);
} }
function changePage(pageIndex: number) { function changePage(pageIndex: number) {
searchProcesses(pageIndex); searchProcesses(pageIndex);
} }
function searchProcesses(pageIndex?: any) { function searchProcesses(pageIndex: number) {
const arr = processes.value.filter( const arr = processes.value.filter(
(d: { name: string; instanceName: string }) => (d: {
name: string;
instanceName: string;
attributes: { name: string; value: string }[];
}) =>
d.name.includes(searchText.value) || d.name.includes(searchText.value) ||
d.instanceName.includes(searchText.value) d.instanceName.includes(searchText.value) ||
searchAttribute(d.attributes, searchText.value)
); );
currentProcesses.value = arr.splice( currentProcesses.value = arr.filter(
(pageIndex - 1 || 0) * pageSize, (d, index: number) =>
pageSize * (pageIndex || 1) (pageIndex - 1 || 0) * pageSize <= index &&
pageSize * (pageIndex || 1) > index
); );
} }
function searchAttribute(
attributes: { name: string; value: string }[],
text: string
) {
const item = attributes.find(
(d: { name: string; value: string }) => d.name === "command_line"
);
if (!item) {
return false;
}
return item.value.includes(text);
}
watch( watch(
() => ebpfStore.eBPFSchedules, () => ebpfStore.eBPFSchedules,
() => { () => {

View File

@ -31,6 +31,8 @@ const ebpfStore = useEbpfStore();
const stackTree = ref<Nullable<StackElement>>(null); const stackTree = ref<Nullable<StackElement>>(null);
const graph = ref<Nullable<HTMLDivElement>>(null); const graph = ref<Nullable<HTMLDivElement>>(null);
const flameChart = ref<any>(null); const flameChart = ref<any>(null);
const min = ref<number>(1);
const max = ref<number>(1);
function drawGraph() { function drawGraph() {
if (flameChart.value) { if (flameChart.value) {
@ -39,8 +41,33 @@ function drawGraph() {
if (!ebpfStore.analyzeTrees.length) { if (!ebpfStore.analyzeTrees.length) {
return (stackTree.value = null); return (stackTree.value = null);
} }
stackTree.value = processTree(ebpfStore.analyzeTrees); const root: StackElement = {
parentId: "0",
originId: "1",
name: "Virtual Root",
children: [],
value: 0,
id: "1",
symbol: "Virtual Root",
dumpCount: 0,
stackType: "",
};
countRange();
for (const tree of ebpfStore.analyzeTrees) {
const ele = processTree(tree.elements);
root.children && root.children.push(ele);
}
const param = (root.children || []).reduce(
(prev: number[], curr: StackElement) => {
prev[0] += curr.value;
prev[1] += curr.dumpCount;
return prev;
},
[0, 0]
);
root.value = param[0];
root.dumpCount = param[1];
stackTree.value = root;
const w = (graph.value && graph.value.getBoundingClientRect().width) || 10; const w = (graph.value && graph.value.getBoundingClientRect().width) || 10;
flameChart.value = flamegraph() flameChart.value = flamegraph()
.width(w - 15) .width(w - 15)
@ -51,6 +78,7 @@ function drawGraph() {
.sort(true) .sort(true)
.title("") .title("")
.selfValue(false) .selfValue(false)
.inverted(true)
.setColorMapper((d, originalColor) => .setColorMapper((d, originalColor) =>
d.highlight ? "#6aff8f" : originalColor d.highlight ? "#6aff8f" : originalColor
); );
@ -59,33 +87,38 @@ function drawGraph() {
.direction("w") .direction("w")
.html( .html(
(d: { data: StackElement }) => (d: { data: StackElement }) =>
`<div class="mb-5">Symbol: ${d.data.name}</div><div class="mb-5">Dump Count: ${d.data.dumpCount}</div>` `<div class="mb-5 name">Symbol: ${d.data.name}</div><div class="mb-5">Dump Count: ${d.data.dumpCount}</div>`
); )
.style("max-width", "500px");
flameChart.value.tooltip(tip); flameChart.value.tooltip(tip);
d3.select("#graph-stack").datum(stackTree.value).call(flameChart.value); d3.select("#graph-stack").datum(stackTree.value).call(flameChart.value);
} }
function countRange() {
const list = [];
for (const tree of ebpfStore.analyzeTrees) {
for (const ele of tree.elements) {
list.push(ele.dumpCount);
}
}
max.value = Math.max(...list);
min.value = Math.min(...list);
}
function processTree(arr: StackElement[]) { function processTree(arr: StackElement[]) {
const copyArr = JSON.parse(JSON.stringify(arr)); const copyArr = (window as any).structuredClone(arr);
const obj: any = {}; const obj: any = {};
let res = null; let res = null;
let min = 1;
let max = 1;
for (const item of copyArr) { for (const item of copyArr) {
item.originId = item.id; item.parentId = String(Number(item.parentId) + 1);
item.originId = String(Number(item.id) + 1);
item.name = item.symbol; item.name = item.symbol;
delete item.id; delete item.id;
obj[item.originId] = item; obj[item.originId] = item;
if (item.dumpCount > max) {
max = item.dumpCount;
}
if (item.dumpCount < min) {
min = item.dumpCount;
}
} }
const scale = d3.scaleLinear().domain([min, max]).range([1, 200]); const scale = d3.scaleLinear().domain([min.value, max.value]).range([1, 200]);
for (const item of copyArr) { for (const item of copyArr) {
if (item.parentId === "0") { if (item.parentId === "1") {
const val = Number(scale(item.dumpCount).toFixed(4)); const val = Number(scale(item.dumpCount).toFixed(4));
res = item; res = item;
res.value = val; res.value = val;
@ -145,4 +178,8 @@ watch(
color: red; color: red;
margin-top: 20px; margin-top: 20px;
} }
.name {
word-wrap: break-word;
}
</style> </style>

View File

@ -111,10 +111,6 @@ function changeType(opt: any[]) {
} }
async function createTask() { async function createTask() {
if (!labels.value.length) {
ElMessage.warning("no labels");
return;
}
const date = monitorTime.value === "0" ? new Date() : time.value; const date = monitorTime.value === "0" ? new Date() : time.value;
const params = { const params = {
serviceId: selectorStore.currentService.id, serviceId: selectorStore.currentService.id,

View File

@ -50,9 +50,14 @@ limitations under the License. -->
@query="searchEndpoints" @query="searchEndpoints"
/> />
</div> </div>
</div> <el-button
<div class="row tips"> class="search-btn"
<b>{{ t("conditionNotice") }}</b> size="small"
type="primary"
@click="searchLogs"
>
{{ t("search") }}
</el-button>
</div> </div>
<div class="flex-h row"> <div class="flex-h row">
<div class="mr-5 traceId" v-show="!isBrowser"> <div class="mr-5 traceId" v-show="!isBrowser">
@ -61,6 +66,9 @@ limitations under the License. -->
</div> </div>
<ConditionTags :type="'LOG'" @update="updateTags" /> <ConditionTags :type="'LOG'" @update="updateTags" />
</div> </div>
<div class="row tips">
<b>{{ t("conditionNotice") }}</b>
</div>
<div class="flex-h" v-show="!isBrowser"> <div class="flex-h" v-show="!isBrowser">
<div class="mr-5" v-show="logStore.supportQueryLogsByKeywords"> <div class="mr-5" v-show="logStore.supportQueryLogsByKeywords">
<span class="mr-5 grey">{{ t("keywordsOfContent") }}:</span> <span class="mr-5 grey">{{ t("keywordsOfContent") }}:</span>
@ -109,14 +117,6 @@ limitations under the License. -->
</span> </span>
</el-tooltip> </el-tooltip>
</div> </div>
<el-button
class="search-btn"
size="small"
type="primary"
@click="searchLogs"
>
{{ t("search") }}
</el-button>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -326,6 +326,7 @@ watch(
.row { .row {
margin-bottom: 5px; margin-bottom: 5px;
position: relative;
} }
.inputs-max { .inputs-max {
@ -337,8 +338,11 @@ watch(
} }
.search-btn { .search-btn {
margin-left: 20px; position: absolute;
top: 0;
right: 10px;
cursor: pointer; cursor: pointer;
width: 120px;
} }
.tips { .tips {

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. --> limitations under the License. -->
<template> <template>
<div class="flex-h row"> <div class="flex-h row">
<div class="mr-5" v-if="dashboardStore.entity === EntityType[1].value"> <div class="mr-10" v-if="dashboardStore.entity === EntityType[1].value">
<span class="grey mr-5">{{ t("service") }}:</span> <span class="grey mr-5">{{ t("service") }}:</span>
<Selector <Selector
size="small" size="small"
@ -24,7 +24,7 @@ limitations under the License. -->
@change="changeField('service', $event)" @change="changeField('service', $event)"
/> />
</div> </div>
<div class="mr-5" v-if="dashboardStore.entity !== EntityType[3].value"> <div class="mr-10" v-if="dashboardStore.entity !== EntityType[3].value">
<span class="grey mr-5">{{ t("instance") }}:</span> <span class="grey mr-5">{{ t("instance") }}:</span>
<Selector <Selector
size="small" size="small"
@ -34,7 +34,7 @@ limitations under the License. -->
@change="changeField('instance', $event)" @change="changeField('instance', $event)"
/> />
</div> </div>
<div class="mr-5" v-if="dashboardStore.entity !== EntityType[2].value"> <div class="mr-10" v-if="dashboardStore.entity !== EntityType[2].value">
<span class="grey mr-5">{{ t("endpoint") }}:</span> <span class="grey mr-5">{{ t("endpoint") }}:</span>
<Selector <Selector
size="small" size="small"
@ -46,7 +46,7 @@ limitations under the License. -->
@query="searchEndpoints" @query="searchEndpoints"
/> />
</div> </div>
<div class="mr-5"> <div class="mr-10">
<span class="grey mr-5">{{ t("status") }}:</span> <span class="grey mr-5">{{ t("status") }}:</span>
<Selector <Selector
size="small" size="small"
@ -56,27 +56,29 @@ limitations under the License. -->
@change="changeField('status', $event)" @change="changeField('status', $event)"
/> />
</div> </div>
<div class="mr-5"> <el-button
size="small"
type="primary"
@click="searchTraces"
class="search-btn"
>
{{ t("search") }}
</el-button>
</div>
<div class="flex-h row">
<div class="mr-10">
<span class="grey mr-5">{{ t("traceID") }}:</span> <span class="grey mr-5">{{ t("traceID") }}:</span>
<el-input size="small" v-model="traceId" class="traceId" /> <el-input size="small" v-model="traceId" class="traceId" />
</div> </div>
</div> <div class="mr-10">
<div class="flex-h">
<div class="mr-5">
<span class="sm b grey mr-5">{{ t("duration") }}:</span> <span class="sm b grey mr-5">{{ t("duration") }}:</span>
<el-input size="small" class="inputs mr-5" v-model="minTraceDuration" /> <el-input size="small" class="inputs mr-5" v-model="minTraceDuration" />
<span class="grey mr-5">-</span> <span class="grey mr-5">-</span>
<el-input size="small" class="inputs" v-model="maxTraceDuration" /> <el-input size="small" class="inputs" v-model="maxTraceDuration" />
</div> </div>
</div>
<div class="flex-h">
<ConditionTags :type="'TRACE'" @update="updateTags" /> <ConditionTags :type="'TRACE'" @update="updateTags" />
<el-button
class="search-btn"
size="small"
type="primary"
@click="searchTraces"
>
{{ t("search") }}
</el-button>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -109,10 +111,6 @@ const state = reactive<any>({
service: { value: "", label: "" }, service: { value: "", label: "" },
}); });
// const dateTime = computed(() => [
// appStore.durationRow.start,
// appStore.durationRow.end,
// ]);
init(); init();
async function init() { async function init() {
if (dashboardStore.entity === EntityType[1].value) { if (dashboardStore.entity === EntityType[1].value) {
@ -241,6 +239,7 @@ watch(
.row { .row {
margin-bottom: 5px; margin-bottom: 5px;
position: relative;
} }
.traceId { .traceId {
@ -248,7 +247,10 @@ watch(
} }
.search-btn { .search-btn {
margin-left: 20px;
cursor: pointer; cursor: pointer;
width: 120px;
position: absolute;
top: 0;
right: 10px;
} }
</style> </style>

View File

@ -200,9 +200,9 @@ export default defineComponent({
dom.style.background = "rgba(0, 0, 0, 0.1)"; dom.style.background = "rgba(0, 0, 0, 0.1)";
} }
function selectSpan(event: any) { function selectSpan(event: any) {
const dom = event.path.find((d: any) => const dom = event
d.className.includes("trace-item") .composedPath()
); .find((d: any) => d.className.includes("trace-item"));
emit("select", props.data); emit("select", props.data);
if (props.headerType === "profile") { if (props.headerType === "profile") {
@ -212,9 +212,9 @@ export default defineComponent({
viewSpanDetail(dom); viewSpanDetail(dom);
} }
function viewSpan(event: any) { function viewSpan(event: any) {
const dom = event.path.find((d: any) => const dom = event
d.className.includes("trace-item") .composedPath()
); .find((d: any) => d.className.includes("trace-item"));
emit("select", props.data); emit("select", props.data);
viewSpanDetail(dom); viewSpanDetail(dom);
} }