diff --git a/0001-feat-golang-ad.patch b/0001-feat-golang-ad.patch deleted file mode 100644 index 61eb0698d55b26749ef91dc2733becfa0b080581..0000000000000000000000000000000000000000 --- a/0001-feat-golang-ad.patch +++ /dev/null @@ -1,165 +0,0 @@ -From e11eae509f944c2f0387d2dbf862dcd5763b84da Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?=E9=9B=86=E5=B7=9D?= -Date: Fri, 6 Sep 2024 16:35:20 +0800 -Subject: [PATCH] =?UTF-8?q?feat:=20golang=E6=9C=8D=E5=8A=A1=E6=8F=90?= - =?UTF-8?q?=E4=BE=9Bad=E6=8E=A5=E5=8F=A3?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: 集川 ---- - ide/server/main.go | 75 ++++++++++++++++++++++++++++++++--- - ide/server/server-config.json | 4 ++ - ide/server/server-config.txt | 1 - - ide/webpack.config.js | 4 +- - 4 files changed, 75 insertions(+), 9 deletions(-) - create mode 100644 ide/server/server-config.json - delete mode 100644 ide/server/server-config.txt - -diff --git a/ide/server/main.go b/ide/server/main.go -index 80a242fb..5de296ef 100644 ---- a/ide/server/main.go -+++ b/ide/server/main.go -@@ -45,6 +45,7 @@ import ( - "runtime" - "strconv" - "strings" -+ "sync" - "time" - ) - -@@ -52,6 +53,7 @@ const HttpPort = 9000 - - var exPath string - var serveInfo string -+var msgPublishData MsgPublishData - var hdcPublicKey string - var hdcPrivateKey *rsa.PrivateKey - -@@ -178,6 +180,7 @@ func main() { - mux.HandleFunc("/application/hdcPublicKey", getHdcPublicKey) - mux.HandleFunc("/application/encryptHdcMsg", encryptHdcMsg) - mux.HandleFunc("/application/signatureHdcMsg", signatureHdcMsg) -+ mux.HandleFunc("/application/messagePublish", getMsgPublish) - fs := http.FileServer(http.Dir(exPath + "/")) - mux.Handle("/application/", http.StripPrefix("/application/", cors(fs, version))) - go func() { -@@ -299,14 +302,74 @@ func signatureHdcMsg(w http.ResponseWriter, r *http.Request) { - } - } - --func readReqServerConfig() string { -- readServerConfig, serverConfigErr := os.ReadFile(exPath + "/server-config.txt") -- if serverConfigErr != nil { -- serveInfo = "" -+func parseMsgPublishFile() { -+ msgPublishData.Mux.RLock() -+ defer msgPublishData.Mux.RUnlock() -+ exist, err := PathExists(msgPublishData.FilePath) -+ if err != nil || !exist { -+ return -+ } -+ buf, err := os.ReadFile(msgPublishData.FilePath) -+ if err != nil { -+ fmt.Println("read fail", err) -+ return -+ } -+ msgPublishData.Msg = string(buf) -+} -+ -+func getMsgPublish(w http.ResponseWriter, r *http.Request) { -+ w.Header().Set("Access-Control-Allow-Origin", "*") -+ w.Header().Set("Content-Type", "text/json") -+ msgPublishData.Mux.Lock() -+ data := msgPublishData.Msg -+ msgPublishData.Mux.Unlock() -+ if len(data) == 0 { -+ resp(&w)(false, -1, "msg failed", nil) - } else { -- serveInfo = string(readServerConfig) -+ resp(&w)(true, 0, "success", map[string]interface{}{ -+ "data": data, -+ }) -+ } -+} -+ -+type ServerConfig struct { -+ ServeInfo string `json:"ServeInfo"` -+ MsgPublishFile string `json:"MsgPublishFile"` -+} -+ -+type MsgPublishData struct { -+ FilePath string -+ Msg string -+ Mux sync.RWMutex -+} -+ -+func loopUpdateMsgPublishData() { -+ loopTime := 30 * time.Second -+ timer := time.NewTimer(loopTime) -+ for { -+ select { -+ case <-timer.C: -+ parseMsgPublishFile() -+ } -+ timer.Reset(loopTime) -+ } -+} -+ -+func readReqServerConfig() { -+ serverConfigBuffer, err := os.ReadFile(exPath + "/server-config.json") -+ if err != nil { -+ return -+ } -+ var sc ServerConfig -+ err = json.Unmarshal(serverConfigBuffer, &sc) -+ if err != nil { -+ return - } -- return serveInfo -+ serveInfo = sc.ServeInfo -+ msgPublishData.Mux.RLock() -+ msgPublishData.FilePath = sc.MsgPublishFile -+ msgPublishData.Mux.RUnlock() -+ go loopUpdateMsgPublishData() - } - - func mapToJson(m map[string]interface{}) (string, error) { -diff --git a/ide/server/server-config.json b/ide/server/server-config.json -new file mode 100644 -index 00000000..637b4034 ---- /dev/null -+++ b/ide/server/server-config.json -@@ -0,0 +1,4 @@ -+{ -+ "ServeInfo": "127.0.0.1:9100/statistics", -+ "MsgPublishFile": "" -+} -\ No newline at end of file -diff --git a/ide/server/server-config.txt b/ide/server/server-config.txt -deleted file mode 100644 -index fde29681..00000000 ---- a/ide/server/server-config.txt -+++ /dev/null -@@ -1 +0,0 @@ --127.0.0.1:9100/statistics -\ No newline at end of file -diff --git a/ide/webpack.config.js b/ide/webpack.config.js -index f7702c1c..55397917 100644 ---- a/ide/webpack.config.js -+++ b/ide/webpack.config.js -@@ -168,8 +168,8 @@ const config = { - to: 'wasm.json', - }, - { -- from: './server/server-config.txt', -- to: 'server-config.txt', -+ from: './server/server-config.json', -+ to: 'server-config.json', - }, - ], - }), --- -2.34.1 - diff --git a/ide/src/base-ui/like/LitLike.ts b/ide/src/base-ui/like/LitLike.ts new file mode 100644 index 0000000000000000000000000000000000000000..c2aa73de6eec73dd22df49d9e4d1ecb652342427 --- /dev/null +++ b/ide/src/base-ui/like/LitLike.ts @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed 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 { BaseElement, element } from '../BaseElement'; +import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil' + +@element('lit-like') +export class LitLike extends BaseElement { + private likeEl: HTMLDivElement | undefined | null; + private dislikeEl: HTMLDivElement | undefined | null; + private isFeedBacked: boolean = false; + private _type?: string; + private _content?: string; + + + static get observedAttributes(): string[] { + return ['type', 'content']; + }; + + get type(): string { + return this.getAttribute('type') || ''; + } + + set type(value: string) { + this._type = value; + this.setAttribute('type', value); + } + + get content(): string { + return this.getAttribute('content') || ''; + } + + set content(value: string) { + this._type = value; + this.setAttribute('content', value); + } + initElements(): void { + this.likeEl = this.shadowRoot?.querySelector('.like'); + this.dislikeEl = this.shadowRoot?.querySelector('.dislike'); + + this.likeEl?.addEventListener('click', (e) => { + if (!this.isFeedBacked) { + this.likeEl!.style.backgroundImage = 'url("img/like-active.png")'; + let secondCat = this.type === 'chat' ? 'user_feedback' : 'feedback_good'; + let thirdCat = this.type === 'chat' ? [1] : [this.content]; + SpStatisticsHttpUtil.generalRecord('AI_statistic', secondCat, thirdCat); + this.isFeedBacked = true; + } else { + return; + } + }) + + this.dislikeEl?.addEventListener('click', (e) => { + if (!this.isFeedBacked) { + this.dislikeEl!.style.backgroundImage = 'url("img/dislike-active.png")'; + let secondCat = this.type === 'chat' ? 'user_feedback' : 'feedback_bad'; + let thirdCat = this.type === 'chat' ? [0] : [this.content]; + SpStatisticsHttpUtil.generalRecord('AI_statistic', secondCat, thirdCat); + this.isFeedBacked = true + } else { + return; + } + }) + } + + + initHtml(): string { + return ` + + +
+ +
+
+
+ `; + } + + +} diff --git a/ide/src/base-ui/loading/LitLoading.ts b/ide/src/base-ui/loading/LitLoading.ts index 28a1b6319ce2d64205d50d8a49f114bdab666185..b4e436d8a2743ffd96cf52b57858b15b2b972379 100644 --- a/ide/src/base-ui/loading/LitLoading.ts +++ b/ide/src/base-ui/loading/LitLoading.ts @@ -13,13 +13,13 @@ * limitations under the License. */ -import { BaseElement, element } from '../BaseElement' +import { BaseElement, element } from '../BaseElement'; @element('lit-loading') export class LitLoading extends BaseElement { - initHtml(): string { - return ` + initHtml(): string { + return ` + + + +
+

扩展程序安装指导

+

HiSmartPerf扩展服务在浏览器之外为HiSmartPerf网站提供AI诊断、trace抓取等能力。 + 该扩展服务主体使用node.js实现,采用插件化设计理念方便后续功能扩展。扩展服务主要提供一个WebSocket服务端, + HiSmartPerf网站做客户端通过WebSocket连接服务端后获取服务。

+

获取扩展服务包

+ 点击这里下载: + hi-smart-perf-host-extend.zip +

+ 附件解压后的文件目录为: +
+ GitHub Logo +

+

开启扩展服务

+

+ 在hi-smart-perf-host-extend目录下,找到start.bat脚本,双击打开,即可开启扩展服务。 +
+ GitHub Logo +

+

注: 如果先打开SP-host网站,再打开扩展服务,网站会在30秒内自动连接扩展服务, + 如无法连接,可尝试刷新浏览器,依旧无法连接可联系工具接口人帮助定位

+

关闭扩展服务

+

+ 在hi-smart-perf-host-extend目录下,找到stop.bat文件,右键选择以管理员身份运行,即可关闭扩展服务。 +

+

+ 备注:当前扩展服务版本为1.0.0,如果本地存在以其他方式安装的非正式版本,请手动关闭扩展服务,并重新按照该指导安装 +

+
+ + + + + \ No newline at end of file diff --git a/ide/src/doc/quickstart_systemtrace.html b/ide/src/doc/quickstart_systemtrace.html index 71c4f9280e5bb7e8bfcb7dcaa6e17d8efd96c055..2d11409149edb14cd6c058e5908b69c2d829996b 100644 --- a/ide/src/doc/quickstart_systemtrace.html +++ b/ide/src/doc/quickstart_systemtrace.html @@ -997,12 +997,10 @@
搜索场景:框选函数调用栈的泳道图,弹出Slices Tab页,点击表格行,会跳转到框选范围内的第一条调用栈的位置,点击下图Slices Tab页的Background concurrent copying - GC调用栈。 + GC调用栈。会在搜索栏显示出该调用栈的搜索结果,并且会跳转到框选范围内第一条Background concurrent copying GC调用栈的位置。
GitHub Logo
- 会在搜索栏显示出该调用栈的搜索结果,并且会跳转到框选范围内第一条Background concurrent copying GC调用栈的位置。 -
GitHub Logo

M键测量功能

diff --git a/ide/src/doc/quickstart_xpower.html b/ide/src/doc/quickstart_xpower.html new file mode 100644 index 0000000000000000000000000000000000000000..67579eb024c724ef6dfeb2b02c1e25c83333996d --- /dev/null +++ b/ide/src/doc/quickstart_xpower.html @@ -0,0 +1,913 @@ + + + + + + quickstart_xpower + + + + + + + +
+

Xpower抓取和展示说明

+ +

Xpower用于查看系统整机和应用功耗数据,当前支持:电源信息、热温度信息。

+

Xpower的抓取

+

Xpower抓取配置参数

+ +

+ 打开Start Xpower Record开关抓取Xpower数据。点击MessageType下拉框,可以选择需要抓取的类型(下拉框支持多选)。 +
+ GitHub Logo +

+

+ 配置项说明: +

+
    +
  • +
    +REAL_BATTERY:电源信息。
    +
    +
  • +
  • +
    +THERMAL_REPORT:热温度信息。
    +
    +
  • +
+

+ 选择后Trace command页面显示对应抓取命令 +
+ GitHub Logo +

+

Xpower展示说明

+ +

+ 将抓取的Xpower文件导入到HiSmartPerf工具中查看,查看系统整机和应用功耗情况。 +
+ GitHub Logo +

+

Xpower泳道图说明——REAL_BATTERY

+

+ 选择REAL_BATTERY会展示六条泳道: +
+ GitHub Logo +

+
    +
  • +
    +Battery.Capacity: 电池容量(单位mAh)。
    +
    +
  • +
  • +
    +Battery.Charge: 充电状态(充电1,非充电0)。
    +
    +
  • +
  • +
    +Battery.GasGauge:电池剩余电量(单位mAh)。
    +
    +
  • +
  • +
    +Battery.Level:电池百分比。
    +
    +
  • +
  • +
    +Battery.RealCurrent: 实时电流(单位mAh,充电时为正数,耗电时为负数)。
    +
    +
  • +
  • +
    +Battery.Screen: 屏幕状态(亮屏1,灭屏0)。
    +
    +
  • +
+

Xpower泳道图说明——THERMAL_REPORT

+

+ 选择THERMAL_REPORT则展示两条泳道: +
+ GitHub Logo +

+
    +
  • +
    +ThermalReport.ShellTemp: 外壳温度(单位℃)。
    +
    +
  • +
  • +
    +ThermalReport.ThermalLevel: 温度等级。
    +
    +
  • +
+
+ + + + + \ No newline at end of file diff --git a/ide/src/figures/Extensions/expandservicecatalog.jpg b/ide/src/figures/Extensions/expandservicecatalog.jpg new file mode 100644 index 0000000000000000000000000000000000000000..badc75bce63eb8e7da316ccb491d131e6a098626 Binary files /dev/null and b/ide/src/figures/Extensions/expandservicecatalog.jpg differ diff --git a/ide/src/figures/Extensions/expandserviceccmd.jpg b/ide/src/figures/Extensions/expandserviceccmd.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b42f06e1e4ac64e57cc49072e85d3632036cbc35 Binary files /dev/null and b/ide/src/figures/Extensions/expandserviceccmd.jpg differ diff --git a/ide/src/figures/Xpower/currentselection.jpg b/ide/src/figures/Xpower/currentselection.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bff52b342e62525b8db5c9d1c1a4012e669e0f7e Binary files /dev/null and b/ide/src/figures/Xpower/currentselection.jpg differ diff --git a/ide/src/figures/Xpower/xpowerbattery.jpg b/ide/src/figures/Xpower/xpowerbattery.jpg new file mode 100644 index 0000000000000000000000000000000000000000..abcbbdafe9887d0d09249b37a976ec52934e9cd7 Binary files /dev/null and b/ide/src/figures/Xpower/xpowerbattery.jpg differ diff --git a/ide/src/figures/Xpower/xpowerconfig.jpg b/ide/src/figures/Xpower/xpowerconfig.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c7682be56b4eaff602c6034d4ba546bcfc7839a7 Binary files /dev/null and b/ide/src/figures/Xpower/xpowerconfig.jpg differ diff --git a/ide/src/figures/Xpower/xpowercounters.jpg b/ide/src/figures/Xpower/xpowercounters.jpg new file mode 100644 index 0000000000000000000000000000000000000000..56443c56aa3ce7bc8f7483f2a6b027a0dd51d8ac Binary files /dev/null and b/ide/src/figures/Xpower/xpowercounters.jpg differ diff --git a/ide/src/figures/Xpower/xpowerthermalreport.jpg b/ide/src/figures/Xpower/xpowerthermalreport.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cdf3faf596e716d3dd7c3da9827086a652a77804 Binary files /dev/null and b/ide/src/figures/Xpower/xpowerthermalreport.jpg differ diff --git a/ide/src/figures/Xpower/xpowertrace.jpg b/ide/src/figures/Xpower/xpowertrace.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1f72bd3610325e4fdb03c52ca5d6248e555154e0 Binary files /dev/null and b/ide/src/figures/Xpower/xpowertrace.jpg differ diff --git a/ide/src/figures/Xpower/xpowertracecommand.jpg b/ide/src/figures/Xpower/xpowertracecommand.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5daeb8812d5b41abb3020cc5701b7b78589e1b5d Binary files /dev/null and b/ide/src/figures/Xpower/xpowertracecommand.jpg differ diff --git a/ide/src/img/dislike-active.png b/ide/src/img/dislike-active.png new file mode 100644 index 0000000000000000000000000000000000000000..4453cfd379c23f834adb7ead018137f1b7b71b43 Binary files /dev/null and b/ide/src/img/dislike-active.png differ diff --git a/ide/src/img/dislike.png b/ide/src/img/dislike.png new file mode 100644 index 0000000000000000000000000000000000000000..50d2015c8c3d284b12d5a30263a27e78435710d2 Binary files /dev/null and b/ide/src/img/dislike.png differ diff --git a/ide/src/img/like-active.png b/ide/src/img/like-active.png new file mode 100644 index 0000000000000000000000000000000000000000..b36af3817d3d1a969ca302e5677fb819b7b81135 Binary files /dev/null and b/ide/src/img/like-active.png differ diff --git a/ide/src/img/like.png b/ide/src/img/like.png new file mode 100644 index 0000000000000000000000000000000000000000..97403866d57400d1ca08d7836532faf633837fab Binary files /dev/null and b/ide/src/img/like.png differ diff --git a/ide/src/img/no-report.png b/ide/src/img/no-report.png new file mode 100644 index 0000000000000000000000000000000000000000..f9760d06ed5b6e8b6f543cd83cd570fb9358ce5e Binary files /dev/null and b/ide/src/img/no-report.png differ diff --git a/ide/src/img/top_up.png b/ide/src/img/top_up.png new file mode 100644 index 0000000000000000000000000000000000000000..829171a0994b856e08d7ad39ac44afc07d5be4f0 Binary files /dev/null and b/ide/src/img/top_up.png differ diff --git a/ide/src/img/xiaoluban.jpg b/ide/src/img/xiaoluban.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bef9ace7ae7b5003a409bfeb1c10441adff8ccf3 Binary files /dev/null and b/ide/src/img/xiaoluban.jpg differ diff --git a/ide/src/statistics/util/SpStatisticsHttpBean.ts b/ide/src/statistics/util/SpStatisticsHttpBean.ts index 6d5f69d318118b4f543f59d685e0330015da46dc..927eff7072fdbba394f70a10a8976373bdcdee39 100644 --- a/ide/src/statistics/util/SpStatisticsHttpBean.ts +++ b/ide/src/statistics/util/SpStatisticsHttpBean.ts @@ -29,3 +29,19 @@ export interface pluginUsage { plugin: Array; } } + +export interface GeneralRecordRequest { + ts: number, + category: string, //'AI_STATISTIC' + /* + smart_luban:小鲁班 + large_model_q&a:AI问答 + large_model_detect:AI诊断 + user_feedback:用户反馈 + */ + /* + 'feedback_good,feedback_bad':诊断反馈 + */ + secondCat: string, + thirdCat: Array +} diff --git a/ide/src/statistics/util/SpStatisticsHttpUtil.ts b/ide/src/statistics/util/SpStatisticsHttpUtil.ts index 001ab515714aef38e165c0eae177552a319586c8..302e56c4d1fcb6beb4a7d5cbddf6dc4b8f3eda3e 100644 --- a/ide/src/statistics/util/SpStatisticsHttpUtil.ts +++ b/ide/src/statistics/util/SpStatisticsHttpUtil.ts @@ -14,7 +14,7 @@ */ import { warn } from '../../log/Log'; -import { BurialPointRequestBody, pluginUsage } from './SpStatisticsHttpBean'; +import { BurialPointRequestBody, GeneralRecordRequest, pluginUsage } from './SpStatisticsHttpBean'; export class SpStatisticsHttpUtil { static requestServerInfo: string = ''; @@ -24,6 +24,9 @@ export class SpStatisticsHttpUtil { static retryMaxCount: number = 5; static pauseRetry: boolean = false; static retryRestTimeOut: boolean = false; + static recordPlugin: Array = []; + static controllersMap: Map = new Map(); + static isInterrupt: boolean = false; static initStatisticsServerConfig(): void { if (SpStatisticsHttpUtil.requestServerInfo === '') { @@ -165,21 +168,46 @@ export class SpStatisticsHttpUtil { .then((resp) => { }); } - static recordPluginUsage(requsetBody: pluginUsage) { + // ai问答 + static generalRecord(category: string, secondCat: string, thirdCat: Array): void { + let requestBody: GeneralRecordRequest = { + ts: SpStatisticsHttpUtil.getCorrectRequestTime(), + category, + secondCat, + thirdCat + }; + fetch(`https://${SpStatisticsHttpUtil.requestServerInfo}/generalRecord`, { + method: 'post', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(requestBody) + }).then( + res => { } + ).catch(err => { + + }) + } + + static recordPluginUsage(): void { fetch(`https://${SpStatisticsHttpUtil.requestServerInfo}/recordPluginUsage`, { method: 'post', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(requsetBody), + body: JSON.stringify({ + eventData: { + plugin: SpStatisticsHttpUtil.recordPlugin + } + }) }).then(res => { }).catch(err => { - this.handleRequestException(); }); + SpStatisticsHttpUtil.recordPlugin = []; } - static getNotice() { - return fetch(`${document.URL}messagePublish`); + static getNotice(): Promise { + return fetch(`https://${window.location.host}${window.location.pathname}messagePublish`); } static getCorrectRequestTime(): number { @@ -190,37 +218,84 @@ export class SpStatisticsHttpUtil { } // ai对话接口--获取token - static async getAItoken() { - let token = '' - await window.fetch(`https://${window.location.host}/takeToken`, { + static async getAItoken(): Promise { + let controller = new AbortController(); + let response: aiResponse = { + status: 0, + data: '' + }; + setTimeout(() => { + controller.abort(); + }, 60000); + let res = await window.fetch(`https://${window.location.host}/takeToken`, { method: 'post', + signal: controller.signal, headers: { 'Content-Type': 'application/json' } - }).then(async (res) => { - let resp = await res.text(); - let resj = await JSON.parse(resp); - token = resj.token; - }).catch(() => { }); - return token; + }).then(async res => { + response.status = res.status; + if (res.status === 200) { + let resp = await res.text(); + let resj = await JSON.parse(resp); + response.data = resj.token; + } + }).catch(err => { + response.status = 700; + }) + return response; } // ai对话接口--问答 // @ts-ignore - static async askAi(requestBody) { - let answer = ''; - let res = await window.fetch(`https://${window.location.host}/ask`, { - method: 'post', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(requestBody) + static askAi(requestBody): Promise { + return new Promise((resolve, reject) => { + let controller = new AbortController(); + let date = Date.now(); + if (!SpStatisticsHttpUtil.controllersMap.has(date)) { + SpStatisticsHttpUtil.controllersMap.set(date, controller) + } + let response: aiResponse = { + status: 0, + data: '', + time: date, + }; + setTimeout(() => { + controller.abort(); + }, 60000); + window.fetch(`https://${window.location.host}/ask`, { + method: 'post', + signal: controller.signal, + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(requestBody) + }).then(async res => { + response.status = res.status; + if (res.status === 200) { + let resp = await res.text(); + let resj = await JSON.parse(resp); + response.data = resj.reason && resj.reason === 'ok' ? resj.chatbot_reply : '服务器异常,请稍后再试'; + } + else { + response.data = '服务器请求失败'; + } + resolve(response); + }).catch((err) => { + if (err.toString().indexOf('AbortError') > -1) { + response.data = '请求超时,已中断!'; + response.status = 504; + } else { + response.data = '请求错误'; + } + reject(response) + }) }) - // 用状态码判断statu = 200? - let resp = await res.text(); - let resj = await JSON.parse(resp); - answer = resj.chatbot_reply; - return answer; } } +export class aiResponse { + status: number = 0; + data: string = ''; + time?: number = 0; +} diff --git a/ide/src/trace/SpApplication.ts b/ide/src/trace/SpApplication.ts index ed72661feed96045cd012c210a246ed2591da214..46670a6aa9efe7b5417bcbfb4a80232674a23e5b 100644 --- a/ide/src/trace/SpApplication.ts +++ b/ide/src/trace/SpApplication.ts @@ -16,7 +16,8 @@ import { BaseElement, element } from '../base-ui/BaseElement'; import '../base-ui/menu/LitMainMenu'; import '../base-ui/icon/LitIcon'; -import '../base-ui/loading/LitLoading' +import '../base-ui/loading/LitLoading'; +import '../base-ui/like/LitLike'; import { SpMetrics } from './component/SpMetrics'; import { SpHelp } from './component/SpHelp'; import './component/SpHelp'; @@ -82,11 +83,11 @@ import './component/SpThirdParty'; import { cancelCurrentTraceRowHighlight } from './component/SpSystemTrace.init'; import './component/SpBubblesAI'; import './component/SpAiAnalysisPage'; -import { shadowRootInput } from './component/trace/base/shadowRootInput'; import { WebSocketManager } from '../webSocket/WebSocketManager'; import { SpAiAnalysisPage } from './component/SpAiAnalysisPage'; -import './component/SpAdvertisement' -import { toUSVString } from 'util'; +import './component/SpAdvertisement'; +import { shadowRootInput } from './component/trace/base/shadowRootInput'; +import { SpBubblesAI } from './component/SpBubblesAI'; @element('sp-application') export class SpApplication extends BaseElement { @@ -119,6 +120,7 @@ export class SpApplication extends BaseElement { | null; static skinChange: Function | null | undefined = null; static skinChange2: Function | null | undefined = null; + static isTraceLoaded: Boolean = false; skinChangeArray: Array = []; private rootEL: HTMLDivElement | undefined | null; private headerDiv: HTMLDivElement | undefined | null; @@ -317,6 +319,7 @@ export class SpApplication extends BaseElement { this.contentLeftOption = this.shadowRoot?.querySelector('.content-left-option'); this.contentCenterOption = this.shadowRoot?.querySelector('.content-center-option'); this.spAiAnalysisPage = this.shadowRoot!.querySelector('#sp-ai-analysis') as SpAiAnalysisPage; + let xiaoLubanEl: HTMLElement | null = this.shadowRoot!.querySelector('#sp-bubbles'); this.initElementsAttr(); this.initEvents(); this.initRecordEvents(); @@ -328,7 +331,26 @@ export class SpApplication extends BaseElement { this.initGlobalEvents(); this.initDocumentListener(); this.initElementsEnd(); + this.dragXiaolubanEvents(xiaoLubanEl!); this.connectWebSocket(); + + } + private dragXiaolubanEvents(xiaoLubanEl: HTMLElement): void { + document.querySelector('body')!.addEventListener('dragover', function (event) { + event.preventDefault(); + event.stopPropagation(); + }); + document.querySelector('body')!.addEventListener('drop', function (event) { + event.preventDefault(); + event.stopPropagation(); + if (!SpBubblesAI.isAIHover) { + return; + }; + const x = event.clientX - 15 < 0 ? 0 : event.clientX - 15; + const y = event.clientY - 15 < 0 ? 0 : event.clientY - 15; + xiaoLubanEl!.style.left = `${x}px`; + xiaoLubanEl!.style.top = `${y}px`; + }); } private connectWebSocket(): void { document.addEventListener('DOMContentLoaded', function () {// @@ -605,6 +627,7 @@ export class SpApplication extends BaseElement { } private openTraceFile(ev: unknown, isClickHandle?: boolean): void { + SpApplication.isTraceLoaded = false; this.returnOriginalUrl(); this.removeAttribute('custom-color'); this.chartFilter!.setAttribute('hidden', ''); @@ -716,7 +739,7 @@ export class SpApplication extends BaseElement { if (urlParams.get('local')) { URL.revokeObjectURL(localUrl); } - this.handleWasmMode(new File([arrayBuf], fileName), showFileName, arrayBuf.byteLength, fileName); + this.handleWasmMode(new File([arrayBuf], fileName), showFileName, arrayBuf.byteLength, fileName, jsonStr); }); }) .catch((e) => { @@ -1230,6 +1253,7 @@ export class SpApplication extends BaseElement { (window as unknown).traceFileName = fileName; } this.showCurrentTraceMenu(fileSize, showFileName, fileName, isDistributed); + SpApplication.isTraceLoaded = true; if (!isDistributed) { this.importConfigDiv!.style.display = Utils.getInstance().getSchedSliceMap().size > 0 ? 'block' : 'none'; } @@ -1583,6 +1607,7 @@ export class SpApplication extends BaseElement { private openFileInit(multiTrace: boolean = false): void { clearTraceFileCache(); this.litSearch!.clear(); + this.spAiAnalysisPage!.clear(); Utils.currentSelectTrace = undefined; this.markJson = undefined; if (!multiTrace) { @@ -1963,8 +1988,11 @@ export class SpApplication extends BaseElement { this.croppingFile(this.progressEL!, this.litSearch!); }); - this.aiAnalysis!.addEventListener('click', (ev) => { - if (this.spAiAnalysisPage!.style.visibility === 'hidden') { + let aiAnalysis = this.shadowRoot + ?.querySelector('lit-main-menu')! + .shadowRoot!.querySelector('.ai_analysis') as HTMLDivElement + aiAnalysis!.addEventListener('click', (ev) => { + if (this.spAiAnalysisPage!.style.visibility === 'hidden' || this.spAiAnalysisPage!.style.display === 'none') { this.spAiAnalysisPage!.style.display = 'block'; this.spAiAnalysisPage!.style.visibility = 'visible'; } else { @@ -1973,11 +2001,15 @@ export class SpApplication extends BaseElement { } }) + this.spAiAnalysisPage!.valueChangeHandler = (value: string, id: number) => { + this.litSearch!.valueChangeHandler!(this.litSearch!.trimSideSpace(value), id); + } + // 鼠标拖动改变大小 - this.aiPageResize() + this.aiPageResize(); } - private aiPageResize() { + private aiPageResize(): void { const resizableDiv = this.spAiAnalysisPage!; let isResizing = false; @@ -1998,12 +2030,13 @@ export class SpApplication extends BaseElement { }); - function changeAiWidth(e: any) { + function changeAiWidth(e: unknown): void { resizableDiv.style.cursor = 'e-resize'; + // @ts-ignore resizableDiv.style.width = window.innerWidth - e.clientX + 'px'; } - function mouseUp() { + function mouseUp(): void { isResizing = false; document.removeEventListener('mousemove', changeAiWidth); document.removeEventListener('mouseup', mouseUp); @@ -2033,7 +2066,7 @@ export class SpApplication extends BaseElement { private initSearchChangeEvents(): void { let timer: NodeJS.Timeout; - this.litSearch!.valueChangeHandler = (value: string): void => { + this.litSearch!.valueChangeHandler = (value: string, id: number = -1): void => { Utils.currentSelectTrace = this.litSearch?.getSearchTraceId(); this.litSearch!.currenSearchValue = value; if (value.length > 0) { @@ -2057,12 +2090,18 @@ export class SpApplication extends BaseElement { list = cpus; let asyncFuncArr = this.spSystemTrace!.seachAsyncFunc(value); this.spSystemTrace!.searchFunction(list, asyncFuncArr, value).then((mixedResults) => { - if (this.litSearch!.searchValue !== '') { + if (this.litSearch!.searchValue !== '' || id > -1) { if (!Utils.isDistributedMode()) { this.litSearch!.list = this.spSystemTrace!.searchSdk(mixedResults, value); } else { this.litSearch!.list = mixedResults; } + if (id > -1) { + this.litSearch!.list = this.litSearch!.list.filter((v: unknown) => { + // @ts-ignore + return v.id === id + }) + } this.litSearch!.index = this.spSystemTrace!.showStruct(false, -1, this.litSearch!.list); } this.progressEL!.loading = false; @@ -2181,6 +2220,9 @@ export class SpApplication extends BaseElement { showNode.style.visibility = 'visible'; let recordSetting = document.querySelector("body > sp-application")?.shadowRoot?.querySelector("#sp-record-trace")?.shadowRoot?.querySelector("#app-content > record-setting"); shadowRootInput.preventBubbling(recordSetting!); + //@ts-ignore + } else if (node.id! === 'sp-ai-analysis' && node.style!.visibility! === 'visible') { + return; } else { (node! as HTMLElement).style.visibility = 'hidden'; } @@ -2392,7 +2434,8 @@ export class SpApplication extends BaseElement { fetch(url) .then((res) => { res.arrayBuffer().then((arrayBuf) => { - let fileName = url.split('/').reverse()[0]; + let urlParams = new URL(url).searchParams; + let fileName = urlParams.get('name') ? decodeURIComponent(urlParams.get('name')!) : url.split('/').reverse()[0]; this.traceFileName = fileName; let showFileName = fileName.lastIndexOf('.') === -1 ? fileName : fileName.substring(0, fileName.lastIndexOf('.')); @@ -2480,18 +2523,18 @@ export class SpApplication extends BaseElement { 'download-db', '', {}, - (reqBufferDB: ArrayBuffer) => { + async (reqBufferDB: ArrayBuffer) => { let a = document.createElement('a'); a.href = URL.createObjectURL(new Blob([reqBufferDB])); a.download = fileName; - a.click(); - this.itemIconLoading(mainMenu, 'Current Trace', 'Download Database', true); - let timer = setInterval(() => { - this.itemIconLoading(mainMenu, 'Current Trace', 'Download Database', false); + await a.click(); + await this.itemIconLoading(mainMenu, 'Current Trace', 'Download Database', true); + let timer = setInterval(async () => { + await this.itemIconLoading(mainMenu, 'Current Trace', 'Download Database', false); clearInterval(timer); }, 4000); // 存入缓存 - caches.open(`${fileName}`).then((cache) => { + await caches.open(`${fileName}`).then(async (cache) => { let headers = new Headers(); headers.append('Content-type', 'application/octet-stream'); headers.append('Content-Transfer-Encoding', 'binary'); diff --git a/ide/src/trace/SpApplicationPublicFunc.ts b/ide/src/trace/SpApplicationPublicFunc.ts index 071c4934dab68813ae700bc23f90984b624439a3..2e29e4589d7034b1b43ec5b18f551f397a38c53f 100644 --- a/ide/src/trace/SpApplicationPublicFunc.ts +++ b/ide/src/trace/SpApplicationPublicFunc.ts @@ -327,7 +327,7 @@ export const applicationHtml: string = ` } #sp-ai-analysis { - top:0px; + top:75px; right:0px; position:absolute; z-index:9999; @@ -338,14 +338,13 @@ export const applicationHtml: string = ` box-shadow:3px 0px 14px #000; border-radius:8px; background-color:#fff; - padding:10px 10px 10px 5px; - user-select:none; + padding:10px 10px 30px 5px; box-sizing:border-box; visibility:hidden; }
- +
- @@ -397,7 +395,6 @@ export const applicationHtml: string = `
- @@ -423,6 +420,7 @@ export const applicationHtml: string = `
+
`; diff --git a/ide/src/trace/bean/BoxSelection.ts b/ide/src/trace/bean/BoxSelection.ts index 2d45cda705556a40491a2eb0607bd62a3afa3623..b741942a6df46a0983758cc52e5ef8d88d7d0217 100644 --- a/ide/src/trace/bean/BoxSelection.ts +++ b/ide/src/trace/bean/BoxSelection.ts @@ -373,7 +373,7 @@ export class SelectionParam { // @ts-ignore let taskData = it.dataListCache.filter((taskData: FuncStruct) => { taskData!.tid = isNaN(Number(it.rowId!)) && typeof it.rowId! === 'string' ? - (function() { + (function(): number | undefined { const match = (it.rowId!).match(/-(\d+)/); return match ? parseInt(match[1]) : undefined; })() : @@ -1154,8 +1154,17 @@ export class SelectionParam { } // @ts-ignore - pushXpower(it: TraceRow, sp: SpSystemTrace): void { - if (it.rowType === TraceRow.ROW_TYPE_XPOWER) { + pushXpower(it: TraceRow, sp: SpSystemTrace): void { + if (it.rowType === TraceRow.ROW_TYPE_XPOWER) { + it.childrenList.forEach((it) => { + it.childrenList.forEach((item) => { + item.rangeSelect = true; + item.checkType = '2'; + this.xpowerMapData.set(item.rowId || '', item.getCacheData); + }) + }); + } + if (it.rowType === TraceRow.ROW_TYPE_XPOWER_SYSTEM_GROUP) { it.childrenList.forEach((it) => { it.rangeSelect = true; it.checkType = '2'; diff --git a/ide/src/trace/component/SpAdvertisement.html.ts b/ide/src/trace/component/SpAdvertisement.html.ts index 64973e79d37ac329321802f6a9853687c5eac744..e69b11fc6bba5e620107eaa812874ad944a2138d 100644 --- a/ide/src/trace/component/SpAdvertisement.html.ts +++ b/ide/src/trace/component/SpAdvertisement.html.ts @@ -15,16 +15,32 @@ export const SpAdvertisementHtml = `
-
+
+ Description +
+
`; \ No newline at end of file diff --git a/ide/src/trace/component/SpAdvertisement.ts b/ide/src/trace/component/SpAdvertisement.ts index 00d9f8c10447a31c3286bbd671e82640ecadb810..83922144ba6618109f450e3fe79f05f98f7e06c6 100644 --- a/ide/src/trace/component/SpAdvertisement.ts +++ b/ide/src/trace/component/SpAdvertisement.ts @@ -14,7 +14,7 @@ */ import { BaseElement, element } from '../../base-ui/BaseElement'; -import { SpAdvertisementHtml } from "./SpAdvertisement.html"; +import { SpAdvertisementHtml } from './SpAdvertisement.html'; import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil'; @element('sp-advertisement') @@ -26,46 +26,56 @@ export class SpAdvertisement extends BaseElement { initElements(): void { // 整个广告 - this.advertisementEL = document.querySelector("body > sp-application")?.shadowRoot?. - querySelector("#sp-advertisement")?.shadowRoot?.querySelector("#sp-advertisement"); + this.advertisementEL = document.querySelector('body > sp-application')?.shadowRoot?. + querySelector('#sp-advertisement')?.shadowRoot?.querySelector('#sp-advertisement'); // 关闭按钮 - this.closeEL = document.querySelector("body > sp-application")?.shadowRoot?. - querySelector("#sp-advertisement")?.shadowRoot?.querySelector("#close"); + this.closeEL = document.querySelector('body > sp-application')?.shadowRoot?. + querySelector('#sp-advertisement')?.shadowRoot?.querySelector('#close'); // 公告内容 - this.noticeEl = document.querySelector("body > sp-application")?.shadowRoot?. - querySelector("#sp-advertisement")?.shadowRoot?.querySelector("#notice"); + this.noticeEl = document.querySelector('body > sp-application')?.shadowRoot?. + querySelector('#sp-advertisement')?.shadowRoot?.querySelector('.text'); this.getMessage(); setInterval(() => { this.getMessage(); - }, 10000); + }, 300000); this.closeEL?.addEventListener('click', () => { this.advertisementEL!.style!.display = 'none'; + localStorage.setItem('isdisplay', 'false'); }) } - private getMessage() { + private getMessage(): void { SpStatisticsHttpUtil.getNotice().then(res => { - res.text().then((it) => { - let resp = JSON.parse(it); - if (resp && resp.data && resp.data.data && resp.data.data !== this.message && resp.data.data !== '') { - this.message = resp.data.data; - if (this.message.startsWith('图片:')) { - this.noticeEl!.style.display = "flex"; - this.noticeEl!.style.justifyContent = "center"; - this.noticeEl!.innerHTML = `图片加载失败` - } else if (this.message.startsWith('链接:')) { - this.noticeEl!.style.height = "auto"; - this.noticeEl!.style.color = "#000"; - this.noticeEl!.innerHTML = `链接: - ${this.message.substring(3, this.message.length)}` + if (res.status === 200) { + res.text().then((it) => { + let resp = JSON.parse(it); + let publish = localStorage.getItem('message'); + if (resp && resp.data && resp.data.data && resp.data.data !== '') { + this.message = resp.data.data; + localStorage.setItem('message', this.message); + let parts = this.message.split(';'); + let linkInfo = parts[2].match(/链接:([^\s]+)/)![1] || ''; + let link = `${parts[1]}`; + let finalString = `${parts[0]}
${link}`; + this.noticeEl!.innerHTML = `

${finalString}

`; + if (publish) { + if (resp.data.data !== publish) { + localStorage.setItem('isdisplay', 'true'); + } + } else { + localStorage.setItem('isdisplay', 'true'); + } } else { - this.noticeEl!.style.color = "red"; - this.noticeEl!.innerHTML = this.message; + localStorage.setItem('isdisplay', 'false'); } - this.advertisementEL!.style!.display = 'block'; - } - }); + let isdisplay = localStorage.getItem('isdisplay'); + this.advertisementEL!.style!.display = isdisplay === 'true' ? 'block' : 'none'; + }); + } else { + this.advertisementEL!.style!.display = 'none'; + } + }).catch(err => { + this.advertisementEL!.style!.display = 'none'; }) } diff --git a/ide/src/trace/component/SpAiAnalysisPage.html.ts b/ide/src/trace/component/SpAiAnalysisPage.html.ts index 94c5850d0e9422ac3c4bef8dda2f8234cc7279a8..de484aaff9a0cd4f8f33ab43659be67b46368b54 100644 --- a/ide/src/trace/component/SpAiAnalysisPage.html.ts +++ b/ide/src/trace/component/SpAiAnalysisPage.html.ts @@ -18,49 +18,79 @@ export const SpAiAnalysisPageHtml = `

HiSmartPerf AI助手

-
+
-
-
- +
+
+
+ +
+
+ 有什么可以帮助您吗? +
+
-
- 有什么可以帮助您吗? -
+
+
+
+
+
+ +
+ 历史记录 +
+
+
+ +
+ 新建聊天 +
+
-
+
+
+ +
+
-
+
- 开始时间: + startTime:
- 结束时间: + endTime:
-
+
-

- 分析报告 -

+

+ 诊断报告 +

-
- -
- 暂无数据 + + + + + + + + +
+
+
+ +
+ 暂无数据 +
-
- 未连接 -
-
@@ -69,31 +99,10 @@ export const SpAiAnalysisPageHtml = `
-
-
-
-
- -
- 历史记录 -
-
-
- -
- 新建聊天 -
-
-
-
-
- - -
-
+
聊天
@@ -103,9 +112,39 @@ export const SpAiAnalysisPageHtml = `
诊断
+ -` \ No newline at end of file +`; \ No newline at end of file diff --git a/ide/src/trace/component/SpAiAnalysisPage.ts b/ide/src/trace/component/SpAiAnalysisPage.ts index 4cb9e287e2c9b495049f45796f5f2811b26d973d..9260c032ffcc34fbaf401d675809ebb8b574e86b 100644 --- a/ide/src/trace/component/SpAiAnalysisPage.ts +++ b/ide/src/trace/component/SpAiAnalysisPage.ts @@ -1,6 +1,6 @@ /* * Copyright (C) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * Licensed 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 * @@ -14,22 +14,31 @@ */ import { BaseElement, element } from '../../base-ui/BaseElement'; -import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil'; +import { aiResponse, SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil'; import { threadPool } from '../database/SqlLite'; -import { SpAiAnalysisPageHtml } from './SpAiAnalysisPage.html' +import { SpAiAnalysisPageHtml } from './SpAiAnalysisPage.html'; import { getTimeString } from './trace/sheet/TabPaneCurrentSelection'; import { WebSocketManager } from '../../webSocket/WebSocketManager'; import { TypeConstants } from '../../webSocket/Constants'; import { TraceRow } from './trace/base/TraceRow'; import { SpSystemTrace } from './SpSystemTrace'; +import { SpApplication } from '../SpApplication'; +import { Utils } from './trace/base/Utils'; +import { LitTable } from '../../base-ui/table/lit-table'; + +const TITLE_HEIGHT = 41; +const TBODY_HEIGHT = 160; @element('sp-ai-analysis') export class SpAiAnalysisPage extends BaseElement { + valueChangeHandler: ((str: string, id: number) => void) | undefined | null; private askQuestion: Element | null | undefined; + private q_a_window: HTMLDivElement | null | undefined; private aiAnswerBox: HTMLDivElement | null | undefined; private newChatEl: HTMLImageElement | null | undefined; - private chatWindow: HTMLDivElement | null | undefined; + private contentWindow: HTMLDivElement | null | undefined; private inputEl: HTMLTextAreaElement | null | undefined; + private tipsContainer: HTMLDivElement | null | undefined; private chatImg: HTMLImageElement | null | undefined; private reportBar: HTMLImageElement | null | undefined; private reportImg: HTMLImageElement | null | undefined; @@ -37,11 +46,11 @@ export class SpAiAnalysisPage extends BaseElement { private draftBtn: HTMLDivElement | null | undefined; private downloadBtn: HTMLDivElement | null | undefined; private draftList: HTMLDivElement | null | undefined; - private noDataEl: HTMLDivElement | null | undefined; - private loginTipEl: HTMLDivElement | null | undefined; + private tipsContent: HTMLDivElement | null | undefined; private loadingItem: HTMLDivElement | null | undefined; private startTimeEl: HTMLSpanElement | null | undefined; private endTimeEl: HTMLSpanElement | null | undefined; + private contentsTable: LitTable | null | undefined; private question: string = ''; private token: string = ''; // 是否点击了新建聊天 @@ -50,12 +59,18 @@ export class SpAiAnalysisPage extends BaseElement { static isRepeatedly: boolean = false; // 拼接下载内容 private reportContent: string = ''; + private isNodata: boolean = true; private md: unknown; + private isResultBack: boolean = true; + static startTime: number = 0; + static endTime: number = 0; // 监听选中时间范围变化 - static selectChangeListener(startTime: number, endTime: number) { - let startEl = document.querySelector("body > sp-application")!.shadowRoot!.querySelector("#sp-ai-analysis")!.shadowRoot?.querySelector("div.chatBox > div > div.report_details > div.selectionBox > div.startBox > span"); + static selectChangeListener(startTime: number, endTime: number): void { + SpAiAnalysisPage.startTime = startTime; + SpAiAnalysisPage.endTime = endTime; + let startEl = document.querySelector('body > sp-application')!.shadowRoot!.querySelector('#sp-ai-analysis')!.shadowRoot?.querySelector('div.chatBox > div > div.report_details > div.selectionBox > div.startBox > span'); startEl!.innerHTML = getTimeString(startTime).toString(); - let endEl = document.querySelector("body > sp-application")!.shadowRoot!.querySelector("#sp-ai-analysis")!.shadowRoot?.querySelector("div.chatBox > div > div.report_details > div.selectionBox > div.endBox > span"); + let endEl = document.querySelector('body > sp-application')!.shadowRoot!.querySelector('#sp-ai-analysis')!.shadowRoot?.querySelector('div.chatBox > div > div.report_details > div.selectionBox > div.endBox > span'); endEl!.innerHTML = getTimeString(endTime).toString(); } initElements(): void { @@ -63,17 +78,20 @@ export class SpAiAnalysisPage extends BaseElement { html: true, typographer: true }); + let aiAssistant = document.querySelector("body > sp-application")!.shadowRoot!.querySelector("#sp-ai-analysis"); let chatBar = this.shadowRoot?.querySelector('.chatBar'); + let closeBtn = document.querySelector("body > sp-application")!.shadowRoot!.querySelector("#sp-ai-analysis")!.shadowRoot!.querySelector("div.rightTabBar > lit-icon")!.shadowRoot!.querySelector("#icon"); this.askQuestion = this.shadowRoot?.querySelector('.ask_question'); this.reportBar = this.shadowRoot?.querySelector('.report'); + this.q_a_window = this.shadowRoot?.querySelector('.q_a_window'); let reportDetails = this.shadowRoot?.querySelector('.report_details'); - let chatInputBox = this.shadowRoot?.querySelector('.chatInputBox'); - this.chatWindow = this.shadowRoot?.querySelector('.ask_question'); + this.contentWindow = this.shadowRoot?.querySelector('.ask_question'); + this.tipsContainer = this.shadowRoot?.querySelector('.tipsContainer'); this.inputEl = this.shadowRoot?.querySelector('.inputText'); this.chatImg = this.shadowRoot?.querySelector('.chatBar')?.getElementsByTagName('img')[0]; this.reportImg = this.shadowRoot?.querySelector('.report')?.getElementsByTagName('img')[0]; - this.sendImg = document.querySelector("body > sp-application")!.shadowRoot!.querySelector("#sp-ai-analysis")!.shadowRoot?.querySelector("div.chatInputBox > div.chatInput > img"); - this.newChatEl = document.querySelector("body > sp-application")!.shadowRoot!.querySelector("#sp-ai-analysis")!.shadowRoot?.querySelector("div.chatBox > div > div.chatInputBox > div.chatConfig > div > div.newChat > img"); + this.sendImg = document.querySelector('body > sp-application')!.shadowRoot!.querySelector('#sp-ai-analysis')!.shadowRoot?.querySelector('div.chatInputBox > div.chatInput > img'); + this.newChatEl = document.querySelector("body > sp-application")!.shadowRoot!.querySelector("#sp-ai-analysis")!.shadowRoot?.querySelector("div.chatBox > div > div.ask_question > div.chatInputBox > div.chatConfig > div > div.newChat > img"); // 诊断按钮 this.draftBtn = this.shadowRoot?.querySelector('.analysisBtn'); // 下载报告按钮 @@ -81,11 +99,11 @@ export class SpAiAnalysisPage extends BaseElement { // 报告列表 this.draftList = this.shadowRoot?.querySelector('.data-record'); // 空数据页面 - this.noDataEl = this.shadowRoot?.querySelector('.no-data'); - // 未连接提示弹窗 - this.loginTipEl = this.shadowRoot?.querySelector('.loginTip'); + this.tipsContent = this.shadowRoot?.querySelector('.tips-content'); // 时间展示区域 this.startTimeEl = this.shadowRoot?.querySelector('.startTime'); + // 诊断信息汇总列表 + this.contentsTable = this.shadowRoot?.querySelector('#tb-contents'); this.startTimeEl!.innerHTML = getTimeString(TraceRow.range?.startNS!); this.endTimeEl = this.shadowRoot?.querySelector('.endTime'); this.endTimeEl!.innerHTML = getTimeString(TraceRow.range?.endNS!); @@ -93,14 +111,24 @@ export class SpAiAnalysisPage extends BaseElement { // 发送消息图标点击事件 this.sendImg?.addEventListener('click', () => { this.sendMessage(); - }) + }); // 新建对话按钮点击事件 this.newChatEl?.addEventListener('click', () => { this.isNewChat = true; + this.isResultBack = true; this.token = ''; - this.askQuestion!.innerHTML = ''; + this.q_a_window!.innerHTML = ''; this.createAiChatBox('有什么可以帮助您的吗?'); + }); + + //通过右上角的‘X’按钮关闭窗口 + //@ts-ignore + closeBtn?.addEventListener('click', () => { + //@ts-ignore + aiAssistant?.style.visibility = 'hidden'; + //@ts-ignore + aiAssistant?.style.display = 'none'; }) // 输入框发送消息 @@ -128,13 +156,13 @@ export class SpAiAnalysisPage extends BaseElement { this.inputEl?.addEventListener('blur', () => { SpSystemTrace.isAiAsk = false; - }) + }); // 监听浏览器刷新,清除db数据 - window.onbeforeunload = function () { + window.onbeforeunload = function (): void { caches.delete(`${window.localStorage.getItem('fileName')}.db`); sessionStorage.removeItem('fileName'); - } + }; // 监听ctrl抬起 this.inputEl?.addEventListener('keyup', (e) => { @@ -144,25 +172,32 @@ export class SpAiAnalysisPage extends BaseElement { }); // 下载诊断报告按钮监听 - this.downloadBtn?.addEventListener('click', (e) => { + this.downloadBtn?.addEventListener('click', () => { let a = document.createElement('a'); a.href = URL.createObjectURL(new Blob([this.reportContent])); a.download = window.sessionStorage.getItem('fileName')! + '诊断报告'; a.click(); - }) + }); - // 诊断按钮 - this.draftBtn?.addEventListener('click', async (e) => { - // 取消已经存在的诊断 + this.draftBtn?.addEventListener('click', async () => { this.draftList!.innerHTML = ''; + this.contentsTable!.style.display = 'none'; + this.tipsContainer!.style.display = 'none'; + this.tipsContent!.style.display = 'none'; + this.downloadBtn!.style.display = 'none'; // 没有登陆,弹窗提示,退出逻辑 if (!WebSocketManager.getInstance()?.isReady()) { - this.loginTipEl!.style.visibility = 'visible'; - setTimeout(() => { - this.loginTipEl!.style.visibility = 'hidden'; - }, 1000); + this.tipsContent!.style.display = 'flex'; + let guideSrc = `https://${window.location.host.split(':')[0]}:${window.location.port + }/application/?action=help_27`; + let linkNodeTips = `未连接,请启动本地扩展程序再试![指导]`; + this.abnormalPageTips(linkNodeTips, '', 4000); return; } + // 清空诊断报告的内容 + this.reportContent = ''; + // 隐藏诊断按钮 + this.draftBtn!.style.display = 'none'; // 同一个trace非第一次诊断,无需再发db文件过去 if (SpAiAnalysisPage.isRepeatedly) { this.initiateDiagnosis(); @@ -174,25 +209,27 @@ export class SpAiAnalysisPage extends BaseElement { caches.match(`${fileName}.db`).then(async (res) => { if (!res) { this.cacheDb(fileName); + } else { + WebSocketManager.getInstance()!.sendMessage( + TypeConstants.DIAGNOSIS_TYPE, + TypeConstants.SENDDB_CMD, + new TextEncoder().encode(await res!.text()) + ); } - WebSocketManager.getInstance()!.sendMessage(TypeConstants.DIAGNOSIS_TYPE, TypeConstants.SENDDB_CMD, new TextEncoder().encode(await res!.text())); }); }; - // 隐藏nodata - this.noDataEl!.style.display = 'none'; - // 加载中的loading模块 - let loadingDiv = document.createElement('div'); - loadingDiv.className = 'loadingBox'; - loadingDiv.innerHTML = ''; - let loadingItem = document.createElement('div'); - loadingItem.className = 'loadingItem'; - this.loadingItem = loadingItem; - loadingItem!.appendChild(loadingDiv); - this.draftList?.appendChild(loadingItem); - }) + // 点击一键诊断时先挂载loading + this.loadingItem = this.loading('style="position:absolute;top:45%;left:45%;z-index:999"'); + this.draftList?.appendChild(this.loadingItem!); + }); // 侧边栏诊断点击事件 *************优化,考虑多个按钮 this.reportBar!.addEventListener('click', () => { + if (!SpApplication.isTraceLoaded) { + let importTraceTips = '请先导入trace,再使用诊断功能'; + this.abnormalPageTips(importTraceTips, '', 4000); + return; + } this.reportImg!.src = 'img/report_active.png'; this.chatImg!.src = 'img/talk.png'; this.reportBar!.classList.add('active'); @@ -200,9 +237,9 @@ export class SpAiAnalysisPage extends BaseElement { //@ts-ignore this.askQuestion!.style.display = 'none'; //@ts-ignore - chatInputBox!.style.display = 'none'; - //@ts-ignore reportDetails!.style.display = 'block'; + this.tipsContent!.style.display = this.isNodata ? 'flex' : 'none'; + this.tipsContainer!.style.display = 'none'; }); // 侧边栏聊天点击事件 @@ -214,62 +251,108 @@ export class SpAiAnalysisPage extends BaseElement { //@ts-ignore this.askQuestion!.style.display = 'block'; //@ts-ignore - chatInputBox!.style.display = 'block'; - //@ts-ignore reportDetails!.style.display = 'none'; + this.tipsContainer!.style.display = 'none'; }); + // 监听表格目录row点击事件,跳转至对应问题行 + this.contentsTable!.addEventListener('row-click', (evt) => { + // @ts-ignore + let index = evt.detail.id; + let targets: any = this.draftList?.querySelectorAll('.title'); + // 目录的(index - 1)对应诊断返回的问题数组下标 + let target = targets[index - 1]; + if (target) { + // 改变滚动条滚动高度,实现点击目录跳转到对应问题 + this.shadowRoot!.querySelector('.analysisList')!.scrollTop = target.parentElement.offsetTop - TITLE_HEIGHT; + } + }); + } + // 加载中的loading模块 + loading(styleStr: string): HTMLDivElement { + let loadingDiv = document.createElement('div'); + loadingDiv.className = 'loadingBox'; + // 动态渲染Loading的样式 + loadingDiv.innerHTML = ``; + let loadingItem = document.createElement('div'); + loadingItem.className = 'loadingItem'; + loadingItem!.appendChild(loadingDiv); + return loadingItem } - // 点击诊断之后,重置 - reset() { + // 重新导trace、db时,初始化诊断功能 + clear(): void { + // 判断是否有上一次未完成的优化建议请求,如果有则断掉 + if (SpStatisticsHttpUtil.controllersMap.size > 0) { + SpStatisticsHttpUtil.isInterrupt = true; + this.breakRequest(); + } + this.contentsTable!.style.display = 'none'; + this.draftList!.innerHTML = ''; this.reportContent = ''; this.downloadBtn!.style.display = 'none'; + this.draftBtn!.style.display = 'inline-block'; + let chatBar = this.shadowRoot?.querySelector('.chatBar'); + let reportDetails = this.shadowRoot?.querySelector('.report_details'); + this.reportImg!.src = 'img/report.png'; + this.chatImg!.src = 'img/talk_active.png'; + this.reportBar!.classList.remove('active'); + chatBar!.classList.add('active'); + //@ts-ignore + this.askQuestion!.style.display = 'block'; + //@ts-ignore + reportDetails!.style.display = 'none'; + this.tipsContainer!.style.display = 'none'; + this.tipsContent!.style.display = 'flex'; + this.isNodata = true; } // 发送消息 - async sendMessage() { - if (this.inputEl!.value != '') { + async sendMessage(): Promise { + if (!this.isResultBack) { + return; + } + if (this.inputEl!.value !== '') { + this.isResultBack = false; if (this.isNewChat) { this.isNewChat = false; } this.question = JSON.parse(JSON.stringify(this.inputEl!.value)); this.createChatBox(); this.createAiChatBox('AI智能分析中...'); - this.chatWindow!.scrollTop = this.chatWindow!.scrollHeight; + this.q_a_window!.scrollTop = this.q_a_window!.scrollHeight; // 没有token if (this.token === '') { - this.token = await SpStatisticsHttpUtil.getAItoken(); - if (this.token === '') { - this.aiAnswerBox!.firstElementChild!.innerHTML = '获取token失败'; - return; - } + await this.getToken90Min(true); } this.answer(); } } // ai对话 - async answer() { + async answer(): Promise { let requestBody = { token: this.token, question: this.question, collection: 'smart_perf_test', scope: 'smartperf' }; - let answer = await SpStatisticsHttpUtil.askAi(requestBody); - if (answer !== '') { - if (!this.isNewChat) { - // @ts-ignore - this.aiAnswerBox!.firstElementChild!.innerHTML = this.md!.render(answer); - // 滚动条滚到底部 - this.chatWindow!.scrollTop = this.chatWindow!.scrollHeight; - } - } else { - this.aiAnswerBox!.firstElementChild!.innerHTML = '服务器异常'; - this.chatWindow!.scrollTop = this.chatWindow!.scrollHeight; + let answer = await (await SpStatisticsHttpUtil.askAi(requestBody)); + if (answer.status === 200) { + SpStatisticsHttpUtil.generalRecord('AI_statistic', 'large_model_q&a', []); } + if (!this.isNewChat) { + // @ts-ignore + this.aiAnswerBox!.firstElementChild!.innerHTML = this.md!.render(answer.data); + let likeDiv = document.createElement('div'); + likeDiv.className = 'likeDiv'; + likeDiv.innerHTML = ''; + this.aiAnswerBox?.appendChild(likeDiv); + // 滚动条滚到底部 + this.q_a_window!.scrollTop = this.q_a_window!.scrollHeight; + } + this.isResultBack = true; } // 创建用户聊天对话气泡 @@ -279,13 +362,9 @@ export class SpAiAnalysisPage extends BaseElement { headerDiv.className = 'userHeader headerDiv'; // 生成聊天内容框 let newQuestion = document.createElement('div'); - newQuestion.className = "usersay"; + newQuestion.className = 'usersay'; // @ts-ignore newQuestion!.innerHTML = this.inputEl!.value; - // 生成聊天气泡三角 - let triangleDiv = document.createElement('div'); - newQuestion.appendChild(triangleDiv); - triangleDiv.className = 'userTriangle'; // 单条消息模块,最大的div,包含头像、消息、清除浮动元素 let newMessage = document.createElement('div'); newMessage.className = 'usermessage message'; @@ -296,22 +375,19 @@ export class SpAiAnalysisPage extends BaseElement { let claerDiv = document.createElement('div'); claerDiv.className = 'clear'; newMessage.appendChild(claerDiv); - this.askQuestion?.appendChild(newMessage); + this.q_a_window?.appendChild(newMessage); } // 创建ai助手聊天对话气泡 - createAiChatBox(aiText: string) { + createAiChatBox(aiText: string): void { // 生成ai头像 let headerDiv = document.createElement('div'); headerDiv.className = 'aiHeader headerDiv'; - headerDiv.innerHTML = `` + headerDiv.innerHTML = ``; let newQuestion = document.createElement('div'); - newQuestion.className = "systemSay"; + newQuestion.className = 'systemSay'; // @ts-ignore newQuestion!.innerHTML = `
${aiText}
`; - let triangleDiv = document.createElement('div'); - newQuestion.appendChild(triangleDiv); - triangleDiv.className = 'aiTriangle'; let newMessage = document.createElement('div'); newMessage.className = 'aiMessage message'; newMessage.appendChild(headerDiv); @@ -320,74 +396,213 @@ export class SpAiAnalysisPage extends BaseElement { claerDiv.className = 'clear'; this.aiAnswerBox = newQuestion; newMessage.appendChild(claerDiv); - this.askQuestion?.appendChild(newMessage); + this.q_a_window?.appendChild(newMessage); } // 页面渲染诊断结果 - async renderData(dataList: any) { + async renderData(dataList: unknown): Promise { + //生成表格导航 + //@ts-ignore + this.renderTblNav(dataList); + // @ts-ignore for (let i = 0; i < dataList.length; i++) { let itemDiv = document.createElement('div'); - itemDiv!.style.visibility = 'hidden'; itemDiv.className = 'analysisItem'; // 生成标题 let titleDiv = document.createElement('div'); titleDiv.className = 'title item-name'; - titleDiv!.innerText = `问题${i + 1}:${dataList[i].type}`; + titleDiv!.innerText = `问题${i + 1}`; + // 生成一键置顶 + let topUp = document.createElement('div'); + topUp.className = 'top-up-image'; + titleDiv.appendChild(topUp); + topUp.addEventListener('click', (e) => { + this.shadowRoot!.querySelector('.analysisList')!.scrollTop = 0; + }) + // 生成类型 + let typeDiv = document.createElement('div'); + typeDiv.className = 'item'; + // @ts-ignore + typeDiv.innerHTML = `问题类型:${dataList[i].type}` // 生成时间 let timeDiv = document.createElement('div'); - timeDiv.className = 'item two'; - // 获取每一个诊断项的时间 + timeDiv.className = 'item two timeDiv'; + timeDiv!.innerHTML = `发生时间:`; let timeList = new Array(); - dataList[i].trace_info.forEach((v: any) => { - timeList.push(getTimeString(v.ts / 1000000)); + // @ts-ignore + dataList[i].trace_info.forEach((v: any, index: number) => { + let timeSpan = document.createElement('span'); + timeSpan.id = v.id; + timeSpan.className = 'timeItem'; + timeSpan.setAttribute('name', v.name); + timeSpan.innerHTML = `[${v.ts! / 1000000000}s] ,`; + timeDiv.appendChild(timeSpan); + timeList.push(v.ts! / 1000000000 + 's'); }); - timeDiv!.innerHTML = `发生时间:${timeList.join(',')}` // 生成问题原因 let reasonDiv = document.createElement('div'); reasonDiv.className = 'item'; - reasonDiv!.innerHTML = `问题原因:${dataList[i].description}`; + // @ts-ignore + reasonDiv!.innerHTML = `问题原因:${dataList[i].description}`; itemDiv.appendChild(titleDiv); + itemDiv.appendChild(typeDiv); itemDiv.appendChild(timeDiv); itemDiv.appendChild(reasonDiv); + this.timeClickHandler(timeDiv); // 生成优化建议 let suggestonDiv = document.createElement('div'); suggestonDiv.className = 'item two'; - let suggestionText = ''; - this.token = await SpStatisticsHttpUtil.getAItoken(); - suggestionText = await this.getSuggestion(dataList[i].description, itemDiv, suggestonDiv); - this.reportContent += `问题${i + 1}:${dataList[i].type}\n\n时间:${timeList.join(',')}\n\n问题原因:${dataList[i].description}\n\n优化建议:${suggestionText}\n\n\n`; + let suggestonTitle = document.createElement('span'); + suggestonTitle.className = 'item-name'; + suggestonTitle.textContent = '优化建议:'; + suggestonDiv!.appendChild(suggestonTitle); + suggestonDiv!.appendChild(this.loading('')); + itemDiv!.appendChild(suggestonDiv); + if (this.token === '') { + await this.getToken90Min(false); + } + // @ts-ignore + this.getSuggestion(dataList, i, itemDiv, suggestonDiv, timeList); + // @ts-ignore } - this.loadingItem!.style.display = 'none'; - this.downloadBtn!.style.display = 'inline-block'; + this.draftList?.removeChild(this.loadingItem!); + } + + // Table数据渲染 + renderTblNav(dataList: unknown): void { + this.contentsTable!.recycleDataSource = []; + this.contentsTable!.style.display = 'block'; + // 修改Tbl样式 + let th = this.contentsTable!.shadowRoot!.querySelector("div.table > div.thead > div")! as HTMLElement; + th.style.backgroundColor = '#8bbcdff7'; + // @ts-ignore + let source = dataList.map((item: unknown, index: number) => { + // @ts-ignore + return { ...item, id: index + 1 } + }) + this.contentsTable!.recycleDataSource = source; + } + + connectedCallback(): void { + super.connectedCallback(); + let tbody = this.contentsTable!.shadowRoot!.querySelector('.table') as HTMLElement; + tbody.style.height = TBODY_HEIGHT + 'px'; + } + + async getToken(isChat?: boolean) { + let data = await SpStatisticsHttpUtil.getAItoken(); + if (data.status !== 200) { + if (isChat) { + this.aiAnswerBox!.firstElementChild!.innerHTML = '获取token失败'; + } + return; + } else { + this.token = data.data; + } + } + + //控制页面异常场景的显示 + abnormalPageTips(tipStr: string, imgSrc: string, setTimeoutTime: number): void { + this.tipsContainer!.style.display = 'flex'; + this.tipsContainer!.innerHTML = ''; + if (imgSrc !== '') { + let mixedTipsBox = document.createElement('div'); + mixedTipsBox.className = 'mixedTips'; + let mixedImg = document.createElement('img'); + mixedImg.src = imgSrc; + let mixedText = document.createElement('div'); + mixedText.className = 'mixedText'; + mixedText.innerHTML = tipStr; + mixedTipsBox.appendChild(mixedImg); + mixedTipsBox.appendChild(mixedText); + this.tipsContainer!.appendChild(mixedTipsBox); + } else { + let textTipsBox = document.createElement('div'); + textTipsBox.className = 'textTips'; + textTipsBox!.innerHTML = tipStr; + this.tipsContainer!.appendChild(textTipsBox); + } + if (setTimeoutTime) { + setTimeout(() => { + this.tipsContainer!.style.display = 'none'; + }, setTimeoutTime); + } + } + + // 每90min重新获取token + async getToken90Min(isChat: boolean) { + await this.getToken(isChat); + await setInterval(async () => { + await this.getToken(isChat); + }, 5400000); } // 发送请求获取优化建议并渲染页面 - async getSuggestion(description: string, itemDiv: HTMLDivElement | null | undefined, suggestonDiv: HTMLDivElement | null | undefined) { - let suggestion = await SpStatisticsHttpUtil.askAi({ - token: this.token, - question: description + ',请问该怎么优化?', + getSuggestion(dataList: unknown, i: number, itemDiv: HTMLDivElement | null | undefined, suggestonDiv: HTMLDivElement | null | undefined, timeList: Array): void { + SpStatisticsHttpUtil.askAi({ + token: this.token,// @ts-ignore + question: dataList[i].description + ',请问该怎么优化?', collection: '' - }); - suggestonDiv!.innerHTML = `优化建议:${suggestion}`; - itemDiv!.appendChild(suggestonDiv!); - // 吧loading放到最后面 - this.draftList!.insertBefore(itemDiv!, this.loadingItem!); - itemDiv!.style.visibility = 'visible'; + }).then((suggestion) => { + this.appendMsg(dataList, i, suggestonDiv, timeList, suggestion); + }).catch((error) => { + this.appendMsg(dataList, i, suggestonDiv, timeList, error); + }) + this.draftList!.appendChild(itemDiv!); itemDiv!.style.animation = 'opcityliner 3s'; - return suggestion; } - cacheDb(fileName: string | null) { + // 优化建议msg处理并渲染 + appendMsg(dataList: unknown, i: number, suggestonDiv: HTMLDivElement | null | undefined, timeList: Array, suggestion: aiResponse) { + // 保证controllersMap里面存的是未完成的请求,并规避重新打开trace时异步msg未请求完毕引入的问题 + if (SpStatisticsHttpUtil.controllersMap.has(suggestion.time!)) { + SpStatisticsHttpUtil.controllersMap.delete(suggestion.time!); + } + if (SpStatisticsHttpUtil.isInterrupt) { + if (SpStatisticsHttpUtil.controllersMap.size === 0) { + SpStatisticsHttpUtil.isInterrupt = false; + } + return; + } + // @ts-ignore + this.reportContent += `问题${i + 1}:${dataList[i].type}\n\n时间:${timeList.join(',')}\n\n问题原因:${dataList[i].description}\n\n优化建议:${suggestion.data}\n\n\n`; + let msgdiv = document.createElement('div'); + msgdiv.className = 'msgdiv'; + //@ts-ignore + msgdiv!.innerHTML = `${this.md!.render(suggestion.data)}`; + suggestonDiv?.removeChild(suggestonDiv.lastElementChild!); + let likeDiv = document.createElement('div'); + likeDiv.className = 'likeDiv'; + // @ts-ignore + likeDiv.innerHTML = ``; + suggestonDiv!.appendChild(msgdiv); + suggestonDiv!.appendChild(likeDiv); + // @ts-ignore + if ((dataList.length - 1) === i) { + this.draftBtn!.style.display = 'inline-block'; + this.downloadBtn!.style.display = 'inline-block'; + } + } + + // 取消或中断请求 + breakRequest() { + for (const controller of SpStatisticsHttpUtil.controllersMap.values()) { + controller.abort(); + } + } + + cacheDb(fileName: string | null): void { threadPool.submit( 'download-db', '', {}, (reqBufferDB: Uint8Array) => { + WebSocketManager.getInstance()!.sendMessage(TypeConstants.DIAGNOSIS_TYPE, TypeConstants.SENDDB_CMD, reqBufferDB); // 存入缓存 caches.open(`${fileName}.db`).then((cache) => { let headers = new Headers(); headers.append('Content-Type', 'application/octet-stream'); - headers.append('Content-Transfer-Encoding', 'binary') + headers.append('Content-Transfer-Encoding', 'binary'); return cache .put( `${fileName}.db`, @@ -402,7 +617,8 @@ export class SpAiAnalysisPage extends BaseElement { } // websocket通信回调注册 - webSocketCallBack = (cmd: number, result: Uint8Array) => { + // @ts-ignore + webSocketCallBack = async (cmd: number, result: Uint8Array): unknown => { const decoder = new TextDecoder(); const jsonString = decoder.decode(result); let jsonRes = JSON.parse(jsonString); @@ -410,29 +626,87 @@ export class SpAiAnalysisPage extends BaseElement { if (cmd === 2) { SpAiAnalysisPage.isRepeatedly = true; this.initiateDiagnosis(); + if (jsonRes.resultCode !== 0) { + this.draftBtn!.style.display = 'inline-block'; + } } - // 诊断结果,resultCode===0:失败;resultCode===1:成功 + // 诊断结果,resultCode===1:失败;resultCode===0:成功 if (cmd === 4) { // 需要处理 if (jsonRes.resultCode !== 0) { - console.log('错误'); + this.isNodata = true; + this.draftList!.innerHTML = ''; + this.contentsTable!.style.display = 'none'; + let textStr = '服务异常'; + let imgsrc = 'img/no-report.png'; + this.tipsContent!.style.display = 'none'; + this.abnormalPageTips(textStr, imgsrc, 0); + this.draftBtn!.style.display = 'inline-block'; + } + if (this.isJsonString(jsonRes.resultMessage)) { + let dataList = JSON.parse(jsonRes.resultMessage) || []; + if (dataList && dataList.length === 0) { + SpStatisticsHttpUtil.generalRecord('AI_statistic', 'large_model_detect', [0]) + this.isNodata = true; + this.draftList!.innerHTML = ''; + this.contentsTable!.style.display = 'none'; + let textStr = '当前未诊断出问题'; + let imgsrc = 'img/no-report.png'; + this.tipsContent!.style.display = 'none'; + this.abnormalPageTips(textStr, imgsrc, 0); + this.draftBtn!.style.display = 'inline-block'; + } else { + SpStatisticsHttpUtil.generalRecord('AI_statistic', 'large_model_detect', [1]); + this.isNodata = false; + // 整理数据,渲染数据 + await this.renderData(dataList); + } } - let dataList = JSON.parse(jsonRes.resultMessage); - // 整理数据,渲染数据 - this.renderData(dataList); } } // 发起诊断 - initiateDiagnosis() { + initiateDiagnosis(): void { let requestBodyObj = { - type: 0 - } + startTime: Math.round(SpAiAnalysisPage.startTime + Utils.getInstance().getRecordStartNS()), + endTime: Math.round(SpAiAnalysisPage.endTime + Utils.getInstance().getRecordStartNS()) + }; let requestBodyString = JSON.stringify(requestBodyObj); let requestBody = new TextEncoder().encode(requestBodyString); WebSocketManager.getInstance()!.sendMessage(TypeConstants.DIAGNOSIS_TYPE, TypeConstants.DIAGNOSIS_CMD, requestBody); } + // 点击时间跳转 + timeClickHandler(timeDiv: HTMLDivElement) { + let timeElementList = timeDiv!.getElementsByClassName('timeItem'); + for (let i = 0; i < timeElementList.length; i++) { + timeElementList[i].addEventListener('click', (e) => { + // 点击项更换颜色 + timeElementList[i].getElementsByClassName('timeText')[0].setAttribute('active', '') + let name = timeElementList[i].getAttribute('name'); + let id = Number(timeElementList[i].getAttribute('id')); + // 其他项重置颜色 + for (let j = 0; j < timeElementList.length; j++) { + if (i !== j) { + timeElementList[j].getElementsByClassName('timeText')[0].removeAttribute('active'); + } + } + // @ts-ignore + this.valueChangeHandler!(name, id); + }) + } + } + + // 判断是否为json + isJsonString(str: string) { + try { + JSON.parse(str); + } catch (e) { + return false; + } + return true; + } + initHtml(): string { return SpAiAnalysisPageHtml; } diff --git a/ide/src/trace/component/SpBubblesAI.html.ts b/ide/src/trace/component/SpBubblesAI.html.ts index fe6bb2c23927dff6ea80a938241a45321517fae1..5ab208c8f0e43797803b6854224e517d70f8da33 100644 --- a/ide/src/trace/component/SpBubblesAI.html.ts +++ b/ide/src/trace/component/SpBubblesAI.html.ts @@ -22,6 +22,10 @@ export const SpBubblesAIHtml = `
-
`; diff --git a/ide/src/trace/component/SpBubblesAI.ts b/ide/src/trace/component/SpBubblesAI.ts index 64aa9e5ef3ddbb71ab26022724594ae0b9fe823d..9e03b84eb4674fa4fc433232b20477d086155934 100644 --- a/ide/src/trace/component/SpBubblesAI.ts +++ b/ide/src/trace/component/SpBubblesAI.ts @@ -20,6 +20,7 @@ import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil @element('sp-bubble-ai') export class SpBubblesAI extends BaseElement { + static isAIHover: boolean = false; initElements(): void { const xiaoLubanEl: HTMLElement | undefined | null = this.shadowRoot?.querySelector('#xiao-luban-help'); xiaoLubanEl?.addEventListener('click', () => { @@ -29,13 +30,23 @@ export class SpBubblesAI extends BaseElement { event: 'AItrace' }; SpStatisticsHttpUtil.addOrdinaryVisitAction(requestBody); + SpStatisticsHttpUtil.generalRecord('AI_statistic', 'smart_luban', []); }); - let isShowXiaoLuban: boolean = FlagsConfig.getFlagsConfigEnableStatus('xiaoLuBan'); + let isShowXiaoLuban: boolean = FlagsConfig.getFlagsConfigEnableStatus('AI'); if (isShowXiaoLuban) { xiaoLubanEl?.setAttribute('enabled', ''); } else { xiaoLubanEl?.removeAttribute('enabled'); } + // 鼠标进入元素 + xiaoLubanEl?.addEventListener('mouseenter', function () { + SpBubblesAI.isAIHover = true; + }); + + // 鼠标离开元素 + xiaoLubanEl?.addEventListener('mouseleave', function () { + SpBubblesAI.isAIHover = false; + }); } initHtml(): string { diff --git a/ide/src/trace/component/SpFlags.ts b/ide/src/trace/component/SpFlags.ts index 8baafef9324ce5b0aed66099fc6c834a9768b81d..0d9617dc54a564e87e8279c0dd7d798c3b6f44cb 100644 --- a/ide/src/trace/component/SpFlags.ts +++ b/ide/src/trace/component/SpFlags.ts @@ -20,7 +20,7 @@ const NUM = '000000'; const VSYNC_CONTENT = [ { value: 'H:VsyncGenerator', content: 'VsyncGeneratior' }, { value: 'H:rs_SendVsync', content: 'Vsync-rs' }, - { value: 'H:rs_SendVsync', content: 'Vsync-app' } + { value: 'H:app_SendVsync', content: 'Vsync-app' } ]; //cat二级下拉选框对应的value和content const CAT_CONTENT = [ diff --git a/ide/src/trace/component/SpHelp.ts b/ide/src/trace/component/SpHelp.ts index 229f9c915fc23c3ed05a629fa1866a30837845fc..11e7a02093a02460cf3fbcc924b048bf853ad3ac 100644 --- a/ide/src/trace/component/SpHelp.ts +++ b/ide/src/trace/component/SpHelp.ts @@ -53,8 +53,10 @@ export class SpHelp extends BaseElement { let mainMenu = this.shadowRoot?.querySelector('#main-menu') as LitMainMenu; let header = mainMenu.shadowRoot?.querySelector('.header') as HTMLDivElement; let color = mainMenu.shadowRoot?.querySelector('.customColor') as HTMLDivElement; + let analysis = mainMenu.shadowRoot?.querySelector('.ai_analysis') as HTMLDivElement; let version = mainMenu.shadowRoot?.querySelector('.version') as HTMLDivElement; color.style.display = 'none'; + analysis.style.display = 'none'; header.style.display = 'none'; version.style.display = 'none'; this.setupMainMenu(mainMenu, this); @@ -214,6 +216,8 @@ export class SpHelp extends BaseElement { this.createSubMenuItem('Trace解析能力增强', 'trace_parsing', 'quickstart_parsing_ability', that, '23'), this.createSubMenuItem('应用操作技巧', 'operation_skills', 'quickstart_Application_operation_skills', that, '24'), this.createSubMenuItem('快捷键说明', 'keywords_shortcuts', 'quickstart_keywords_shortcuts', that, '25'), + this.createSubMenuItem('Xpower抓取和展示说明', 'xpower', 'quickstart_xpower', that, '26'), + this.createSubMenuItem('扩展程序安装指导', 'extensions', 'quickstart_extensions', that, '27'), ]; } @@ -453,7 +457,7 @@ export class SpHelp extends BaseElement { title: 'TraceStreamer数据库说明', icon: '', clickHandler: function (item: MenuItem): void { - that.handleMemoryMenuItemClick(that, 'trace_streamer_explain', 'des_tables', '26'); + that.handleMemoryMenuItemClick(that, 'trace_streamer_explain', 'des_tables', '28'); }, }; } diff --git a/ide/src/trace/component/SpRecordConfigModel.ts b/ide/src/trace/component/SpRecordConfigModel.ts index c49ba3c8071ff7d25cc92825988629d4d1dcfd98..01cb2789b1bd4be3f82dcbeb7e5e1bea036fb028 100644 --- a/ide/src/trace/component/SpRecordConfigModel.ts +++ b/ide/src/trace/component/SpRecordConfigModel.ts @@ -670,7 +670,7 @@ export function createHiPerfConfig( } } } else { - recordArgs = `${recordArgs} -a `; + recordArgs = `${recordArgs} -a --exclude-hiperf`; } recordArgs = initHiPerfConfig(perfConfig, recordArgs); info('record config Args is: ', recordArgs); @@ -914,10 +914,10 @@ export function createXPowerConfig( } let type = spXPower.getXpowerConfig(); let typeList: Array = []; - typeList = type!.split(","); + typeList = type!.split(','); let xPowerConfig = { messageType: typeList - } + }; request.pluginConfigs.push({ pluginName: 'xpower-plugin', sampleInterval: 1000, diff --git a/ide/src/trace/component/SpSystemTrace.event.ts b/ide/src/trace/component/SpSystemTrace.event.ts index cded71deb44aad2208bf002cb5c05e5e4ce0d949..23e16b713eec7ff206f7cbfd43343e3e4dd20aba 100644 --- a/ide/src/trace/component/SpSystemTrace.event.ts +++ b/ide/src/trace/component/SpSystemTrace.event.ts @@ -53,7 +53,7 @@ import { Utils } from './trace/base/Utils'; import { BaseStruct } from '../bean/BaseStruct'; import { GpuCounterStruct, gpuCounterStructOnClick } from '../database/ui-worker/ProcedureWorkerGpuCounter'; import { HangStructOnClick } from '../database/ui-worker/ProcedureWorkerHang'; -import { XpowerStruct, XpowerStructOnClick } from '../database/ui-worker/ProcedureWorkerXpower'; +import { XpowerStruct, XpowerStructOnClick } from '../database/ui-worker/ProcedureWorkerXpower'; import { SpAiAnalysisPage } from './SpAiAnalysisPage'; function timeoutJudge(sp: SpSystemTrace): number { @@ -419,7 +419,10 @@ function allStructOnClick(clickRowType: string, sp: SpSystemTrace, row?: TraceRo }) .catch((e): void => { }); // @ts-ignore - SpAiAnalysisPage.selectChangeListener(entry.startTime || entry.startTs, (entry.startTime! || entry.startTs) + entry.dur) + if (entry && entry.dur && (entry.startTime! || entry.startTs)) { + // @ts-ignore + SpAiAnalysisPage.selectChangeListener(entry.startTime || entry.startTs, (entry.startTime! || entry.startTs) + entry.dur); + } } export default function spSystemTraceOnClickHandler( sp: SpSystemTrace, @@ -436,7 +439,10 @@ export default function spSystemTraceOnClickHandler( if (!sp.loadTraceCompleted) { return; } - sp.queryAllTraceRow().forEach((it): boolean => (it.rangeSelect = false)); + sp.queryAllTraceRow().forEach(it => { + it.checkType = '-1'; + it.rangeSelect = false; + }); sp.selectStructNull(); sp._slicesList.forEach((slice: { selected: boolean }): void => { slice.selected = false; @@ -495,7 +501,7 @@ function handleMouseInTimeShaft(sp: SpSystemTrace, ev: MouseEvent): boolean | un export function spSystemTraceDocumentOnMouseMove(sp: SpSystemTrace, ev: MouseEvent): void { //@ts-ignore - if (!sp.loadTraceCompleted || (window as unknown).flagInputFocus || !sp.mouseEventEnable) { + if (!sp.loadTraceCompleted || !sp.mouseEventEnable) { return; } //@ts-ignore @@ -602,6 +608,9 @@ export function spSystemTraceDocumentOnMouseOut(sp: SpSystemTrace, ev: MouseEven CpuStruct.hoverCpuStruct = undefined; TraceRow.isUserInteraction = false; SpSystemTrace.isMouseLeftDown = false; + if(!sp.keyboardEnable){ + return; + } if (sp.isMouseInSheet(ev)) { return; } @@ -792,17 +801,23 @@ export function spSystemTraceDocumentOnMouseUp(sp: SpSystemTrace, ev: MouseEvent } export function spSystemTraceDocumentOnKeyUp(sp: SpSystemTrace, ev: KeyboardEvent): void { + if (SpSystemTrace.isAiAsk) { + return; + } SpSystemTrace.isKeyUp = true; if (sp.times.size > 0) { for (let timerId of sp.times) { clearTimeout(timerId); } } + if(!sp.keyboardEnable){ + return; + } let flag: boolean = sp.parentElement ?.querySelector('sp-record-trace')! .shadowRoot?.querySelector('lit-main-menu-item[icon="file-config"]')! .hasAttribute('back')!; - if (ev.key.toLocaleLowerCase() === String.fromCharCode(47) && !flag) { + if (ev.key.toLocaleLowerCase() === String.fromCharCode(47) && !flag && !SpSystemTrace.isAiAsk) { if (SpSystemTrace.keyboardFlar) { document .querySelector('body > sp-application')! @@ -821,7 +836,7 @@ export function spSystemTraceDocumentOnKeyUp(sp: SpSystemTrace, ev: KeyboardEven let flagsItem = window.localStorage.getItem(FlagsConfig.FLAGS_CONFIG_KEY); let flagsItemJson = JSON.parse(flagsItem!); if (flagsItemJson.VSync === 'Enabled') { - sp.keyboardEnable && enableVSync(false, ev, () => sp.refreshCanvas(true, 'sp key up')); + enableVSync(false, ev, () => sp.refreshCanvas(true, 'sp key up')); } let keyPress = ev.key.toLocaleLowerCase(); if (keyPress === 'w' || keyPress === 'a' || keyPress === 's' || keyPress === 'd') { diff --git a/ide/src/trace/component/SpSystemTrace.init.ts b/ide/src/trace/component/SpSystemTrace.init.ts index 337a4c425960a80df130ebf2d36a5f5889b56e26..3ccb9bc579a9336315f90f13823773278a3665ac 100644 --- a/ide/src/trace/component/SpSystemTrace.init.ts +++ b/ide/src/trace/component/SpSystemTrace.init.ts @@ -22,7 +22,7 @@ import { SportRuler } from './trace/timer-shaft/SportRuler'; import { SelectionParam } from '../bean/BoxSelection'; import { error, info } from '../../log/Log'; import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil'; -import { queryEbpfSamplesCount } from '../database/sql/Memory.sql'; +import { queryEbpfSamplesCount, queryPlugins } from '../database/sql/Memory.sql'; import { SpChartManager } from './chart/SpChartManager'; import { ThreadStruct } from '../database/ui-worker/ProcedureWorkerThread'; import { FlagsConfig } from './SpFlags'; @@ -36,6 +36,99 @@ import { SpChartList } from './trace/SpChartList'; type HTMLElementAlias = HTMLElement | null | undefined; import { Utils } from './trace/base/Utils'; import { fuzzyQueryFuncRowData, queryFuncRowData } from '../database/sql/Func.sql'; +import { convertTitle } from './chart/SpXpowerChart'; + +// 所有插件以及对应的表 +const pluginArray = [ + { + pluginName: 'ftrace-plugin', + tables: [ + 'animation', 'app_startup', 'args', 'callstack', 'clk_event_filter', + 'clock_event_filter', 'cpu_measure_filter', 'device_info', 'dynamic_frame', 'frame_maps', + 'frame_slice', 'gpu_slice', 'instant', 'irq', 'process_measure_filter', 'process_measure', + 'sched_slice', 'static_initalize', 'symbols', 'syscall', 'task_pool', 'thread_state','dma_fence' + ] + }, + { + pluginName: 'hiperf-plugin', + tables: [ + 'perf_callchain', 'perf_files', 'perf_report', 'perf_sample', 'perf_thread' + ] + }, + { + pluginName: 'nativehook-plugin', + tables: [ + 'native_hook', 'native_hook_frame', 'native_hook_statistic' + ] + }, + { + pluginName: 'arkTs-plugin', + tables: [ + 'js_config', 'js_cpu_profiler_node', 'js_cpu_profiler_sample', 'js_heap_files', 'js_heap_info', 'js_heap_location', + 'js_heap_nodes', 'js_heap_sample', 'js_heap_string', 'js_heap_trace_function_info', 'js_heap_trace_node','js_heap_edges' + ] + }, + { + pluginName: 'memory-plugin', + tables: [ + 'memory_ashmem', 'memory_cpu', 'memory_dma', 'memory_process_gpu', 'memory_profile,', 'memory_rs_image', 'memory_window_gpu','smaps','sys_event_filter','sys_mem_measure' + ] + }, + { + pluginName: 'hisysevent-plugin', + tables: [ + 'app_name', 'device_state', 'hisys_all_event', 'hisys_event_measure' + ] + }, + { + pluginName: 'ebpf-plugin', + tables: [ + 'bio_latency_sample', 'ebpf_callstack', 'file_system_sample', 'paged_memory_sample' + ] + }, + { + pluginName: 'cpu-plugin', + tables: [ + 'cpu_usage' + ] + }, + { + pluginName: 'diskio-plugin', + tables: [ + 'diskio' + ] + }, + { + pluginName: 'hidump-plugin', + tables: [ + 'hidump' + ] + }, + { + pluginName: 'process-plugin', + tables: [ + 'live_process' + ] + }, + { + pluginName: 'hilog-plugin', + tables: [ + 'log' + ] + }, + { + pluginName: 'network-plugin', + tables: [ + 'network' + ] + }, + { + pluginName: 'xpower-plugin', + tables: [ + 'xpower_measure' + ] + } +] function rightButtonOnClick(sp: SpSystemTrace, rightStar: HTMLElementAlias): unknown { Object.assign(sp, { @@ -57,7 +150,7 @@ function rightButtonOnClick(sp: SpSystemTrace, rightStar: HTMLElementAlias): unk CpuStruct.selectCpuStruct!.ts = CpuStruct.selectCpuStruct!.startTime; CpuStruct.selectCpuStruct!.thread = CpuStruct.selectCpuStruct!.name; CpuStruct.selectCpuStruct!.pid = CpuStruct.selectCpuStruct!.processId; - CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim(); + CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim() || CpuStruct.selectCpuStruct!.processName; CpuStruct.selectCpuStruct!.itid = CpuStruct.wakeupBean!.itid; sessionStorage.setItem('saveselectcpustruct', JSON.stringify(CpuStruct.selectCpuStruct)); } else { @@ -67,7 +160,7 @@ function rightButtonOnClick(sp: SpSystemTrace, rightStar: HTMLElementAlias): unk CpuStruct.selectCpuStruct!.ts = CpuStruct.selectCpuStruct!.startTime; CpuStruct.selectCpuStruct!.thread = CpuStruct.selectCpuStruct!.name; CpuStruct.selectCpuStruct!.pid = CpuStruct.selectCpuStruct!.processId; - CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim(); + CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim() || CpuStruct.selectCpuStruct!.processName; CpuStruct.selectCpuStruct!.itid = CpuStruct.wakeupBean!.itid; sessionStorage.setItem('saveselectcpustruct', JSON.stringify(CpuStruct.selectCpuStruct)); } @@ -368,6 +461,13 @@ function collectHandlerNo(sp: SpSystemTrace, currentRow: unknown, event: unknown // 取消收藏时,删除父亲ID // @ts-ignore currentRow.name = currentRow.tampName; + //@ts-ignore xpower转换名称 + if (currentRow.rowType === 'xpower-system') { + //@ts-ignore + let titleEl = currentRow.shadowRoot?.querySelector('.name') as HTMLLabelElement; + //@ts-ignore + titleEl.title = convertTitle(currentRow.tampName); + } if (replaceRow !== null) { // @ts-ignore sp.rowsEL!.replaceChild(currentRow, replaceRow); @@ -428,6 +528,13 @@ function collectHandlerYes(sp: SpSystemTrace, currentRow: unknown, event: unknow // @ts-ignore sp.rowsEL!.replaceChild(replaceRow, currentRow); } + //@ts-ignore xpower转换名称 + if (currentRow.rowType === 'xpower-system') { + //@ts-ignore + let titleEl = currentRow.shadowRoot?.querySelector('.name') as HTMLLabelElement; + //@ts-ignore + titleEl.title = convertTitle(currentRow.tampName); + } // @ts-ignore let group = currentRow.traceId || sp.currentCollectGroup; // @ts-ignore @@ -517,6 +624,9 @@ function selectHandler(sp: SpSystemTrace): void { ...sp.favoriteChartListEL!.getAllSelectCollectRows(), ]; } + checkRows = checkRows.filter((item, index, self) => { //去重 + return self.findIndex(obj => obj.rowId === item.rowId && obj.rowType === item.rowType && obj.name === item.name) === index; + }); selectHandlerRefreshCheckBox(sp, checkRows, refreshCheckBox); if (!sp.isSelectClick) { sp.rangeTraceRow = []; @@ -759,6 +869,8 @@ export function spSystemTraceInitElement(sp: SpSystemTrace): void { sp.spacerEL = sp.shadowRoot.querySelector('.spacer'); sp.timerShaftEL = sp.shadowRoot.querySelector('.timer-shaft'); sp.favoriteChartListEL = sp.shadowRoot.querySelector('#favorite-chart-list'); + sp.collectEl1 = sp.favoriteChartListEL?.shadowRoot?.querySelector('#collect-group-1'); + sp.groupTitle1 = sp.favoriteChartListEL?.shadowRoot?.querySelector('#group-1-title'); if (!sp.traceSheetEL.shadowRoot) { return; } @@ -828,7 +940,25 @@ export function cancelCurrentTraceRowHighlight(sp: SpSystemTrace, currentEntry: if (!parentRow) { return; } - let filterRow = parentRow.childrenList.filter((child) => child.rowId === funcRowID && child.rowType === 'func')[0]; + // @ts-ignore + let filterRow: TraceRow | undefined; + parentRow.childrenList.forEach((item) => { + if (item.rowId === 'sameThreadProcess') { + filterRow = parentRow.childrenList.concat(item.childrenList).filter((child) => child.rowId === funcRowID && child.rowType === 'func')[0]; + } else { + filterRow = parentRow.childrenList.filter((child) => child.rowId === funcRowID && child.rowType === 'func')[0]; + } + }); + if (!filterRow) { + let rowsPaneEL = document.querySelector("body > sp-application")?.shadowRoot?.querySelector("#sp-system-trace")?.shadowRoot?.querySelector("div > div.rows-pane") + // @ts-ignore + let funcRow = rowsPaneEL?.querySelector>(`trace-row[row-id='${funcRowID}'][row-type='func']`); + if (funcRow) { + filterRow = funcRow; + } else { + return; + } + } filterRow.highlight = false; // @ts-ignore } else if (currentEntry?.type === 'sdk') { @@ -1143,6 +1273,23 @@ export async function spSystemTraceInit( } sp.intersectionObserver?.observe(it); }); + + for (let i = 0; i < pluginArray.length; i++) { + let item = pluginArray[i]; + for (let j = 0; j < item.tables.length; j++) { + let tableItem = item.tables[j] + let res = await queryPlugins(tableItem) || []; + if (res.length > 0) { + SpStatisticsHttpUtil.recordPlugin.push(item.pluginName); + break; + } else { + continue; + } + } + } + + // 统计插件 + SpStatisticsHttpUtil.recordPluginUsage(); // trace文件加载完毕,将动效json文件读取并存入缓存 let funDetailUrl = `https://${window.location.host.split(':')[0]}:${window.location.port }/application/doc/funDetail.json`; diff --git a/ide/src/trace/component/SpSystemTrace.line.ts b/ide/src/trace/component/SpSystemTrace.line.ts index d86c67df29fb3c70e9f62f220142b4741276c23c..7bcc1e0c9d91851d378797fc6d61018c57bdc85d 100644 --- a/ide/src/trace/component/SpSystemTrace.line.ts +++ b/ide/src/trace/component/SpSystemTrace.line.ts @@ -689,7 +689,7 @@ function jankPoint( let ts: number = 0; if (findJankEntry) { ts = selectThreadStruct.startTime! + selectThreadStruct.dur! / 2; - const [startY, startRowEl, startOffSetY] = sp.calculateStartY(startRow, selectThreadStruct.pid); + const [startY, startRowEl, startOffSetY] = sp.calculateStartY(startRow, selectThreadStruct.pid,selectThreadStruct.tid); const [endY, endRowEl, endOffSetY] = sp.calculateEndY(endParentRow, endRowStruct); sp.addPointPair( sp.makePoint( @@ -729,7 +729,7 @@ function junkBinder( let ts: number = 0; if (findJankEntry) { ts = selectFuncStruct.startTs! + selectFuncStruct.dur! / 2; - const [startY, startRowEl, startOffSetY] = sp.calculateStartY(startRow, selectFuncStruct.pid, selectFuncStruct); + const [startY, startRowEl, startOffSetY] = sp.calculateStartY(startRow, selectFuncStruct.pid, selectFuncStruct.tid, selectFuncStruct); const [endY, endRowEl, endOffSetY] = sp.calculateEndY(endParentRow, endRowStruct, data); sp.addPointPair( sp.makePoint( @@ -820,11 +820,21 @@ export function spSystemTraceDrawFuncLine( // @ts-ignore `trace-row[row-id='${data.tid}'][row-type='func']` ); - if (!endRowStruct) { - // @ts-ignore - endRowStruct = endParentRow.childrenList.find((item: TraceRow) => { - // @ts-ignore - return item.rowId === `${data.tid}` && item.rowType === 'func'; + if (!endRowStruct) {// @ts-ignore + endParentRow.childrenList.forEach((item) => { + if (item.rowId === 'sameThreadProcess') {// @ts-ignore + endRowStruct = endParentRow.childrenList.concat(item.childrenList).find((item: TraceRow) => { + // @ts-ignore + return item.rowId === `${data.tid}` && item.rowType === 'func'; + });// @ts-ignore + endRowStruct.parentRowEl.expansion = true; + } else { + // @ts-ignore + endRowStruct = endParentRow.childrenList.find((item: TraceRow) => { + // @ts-ignore + return item.rowId === `${data.tid}` && item.rowType === 'func'; + }); + } }); } if (endRowStruct) { diff --git a/ide/src/trace/component/SpSystemTrace.ts b/ide/src/trace/component/SpSystemTrace.ts index b522663aefe5be6c4081de51c002a1513104a971..ec193b177c6aac326e4ecc00cc536a291268abac 100644 --- a/ide/src/trace/component/SpSystemTrace.ts +++ b/ide/src/trace/component/SpSystemTrace.ts @@ -233,6 +233,8 @@ export class SpSystemTrace extends BaseElement { repaintList: Array = []; presentList: Array = []; static isAiAsk: boolean = false; + collectEl1: HTMLDivElement | undefined | null; + groupTitle1: HTMLDivElement | undefined | null; set snapshotFile(data: FileInfo) { this.snapshotFiles = data; @@ -305,11 +307,47 @@ export class SpSystemTrace extends BaseElement { } else { startPoint.rowEL.translateY = startPoint.rowEL.getBoundingClientRect().top - 195; } + if (!this.favoriteChartListEL?.collect1Expand) { // 折叠G1收藏栏 + if (startPoint.rowEL.collectGroup === startPoint.rowEL.collectGroup && startPoint.rowEL.collectGroup === '1') { // 起点终点都在G1 + startPoint.rowEL.translateY = 23; + } else if (startPoint.rowEL.collectGroup !== endPoint.rowEL.collectGroup) { // 起点终点不在同个收藏栏 + if (startPoint.rowEL.collectGroup === '1') { + startPoint.rowEL.translateY = 23; + } + } + } + if (!this.favoriteChartListEL?.collect2Expand) { // 折叠G2收藏栏 + if (startPoint.rowEL.collectGroup === endPoint.rowEL.collectGroup && endPoint.rowEL.collectGroup === '2') { // 起点终点都在G2 + startPoint.rowEL.translateY = 23; + } else if (startPoint.rowEL.collectGroup !== endPoint.rowEL.collectGroup) { // 起点终点不在同个收藏栏 + if (startPoint.rowEL.collectGroup === '2') { + startPoint.rowEL.translateY = Number(this.groupTitle1?.clientHeight) + Number(this.collectEl1?.clientHeight) + 27; + } + } + } } else { startPoint.rowEL.translateY = startPoint.rowEL.offsetTop - this.rowsPaneEL!.scrollTop; } if (endPoint.rowEL.collect) { endPoint.rowEL.translateY = endPoint.rowEL.getBoundingClientRect().top - 195; + if (!this.favoriteChartListEL?.collect1Expand) { // 折叠G1收藏栏 + if (startPoint.rowEL.collectGroup === endPoint.rowEL.collectGroup && endPoint.rowEL.collectGroup === '1') { // 起点终点都在G1 + endPoint.rowEL.translateY = 23; + } else if (startPoint.rowEL.collectGroup !== endPoint.rowEL.collectGroup) { // 起点终点不在同个收藏栏 + if (endPoint.rowEL.collectGroup === '1') { + endPoint.rowEL.translateY = 23; + } + } + } + if (!this.favoriteChartListEL?.collect2Expand) { // 折叠G2收藏栏 + if (startPoint.rowEL.collectGroup === endPoint.rowEL.collectGroup && endPoint.rowEL.collectGroup === '2') { // 起点终点都在G2 + endPoint.rowEL.translateY = 23; + } else if (startPoint.rowEL.collectGroup !== endPoint.rowEL.collectGroup) { // 起点终点不在同个收藏栏 + if (endPoint.rowEL.collectGroup === '2') { + endPoint.rowEL.translateY = Number(this.groupTitle1?.clientHeight) + Number(this.collectEl1?.clientHeight) + 27; + } + } + } } else { endPoint.rowEL.translateY = endPoint.rowEL.offsetTop - this.rowsPaneEL!.scrollTop; } @@ -317,6 +355,8 @@ export class SpSystemTrace extends BaseElement { endPoint.y = endPoint.rowEL!.translateY! + endPoint.offsetY; startPoint.backrowEL = startPoint.rowEL; endPoint.backrowEL = endPoint.rowEL; + startPoint.sourcebackrowEL = startPoint.rowEL; + endPoint.sourcebackrowEL = endPoint.rowEL; //判断是否是分布式连线,分布式连线需有rangeTime if (!lineType) { this.linkNodes.push([startPoint, endPoint]); @@ -561,7 +601,7 @@ export class SpSystemTrace extends BaseElement { ); } if (!TraceRow.rangeSelectObject && !this.isSlectStruct()) { - SpAiAnalysisPage.selectChangeListener(TraceRow.range?.startNS!, TraceRow.range?.endNS!) + SpAiAnalysisPage.selectChangeListener(TraceRow.range?.startNS!, TraceRow.range?.endNS!); } //在rowsEL显示范围内的 trace-row组件将收到时间区间变化通知 this.linkNodes.forEach((it) => { @@ -572,7 +612,7 @@ export class SpSystemTrace extends BaseElement { this.visibleRows.forEach((it) => (it.needRefresh = true)); this.refreshCanvas(false, 'rangeChange'); }; - isSlectStruct() { + isSlectStruct(): unknown { return CpuStruct.selectCpuStruct || CpuStruct.wakeupBean || CpuFreqStruct.selectCpuFreqStruct || @@ -617,6 +657,24 @@ export class SpSystemTrace extends BaseElement { } else { itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; } + if (!this.favoriteChartListEL?.collect1Expand) { // 折叠G1收藏栏 + if (itln[0].rowEL.collectGroup === itln[1].rowEL.collectGroup && itln[1].rowEL.collectGroup === '1') { // 起点终点都在G1 + itln[0].rowEL.translateY = 23; + } else if (itln[0].rowEL.collectGroup !== itln[1].rowEL.collectGroup) { // 起点终点不在同个收藏栏 + if (itln[0].rowEL.collectGroup === '1') { + itln[0].rowEL.translateY = 23; + } + } + } + if (!this.favoriteChartListEL?.collect2Expand) { // 折叠G2收藏栏 + if (itln[0].rowEL.collectGroup === itln[1].rowEL.collectGroup && itln[1].rowEL.collectGroup === '2') { // 起点终点都在G2 + itln[0].rowEL.translateY = 23; + } else if (itln[0].rowEL.collectGroup !== itln[1].rowEL.collectGroup) { // 起点终点不在同个收藏栏 + if (itln[0].rowEL.collectGroup === '2') { + itln[0].rowEL.translateY = Number(this.groupTitle1?.clientHeight) + Number(this.collectEl1?.clientHeight) + 27; + } + } + } } else { itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - this.rowsPaneEL!.scrollTop; } @@ -627,6 +685,24 @@ export class SpSystemTrace extends BaseElement { } else { itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; } + if (!this.favoriteChartListEL?.collect1Expand) { // 折叠G1收藏栏 + if (itln[0].rowEL.collectGroup === itln[1].rowEL.collectGroup && itln[1].rowEL.collectGroup === '1') { // 起点终点都在G1 + itln[1].rowEL.translateY = 23; + } else if (itln[0].rowEL.collectGroup !== itln[1].rowEL.collectGroup) { // 起点终点不在同个收藏栏 + if (itln[1].rowEL.collectGroup === '1') { + itln[1].rowEL.translateY = 23; + } + } + } + if (!this.favoriteChartListEL?.collect2Expand) { // 折叠G2收藏栏 + if (itln[0].rowEL.collectGroup === itln[1].rowEL.collectGroup && itln[1].rowEL.collectGroup === '2') { // 起点终点都在G2 + itln[1].rowEL.translateY = 23; + } else if (itln[0].rowEL.collectGroup !== itln[1].rowEL.collectGroup) { // 起点终点不在同个收藏栏 + if (itln[1].rowEL.collectGroup === '2') { + itln[1].rowEL.translateY = Number(this.groupTitle1?.clientHeight) + Number(this.collectEl1?.clientHeight) + 27; + } + } + } } else { itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - this.rowsPaneEL!.scrollTop; } @@ -956,6 +1032,9 @@ export class SpSystemTrace extends BaseElement { this.currentSlicesTime.startTime = DmaFenceStruct.selectDmaFenceStruct.startTime; this.currentSlicesTime.endTime = DmaFenceStruct.selectDmaFenceStruct.startTime + DmaFenceStruct.selectDmaFenceStruct.dur; } + } else if (HangStruct.selectHangStruct) { + this.currentSlicesTime.startTime = HangStruct.selectHangStruct.startTime; + this.currentSlicesTime.endTime = HangStruct.selectHangStruct.startTime! + HangStruct.selectHangStruct.dur!; } else { this.currentSlicesTime.startTime = 0; this.currentSlicesTime.endTime = 0; @@ -978,7 +1057,8 @@ export class SpSystemTrace extends BaseElement { FrameAnimationStruct.selectFrameAnimationStruct || JsCpuProfilerStruct.selectJsCpuProfilerStruct || PerfToolStruct.selectPerfToolStruct || - DmaFenceStruct.selectDmaFenceStruct; + DmaFenceStruct.selectDmaFenceStruct || + HangStruct.selectHangStruct; this.calculateSlicesTime(selectedStruct, shiftKey); return this.slicestime; @@ -1026,6 +1106,9 @@ export class SpSystemTrace extends BaseElement { // 一直按着回车键的时候执行搜索功能 continueSearch = (ev: KeyboardEvent): void => { + if(!this.keyboardEnable){ + return; + } if (ev.key === 'Enter') { if (ev.shiftKey) { this.dispatchEvent( @@ -1566,15 +1649,25 @@ export class SpSystemTrace extends BaseElement { return startRow; } - calculateStartY(startRow: unknown, pid: number | undefined, selectFuncStruct?: FuncStruct): [number, unknown, number] { + calculateStartY(startRow: unknown, pid: number | undefined, tid: number | undefined, selectFuncStruct?: FuncStruct): [number, unknown, number] { // @ts-ignore let startY = startRow ? startRow!.translateY! : 0; let startRowEl = startRow; let startOffSetY = selectFuncStruct ? 20 * (0.5 + Number(selectFuncStruct.depth)) : 20 * 0.5; // @ts-ignore - const startParentRow = startRow ? this.shadowRoot?.querySelector>(`trace-row[row-id='${startRow.rowParentId}'][folder]`) : this.shadowRoot?.querySelector>( + let startParentRow = startRow ? this.shadowRoot?.querySelector>(`trace-row[row-id='${startRow.rowParentId}'][folder]`) : this.shadowRoot?.querySelector>( `trace-row[row-id='${pid}'][folder]` ); + if (startParentRow && startParentRow.expansion){ + let filterRow = startParentRow?.childrenList.filter((item)=>item.rowId === tid)[0]; + !filterRow && startParentRow?.childrenList.forEach((i)=>{ + if(i.rowId === 'sameThreadProcess'){// @ts-ignore + filterRow = startParentRow?.childrenList.concat(i.childrenList).filter((item)=>item.rowId === String(tid))[0]; + // @ts-ignore + startParentRow = filterRow!.parentRowEl!; + } + }); + } const expansionFlag = this.collectionHasThread(startRow); if (startParentRow && !startParentRow.expansion && expansionFlag) { startY = startParentRow.translateY!; @@ -1914,13 +2007,26 @@ export class SpSystemTrace extends BaseElement { subscribeBottomTabVisibleEvent(): void { //@ts-ignore window.subscribe(window.SmartEvent.UI.ShowBottomTab, (data: { show: number; delta: number }): void => { + let heightTimeOut: unknown = undefined; + if (heightTimeOut) { + //@ts-ignore + clearTimeout(heightTimeOut); + } if (data.show === 1) { //显示底部tab this.scrollH = this.rowsEL!.scrollHeight; } else { // 底部 tab 为 最小化 或者隐藏 时候 if (this.rowsEL!.scrollHeight > this.scrollH) { - this.rowsEL!.scrollTop = this.rowsEL!.scrollTop - data.delta; + heightTimeOut = setTimeout(() => { + let litTab = this.traceSheetEL?.shadowRoot?.querySelector("#tabs"); + if (this.traceSheetEL?.getAttribute('mode') === 'hidden') { + this.rowsEL!.scrollTop = this.rowsEL!.scrollTop - data.delta; + } + if (litTab?.style.height && litTab?.style.height === '38px') { + this.rowsEL!.scrollTop = this.rowsEL!.scrollTop - data.delta; + } + }, 50); } } }); @@ -2407,7 +2513,21 @@ export class SpSystemTrace extends BaseElement { if (!parentRow) { return; } - let filterRow = parentRow.childrenList.filter((child) => child.rowId === funcRowID && child.rowType === 'func')[0]; + // @ts-ignore + let filterRow: TraceRow | undefined; + let isSameThreadProcess = false; + parentRow.childrenList.forEach((item) => { + if (item.rowId === 'sameThreadProcess') { + filterRow = parentRow.childrenList.concat(item.childrenList).filter((child) => child.rowId === funcRowID && child.rowType === 'func')[0]; + item.childrenList.forEach((i) => { + if (filterRow!.rowId === i.rowId) { + isSameThreadProcess = true; + } + }); + } else { + filterRow = parentRow.childrenList.filter((child) => child.rowId === funcRowID && child.rowType === 'func')[0]; + } + }); if (!filterRow) { // @ts-ignore let funcRow = this.rowsEL?.querySelector>(`trace-row[row-id='${funcRowID}'][row-type='func']`); @@ -2426,8 +2546,15 @@ export class SpSystemTrace extends BaseElement { if (row && !row.expansion) { row.expansion = true; } + if (row!.expansion) { + if (isSameThreadProcess) { + this.currentRow = this.rowsEL!.querySelector>( // @ts-ignore + 'trace-row[row-id="sameThreadProcess"][folder]'); + this.currentRow!.expansion = true; + } + } const completeEntry = (): void => { - this.toTargetDepth(filterRow.fixedList[0], funcRowID, funcStract); + this.toTargetDepth(filterRow!.fixedList[0], funcRowID, funcStract); }; if (filterRow!.isComplete) { completeEntry(); diff --git a/ide/src/trace/component/chart/FrameChart.ts b/ide/src/trace/component/chart/FrameChart.ts index 12c7f0a8060c045d557db2bdd920f5e6bc99c994..3171047e4b1c9c734a99e1f6c7a8ecae695e3787 100644 --- a/ide/src/trace/component/chart/FrameChart.ts +++ b/ide/src/trace/component/chart/FrameChart.ts @@ -18,6 +18,7 @@ import { Rect } from '../trace/timer-shaft/Rect'; import { ChartMode, ChartStruct, draw, setFuncFrame } from '../../bean/FrameChartStruct'; import { SpApplication } from '../../SpApplication'; import { Utils } from '../trace/base/Utils'; +import { TabPaneFilter } from '../trace/sheet/TabPaneFilter'; const scaleHeight = 30; // 刻度尺高度 const depthHeight = 20; // 调用栈高度 @@ -67,6 +68,7 @@ export class FrameChart extends BaseElement { private isClickMode = false; //是否为点选模式 _totalRootData: Array = [];//初始化顶部root的数据 private totalRootNode!: ChartStruct; + private tabPaneFilter: TabPaneFilter | undefined; /** * set chart mode @@ -77,6 +79,7 @@ export class FrameChart extends BaseElement { } set data(val: Array) { + this.tabPaneFilter = document.querySelector("body > sp-application")?.shadowRoot?.querySelector("#sp-system-trace")?.shadowRoot?.querySelector("div > trace-sheet")?.shadowRoot?.querySelector("#box-native-calltree > tabpane-nm-calltree")?.shadowRoot?.querySelector("#nm-call-tree-filter") as TabPaneFilter; ChartStruct.lastSelectFuncStruct = undefined; this.setSelectStatusRecursive(ChartStruct.selectFuncStruct, true); ChartStruct.selectFuncStruct = undefined; @@ -665,6 +668,7 @@ export class FrameChart extends BaseElement { private showTip(): void { this.floatHint!.innerHTML = this.hintContent; this.floatHint!.style.display = 'block'; + let tipArea = this.tabPaneFilter?.getBoundingClientRect().top! - this.canvas.getBoundingClientRect().top - this.canvasScrollTop - scaleHeight; let x = this.canvasX; let y = this.canvasY - this.canvasScrollTop; //右边的函数块悬浮框显示在函数左边 @@ -674,7 +678,7 @@ export class FrameChart extends BaseElement { x += scaleHeight; } //顶部悬浮框显示在函数下边,下半部分悬浮框显示在函数上边 - if (y > this.floatHint!.clientHeight) { + if (y > this.floatHint!.clientHeight || y + this.floatHint!.clientHeight > tipArea) { y -= this.floatHint!.clientHeight - 1; } diff --git a/ide/src/trace/component/chart/SpAbilityMonitorChart.ts b/ide/src/trace/component/chart/SpAbilityMonitorChart.ts index dd6358fc85f5ba223669b4e0ce674cce8c992dd2..5614195b895658bfca2230abb164839ad455f9c4 100644 --- a/ide/src/trace/component/chart/SpAbilityMonitorChart.ts +++ b/ide/src/trace/component/chart/SpAbilityMonitorChart.ts @@ -48,7 +48,6 @@ const networkNameList: Array = ['Bytes In/Sec', 'Bytes Out/Sec', 'Packet const memoryNameList: Array = ['MemoryTotal', 'Cached', 'SwapTotal']; const diskIONameList: Array = ['Bytes Read/Sec', 'Bytes Written/Sec', 'Read Ops/Sec', 'Written Ops/Sec']; const key = 'abilityMonitor'; - export class SpAbilityMonitorChart { private trace: SpSystemTrace; constructor(trace: SpSystemTrace) { @@ -94,13 +93,6 @@ export class SpAbilityMonitorChart { } if (this.hasTable(result, 'trace_diskio')) { await this.initDiskAbility(processRow); - // 统计diskio插件 - let requestBody = { - eventData: { - plugin: ['diskio-plugin'] - } - }; - SpStatisticsHttpUtil.recordPluginUsage(requestBody); } if (this.hasTable(result, 'trace_network')) { await this.initNetworkAbility(processRow); diff --git a/ide/src/trace/component/chart/SpArkTsChart.ts b/ide/src/trace/component/chart/SpArkTsChart.ts index ece549344366b7b030a517b4187ec2b162a63a6a..e5e67ff1c08f32463a67ca992d64759dd029325c 100644 --- a/ide/src/trace/component/chart/SpArkTsChart.ts +++ b/ide/src/trace/component/chart/SpArkTsChart.ts @@ -157,13 +157,6 @@ export class SpArkTsChart implements ParseListener { if (this.jsCpuProfilerRow && jsCpu.length > 0) { this.cpuProfilerSupplierFrame(); } - // 统计arkTs插件 - let requsetBody = { - eventData:{ - plugin:['arkts-plugin'] - } - }; - SpStatisticsHttpUtil.recordPluginUsage(requsetBody); } } diff --git a/ide/src/trace/component/chart/SpCpuChart.ts b/ide/src/trace/component/chart/SpCpuChart.ts index 689b4a0bd7b293bf5b30cde7a9436accdf9cd5ac..36d00ecd583d15db6756771922186a866964df9b 100644 --- a/ide/src/trace/component/chart/SpCpuChart.ts +++ b/ide/src/trace/component/chart/SpCpuChart.ts @@ -93,13 +93,6 @@ export class SpCpuChart { this.initSchedSliceData(cpuSchedSlice, traceId); info('Cpu trace row data size is: ', array.length); if (array && array.length > 0 && array[0]) { - // 有cpu泳道,统计ftrace插件,cpu插件 - let requestBody = { - eventData: { - plugin: ['ftrace-plugin', 'cpu-plugin'] - } - }; - SpStatisticsHttpUtil.recordPluginUsage(requestBody); //@ts-ignore let cpuMax = array[0].cpu + 1; Utils.getInstance().setCpuCount(cpuMax, traceId); diff --git a/ide/src/trace/component/chart/SpEBPFChart.ts b/ide/src/trace/component/chart/SpEBPFChart.ts index 366470a42099b2d7e4450dc5390190000f8928fe..255434bce81febee018b9268f408a4ecfbc5cd09 100644 --- a/ide/src/trace/component/chart/SpEBPFChart.ts +++ b/ide/src/trace/component/chart/SpEBPFChart.ts @@ -56,13 +56,6 @@ export class SpEBPFChart { await this.initDiskIOLatency(folder); await this.initProcessDiskIOLatency(folder); } - // 统计ebpf插件 - let requsetBody = { - eventData: { - plugin: ['hiebpf-plugin'] - } - }; - SpStatisticsHttpUtil.recordPluginUsage(requsetBody); } } } diff --git a/ide/src/trace/component/chart/SpHiPerf.ts b/ide/src/trace/component/chart/SpHiPerf.ts index bcf66335d02f7592c3fb0337541c4469b1003280..bcefde8d4c16bf2c28475d4a7a54991debde1be6 100644 --- a/ide/src/trace/component/chart/SpHiPerf.ts +++ b/ide/src/trace/component/chart/SpHiPerf.ts @@ -88,13 +88,6 @@ export class SpHiPerf { this.eventTypeId = -2; //@ts-ignore this.maxCpuId = this.cpuData.length > 0 ? this.cpuData[0].cpu_id : -Infinity; if (this.cpuData.length > 0) { - // 统计hiperf插件 - let requestBody = { - eventData: { - plugin: ['hiperf-plugin'] - } - }; - SpStatisticsHttpUtil.recordPluginUsage(requestBody); await this.initFolder(); await this.initCallChart(); await this.initCpuMerge(); diff --git a/ide/src/trace/component/chart/SpHiSysEventChart.ts b/ide/src/trace/component/chart/SpHiSysEventChart.ts index 87b7534b11f038ad9c099006ce81aca7c6b5aece..2a72ace9d5965904015f2437434df7afb859ce73 100644 --- a/ide/src/trace/component/chart/SpHiSysEventChart.ts +++ b/ide/src/trace/component/chart/SpHiSysEventChart.ts @@ -35,13 +35,6 @@ export class SpHiSysEventChart { } let eventRow = await this.initRow(); this.trace.rowsEL?.appendChild(eventRow); - // 统计hiSysevent插件 - let requestBody = { - eventData:{ - plugin:['hisysevent'] - } - }; - SpStatisticsHttpUtil.recordPluginUsage(requestBody); } async initRow(): Promise> { diff --git a/ide/src/trace/component/chart/SpLogChart.ts b/ide/src/trace/component/chart/SpLogChart.ts index 898fe37e2a2dcee784a9e58b339f5cb262b170df..344e1e77272ad306bf288d2fcda2ef8526bffd7e 100644 --- a/ide/src/trace/component/chart/SpLogChart.ts +++ b/ide/src/trace/component/chart/SpLogChart.ts @@ -35,13 +35,6 @@ export class SpLogChart { } let folder = await this.initFolder(); this.trace.rowsEL?.appendChild(folder); - // 统计hilog插件 - let requestBody = { - eventData:{ - plugin:['hilog-plugin'] - } - }; - SpStatisticsHttpUtil.recordPluginUsage(requestBody); } async initFolder(): Promise> { diff --git a/ide/src/trace/component/chart/SpNativeMemoryChart.ts b/ide/src/trace/component/chart/SpNativeMemoryChart.ts index 53f703517bf1ee6daafbf3c4b0475126f5daed5f..2621e4284d55697c67f18de5541024c8a121418b 100644 --- a/ide/src/trace/component/chart/SpNativeMemoryChart.ts +++ b/ide/src/trace/component/chart/SpNativeMemoryChart.ts @@ -182,13 +182,6 @@ export class SpNativeMemoryChart { if (nativeProcess.length === 0) { return; } - // 有native_memory进程,统计nativehook插件 - let requestBody = { - eventData: { - plugin: ['nativehook'] - } - }; - SpStatisticsHttpUtil.recordPluginUsage(requestBody); await this.initNativeMemory(); await nativeMemoryChartDataCacheSender( nativeProcess.map((it) => it.ipid), diff --git a/ide/src/trace/component/chart/SpProcessChart.ts b/ide/src/trace/component/chart/SpProcessChart.ts index e316dcd5cefd66feddec1a7b31db16dbecfd0ba2..11519b54d1bd9ebfd8b7dea2b3fa7fed79540487 100644 --- a/ide/src/trace/component/chart/SpProcessChart.ts +++ b/ide/src/trace/component/chart/SpProcessChart.ts @@ -427,10 +427,10 @@ export class SpProcessChart { } renderServiceProcess = await queryRsProcess(); } - + // @ts-ignore info('ProcessList Data size is: ', processList!.length); - + this.hangProcessSet = new Set((await queryHangData()).map(item => item.id)); @@ -742,7 +742,9 @@ export class SpProcessChart { ThreadStruct.selectThreadStruct = selectProcessStruct; //@ts-ignore ThreadStruct.hoverThreadStruct = selectProcessStruct; } - }); + });//@ts-ignore + linkItem[0].backrowEL = linkItem[0].sourcebackrowEL!.parentRowEl?.expansion ? linkItem[0].sourcebackrowEL! : linkItem[0].sourcebackrowEL!.parentRowEl;//@ts-ignore + linkItem[1].backrowEL = linkItem[1].sourcebackrowEL!.parentRowEl?.expansion ? linkItem[1].sourcebackrowEL! : linkItem[1].sourcebackrowEL!.parentRowEl; if (linkItem[0].rowEL.expansion && linkItem[0].backrowEL) { this.updatePairPointTranslateY(linkItem[0]); linkItem[0].x = ns2xByTimeShaft(linkItem[0].ns, this.trace.timerShaftEL!); @@ -757,6 +759,8 @@ export class SpProcessChart { linkItem[1].offsetY = linkItem[1].offsetY * 2; linkItem[1].rowEL = linkItem[1].backrowEL; } + this.updatePairPointTranslateY(linkItem[0]); + this.updatePairPointTranslateY(linkItem[1]); } handler4(e: unknown, linkItem: PairPoint[], processRow: TraceRow): void { @@ -764,21 +768,57 @@ export class SpProcessChart { linkItem[0].y = processRow!.translateY + linkItem[0].offsetY; this.updatePairPointTranslateY(linkItem[1]); linkItem[1].y = linkItem[1].rowEL!.translateY + linkItem[1].offsetY; //@ts-ignore - if (linkItem[0].rowEL.rowParentId === e.detail.rowId) { - //@ts-ignore - this.updatePairPoint(linkItem[0], processRow); - } //@ts-ignore - if (linkItem[1].rowEL.rowParentId === e.detail.rowId) { - this.updatePairPoint(linkItem[1], processRow); + if (e.detail.rowId === 'sameThreadProcess') {//@ts-ignore + if (linkItem[0].rowEL.parentRowEl?.rowId === e.detail.rowId) { + //@ts-ignore + this.updatePairPoint(linkItem[0], processRow); + } //@ts-ignore + if (linkItem[1].rowEL.parentRowEl?.rowId === e.detail.rowId) { + this.updatePairPoint(linkItem[1], processRow); + } + } + //@ts-ignore + if (e.detail.rowId !== 'sameThreadProcess') {//@ts-ignore + if (linkItem[0].rowEL.rowParentId === e.detail.rowId) { + this.updatePairPoint(linkItem[0], processRow); + }//@ts-ignore + if (linkItem[1].rowEL.rowParentId === e.detail.rowId) { + this.updatePairPoint(linkItem[1], processRow); + } } } updatePairPointTranslateY(pair: PairPoint): void { + let linkNodeYTimeOut: unknown = undefined; + if (linkNodeYTimeOut) { + //@ts-ignore + clearTimeout(linkNodeYTimeOut); + } if (pair.rowEL.collect) { pair.rowEL.translateY = pair.rowEL.getBoundingClientRect().top - 195; + linkNodeYTimeOut = setTimeout(() => { + if (this.trace.favoriteChartListEL?.collect1Expand === false) { // G1折叠 + if (pair.rowEL.collectGroup === '1') { + pair.rowEL.translateY = 23; + } + } + if (this.trace.favoriteChartListEL?.collect2Expand === false) {// G2折叠 + if (pair.rowEL.collectGroup === '2') { + if (this.trace.groupTitle1?.style.display === 'none') { + pair.rowEL.translateY = 23; + } else if (this.trace.groupTitle1?.style.display === 'flex' || this.trace.groupTitle1?.style.display === 'block') { + pair.rowEL.translateY = Number(this.trace.groupTitle1?.clientHeight) + Number(this.trace.collectEl1?.clientHeight) + 27; + } + } + } + }, 300); } else { pair.rowEL.translateY = pair.rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; } + let refreshTimeOut = setTimeout(() => { + this.trace.refreshCanvas(true); + clearTimeout(refreshTimeOut); + }, 300); } updatePairPoint(pair: PairPoint, processRow: TraceRow): void { @@ -878,9 +918,9 @@ export class SpProcessChart { processName: string | null; }, processRow: TraceRow, - funcRow: TraceRow, + threadRow: TraceRow, thread: unknown - ): void { + ): TraceRow | null { if (this.hangProcessSet.has(data.pid!) && FlagsConfig.getFlagsConfigEnableStatus('Hangs Detection')) { //@ts-ignore if (data.pid === thread.tid) { @@ -922,9 +962,11 @@ export class SpProcessChart { hangsRow, this.trace ); - processRow.addChildTraceRowAfter(hangsRow, funcRow); + processRow.addChildTraceRowBefore(hangsRow, threadRow); + return hangsRow; } } + return null; } jankSenderCallback( @@ -1074,12 +1116,12 @@ export class SpProcessChart { ): Promise { let threads = this.processThreads.filter((thread) => thread.pid === it.pid && thread.tid !== 0); const sameThreadCounts: Record = {}; //同名thread添加子进程 - const sameThreadList: any[] = []; - const differentThreadList: any[] = []; + const sameThreadList: unknown[] = []; + const differentThreadList: unknown[] = []; threads.forEach(item => { const sameThread = item.threadName; if (sameThread !== undefined) { - if (sameThread in sameThreadCounts) { + if (sameThread in sameThreadCounts && item.tid !== item.pid) { sameThreadCounts[sameThread]++; } else { sameThreadCounts[sameThread] = 1; @@ -1089,7 +1131,7 @@ export class SpProcessChart { threads.forEach((item) => { const sameThread = item.threadName; - if (sameThreadCounts[sameThread!] > 128) { + if (sameThreadCounts[sameThread!] > 128 && item.tid !== item.pid) { sameThreadList.push(item); } else { differentThreadList.push(item); @@ -1101,18 +1143,20 @@ export class SpProcessChart { let sameThreadFolder = await this.initSameThreadFolder(it, pRow, sameThreadList, traceId!); if (sameThreadFolder) { pRow.addChildTraceRow(this.sameThreadFolder); + this.addProcessRowListener(this.sameThreadFolder, actualRow); } await this.initSameThreadData(sameThreadFolder, it, expectedRow, actualRow, soRow, startupRow, sameThreadList, traceId); } } - initSameThreadFolder(it: { pid: number | null; processName: string | null }, pRow: TraceRow, list: Array, traceId?: string) { + initSameThreadFolder(it: { pid: number | null; processName: string | null }, pRow: TraceRow, list: Array, traceId?: string): TraceRow { let sameThreadRow = TraceRow.skeleton(); sameThreadRow.rowId = 'sameThreadProcess'; sameThreadRow.rowParentId = `${it.pid}`; sameThreadRow.rowHidden = !pRow.expansion; sameThreadRow.rowType = TraceRow.ROW_TYPE_THREAD_NAME; sameThreadRow.folder = true; + // @ts-ignore sameThreadRow.name = list[0].threadName; sameThreadRow.folderPaddingLeft = 20; sameThreadRow.style.height = '40px'; @@ -1152,25 +1196,30 @@ export class SpProcessChart { expectedRow: TraceRow | null, actualRow: TraceRow | null, soRow: TraceRow | undefined, - startupRow: TraceRow | undefined, sameThreadList: Array, traceId?: string): Promise { + startupRow: TraceRow | undefined, sameThreadList: Array, traceId?: string): Promise { let tRowArr: Array> = []; for (let j = 0; j < sameThreadList.length; j++) { let thread = sameThreadList[j]; let tRow = TraceRow.skeleton(this.traceId); + // @ts-ignore tRow.rowId = `${thread.tid}`; tRow.rowType = TraceRow.ROW_TYPE_THREAD; - tRow.rowParentId = sameThreadFolder.rowId; + // @ts-ignore + tRow.rowParentId = `${thread.pid}`; tRow.rowHidden = !sameThreadFolder.expansion; tRow.index = j; tRow.style.height = '18px'; tRow.style.width = '100%'; + // @ts-ignore tRow.name = `${thread.threadName || 'Thread'} ${thread.tid}`; + // @ts-ignore tRow.namePrefix = `${thread.threadName || 'Thread'}`; tRow.setAttribute('children', ''); tRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; tRow.selectChangeHandler = this.trace.selectChangeHandler; tRow.findHoverStruct = (): void => this.threadRowFindHoverStruct(tRow); tRow.supplierFrame = async (): Promise> => { + // @ts-ignore const res = await threadDataSender(thread.tid || 0, it.pid || 0, tRow, this.traceId); if (res === true) { return []; @@ -1185,14 +1234,17 @@ export class SpProcessChart { 'thread', 'context', { + // @ts-ignore type: `thread ${thread.tid} ${thread.threadName}`, translateY: tRow.translateY, }, tRow, this.trace ); + // @ts-ignore this.insertRowToDoc(it, j, thread, sameThreadFolder, tRow, sameThreadList, tRowArr, actualRow, expectedRow, startupRow, soRow); - this.addFuncStackRow(it, thread, j, sameThreadList, tRowArr, tRow, sameThreadFolder, sameThreadFolder.rowId!); + this.addFuncStackRow(it, thread, j, sameThreadList, tRowArr, tRow, sameThreadFolder); + // @ts-ignore if ((thread.switchCount || 0) === 0) { tRow.rowDiscard = true; } @@ -1206,11 +1258,12 @@ export class SpProcessChart { actualRow: TraceRow | null, soRow: TraceRow | undefined, startupRow: TraceRow | undefined, - list: Array, traceId?: string) { + list: Array, traceId?: string): void { let tRowArr: Array> = []; for (let j = 0; j < list.length; j++) { let thread = list[j]; let tRow = TraceRow.skeleton(this.traceId); + // @ts-ignore tRow.rowId = `${thread.tid}`; tRow.rowType = TraceRow.ROW_TYPE_THREAD; tRow.rowParentId = `${it.pid}`; @@ -1218,13 +1271,16 @@ export class SpProcessChart { tRow.index = j; tRow.style.height = '18px'; tRow.style.width = '100%'; + // @ts-ignore tRow.name = `${thread.threadName || 'Thread'} ${thread.tid}`; + // @ts-ignore tRow.namePrefix = `${thread.threadName || 'Thread'}`; tRow.setAttribute('children', ''); tRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; tRow.selectChangeHandler = this.trace.selectChangeHandler; tRow.findHoverStruct = (): void => this.threadRowFindHoverStruct(tRow); tRow.supplierFrame = async (): Promise> => { + // @ts-ignore const res = await threadDataSender(thread.tid || 0, it.pid || 0, tRow, this.traceId); if (res === true) { return []; @@ -1239,14 +1295,18 @@ export class SpProcessChart { 'thread', 'context', { + // @ts-ignore type: `thread ${thread.tid} ${thread.threadName}`, translateY: tRow.translateY, }, tRow, this.trace ); - this.insertRowToDoc(it, j, thread, pRow, tRow, list, tRowArr, actualRow, expectedRow, startupRow, soRow); + let hangRow: TraceRow | null = null; + // @ts-ignore + this.insertRowToDoc(it, j, thread, pRow, tRow, list, tRowArr, actualRow, expectedRow, hangRow, startupRow, soRow); this.addFuncStackRow(it, thread, j, list, tRowArr, tRow, pRow); + // @ts-ignore if ((thread.switchCount || 0) === 0) { tRow.rowDiscard = true; } @@ -1283,6 +1343,7 @@ export class SpProcessChart { actualRow: TraceRow | null, //@ts-ignore expectedRow: TraceRow | null, + hangRow: TraceRow | null, startupRow: TraceRow | null | undefined, soRow: TraceRow | null | undefined ): void { @@ -1305,6 +1366,8 @@ export class SpProcessChart { processRow.addChildTraceRowAfter(threadRow, soRow); } else if (startupRow) { processRow.addChildTraceRowAfter(threadRow, startupRow); + } else if (hangRow !== null) { + processRow.addChildTraceRowAfter(threadRow, hangRow); } else { processRow.addChildTraceRowSpecifyLocation(threadRow, 0); } @@ -1321,11 +1384,11 @@ export class SpProcessChart { threads: Array, threadRowArr: Array, threadRow: TraceRow, - processRow: TraceRow, - parentId?: string + processRow: TraceRow ): void { //@ts-ignore if (this.threadFuncMaxDepthMap.get(`${thread.upid}-${thread.tid}`) !== undefined) { + this.addHangRow(process, processRow, threadRow,thread); //@ts-ignore let max = this.threadFuncMaxDepthMap.get(`${thread.upid}-${thread.tid}`) || 1; let maxHeight = max * 18 + 6; @@ -1335,7 +1398,7 @@ export class SpProcessChart { funcRow.rowType = TraceRow.ROW_TYPE_FUNC; funcRow.enableCollapseChart(FOLD_HEIGHT, this.trace); //允许折叠泳道图 //@ts-ignore - funcRow.rowParentId = parentId ? parentId : `${process.pid}`; + funcRow.rowParentId = `${thread.pid}`; funcRow.rowHidden = !processRow.expansion; funcRow.checkType = threadRow.checkType; funcRow.style.width = '100%'; @@ -1373,7 +1436,6 @@ export class SpProcessChart { } else { processRow.addChildTraceRowAfter(funcRow, threadRow); } - this.addHangRow(process, processRow, funcRow, thread); } } @@ -1520,7 +1582,7 @@ export class SpProcessChart { ({ asyncRemoveCatArr, asyncCat } = this.hanldCatFunc(asyncFuncList, flag));//处理是否cat ({ setArrayLenThanOne, setArrayLenOnlyOne } = this.hanldAsyncFunc(it, asyncRemoveCatArr));//len等于0和大于0的分类 //@ts-ignore - let aggregateData = {...setArrayLenThanOne, ...setArrayLenOnlyOne }; + let aggregateData = { ...setArrayLenThanOne, ...setArrayLenOnlyOne }; Reflect.ownKeys(aggregateData).map((key: unknown) => { let param: Array = aggregateData[key]; //@ts-ignore @@ -1532,7 +1594,7 @@ export class SpProcessChart { let param: Array = asyncCat[key]; if (flag) {//处理business //@ts-ignore - this.makeAddAsyncFunction(param, it, processRow, key); + this.makeAddAsyncFunction(param, it, processRow, key); } else {//处理thread //@ts-ignore this.makeAddAsyncFunction(param, it, processRow, key, param[0].tid); diff --git a/ide/src/trace/component/chart/SpSdkChart.ts b/ide/src/trace/component/chart/SpSdkChart.ts index 8ddd2286015774eeb2607d84a8177a815a82489d..38ced36ab4ba08be402397a6bbebfa9ec1e86eb7 100644 --- a/ide/src/trace/component/chart/SpSdkChart.ts +++ b/ide/src/trace/component/chart/SpSdkChart.ts @@ -25,6 +25,7 @@ import { TabUtil } from '../trace/sheet/sdk/TabUtil'; import { queryCounterMax, querySdkCount, querySdkCounterData, querySdkSliceData } from '../../database/sql/Sdk.sql'; import { queryStartTime } from '../../database/sql/SqlLite.sql'; import { NUM_7 } from '../../bean/NumBean'; +import { SpStatisticsHttpUtil } from '../../../statistics/util/SpStatisticsHttpUtil'; export class SpSdkChart { trace: SpSystemTrace; diff --git a/ide/src/trace/component/chart/SpVmTrackerChart.ts b/ide/src/trace/component/chart/SpVmTrackerChart.ts index 89f16c8b7c9080281a63018c759d81a8a28d1387..da031c881a053f4286eb6b2f513025ffa2c71f36 100644 --- a/ide/src/trace/component/chart/SpVmTrackerChart.ts +++ b/ide/src/trace/component/chart/SpVmTrackerChart.ts @@ -49,6 +49,7 @@ import { queryisExistsGpuData, queryisExistsGpuResourceData, } from '../../database/sql/Gpu.sql'; +import { SpStatisticsHttpUtil } from '../../../statistics/util/SpStatisticsHttpUtil'; export class VmTrackerChart { private trace: SpSystemTrace; diff --git a/ide/src/trace/component/chart/SpXpowerChart.ts b/ide/src/trace/component/chart/SpXpowerChart.ts index 21d63b0b4bf3c78b27cd70e61d5bf7f5df5638f0..f933b4c6c64db53df1c16514b1aa37188ebdfb8e 100644 --- a/ide/src/trace/component/chart/SpXpowerChart.ts +++ b/ide/src/trace/component/chart/SpXpowerChart.ts @@ -23,6 +23,7 @@ import { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; import { xpowerDataSender } from '../../database/data-trafic/XpowerDataSender'; import { queryXpowerData, queryXpowerMeasureData } from '../../database/sql/Xpower.sql'; import { BaseStruct } from '../../bean/BaseStruct'; +import { SpStatisticsHttpUtil } from '../../../statistics/util/SpStatisticsHttpUtil'; export class SpXpowerChart { private readonly trace: SpSystemTrace; @@ -84,7 +85,7 @@ export class SpXpowerChart { systemFolder.rowId = 'system'; systemFolder.rowParentId = 'Xpowers'; systemFolder.rowHidden = !this.rowFolder.expansion; - systemFolder.rowType = TraceRow.ROW_TYPE_XPOWER_SYSTEM; + systemFolder.rowType = TraceRow.ROW_TYPE_XPOWER_SYSTEM_GROUP; systemFolder.folder = true; systemFolder.name = 'System'; systemFolder.folderPaddingLeft = 20; @@ -118,6 +119,7 @@ export class SpXpowerChart { name: string; num: number; maxValue?: number; + minValue?: number; }, ): void { traceRow.supplierFrame = (): Promise => { @@ -131,11 +133,6 @@ export class SpXpowerChart { // @ts-ignore return promiseData.then((resultXpower: Array) => { for (let j = 0; j < resultXpower.length; j++) { - // @ts-ignore - if ((resultXpower[j].value || 0) > it.maxValue!) { - // @ts-ignore - it.maxValue = resultXpower[j].value || 0; - } if (j > 0) { // @ts-ignore resultXpower[j].delta = (resultXpower[j].value || 0) - (resultXpower[j - 1].value || 0); @@ -156,6 +153,7 @@ export class SpXpowerChart { name: string; num: number; maxValue?: number; + minValue?: number; }, xpowerId: number ): void { @@ -173,6 +171,7 @@ export class SpXpowerChart { useCache: useCache, type: it.name, maxValue: it.maxValue === 0 ? 1 : it.maxValue!, + minValue: it.minValue || 0, index: xpowerId, maxName: it.maxValue!.toString() }, @@ -185,13 +184,13 @@ export class SpXpowerChart { async initSystemData(folder: TraceRow, xpowerList: Array<{ name: string; num: number; - maxValue?: number; + maxValue: number; + minValue: number; }>, traceId?: string): Promise { info('xpowerList data size is: ', xpowerList!.length); XpowerStruct.maxValue = xpowerList.map((item) => item.num).reduce((a, b) => Math.max(a, b)); for (let i = 0; i < xpowerList.length; i++) { const it = xpowerList[i]; - it.maxValue = 0; let traceRow = TraceRow.skeleton(traceId); traceRow.rowId = it.name; traceRow.rowType = TraceRow.ROW_TYPE_XPOWER_SYSTEM; @@ -200,7 +199,10 @@ export class SpXpowerChart { traceRow.name = it.name; traceRow.rowHidden = !folder.expansion; traceRow.folderTextLeft = 40; - traceRow.xpowerRowTitle = this.convertTitle(it.name); + if (it.name === 'ThermalReport.ShellTemp') { + it.maxValue = it.maxValue / 1000; + } + traceRow.xpowerRowTitle = convertTitle(it.name); traceRow.setAttribute('children', ''); traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; traceRow.selectChangeHandler = this.trace.selectChangeHandler; @@ -215,6 +217,7 @@ export class SpXpowerChart { traceRow, XpowerStruct.hoverXpowerStruct, `${it.name === 'ThermalReport.ShellTemp' ? XpowerStruct.hoverXpowerStruct?.value! : + it.name === 'ThermalReport.ThermalLevel' ? convertHoverValue(String(XpowerStruct.hoverXpowerStruct?.value!)) : ColorUtils.formatNumberComma(XpowerStruct.hoverXpowerStruct?.value!)}` ); }; @@ -225,28 +228,44 @@ export class SpXpowerChart { folder.addChildTraceRow(traceRow); } } +} - convertTitle(title: string): string { - switch (title) { - case 'Battery.Capacity': - return '电池容量(单位mAh)'; - case 'Battery.Charge': - return '充电状态(充电1,非充电0)'; - case 'Battery.GasGauge': - return '电池剩余电量(单位mAh)'; - case 'Battery.Level': - return '电池百分比'; - case 'Battery.RealCurrent': - return '实时电流(单位mAh,充电时为正数,耗电时为负数)'; - case 'Battery.Screen': - return '屏幕状态(亮屏1,灭屏0)'; - case 'ThermalReport.ShellTemp': - return '外壳温度(单位℃)'; - case 'ThermalReport.ThermalLevel': - return '温度等级'; - default: - return title; - } +// 鼠标悬浮时转换xpower泳道名 +export function convertTitle(title: string): string { + switch (title) { + case 'Battery.Capacity': + return '电池容量(单位mAh)'; + case 'Battery.Charge': + return '充电状态(充电1,非充电0)'; + case 'Battery.GasGauge': + return '电池剩余电量(单位mAh)'; + case 'Battery.Level': + return '电池百分比'; + case 'Battery.RealCurrent': + return '实时电流(单位mAh,充电时为正数,耗电时为负数)'; + case 'Battery.Screen': + return '屏幕状态(亮屏1,灭屏0)'; + case 'ThermalReport.ShellTemp': + return '外壳温度(单位℃)'; + case 'ThermalReport.ThermalLevel': + return '温度等级'; + default: + return title; } +} +// 鼠标悬浮ThermalReport.ThermalLevel泳道时转换悬浮框内容 +export function convertHoverValue(value: string): string { + switch (value) { + case '0': + return 'COOL'; + case '1': + return 'WARM'; + case '2': + return 'HOT'; + case '3': + return 'OVERHEATED'; + default: + return value; + } } diff --git a/ide/src/trace/component/setting/SpProbesConfig.ts b/ide/src/trace/component/setting/SpProbesConfig.ts index 79568fbfec90e695c9cb19fbeac14851eab3d01f..6e280d008c2b60d35323dd79ffd08e27dc4f2f13 100644 --- a/ide/src/trace/component/setting/SpProbesConfig.ts +++ b/ide/src/trace/component/setting/SpProbesConfig.ts @@ -62,7 +62,7 @@ export class SpProbesConfig extends BaseElement { if (this.ftraceBufferSizeResult?.hasAttribute('percent')) { return Number(this.ftraceBufferSizeResult?.getAttribute('percent')); } - return 20480; + return 204800; } get memoryConfig(): string[] { @@ -235,10 +235,10 @@ export class SpProbesConfig extends BaseElement { if (this.ftraceBufferSizeResult!.hasAttribute('percent')) { buffSizeResult.value = Number(this.ftraceBufferSizeResult!.getAttribute('percent')).toString(); } else { - buffSizeResult.value = '20480'; + buffSizeResult.value = '204800'; } }); - bufferSizeSliderParent.setAttribute('percent', '20480'); + bufferSizeSliderParent.setAttribute('percent', '204800'); buffSizeResult.style.color = 'var(--dark-color1,#000000)'; buffSizeResult.addEventListener('input', () => { this.ftraceBuffSizeResultInputHandler(buffSizeResult, bufferSizeSliderParent, bufferSizeSlider); @@ -246,8 +246,8 @@ export class SpProbesConfig extends BaseElement { buffSizeResult.addEventListener('focusout', () => { if (buffSizeResult.value.trim() === '') { buffSizeResult.parentElement!.classList.remove('border-red'); - bufferSizeSliderParent.setAttribute('percent', '20480'); - buffSizeResult.value = '20480'; + bufferSizeSliderParent.setAttribute('percent', '204800'); + buffSizeResult.value = '204800'; buffSizeResult.style.color = 'var(--dark-color,#6a6f77)'; bufferSizeSliderParent.setAttribute('percent', buffSizeResult.value); bufferSizeSliderParent.setAttribute('percentValue', buffSizeResult.value); @@ -271,7 +271,7 @@ export class SpProbesConfig extends BaseElement { buffSizeResultEl.style.backgroundColor = 'var(--dark-background5,#F2F2F2)'; if (buffSizeResultEl.value.trim() === '') { buffSizeResultEl.style.color = 'red'; - bufferSizeSliderParentEl.setAttribute('percent', '20480'); + bufferSizeSliderParentEl.setAttribute('percent', '204800'); return; } let ftraceBufferSize = Number(buffSizeResultEl.value); @@ -280,7 +280,7 @@ export class SpProbesConfig extends BaseElement { ftraceBufferSize > bufferSizeSliderEl!.sliderStyle.maxRange ) { buffSizeResultEl.parentElement!.classList.add('border-red'); - bufferSizeSliderParentEl.setAttribute('percent', '20480'); + bufferSizeSliderParentEl.setAttribute('percent', '204800'); } else { buffSizeResultEl.parentElement!.classList.remove('border-red'); bufferSizeSliderEl!.percent = buffSizeResultEl.value; diff --git a/ide/src/trace/component/setting/SpXPowerRecord.ts b/ide/src/trace/component/setting/SpXPowerRecord.ts index dae8f9fe3d271b16962fe4de00ab597fc8570b83..1db53945445b71ab17446ebc793707cc6255f4f2 100644 --- a/ide/src/trace/component/setting/SpXPowerRecord.ts +++ b/ide/src/trace/component/setting/SpXPowerRecord.ts @@ -66,7 +66,7 @@ export class SpXPowerRecord extends BaseElement { default: break; } - }) + }); } private configTypeBySelectMultiple(config: unknown, recordXpowerDiv: HTMLDivElement): void { @@ -92,7 +92,7 @@ export class SpXPowerRecord extends BaseElement { getXpowerConfig(): string | undefined { let recordXpowerConfigVal = this.shadowRoot?.querySelectorAll('.config'); - let xpowerConfig: string = '' + let xpowerConfig: string = ''; recordXpowerConfigVal!.forEach((value) => { xpowerConfig = this.getXpowerConfigData(value, xpowerConfig); }); @@ -109,7 +109,7 @@ export class SpXPowerRecord extends BaseElement { } private xpowerConfigByTypeList(xpowerConfig: string, selectValue: LitSelectV): string { - xpowerConfig = selectValue.value + xpowerConfig = selectValue.value; return xpowerConfig; } @@ -149,4 +149,4 @@ const xpowerConfigList = [ type: 'select-multiple', selectArray: [''], } -] +]; diff --git a/ide/src/trace/component/trace/SpChartList.ts b/ide/src/trace/component/trace/SpChartList.ts index 41d5a791f3ad56469bdcd7164379a8f9098f0aa1..6a11b1fce0c1894c9e475a797048f97d409da1a0 100644 --- a/ide/src/trace/component/trace/SpChartList.ts +++ b/ide/src/trace/component/trace/SpChartList.ts @@ -31,6 +31,7 @@ import { TimerShaftElement } from './TimerShaftElement'; import { CpuStruct } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; import { WakeupBean } from '../../bean/WakeupBean'; import { LitIcon } from '../../../base-ui/icon/LitIcon'; +import { SpSystemTrace } from '../SpSystemTrace'; const maxScale = 0.8; //收藏最大高度为界面最大高度的80% const topHeight = 150; // 顶部cpu使用率部分高度固定为150px @@ -59,16 +60,18 @@ export class SpChartList extends BaseElement { private startPageY = 0; private startClientHeight: number = 0; private scrollTimer: unknown; - private collect1Expand: boolean = true; - private collect2Expand: boolean = true; + collect1Expand: boolean = true; + collect2Expand: boolean = true; // @ts-ignore private collectRowList1: Array> = []; // @ts-ignore private collectRowList2: Array> = []; private maxHeight = 0; private manualHeight = 0; + private spSystemTrace: SpSystemTrace | undefined | null; initElements(): void { + this.spSystemTrace = document?.querySelector("body > sp-application")?.shadowRoot?.querySelector("#sp-system-trace"); this.collectEl1 = this.shadowRoot?.querySelector('#collect-group-1'); this.collectEl2 = this.shadowRoot?.querySelector('#collect-group-2'); this.groupTitle1 = this.shadowRoot?.querySelector('#group-1-title'); @@ -93,14 +96,29 @@ export class SpChartList extends BaseElement { } private initChartListListener(): void { + let offsetYTimeOut: unknown = undefined; const foldCollect1 = (): void => { + if (offsetYTimeOut) { + //@ts-ignore + clearTimeout(offsetYTimeOut); + } this.collect1Expand = !this.collect1Expand; if (this.collect1Expand) { this.icon1!.style.transform = 'rotateZ(0deg)'; this.collectEl1?.appendChild(this.fragmentGroup1); + if (!this.collect2Expand) { // G1展开,G2折叠时处理连线y坐标 + this.handleCollect2LinkNodeY(); + } } else { this.icon1!.style.transform = 'rotateZ(-90deg)'; this.collectRowList1.forEach((row) => this.fragmentGroup1.appendChild(row)); + offsetYTimeOut = setTimeout(() => { //折叠G1收藏栏,连线处理 + this.handleCollect1LinkNodeY(); + if (!this.collect2Expand) { + this.handleCollect2LinkNodeY(); + } + this.spSystemTrace?.refreshCanvas(true); + }, 50); } this.resizeHeight(); }; @@ -115,12 +133,16 @@ export class SpChartList extends BaseElement { this.icon2!.style.transform = 'rotateZ(-90deg)'; this.collectRowList2.forEach((row) => this.fragmentGroup2.appendChild(row)); this.scrollTop = 0; + offsetYTimeOut = setTimeout(() => { + this.handleCollect2LinkNodeY(); + this.spSystemTrace?.refreshCanvas(true); + }, 50); } this.resizeHeight(); }; this.icon2?.addEventListener('click', () => foldCollect2()); document.addEventListener('keyup', (e) => { - if (e.key.toLowerCase() === 'b' && e.ctrlKey === false) { + if (e.key.toLowerCase() === 'b' && e.ctrlKey === false && this.spSystemTrace?.keyboardEnable) { // 收藏夹有泳道时 为true const hasChildNode1 = this.collectEl1?.hasChildNodes() || this.fragmentGroup1.hasChildNodes(); const hasChildNode2 = this.collectEl2?.hasChildNodes() || this.fragmentGroup2.hasChildNodes(); @@ -163,6 +185,38 @@ export class SpChartList extends BaseElement { }); } + // 处理G1收藏栏折叠时,连线的y坐标 + private handleCollect1LinkNodeY(): void { + this.spSystemTrace?.linkNodes?.forEach(linkItem => { + if (linkItem[0].rowEL.collectGroup === linkItem[1].rowEL.collectGroup && linkItem[1].rowEL.collectGroup === '1') { // 起点终点都在G1 + linkItem[0].rowEL.translateY = 23; + linkItem[1].rowEL.translateY = 23; + } else if (linkItem[0].rowEL.collectGroup !== linkItem[1].rowEL.collectGroup) { // 起点终点不在同个收藏栏 + if (linkItem[0].rowEL.collectGroup === '1') { + linkItem[0].rowEL.translateY = 23; + } else if (linkItem[1].rowEL.collectGroup === '1') { + linkItem[1].rowEL.translateY = 23; + } + } + }); + } + + // 处理G2收藏栏折叠时,连线的y坐标 + private handleCollect2LinkNodeY(): void { + this.spSystemTrace?.linkNodes?.forEach(linkItem => { + if (linkItem[0].rowEL.collectGroup === linkItem[1].rowEL.collectGroup && linkItem[1].rowEL.collectGroup === '2') { // 起点终点都在G2 + linkItem[0].rowEL.translateY = 23; + linkItem[1].rowEL.translateY = 23; + } else if (linkItem[0].rowEL.collectGroup !== linkItem[1].rowEL.collectGroup) { // 起点终点不在同个收藏栏 + if (linkItem[0].rowEL.collectGroup === '2') { + linkItem[0].rowEL.translateY = Number(this.groupTitle1?.clientHeight) + Number(this.collectEl1?.clientHeight) + 27; + } else if (linkItem[1].rowEL.collectGroup === '2') { + linkItem[1].rowEL.translateY = Number(this.groupTitle1?.clientHeight) + Number(this.collectEl1?.clientHeight) + 27; + } + } + }); + } + removeAllCollectRow(): void { Array.from(this.collectRowList1).forEach(row => { row.collectEL?.click(); diff --git a/ide/src/trace/component/trace/base/RangeSelect.ts b/ide/src/trace/component/trace/base/RangeSelect.ts index c51de049b494f04476e04c1990be50efbeba02ea..8062044fa3c49fd39e2a05be7f8f414b12ea38d6 100644 --- a/ide/src/trace/component/trace/base/RangeSelect.ts +++ b/ide/src/trace/component/trace/base/RangeSelect.ts @@ -341,6 +341,7 @@ export class RangeSelect { } } TraceRow.rangeSelectObject = rangeSelect; + SpAiAnalysisPage.selectChangeListener(rangeSelect.startNS!, rangeSelect.endNS!); result = true; } else { result = false; diff --git a/ide/src/trace/component/trace/base/TraceRow.ts b/ide/src/trace/component/trace/base/TraceRow.ts index 93943404f02ed7f0e38ee81fedfaae6ae82342e0..da879a1d73e91fdf7b06afbfdc2d6bf671704519 100644 --- a/ide/src/trace/component/trace/base/TraceRow.ts +++ b/ide/src/trace/component/trace/base/TraceRow.ts @@ -123,6 +123,7 @@ export class TraceRow extends HTMLElement { static ROW_TYPE_HANG_INNER = 'hang-inner'; static ROW_TYPE_CLOCK = 'clock'; static ROW_TYPE_XPOWER = 'xpower'; + static ROW_TYPE_XPOWER_SYSTEM_GROUP = 'xpower-system-group'; static ROW_TYPE_XPOWER_SYSTEM = 'xpower-system'; static ROW_TYPE_IRQ_GROUP = 'irq-group'; static ROW_TYPE_IRQ = 'irq'; diff --git a/ide/src/trace/component/trace/base/TraceSheet.ts b/ide/src/trace/component/trace/base/TraceSheet.ts index dbd71a4dff81f35e6b4fed8185074caf0ca8900e..aae578e1b8f9c65d5dbbc7c644344a626b7357f1 100644 --- a/ide/src/trace/component/trace/base/TraceSheet.ts +++ b/ide/src/trace/component/trace/base/TraceSheet.ts @@ -144,14 +144,9 @@ export class TraceSheet extends BaseElement { displayTab(...names: string[]): T { this.setMode('max'); - if (names.includes('box-flag') || names.includes('tabpane-current')) { - this.showUploadSoBt(this.selection); - this.showSwitchProcessBt(this.selection); - } else { - this.showOptionsBt(null); - this.showUploadSoBt(null); - this.showSwitchProcessBt(null); - } + this.showOptionsBt(this.selection); + this.showUploadSoBt(this.selection); + this.showSwitchProcessBt(this.selection); this.shadowRoot ?.querySelectorAll('#tabs lit-tabpane') .forEach((it) => (it.hidden = !names.some((k) => k === it.id))); @@ -692,7 +687,7 @@ export class TraceSheet extends BaseElement { // @ts-ignore this.displayTab('current-selection').setDmaFenceData(data, rowData); displayXpowerData = (data: XpowerStruct): Promise => - this.displayTab('current-selection').setXpowerData(data); + this.displayTab('current-selection').setXpowerData(data); displayPerfToolsData = (data: PerfToolStruct): void => this.displayTab('current-selection').setPerfToolsData(data); displayIrqData = (data: IrqStruct): void => diff --git a/ide/src/trace/component/trace/base/TraceSheetConfig.ts b/ide/src/trace/component/trace/base/TraceSheetConfig.ts index fbd8969a4e707b4e6aaccbfdd33aeb3817f0aa4b..f1d1af535ec72fc69aaa0d005bbdf98d010094f1 100644 --- a/ide/src/trace/component/trace/base/TraceSheetConfig.ts +++ b/ide/src/trace/component/trace/base/TraceSheetConfig.ts @@ -688,11 +688,6 @@ export let tabConfig: { type: TabPaneHiSysEventSummary, require: (param: SelectionParam) => param.hiSysEvents.length > 0, }, - 'tabpane-binders': { - title: 'Thread Binders', - type: TabPaneBinders, - require: (param: SelectionParam) => param.threadIds.length > 0, - }, 'tabpane-gpufreq': { title: 'Gpufreq Usage', type: TabPaneGpufreq, diff --git a/ide/src/trace/component/trace/base/shadowRootInput.ts b/ide/src/trace/component/trace/base/shadowRootInput.ts index fa3459267f6437aaff46bf622074da96e958a50a..53984ee1702e81ece0bab3057e4c78e9a49c7b6f 100644 --- a/ide/src/trace/component/trace/base/shadowRootInput.ts +++ b/ide/src/trace/component/trace/base/shadowRootInput.ts @@ -1,5 +1,3 @@ -import { BaseElement } from "../../../../base-ui/BaseElement"; - /* * Copyright (C) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,16 +12,23 @@ import { BaseElement } from "../../../../base-ui/BaseElement"; * See the License for the specific language governing permissions and * limitations under the License. */ +import { BaseElement } from "../../../../base-ui/BaseElement"; +import { SpSystemTrace } from "../../SpSystemTrace"; export class shadowRootInput { public static preventBubbling(page: BaseElement | Element) { let pageInputList = shadowRootInput.findInputListInShadowDOM(page); + let sp = document?.querySelector("body > sp-application")?.shadowRoot?.querySelector("#sp-system-trace") as SpSystemTrace; pageInputList.forEach(input => { - input.addEventListener('keydown', (e) => e.stopPropagation()); - input.addEventListener('keyup', (e) => e.stopPropagation()); + input.addEventListener('focus', (e) => { + sp.keyboardEnable = false; + }); + input.addEventListener('blur', (e) => { + sp.keyboardEnable = true; + }); }); } - public static findInputListInShadowDOM(startNode: BaseElement | Element | null) { - let queue: (Element | null)[] = [startNode]; + public static findInputListInShadowDOM(page: BaseElement | Element | null) { + let queue: (Element | null)[] = [page]; let inputList: Element[] = []; while (queue.length > 0) { let currentNode = queue.shift(); // 从队列中取出一个节点 diff --git a/ide/src/trace/component/trace/search/Search.ts b/ide/src/trace/component/trace/search/Search.ts index f272f0147b82636a55f68d9b19894af007afd6ce..03c14b4251aabae0c5002551266fa3dbc9bb33b2 100644 --- a/ide/src/trace/component/trace/search/Search.ts +++ b/ide/src/trace/component/trace/search/Search.ts @@ -26,7 +26,7 @@ const LOCAL_STORAGE_SEARCH_KEY = 'search_key'; let timerId: unknown = null; @element('lit-search') export class LitSearch extends BaseElement { - valueChangeHandler: ((str: string) => void) | undefined | null; + valueChangeHandler: ((str: string, id?: number) => void) | undefined | null; private search: HTMLInputElement | undefined | null; private _total: number = 0; private _index: number = 0; @@ -200,7 +200,7 @@ export class LitSearch extends BaseElement { private searchKeyupListener(e: unknown): void { timerId = null; // @ts-ignore - if (e.keyCode === 13 ) { + if (e.keyCode === 13) { this.updateSearchList(this.search!.value); // @ts-ignore if (e.shiftKey) { @@ -359,6 +359,7 @@ export class LitSearch extends BaseElement { this._retarge_index!.value = ''; }, 2000); } + SpSystemTrace.isKeyUp = true; // @ts-ignore e.target.blur(); } diff --git a/ide/src/trace/component/trace/sheet/TabPaneCurrent.ts b/ide/src/trace/component/trace/sheet/TabPaneCurrent.ts index 22d9c57e68562fac6e6ea72be4b6e0770610954a..a9bed5c3ad8957ac130d3f67d78cf12896a6fcae 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneCurrent.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneCurrent.ts @@ -102,6 +102,10 @@ export class TabPaneCurrent extends BaseElement { if (this.slicesTimeList.length === 0) { return; } + // @ts-ignore + if((window as unknown).flagInputFocus){ + return; + } let tr = this.panelTable!.shadowRoot!.querySelectorAll('.tr') as NodeListOf; // 第一个tr是移除全部,所以跳过,从第二个tr开始,和this.slicesTimeList数组的第一个对应……,所以i从1开始,在this.slicesTimeList数组中取值时用i-1 for (let i = 1; i < tr.length; i++) { @@ -218,9 +222,6 @@ export class TabPaneCurrent extends BaseElement { this.systemTrace!.slicesList = this.slicesTimeList || []; // @ts-ignore this.slicesTimeList[i - 1].text = event?.target.value; - window.publish(window.SmartEvent.UI.KeyboardEnable, { - enable: true, - }); document.dispatchEvent(new CustomEvent('slices-change', { detail: this.slicesTimeList[i - 1] })); this.systemTrace?.refreshCanvas(true); diff --git a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts index b002feaa2b91e0f13da8a20110b41f2a7d4983a5..4792d72257d116b21e0e088de855ff1f55096f82 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts @@ -133,6 +133,7 @@ export class TabPaneCurrentSelection extends BaseElement { private bootTime: number = 0; private funcDetailMap: Map> = new Map(); private topChainStr: string = ''; + private fpsResult: Array = []; set data(selection: unknown) { // @ts-ignore @@ -413,6 +414,36 @@ export class TabPaneCurrentSelection extends BaseElement { } else { this.handleNonBinder(data, list, name, information); } + } else if (data.funName!.startsWith("H:Et") && (data.depth === 1 || data.depth === 0)) { + list.push({ + name: 'StartTime(Relative)', + value: getTimeString(data.startTs || 0), + }); + this.createStartTimeNode(list, data.startTs || 0, FUN_TRANSF_BTN_ID, FUN_STARTTIME_ABSALUTED_ID); + list.push({ + name: 'Duration', + value: getTimeString(data.dur || 0), + }); + data.funName!.split(',').map((item, index) => ({ + name: [ + 'Sender tid', + 'Send time', + 'Expect handle time', + 'Task name/ID', + 'Prio', + 'Sender' + ][index], + value: item, + })).forEach((item, index) => { + if (index === 0) { + item.value = item.value.split(':').at(-1)!; + } + list.push(item); + }); + this.currentSelectionTbl!.dataSource = list; + // @ts-ignore + let startTimeAbsolute = (data.startTs || 0) + (window as unknown).recordStartNS; + this.addClickToTransfBtn(startTimeAbsolute, FUN_TRANSF_BTN_ID, FUN_STARTTIME_ABSALUTED_ID); } else { this.setTableHeight('auto'); list.push({ name: 'Name', value: name }); @@ -839,9 +870,9 @@ export class TabPaneCurrentSelection extends BaseElement { let list: unknown[] = []; list.push({ name: 'StartTime(Relative)', - value: getTimeString(data.startNS || 0), + value: getTimeString(data.startTime || 0), }); - this.createStartTimeNode(list, data.startNS || 0, CLOCK_TRANSF_BTN_ID, CLOCK_STARTTIME_ABSALUTED_ID); + this.createStartTimeNode(list, data.startTime || 0, CLOCK_TRANSF_BTN_ID, CLOCK_STARTTIME_ABSALUTED_ID); list.push({ name: 'Duration', value: getTimeString(data.dur || 0) }); list.push({ name: 'Hang type', @@ -869,7 +900,7 @@ export class TabPaneCurrentSelection extends BaseElement { this.currentSelectionTbl!.dataSource = list; // @ts-ignore - let startTimeAbsolute = (data.startNS || 0) + window.recordStartNS; + let startTimeAbsolute = (data.startTime || 0) + window.recordStartNS; this.addClickToTransfBtn(startTimeAbsolute, CLOCK_TRANSF_BTN_ID, CLOCK_STARTTIME_ABSALUTED_ID); this.hangScrollHandler(data, sp, scrollCallback); } @@ -894,7 +925,7 @@ export class TabPaneCurrentSelection extends BaseElement { } const findEntry = funcRow?.dataListCache.find((funcstruct: unknown) => { //@ts-ignore - return (funcstruct.startTs === data.startNS && funcstruct.funName === data.content); + return (funcstruct.startTs === data.startTime && funcstruct.funName === data.content); }) scrollCallback({ //@ts-ignore @@ -1853,7 +1884,16 @@ export class TabPaneCurrentSelection extends BaseElement { }); list.push({ name: 'Duration', value: `${Utils.getTimeString(data.dur || 0)}` }); if (data.status === 'Completion delay') { + let queryJoinName = `${data.frameInfo?.split(':')[1]}: ${data.name?.split(':')![1]}`; let frameFpsMessage = data.frameInfo?.split(':'); + await queryFpsSourceList(data.inputTime, data.endTime, queryJoinName).then((result) => { + if (result.length > 0) { + this.isFpsAvailable = true; + this.fpsResult = result; + } else { + this.isFpsAvailable = false; + } + }); if (frameFpsMessage) { if (frameFpsMessage[1] !== '0') { if (this.isFpsAvailable) { @@ -1879,33 +1919,25 @@ export class TabPaneCurrentSelection extends BaseElement { } private fpsClickEvent(data: FrameAnimationStruct, scrollCallback: Function): void { - let queryJoinName = `${data.frameInfo?.split(':')[1]}: ${data.name?.split(':')![1]}`; let recordNs: number = Utils.getInstance().getRecordStartNS(); - this.currentSelectionTbl?.shadowRoot?.querySelector('#fps-jump')?.addEventListener('click', () => { - queryFpsSourceList(data.inputTime, data.endTime, queryJoinName).then((result) => { - if (result.length > 0) { - this.isFpsAvailable = true; - let pt: { - pid: number; - tid: number; - name: string; - ts: number; - dur: number; - depth: number; - } = result[0]; - scrollCallback({ - pid: pt.tid, - tid: pt.tid, - dur: pt.dur, - type: 'func', - depth: pt.depth, - funName: pt.name, - startTs: pt.ts - recordNs, - keepOpen: true, - }); - } else { - this.isFpsAvailable = false; - } + this.currentSelectionTbl?.shadowRoot?.querySelector('#fps-jump')?.addEventListener('click', () => {// @ts-ignore + let pt: { + pid: number; + tid: number; + name: string; + ts: number; + dur: number; + depth: number; + } = this.fpsResult[0]; + scrollCallback({ + pid: pt.tid, + tid: pt.tid, + dur: pt.dur, + type: 'func', + depth: pt.depth, + funName: pt.name, + startTs: pt.ts - recordNs, + keepOpen: true, }); }); } diff --git a/ide/src/trace/component/trace/sheet/TabPaneDataCut.ts b/ide/src/trace/component/trace/sheet/TabPaneDataCut.ts index 7fa2a3c4e5a9edbbd17670d1b7c6baecb2b99749..3e71ecea68f00b6efddcb2603c84a7ad0be5074a 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneDataCut.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneDataCut.ts @@ -68,8 +68,8 @@ export class TabPaneDataCut extends BaseElement { this.tabContainer?.appendChild(this.currentTabPane); this.currentTabPane.data = this.currentSelection; } - let tabs = document.querySelector("body > sp-application")?.shadowRoot?.querySelector("#sp-system-trace")?.shadowRoot?.querySelector("div > trace-sheet")?.shadowRoot?.querySelector("#tabs") as LitTabs; - let pane = document.querySelector("body > sp-application")?.shadowRoot?.querySelector("#sp-system-trace")?.shadowRoot?.querySelector("div > trace-sheet")?.shadowRoot?.querySelector("#tabpane-datacut") as LitTabpane; + let tabs = document.querySelector('body > sp-application')?.shadowRoot?.querySelector('#sp-system-trace')?.shadowRoot?.querySelector('div > trace-sheet')?.shadowRoot?.querySelector('#tabs') as LitTabs; + let pane = document.querySelector('body > sp-application')?.shadowRoot?.querySelector('#sp-system-trace')?.shadowRoot?.querySelector('div > trace-sheet')?.shadowRoot?.querySelector('#tabpane-datacut') as LitTabpane; tabs.activeByKey(pane.key); } } diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneCounterSample.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneCounterSample.ts index 6e63e843839236c57d662067179df506463dbc1f..13c68b26456d5f96890e24ecd63a3eae28c4e3e6 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneCounterSample.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneCounterSample.ts @@ -278,6 +278,14 @@ export class TabPaneCounterSample extends BaseElement { // @ts-ignore return sortByColumnRightData.value - sortByColumnLeftData.value; } + } else if (key === 'count') { + if (type === 1) { + // @ts-ignore + return sortByColumnLeftData.count - sortByColumnRightData.count; + } else { + // @ts-ignore + return sortByColumnRightData.count - sortByColumnLeftData.count; + } } else { return 0; } diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts index 3f107c5b2a691df4d86a0a64c1115e3dbddea01c..98eebd75fc74f319ad124fdb8bb60bed8eb39612 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts @@ -157,6 +157,7 @@ export class TabPaneFrequencySample extends BaseElement { async queryDataByDB(frqSampleParam: SelectionParam | unknown): Promise { let sampleMap = new Map(); + let weightMap = new Map(); let frqSampleList: unknown[] = []; this.frequencySampleTbl!.loading = true; if (this.frequencySampleClickType) { @@ -176,6 +177,7 @@ export class TabPaneFrequencySample extends BaseElement { this.freqResult = result; // @ts-ignore frqSampleParam.cpuFreqFilterIds.forEach((a: number): void => { + weightMap.set(`${a}`, { counter: '', filterId: a }); this.getInitTime( //@ts-ignore result.filter((f) => f.filterId === a), @@ -184,9 +186,33 @@ export class TabPaneFrequencySample extends BaseElement { frqSampleParam ); }); + let tmpCpuArr = Array.from(sampleMap.entries()); + let weightMapArr = Array.from(weightMap.entries()); + console.log(tmpCpuArr, weightMap); + for (let j = 0; j < weightMapArr.length; j++) { + // @ts-ignore + let singleCpuArr = tmpCpuArr.filter((item) => item[1].filterId && item[1].filterId === Number(weightMapArr[j][1].filterId)); + // console.log(singleCpuArr); + let tmpTotalTime = 0; + let tmpTotalCount = 0; + for (let i = 0; i < singleCpuArr.length; i++) { + // @ts-ignore + tmpTotalTime += singleCpuArr[i][1].time; + // @ts-ignore + tmpTotalCount += singleCpuArr[i][1].time / 1000000 * singleCpuArr[i][1].value; + } + // @ts-ignore + let tmpPosition = tmpCpuArr.findIndex(item => item[1].filterId === weightMapArr[j][1].filterId); + // @ts-ignore + tmpCpuArr.splice(tmpPosition, 0, [`${weightMapArr[j][1].filterId}-0`, { counter: `${singleCpuArr[0][1].counter}:( WA )`, time: tmpTotalTime, valueStr: ColorUtils.formatNumberComma(Math.round(tmpTotalCount / (tmpTotalTime / 1000000)))}]); + }; + sampleMap = new Map(tmpCpuArr); sampleMap.forEach((a): void => { // @ts-ignore - a.timeStr = parseFloat((a.time / 1000000.0).toFixed(6)); + if (a.time) { + // @ts-ignore + a.timeStr = parseFloat((a.time / 1000000.0).toFixed(6)); + } frqSampleList.push(a); }); this.frequencySampleSource = frqSampleList; @@ -316,7 +342,13 @@ export class TabPaneFrequencySample extends BaseElement { if (this.freqBusyDataList.length > 0) { this.frequencySampleTbl!.recycleDataSource.forEach((value): void => { // @ts-ignore - value.busyTimeStr = type ? value.busyTime : '-'; + if(value.counter.includes('( WA )')){ + // @ts-ignore + value.busyTimeStr = '-' + }else { + // @ts-ignore + value.busyTimeStr = type ? value.busyTime : '-'; + } res.push(value); }); this.frequencySampleTbl!.recycleDataSource = res; diff --git a/ide/src/trace/component/trace/sheet/hang/TabPaneHang.html.ts b/ide/src/trace/component/trace/sheet/hang/TabPaneHang.html.ts index f085a0424759d78694d6cb06f7b02cffc34d6409..b5624a692885f37f7f8b2e9e60dbd77164d18258 100644 --- a/ide/src/trace/component/trace/sheet/hang/TabPaneHang.html.ts +++ b/ide/src/trace/component/trace/sheet/hang/TabPaneHang.html.ts @@ -100,25 +100,25 @@ option {
- + - + - + - + - + - + - + - + - + - + `; diff --git a/ide/src/trace/component/trace/sheet/hang/TabPaneHang.ts b/ide/src/trace/component/trace/sheet/hang/TabPaneHang.ts index 4a3d5b1ef3093514ca9a91335dd0e0c82b27370f..4dc767a20b8771c73eb494ebfa1addec9dc5e305 100644 --- a/ide/src/trace/component/trace/sheet/hang/TabPaneHang.ts +++ b/ide/src/trace/component/trace/sheet/hang/TabPaneHang.ts @@ -62,8 +62,8 @@ export class TabPaneHang extends BaseElement { const filter = new Set([...selectionParam.hangMapData.keys()].map(key => key.split(' ').at(-1))); ret = ret.filter(struct => ( filter.has(`${struct.pid ?? 0}`) && - ((struct.startNS ?? 0) <= selectionParam.rightNs) && - (selectionParam.leftNs <= ((struct.startNS ?? 0) + (struct.dur ?? 0))) + ((struct.startTime ?? 0) <= selectionParam.rightNs) && + (selectionParam.leftNs <= ((struct.startTime ?? 0) + (struct.dur ?? 0))) )); if (ret.length === 0) { @@ -88,7 +88,7 @@ export class TabPaneHang extends BaseElement { const hangData = data as HangStructInPane; return ColorUtils.getHangColor(hangData.type as HangType); }; - this.hangTbl!.itemTextHandleMap.set('startNS', (startTs) => { + this.hangTbl!.itemTextHandleMap.set('startTime', (startTs) => { // @ts-ignore return ns2Timestamp(startTs); }); @@ -97,14 +97,14 @@ export class TabPaneHang extends BaseElement { let data = e.detail.data as HangStructInPane; if (data) { let pointX: number = ns2x( - data.startNS || 0, + data.startTime || 0, TraceRow.range!.startNS, TraceRow.range!.endNS, TraceRow.range!.totalNS, new Rect(0, 0, TraceRow.FRAME_WIDTH, 0), ); this.traceSheetEl!.systemLogFlag = new Flag( - Math.floor(pointX), 0, 0, 0, data.startNS, '#999999', '', true, '', + Math.floor(pointX), 0, 0, 0, data.startTime, '#999999', '', true, '', ); this.spSystemTrace?.refreshCanvas(false); } @@ -113,6 +113,15 @@ export class TabPaneHang extends BaseElement { tbl!.addEventListener('scroll', () => { this.tableTitleTimeHandle?.(); }); + this.hangTbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key; + // @ts-ignore + this.sortType = evt.detail.sort; + // @ts-ignore + this.sortByColumn(evt.detail.key, evt.detail.sort); + this.refreshHangTab(); + }); } initElements(): void { @@ -264,14 +273,111 @@ export class TabPaneHang extends BaseElement { }, dur); }; } + + sortByColumn(key: string, type: number): void { + if (type === 0) { + this.hangTbl!.recycleDataSource = this.filterData; + } else { + let arr = Array.from(this.filterData); + arr.sort((a, b): number => { + if (key === "startTime") { + if (type === 1) { + // @ts-ignore + return a.startTime - b.startTime; + } else { + // @ts-ignore + return b.startTime - a.startTime; + } + } else if (key === 'durStr') { + if (type === 1) { + // @ts-ignore + return a.dur - b.dur; + } else { + // @ts-ignore + return b.dur - a.dur; + } + } else if (key === 'type') { + if (type === 1) { + // @ts-ignore + return a[key].localeCompare(b[key]); + } else { + // @ts-ignore + return b[key].localeCompare(a[key]); + } + } else if (key === 'pname') { + if (type === 1) { + // @ts-ignore + return a[key].localeCompare(b[key]); + } else { + // @ts-ignore + return b[key].localeCompare(a[key]); + } + } else if (key === 'sendEventTid') { + if (type === 1) { + // @ts-ignore + return Number(a.sendEventTid) - Number(b.sendEventTid); + } else { + // @ts-ignore + return Number(b.sendEventTid) - Number(a.sendEventTid); + } + } else if (key === 'sendTime') { + if (type === 1) { + // @ts-ignore + return Number(a.sendTime) - Number(b.sendTime); + } else { + // @ts-ignore + return Number(b.sendTime) - Number(a.sendTime); + } + } else if (key === 'expectHandleTime') { + if (type === 1) { + // @ts-ignore + return Number(a.expectHandleTime) - Number(b.expectHandleTime); + } else { + // @ts-ignore + return Number(b.expectHandleTime) - Number(a.expectHandleTime); + } + } else if (key === 'taskNameId') { + if (type === 1) { + // @ts-ignore + return a[key].localeCompare(b[key]); + } else { + // @ts-ignore + return b[key].localeCompare(a[key]); + } + } else if (key === 'prio') { + if (type === 1) { + // @ts-ignore + return a.prio - b.prio; + } else { + // @ts-ignore + return b.prio - a.prio; + } + } else if (key === 'caller') { + if (type === 1) { + // @ts-ignore + return a[key].localeCompare(b[key]); + } else { + // @ts-ignore + return b[key].localeCompare(a[key]); + } + } else { + return 0; + } + + }); + + this.hangTbl!.recycleDataSource = arr; + } + } } let defaultIndex: number = 1; let tableTimeOut: number = 50; export class HangStructInPane { - startNS: number = 0; - dur: string = '0'; + startTime: number = 0; + dur: number = 0; + durStr: string = '0'; pname: string = 'Process'; type: string; sendEventTid: string; @@ -282,8 +388,9 @@ export class HangStructInPane { caller: string; constructor(parent: HangStruct) { - this.startNS = parent.startNS ?? this.startNS; - this.dur = getTimeString(parent.dur ?? 0); + this.startTime = parent.startTime ?? this.startTime; + this.dur = parent.dur ?? 0; + this.durStr = getTimeString(parent.dur ?? 0); this.pname = `${parent.pname ?? this.pname} ${parent.pid ?? ''}`.trim(); this.type = SpHangChart.calculateHangType(parent.dur ?? 0); [this.sendEventTid, this.sendTime, this.expectHandleTime, this.taskNameId, this.prio, this.caller] = (parent.content ?? ',0,0,,,').split(',').map(i => i.trim()); diff --git a/ide/src/trace/component/trace/sheet/hang/TabPaneHangSummary.ts b/ide/src/trace/component/trace/sheet/hang/TabPaneHangSummary.ts index 4304bd25b82916a27b728ff750b14011ea607ddb..d66280f1f3e0ed1e585c8dc512e9fb91721aa263 100644 --- a/ide/src/trace/component/trace/sheet/hang/TabPaneHangSummary.ts +++ b/ide/src/trace/component/trace/sheet/hang/TabPaneHangSummary.ts @@ -54,8 +54,8 @@ export class TabPaneHangSummary extends BaseElement { const filter = new Set([...selectionParam.hangMapData.keys()].map(key => key.split(' ').at(-1))); ret = ret.filter(struct => ( filter.has(`${struct.pid ?? 0}`) && - ((struct.startNS ?? 0) <= selectionParam.rightNs) && - (selectionParam.leftNs <= ((struct.startNS ?? 0) + (struct.dur ?? 0))) + ((struct.startTime ?? 0) <= selectionParam.rightNs) && + (selectionParam.leftNs <= ((struct.startTime ?? 0) + (struct.dur ?? 0))) )); this.systemHangSource = ret; if (filter.size > 0 && selectionParam) { diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts index 05037d71d2d73e3b48a85f45245fa21e878db32e..a2ae261cdba15d205e08991700d8f764185a55ad 100644 --- a/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts @@ -62,6 +62,8 @@ export class TabPanePerfAnalysis extends BaseElement { private hideThreadCheckBox: LitCheckBox | undefined | null; private checkBoxs: NodeListOf | undefined | null; private tableArray: NodeListOf | undefined | null; + private isComplete: boolean = true; + private currentSelectionParam: SelectionParam | undefined | null; set data(val: SelectionParam) { if (val === this.currentSelection) { @@ -85,7 +87,9 @@ export class TabPanePerfAnalysis extends BaseElement { this.perfAnalysisRange!.textContent = `Selected range: ${parseFloat( ((val.rightNs - val.leftNs) / 1000000.0).toFixed(5) )} ms`; - if (!this.callChainMap) { + this.currentSelectionParam = val; + if (!this.callChainMap && this.isComplete) { + this.isComplete = false; this.getCallChainDataFromWorker(val); } } @@ -1090,6 +1094,11 @@ export class TabPanePerfAnalysis extends BaseElement { private getCallChainDataFromWorker(val: SelectionParam): void { this.getDataByWorker(val, (results: unknown) => { + this.isComplete = true; + if (this.currentSelectionParam !== val) { + this.getCallChainDataFromWorker(this.currentSelectionParam!); + return; + } // @ts-ignore this.processData = results; if (this.processData.length === 0) { @@ -1099,6 +1108,7 @@ export class TabPanePerfAnalysis extends BaseElement { this.hideProcessCheckBox?.removeAttribute('disabled'); this.hideThreadCheckBox?.removeAttribute('disabled'); } + this.progressEL!.loading = false; this.getHiperfProcess(val); }); } @@ -1121,7 +1131,6 @@ export class TabPanePerfAnalysis extends BaseElement { ]; procedurePool.submitWithName('logic0', 'perf-action', args, undefined, (results: unknown) => { handler(results); - this.progressEL!.loading = false; }); } diff --git a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatisticAnalysis.ts b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatisticAnalysis.ts index 9ce9c1a00744c3d36e78ca7c388d0a0ee702ec25..852d6ad5ce9a47eeaf815524930f862523330446 100644 --- a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatisticAnalysis.ts +++ b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatisticAnalysis.ts @@ -135,11 +135,13 @@ export class TabPaneNMStatisticAnalysis extends BaseElement { set data(statisticAnalysisParam: SelectionParam) { if (statisticAnalysisParam === this.currentSelection) { - // @ts-ignore - this.eventTypeData.unshift(this.typeStatisticsData); - this.typeUsageTbl!.recycleDataSource = this.eventTypeData; - // @ts-ignore - this.eventTypeData.shift(this.typeStatisticsData); + if (this.eventTypeData) { + // @ts-ignore + this.eventTypeData.unshift(this.typeStatisticsData); + this.typeUsageTbl!.recycleDataSource = this.eventTypeData; + // @ts-ignore + this.eventTypeData.shift(this.typeStatisticsData); + } return; } if (this.nmTableArray) { diff --git a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.ts b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.ts index 9890791fff5223101f7eb10f010a04f75bb12752..8b989edc8f927a8e72d7be92031bc13b42624513 100644 --- a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.ts +++ b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.ts @@ -28,6 +28,8 @@ import { queryNativeHookStatisticsMalloc, queryNativeHookStatisticsSubType, } from '../../../../database/sql/NativeHook.sql'; +import { queryHeapSizeByIpid } from '../../../../database/sql/SqlLite.sql'; + @element('tabpane-native-statistics') export class TabPaneNMStatstics extends BaseElement { @@ -48,18 +50,15 @@ export class TabPaneNMStatstics extends BaseElement { this.currentSelection = nativeStatisticsParam; this.allMax = 0; TabPaneNMSampleList.clearData(); - SpNativeMemoryChart.EVENT_HEAP.map((heap) => { - this.allMax += heap.sumHeapSize; - }); + this.recordEventHeap(nativeStatisticsParam.nativeMemoryCurrentIPid); if (nativeStatisticsParam.nativeMemory.length > 0) { Utils.getInstance().setCurrentSelectIPid(this.currentSelectIPid); Utils.getInstance().initResponseTypeList(nativeStatisticsParam); } if (this.nativeStatisticsTbl) { // @ts-ignore - this.nativeStatisticsTbl.shadowRoot.querySelector('.table').style.height = `${ - this.parentElement!.clientHeight - 25 - }px`; + this.nativeStatisticsTbl.shadowRoot.querySelector('.table').style.height = `${this.parentElement!.clientHeight - 25 + }px`; // @ts-ignore this.nativeStatisticsTbl.recycleDataSource = []; } @@ -67,6 +66,13 @@ export class TabPaneNMStatstics extends BaseElement { this.queryData(nativeStatisticsParam); } + async recordEventHeap(ipid: number) { + SpNativeMemoryChart.EVENT_HEAP = await queryHeapSizeByIpid(ipid); + SpNativeMemoryChart.EVENT_HEAP.map((heap) => { + this.allMax += heap.sumHeapSize; + }); + } + queryData(nativeStatisticsParam: SelectionParam): void { Promise.all([ queryNativeHookStatistics(nativeStatisticsParam.leftNs, nativeStatisticsParam.rightNs, this.currentSelectIPid), @@ -187,7 +193,7 @@ export class TabPaneNMStatstics extends BaseElement { this.processHookData(hook, anonymous); } } - if (all?.maxStr === '' && all?.max === 0) { + if (all?.maxStr === '' && all?.max === 0) { all.maxStr = Utils.getByteWithUnit(all?.max); } if (heap?.maxStr === '' && heap?.max === 0) { diff --git a/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts b/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts index e876bacb8043a31a71ed2bf7051da952d19d2365..2ca0e4998c4f595bf8e7ed198c18d222fdd84441 100644 --- a/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts +++ b/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts @@ -74,6 +74,10 @@ export class TabPaneSlices extends BaseElement { this.slicesTbl = this.shadowRoot?.querySelector('#tb-slices'); this.slicesRange = this.shadowRoot?.querySelector('#time-range'); let slicesInput = this.shadowRoot?.querySelector('#filterName'); + let spApplication = document.querySelector('body > sp-application'); + let spSystemTrace = spApplication?.shadowRoot?.querySelector( + 'div > div.content > sp-system-trace' + ) as SpSystemTrace; this.slicesTbl!.addEventListener('column-click', (evt) => { // @ts-ignore this.sortByColumn(evt.detail); @@ -204,7 +208,6 @@ export class TabPaneSlices extends BaseElement { let search = spApplication!.shadowRoot?.querySelector('#lit-search') as LitSearch; spSystemTrace?.visibleRows.forEach((it) => { it.highlight = false; - it.draw(); }); spSystemTrace?.timerShaftEL?.removeTriangle('inverted'); // @ts-ignore @@ -234,6 +237,9 @@ export class TabPaneSlices extends BaseElement { return; } this.slicesTblFreshSearchSelect(search, sliceRowList, data, spSystemTrace); + spSystemTrace?.visibleRows.forEach((it) => { + it.draw(); + }); }); } diff --git a/ide/src/trace/component/trace/sheet/xpower/TabPaneXpowerCounter.ts b/ide/src/trace/component/trace/sheet/xpower/TabPaneXpowerCounter.ts index 0271347c1fe0cd4967486e00c5b87b6dce3993fe..ccb89b6b26b282204485d26fabc2fc0118f210d2 100644 --- a/ide/src/trace/component/trace/sheet/xpower/TabPaneXpowerCounter.ts +++ b/ide/src/trace/component/trace/sheet/xpower/TabPaneXpowerCounter.ts @@ -123,21 +123,22 @@ export class TabPaneXpowerCounter extends BaseElement { selectCounterData.count = `${list.length}`; // @ts-ignore selectCounterData.last = `${list[list.length - 1].value}`; - selectCounterData.delta = `${parseInt(selectCounterData.last) - parseInt(selectCounterData.first)}`; - selectCounterData.rate = (parseInt(selectCounterData.delta) / ((range * 1.0) / 1000000000)).toFixed(4); + selectCounterData.delta = `${(Number(selectCounterData.last) - Number(selectCounterData.first)).toFixed(4)}`; + selectCounterData.rate = (Number(selectCounterData.delta) / ((range * 1.0) / 1000000000)).toFixed(4); // @ts-ignore selectCounterData.min = `${first.value}`; - selectCounterData.max = '0'; + // @ts-ignore + selectCounterData.max = `${first.value}`; let weightAvg = 0.0; for (let i = 0; i < list.length; i++) { let counter = list[i]; // @ts-ignore - if (counter.value < parseInt(selectCounterData.min)) { + if (counter.value < Number(selectCounterData.min)) { // @ts-ignore selectCounterData.min = counter.value.toString(); } // @ts-ignore - if (counter.value > parseInt(selectCounterData.max)) { + if (counter.value > Number(selectCounterData.max)) { // @ts-ignore selectCounterData.max = counter.value.toString(); } diff --git a/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts b/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts index 00c233f84904d6b78ae1a53ec3bb08e697c76659..777db737caa05078673c26fa6174aac31e4fb2f3 100644 --- a/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts +++ b/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts @@ -61,6 +61,10 @@ export class TabPaneFlag extends BaseElement { if (this.flagList.length === 0) { return; } + // @ts-ignore + if((window as unknown).flagInputFocus){ + return; + } let tr = this.panelTable!.shadowRoot!.querySelectorAll('.tr') as NodeListOf; // 第一个tr是移除全部,所以跳过,从第二个tr开始,和this.slicestimeList数组的第一个对应……,所以i从1开始,在this.slicestimeList数组中取值时用i-1 for (let i = 1; i < tr.length; i++) { diff --git a/ide/src/trace/database/data-trafic/HangDataReceiver.ts b/ide/src/trace/database/data-trafic/HangDataReceiver.ts index 852224544ad31a5c0c83621c846044a26e874ab7..61735ca8e8763cbdbb48016b37f1e36442947184 100644 --- a/ide/src/trace/database/data-trafic/HangDataReceiver.ts +++ b/ide/src/trace/database/data-trafic/HangDataReceiver.ts @@ -18,7 +18,7 @@ import { Args } from './CommonArgs'; export const chartHangDataSql = (args: Args): string => ` SELECT c.id as id, - c.ts - r.start_ts as startNS, + c.ts - r.start_ts as startTime, c.dur as dur, t.tid as tid, t.name as tname, @@ -39,7 +39,7 @@ WHERE export interface HangSQLStruct { id: number; - startNS: number; + startTime: number; dur: number; tid: number; pid: number; @@ -68,7 +68,7 @@ export function hangDataReceiver(data: unknown, proc: Function): void { if (data.params.queryAll) { res = list.filter( //@ts-ignore - (it) => it.startNS + it.dur >= data.params.selectStartNS && it.startNS <= data.params.selectEndNS + (it) => it.startTime + it.dur >= data.params.selectStartNS && it.startTime <= data.params.selectEndNS ); } else { @@ -90,7 +90,7 @@ function arrayBufferHandler(data: unknown, res: HangSQLStruct[], transfer: boole // @ts-ignore let id = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.id); // @ts-ignore - let startNS = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startNS); + let startTime = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startTime); // @ts-ignore let dur = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.dur); // @ts-ignore @@ -99,7 +99,7 @@ function arrayBufferHandler(data: unknown, res: HangSQLStruct[], transfer: boole let pid = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.pid); res.forEach((it, i) => { id[i] = it.id; - startNS[i] = it.startNS; + startTime[i] = it.startTime; dur[i] = it.dur; tid[i] = it.tid; pid[i] = it.pid; @@ -112,7 +112,7 @@ function arrayBufferHandler(data: unknown, res: HangSQLStruct[], transfer: boole action: data.action, results: { id: id.buffer, - startNS: startNS.buffer, + startTime: startTime.buffer, dur: dur.buffer, tid: tid.buffer, pid: pid.buffer, @@ -122,7 +122,7 @@ function arrayBufferHandler(data: unknown, res: HangSQLStruct[], transfer: boole }; let arg2 = [ id.buffer, - startNS.buffer, + startTime.buffer, dur.buffer, tid.buffer, pid.buffer, diff --git a/ide/src/trace/database/data-trafic/HangDataSender.ts b/ide/src/trace/database/data-trafic/HangDataSender.ts index 91ec3a2a42a7593338bbce7b5c2c91f42f79bc0d..a6d0e0cc9d7b0d7d3145c5b6b5f41ffba2073359 100644 --- a/ide/src/trace/database/data-trafic/HangDataSender.ts +++ b/ide/src/trace/database/data-trafic/HangDataSender.ts @@ -57,7 +57,7 @@ function arrayBufferHandler(buffers: unknown, len: number): HangStruct[] { // @ts-ignore let id = new Int32Array(buffers.id); // @ts-ignore - let startNS = new Float64Array(buffers.startNS); + let startTime = new Float64Array(buffers.startTime); // @ts-ignore let dur = new Float64Array(buffers.dur); // @ts-ignore @@ -67,7 +67,7 @@ function arrayBufferHandler(buffers: unknown, len: number): HangStruct[] { for (let i = 0; i < len; i += 1) { outArr.push({ id: id[i], - startNS: startNS[i], + startTime: startTime[i], dur: dur[i], tid: tid[i], pid: pid[i], diff --git a/ide/src/trace/database/sql/Hang.sql.ts b/ide/src/trace/database/sql/Hang.sql.ts index 35181e4b6176edbdb4135c5afced167148c1b322..b4cf2a0361d1fac5d4ea4d6b96b05771eb6bcb20 100644 --- a/ide/src/trace/database/sql/Hang.sql.ts +++ b/ide/src/trace/database/sql/Hang.sql.ts @@ -55,7 +55,7 @@ export const queryAllHangs = (): Promise> => query( ` SELECT c.id as id, - c.ts - r.start_ts as startNS, + c.ts - r.start_ts as startTime, c.dur as dur, t.tid as tid, p.pid as pid, diff --git a/ide/src/trace/database/sql/Memory.sql.ts b/ide/src/trace/database/sql/Memory.sql.ts index c1e3091273adefc02ab54cfea53faf3f449feca3..a8562ca423f418be7c26f06fcf516bacc9db59a6 100644 --- a/ide/src/trace/database/sql/Memory.sql.ts +++ b/ide/src/trace/database/sql/Memory.sql.ts @@ -471,6 +471,16 @@ where s.end_ts between $startTime + t.start_ts and $endTime + t.start_ts ${ipids { $startTime: startTime, $endTime: endTime } ); +// 查询是否使用插件插件 +export const queryPlugins = ( + table: string +): Promise> => + query( + 'queryPlugins', + `select 1 from ${table} limit 1`, + {} + ); + export const queryisExistsShmData = ( iPid: number ): //@ts-ignore diff --git a/ide/src/trace/database/sql/SqlLite.sql.ts b/ide/src/trace/database/sql/SqlLite.sql.ts index 15953b0784f70239c21949d2fe00a9e92aaaa6e8..cbe64a33b84bf58d6f69da985fd725c8ff38e858 100644 --- a/ide/src/trace/database/sql/SqlLite.sql.ts +++ b/ide/src/trace/database/sql/SqlLite.sql.ts @@ -119,7 +119,7 @@ export const getTabVirtualCounters = (virtualFilterIds: Array, startTime ); export const queryAllSoInitNames = (): //@ts-ignore -Promise> => { + Promise> => { return query( 'queryAllSoInitNames', ` @@ -128,7 +128,7 @@ Promise> => { }; export const queryAllSrcSlices = (): //@ts-ignore -Promise> => { + Promise> => { return query( 'queryAllSrcSlices', ` @@ -136,6 +136,29 @@ Promise> => { ); }; +export const queryHeapSizeByIpid = (ipid: number): //@ts-ignore + Promise> => { + return query( + 'queryHeapSizeByIpid', + `SELECT + event_type AS eventType, + sum(heap_size) AS sumHeapSize + FROM + native_hook h left join process p on p.ipid = h.ipid + WHERE + event_type = 'AllocEvent' and + p.ipid = ${ipid} + UNION ALL + SELECT + event_type AS eventType, + sum(heap_size) AS sumHeapSize + FROM + native_hook h left join process p on p.ipid = h.ipid + WHERE + event_type = 'MmapEvent' and + p.ipid = ${ipid}` + ); +}; /*-------------------------------------------------------------------------------------*/ export const queryHeapGroupByEvent = (type: string): Promise> => { let sql1 = ` @@ -228,7 +251,7 @@ export const querySelectTraceStats = (): Promise< export const queryCustomizeSelect = ( sql: string ): //@ts-ignore -Promise> => query('queryCustomizeSelect', sql); + Promise> => query('queryCustomizeSelect', sql); export const queryDistributedTerm = (): Promise< Array<{ @@ -339,7 +362,7 @@ export const querySystemCalls = (): Promise< ); export const queryNetWorkMaxData = (): //@ts-ignore -Promise> => + Promise> => query( 'queryNetWorkMaxData', `select @@ -351,7 +374,7 @@ Promise> => ); export const queryDiskIoMaxData = (): //@ts-ignore -Promise> => + Promise> => query( 'queryDiskIoMaxData', `select @@ -371,7 +394,7 @@ export const queryRangeTime = (): Promise> => export const queryBinderBySliceId = ( id: number ): //@ts-ignore -Promise> => + Promise> => query( 'queryBinderBySliceId', `SELECT @@ -398,7 +421,7 @@ export const queryThreadByItid = ( itid: number, ts: number ): //@ts-ignore -Promise> => + Promise> => query( 'queryThreadByItid', `SELECT @@ -419,7 +442,7 @@ export const queryBinderByArgsId = ( startTime: number, isNext: boolean ): //@ts-ignore -Promise> => { + Promise> => { let sql = `select c.ts - D.start_ts as startTs, c.dur, t.tid, @@ -437,8 +460,8 @@ where cat = 'binder' and c.argsetid = $id`; } else { sql += ' and c.ts < $startTime + D.start_ts'; } - return query('queryBinderByArgsId', sql, { $id: id, $startTime: startTime}, - { traceId : Utils.currentSelectTrace } + return query('queryBinderByArgsId', sql, { $id: id, $startTime: startTime }, + { traceId: Utils.currentSelectTrace } ); }; @@ -446,7 +469,7 @@ export const getTabPaneFilesystemStatisticsFather = ( leftNs: number, rightNs: number ): //@ts-ignore -Promise> => + Promise> => query( 'getTabPaneFilesystemStatisticsFather', ` @@ -472,7 +495,7 @@ export const getTabPaneFilesystemStatisticsChild = ( leftNs: number, rightNs: number ): //@ts-ignore -Promise> => + Promise> => query( 'getTabPaneFilesystemStatisticsChild', ` @@ -497,7 +520,7 @@ export const getTabPaneFilesystemStatisticsAll = ( leftNs: number, rightNs: number ): //@ts-ignore -Promise> => + Promise> => query( 'getTabPaneFilesystemStatisticsAll', ` @@ -519,7 +542,7 @@ export const getTabPaneFilesystemStatistics = ( rightNs: number, types: number[] ): //@ts-ignore -Promise> => + Promise> => query( 'getTabPaneFilesystemStatistics', ` @@ -550,7 +573,7 @@ export const getTabPaneIOTierStatisticsData = ( rightNs: number, diskIOipids: Array ): //@ts-ignore -Promise> => { + Promise> => { let str = ''; if (diskIOipids.length > 0) { str = ` and i.ipid in (${diskIOipids.join(',')})`; @@ -584,7 +607,7 @@ export const getTabPaneFrequencySampleData = ( rightNs: number, cpuFreqFilterIds: Array ): //@ts-ignore -Promise> => { + Promise> => { let str = ''; if (cpuFreqFilterIds.length > 0) { str = ` and filter_id in (${cpuFreqFilterIds.join(',')})`; @@ -597,14 +620,14 @@ Promise> => { where ts <= $rightNs${str} order by ts asc; `, - { $leftNs: leftNs, $rightNs: rightNs }, {traceId: Utils.currentSelectTrace} + { $leftNs: leftNs, $rightNs: rightNs }, { traceId: Utils.currentSelectTrace } ); }; export const getFileSysChartDataByType = ( type: number ): //@ts-ignore -Promise> => + Promise> => query( 'getFileSysChartData', ` @@ -618,7 +641,7 @@ Promise> => ); export const getDiskIOProcess = (): //@ts-ignore -Promise> => + Promise> => query( 'getDiskIOProcess', ` @@ -634,7 +657,7 @@ export const getDiskIOLatencyChartDataByProcess = ( ipid: number, typeArr: Array ): //@ts-ignore -Promise> => + Promise> => query( 'getDiskIOLatencyChartDataByProcess', ` @@ -927,7 +950,7 @@ export const getTabIoCompletionTimesType = (startTime: number, endTime: number): ); export const queryEnergyEventExits = (): //@ts-ignore -Promise> => + Promise> => query( 'queryEnergyEventExits', `select @@ -1019,7 +1042,7 @@ export const queryConfigEnergyAppName = (): Promise< ); export const queryAllExpectedData = (): //@ts-ignore -Promise> => + Promise> => query( 'queryAllExpectedData', ` @@ -1041,7 +1064,7 @@ Promise> => export const queryFlowsData = ( src_slice: Array ): //@ts-ignore -Promise> => + Promise> => query( 'queryFlowsData', ` @@ -1058,7 +1081,7 @@ Promise> => export const queryPrecedingData = ( dst_slice: string ): //@ts-ignore -Promise> => + Promise> => query( 'queryFlowsData', ` @@ -1074,7 +1097,7 @@ Promise> => ); export const queryFrameTimeData = (): //@ts-ignore -Promise> => + Promise> => query( 'queryFrameTimeData', ` @@ -1117,7 +1140,7 @@ export const queryHeapFile = (): Promise> => export const queryHeapInfo = ( fileId: number ): //@ts-ignore -Promise> => + Promise> => query( 'queryHeapInfo', `SELECT file_id as fileId, key, type, int_value as intValue, str_value as strValue @@ -1168,7 +1191,7 @@ export const queryHeapLocation = (fileId: number): Promise> export const queryHeapString = ( fileId: number ): //@ts-ignore -Promise> => + Promise> => query( 'queryHeapString', `SELECT string @@ -1523,7 +1546,7 @@ export const queryStateFreqList = ( endTime: number, cpu: number ): //@ts-ignore -Promise> => { + Promise> => { let sql = `select c.value, c.ts, c.dur, diff --git a/ide/src/trace/database/sql/Xpower.sql.ts b/ide/src/trace/database/sql/Xpower.sql.ts index 94f19bba13523a4030ddef28a8b51c611f2eeb7f..06e7a783d620cf97be8a5aba6606b737d3c3ba0d 100644 --- a/ide/src/trace/database/sql/Xpower.sql.ts +++ b/ide/src/trace/database/sql/Xpower.sql.ts @@ -14,7 +14,6 @@ */ import { query } from '../SqlLite'; -// import { XpowerStruct } from '../ui-worker/ProcedureWorkerXpower'; export const queryXpowerMeasureData = (traceId?: string): Promise< Array<{ filter_id: number; @@ -32,30 +31,34 @@ export const queryXpowerMeasureData = (traceId?: string): Promise< ; `, {}, {traceId: traceId} ); -export const queryXpowerData = (traceId?: string): Promise< + +export const queryXpowerData = (traceId?: string): Promise< Array<{ name: string; num: number; - maxValue?: number; + maxValue: number; + minValue: number; }> > => query( 'queryXpowerData', ` - select + select name, - COUNT(*) num - from + COUNT(*) num, + max(value) maxValue, + min(value) minValue + from measure_filter mf - left join + left join xpower_measure xm - on + on mf.id = xm.filter_id - where + where mf.type = 'xpower_filter' - group by name + group by name ; -`, {}, {traceId: traceId} +`, {}, { traceId: traceId } ); diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts index 7bcf30f051f9cfa88baafc5895ad34a0f1e1b053..0d537e0bf668092cae005562c3a281b028809b91 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts @@ -555,6 +555,7 @@ export class PairPoint { hidden?: boolean = false; backrowEL?: TraceRow; rangeTime?: string; + sourcebackrowEL?: TraceRow; constructor( rowEL: TraceRow, diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerHang.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerHang.ts index 203c80e0e4ada1ecd1c651baa519cd2298fd2ca6..9d8f548bdc3a3a64854bfa226a00806683a4a154 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerHang.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerHang.ts @@ -33,7 +33,7 @@ export class HangRender extends Render { let hangList = row.dataList; let hangFilter = row.dataListCache; let filterConfig = { - startKey: 'startNS', + startKey: 'startTime', durKey: 'dur', startNS: TraceRow.range?.startNS ?? 0, endNS: TraceRow.range?.endNS ?? 0, @@ -79,7 +79,7 @@ export class HangStruct extends BaseStruct { static selectHangStruct: HangStruct | undefined; static index = 0; id: number | undefined; - startNS: number | undefined; + startTime: number | undefined; dur: number | undefined; tid: number | undefined; pid: number | undefined; @@ -144,7 +144,7 @@ export class HangStruct extends BaseStruct { d1.pid === d2.pid && d1.tid === d2.tid && d1.pname === d2.pname && - d1.startNS === d2.startNS && + d1.startTime === d2.startTime && d1.dur === d2.dur && d1.type === d2.type && d1.id === d2.id && diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerXpower.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerXpower.ts index 41cf920dc1411516b2585abc1e1ac3e939ca51cf..6bd7bfa3936a180a4ac2e9af930cff8b4afc749d 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerXpower.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerXpower.ts @@ -25,6 +25,7 @@ export class XpowerRender extends Render { useCache: boolean; type: string; maxValue: number; + minValue: number; index: number; maxName: string; }, @@ -47,7 +48,7 @@ export class XpowerRender extends Render { xpowerReq.context.beginPath(); let find = false; for (let re of xpowerFilter) { - XpowerStruct.draw(xpowerReq.context, re, xpowerReq.maxValue); + XpowerStruct.draw(xpowerReq.context, re, xpowerReq.maxValue, xpowerReq.minValue); if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { XpowerStruct.hoverXpowerStruct = re; find = true; @@ -96,41 +97,84 @@ export class XpowerStruct extends BaseStruct { dur: number | undefined; //自补充,数据库没有返回 delta: number | undefined; //自补充,数据库没有返回 - static draw(xpowerContext: CanvasRenderingContext2D, data: XpowerStruct, maxValue: number): void { + static draw(xpowerContext: CanvasRenderingContext2D, data: XpowerStruct, maxValue: number, minValue: number): void { if (data.frame) { let width = data.frame.width || 0; xpowerContext.fillStyle = ColorUtils.colorForTid(XpowerStruct.index); xpowerContext.strokeStyle = ColorUtils.colorForTid(XpowerStruct.index); + if ((data.value || 0) < 0) { //数据为负数时显示不同颜色 + xpowerContext.fillStyle = ColorUtils.colorForTid(XpowerStruct.index + 6); + xpowerContext.strokeStyle = ColorUtils.colorForTid(XpowerStruct.index + 6); + } let drawHeight: number = Math.floor(((data.value || 0) * (data.frame.height || 0) * 1.0) / maxValue); if (drawHeight === 0) { drawHeight = 1; } + let minHeight: number = 0; + let maxHeight: number = 0; + let sumHeight: number = 0; + let cutHeight: number = 0; + if (minValue < 0) { // 数据包含负数时 + minHeight = (Math.floor(((minValue || 0) * (data.frame.height || 0) * 1.0) / maxValue)); + maxHeight = (Math.floor(((maxValue || 0) * (data.frame.height || 0) * 1.0) / maxValue)); + sumHeight = Math.abs(minHeight) + Math.abs(maxHeight); + let num = this.cal(Math.abs(minHeight), Math.abs(maxHeight)); + drawHeight = Math.floor(drawHeight / num); //根据比例缩小绘制高度避免超出泳道 + + cutHeight = Math.abs((Math.floor(((minValue || 0) * (data.frame.height || 0) * 1.0) / maxValue)) / num) + 1; + if (maxValue < 0) { // 全部数据都是负数时 + drawHeight = -drawHeight; + cutHeight = 30; + } + } if (XpowerStruct.isHover(data)) { xpowerContext.lineWidth = 1; xpowerContext.globalAlpha = 0.6; - xpowerContext.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight); + xpowerContext.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight - cutHeight, width, drawHeight); xpowerContext.beginPath(); - xpowerContext.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight, 3, 0, 2 * Math.PI, true); + xpowerContext.arc(data.frame.x, data.frame.y + data.frame.height - drawHeight - cutHeight, 3, 0, 2 * Math.PI, true); xpowerContext.fill(); xpowerContext.globalAlpha = 1.0; xpowerContext.stroke(); xpowerContext.beginPath(); - xpowerContext.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight); + xpowerContext.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - drawHeight - cutHeight); xpowerContext.lineWidth = 3; - xpowerContext.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight); + xpowerContext.lineTo(data.frame.x + width, data.frame.y + data.frame.height - drawHeight - cutHeight); xpowerContext.stroke(); } else { xpowerContext.lineWidth = 1; xpowerContext.globalAlpha = 1.0; - xpowerContext.strokeRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight); + xpowerContext.strokeRect(data.frame.x, data.frame.y + data.frame.height - drawHeight - cutHeight, width, drawHeight); xpowerContext.globalAlpha = 0.6; - xpowerContext.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight); + xpowerContext.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight - cutHeight, width, drawHeight); } } xpowerContext.globalAlpha = 1.0; xpowerContext.lineWidth = 1; } + static cal(minHeight: number, maxHeight: number): number { + let multiplier = 1; // 初始倍数为1 + let newSum: number; + do { + newSum = minHeight / multiplier + maxHeight / multiplier; + multiplier += 2; // 每次循环,倍数增加2 + } while (newSum > 30 && multiplier <= (minHeight + maxHeight) * 2); // 确保不会除以0或过大数导致无限循环 + + // 检查是否找到了合适的倍数使得newSum <= 30 + if (newSum <= 30) { + // 如果最后一次循环使multiplier超出了实际需要的值,需要调整回正确的倍数 + multiplier -= 2; + while (minHeight / (multiplier + 2) + maxHeight / (multiplier + 2) > 30) { + multiplier += 2; + } + return multiplier; + } else { + // 如果没有找到合适的倍数,返回2 + return 2; + } + } + static isHover(xpower: XpowerStruct): boolean { return xpower === XpowerStruct.hoverXpowerStruct || xpower === XpowerStruct.selectXpowerStruct; } diff --git a/ide/src/trace/database/ui-worker/cpu/ProcedureWorkerCPU.ts b/ide/src/trace/database/ui-worker/cpu/ProcedureWorkerCPU.ts index 9419ba8e56728ea69682687e42a3f2cd209ce3fc..cfdc6fe9ba3f8cca2b856e85e507131da296cd45 100644 --- a/ide/src/trace/database/ui-worker/cpu/ProcedureWorkerCPU.ts +++ b/ide/src/trace/database/ui-worker/cpu/ProcedureWorkerCPU.ts @@ -263,18 +263,15 @@ export class CpuStruct extends BaseStruct { let pid = data.processId || 0; let tid = data.tid || 0; let width = data.frame.width || 0; + ctx.globalAlpha = 1; if (data.tid === CpuStruct.hoverCpuStruct?.tid || !CpuStruct.hoverCpuStruct) { - ctx.globalAlpha = 1; ctx.fillStyle = ColorUtils.colorForTid(pid > 0 ? pid : tid); } else if (data.processId === CpuStruct.hoverCpuStruct?.processId) { - ctx.globalAlpha = 0.6; ctx.fillStyle = ColorUtils.colorForTid(pid > 0 ? pid : tid); } else { - ctx.globalAlpha = 1; ctx.fillStyle = '#e0e0e0'; } ctx.fillRect(data.frame.x, data.frame.y, width, data.frame.height); - ctx.globalAlpha = 1; CpuStruct.drawText(ctx, data, width, pid, tid); CpuStruct.drawRim(ctx, data, width); } diff --git a/ide/src/trace/enums/helpDocEnums.ts b/ide/src/trace/enums/helpDocEnums.ts index 65e349853cf959744306a0d7f85c80c6341ef929..68aa4e03a6d718afc73c6a69aeb75aac78f520fe 100644 --- a/ide/src/trace/enums/helpDocEnums.ts +++ b/ide/src/trace/enums/helpDocEnums.ts @@ -38,6 +38,8 @@ const events = { TRACE_PARSING_EVENT: 'trace_parsing', OPERATION_SKILLS_EVENT: 'operation_skills', KEYWORDS_SHORTCUTS_EVENT: 'keywords_shortcuts', + XPOWER_EVENT: 'xpower', + EXTEND_EVENT: 'extensions', TRACE_STREAMER_EXPLAIN_EVENT: 'trace_streamer_explain', }; @@ -173,9 +175,19 @@ export const eventDefinitions: { [key: string]: EventDefinition } = { name: 'quickstart_keywords_shortcuts', index: 25, }, + quickstart_xpower: { + event: events.XPOWER_EVENT, + name: 'quickstart_xpower', + index: 26, + }, + quickstart_extensions: { + event: events.EXTEND_EVENT, + name: 'quickstart_extensions', + index: 27, + }, des_tables: { event: events.TRACE_STREAMER_EXPLAIN_EVENT, name: 'des_tables', - index: 26, + index: 28, }, }; diff --git a/ide/src/webSocket/Constants.ts b/ide/src/webSocket/Constants.ts index 60de653ce1bc4c5d417d897e2e133eb19f244d5b..f39f64e1b90bd41063eb3c6ba0ab89d71c9d32bf 100644 --- a/ide/src/webSocket/Constants.ts +++ b/ide/src/webSocket/Constants.ts @@ -13,14 +13,18 @@ * limitations under the License. */ export class Constants { + static NODE_PORT = 19099; static INTERVAL_TIME = 30000; static LOGIN_PARAM = { type: 0, cmd: 1 }; static LOGIN_CMD = 2;// cmd 2 有效 3无效 + static GET_CMD = 1; + static UPDATE_CMD = 3; } export class TypeConstants { - static LOGIN_TYPE = 0;// 先判断type 0(登录) 和 其他(业务) + static LOGIN_TYPE = 0; static HEARTBEAT_TYPE = 1; + static UPDATE_TYPE = 2; static DIAGNOSIS_TYPE = 8; static SENDDB_CMD = 1; static DIAGNOSIS_CMD = 3; diff --git a/ide/src/webSocket/Util.ts b/ide/src/webSocket/Util.ts index b5a48210e85e9e3e511278f9b5f420178ac92f7b..2b2798403a15c7a9efde953787e56d1cd05a0e5d 100644 --- a/ide/src/webSocket/Util.ts +++ b/ide/src/webSocket/Util.ts @@ -20,7 +20,7 @@ const SESSION_ID_LENGTH = 1; const SESSION_LENGTH = 4; export class Utils { // 模块传进来的数据 - static encode(message: MessageParam) { + static encode(message: MessageParam): ArrayBuffer { let splitUint64 = message.session ? Utils.splitUint64ToUint32s(BigInt(message.session!)) : { high32: 0, low32: 0 };// 需处理64bit(session) let totalByteLength = MSG_HEAD_LENGTH + (message.data_lenght ? message.data_lenght : 0); let combinedBuffer = new ArrayBuffer(totalByteLength);// 一个更大的ArrayBuffer,合并前20个字节和data @@ -44,11 +44,11 @@ export class Utils { // 分别将前20个字节和data对应的字节流set至combinedBuffer combinedArray.set(existingArray, 0); combinedArray.set(message.data ? message.data : new Uint8Array(0), headBuffer.byteLength); - return combinedBuffer + return combinedBuffer; } // onmessage接收到的数据解码 - public static decode(message: ArrayBuffer) { + public static decode(message: ArrayBuffer): MessageParam { let decode: MessageParam | undefined; let dataView = new DataView(message); let sessionHigh = dataView.getUint32(4); @@ -65,8 +65,8 @@ export class Utils { session: session, data_lenght: dataView.getUint32(12), data: dataBytes - } - return decode + }; + return decode; } // 处理64bit 需要拆分成两个32bit @@ -85,5 +85,5 @@ export class MessageParam { session_id?: number | undefined; session?: bigint | undefined; data_lenght?: number | undefined; - data?: Uint8Array | undefined + data?: Uint8Array | undefined; } \ No newline at end of file diff --git a/ide/src/webSocket/WebSocketManager.ts b/ide/src/webSocket/WebSocketManager.ts index d2d17df841ea9398c7c7e035df93e485287d9792..c10bdd19cfd9fba3efe0064b223b9fe5a698f48f 100644 --- a/ide/src/webSocket/WebSocketManager.ts +++ b/ide/src/webSocket/WebSocketManager.ts @@ -12,12 +12,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Utils, MessageParam } from "./Util" -import { Constants, TypeConstants } from "./Constants"; +import { Utils, MessageParam } from './Util'; +import { Constants, TypeConstants } from './Constants'; export class WebSocketManager { static instance: WebSocketManager | null | undefined = null; - url: string = 'ws://localhost:18080';//8080后期需要修改 + url: string = `ws://localhost:${Constants.NODE_PORT}`;//8080后期需要修改 private websocket: WebSocket | null | undefined = null; private ready: boolean = false; private distributeMap: Map = new Map(); @@ -36,16 +36,16 @@ export class WebSocketManager { //连接WebSocket connectWebSocket(): void { this.websocket = new WebSocket(this.url); - this.websocket.binaryType = "arraybuffer"; - this.websocket.onopen = () => { + this.websocket.binaryType = 'arraybuffer'; + this.websocket.onopen = (): void => { // 设置心跳定时器 this.sendHeartbeat(); - // 连接后登录 - this.login(); + //检查版本 + this.getVersion(); }; //接受webSocket的消息 - this.websocket.onmessage = (event) => { + this.websocket.onmessage = (event): void => { // 先解码 let decode: MessageParam = Utils.decode(event.data); if (decode.type === TypeConstants.HEARTBEAT_TYPE) { @@ -54,11 +54,11 @@ export class WebSocketManager { this.onmessage(decode!); }; - this.websocket.onerror = (error) => { + this.websocket.onerror = (error): void => { console.error('error:', error); }; - this.websocket.onclose = (event) => { + this.websocket.onclose = (event): void => { this.initLoginInfor(); this.clearHeartbeat(); this.reconnect(event); @@ -72,7 +72,20 @@ export class WebSocketManager { */ onmessage(decode: MessageParam): void { // 解码event 调decode - if (decode.type === TypeConstants.LOGIN_TYPE) {// 登录 + if (decode.type === TypeConstants.UPDATE_TYPE) {// 升级 + if (decode.cmd === Constants.GET_CMD) { + // 小于则升级 + let targetVersion = '1.0.1'; + let currentVersion = new TextDecoder().decode(decode.data) + let result = this.compareVersion(currentVersion, targetVersion); + if (result === -1) { + this.updateVersion(); + } else { + // 连接后登录 + this.login(); + } + } + } else if (decode.type === TypeConstants.LOGIN_TYPE) {// 登录 if (decode.cmd === Constants.LOGIN_CMD) { this.ready = true; this.sessionId = decode.session_id; @@ -87,6 +100,50 @@ export class WebSocketManager { } } + // get版本 + getVersion() { + // 获取扩展程序版本 + this.send(TypeConstants.UPDATE_TYPE, Constants.GET_CMD); + } + + //check版本 + compareVersion(currentVersion: string, targetVersion: string) { + // 将版本字符串分割成数组 + let parts1 = currentVersion.split('.'); + let parts2 = targetVersion.split('.'); + + // 遍历数组,各部分进行比较 + for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) { + let currentNum = i < parts1.length ? parseInt(parts1[i], 10) : 0; + let targetNum = i < parts2.length ? parseInt(parts2[i], 10) : 0; + + // 比较 + if (currentNum > targetNum) {// 无需更新 + return 1; + } else if (currentNum < targetNum) { // 需要更新 + return -1; + } + } + return 0; // 无需更新 + } + + // 更新扩展程序 + updateVersion() { + // 扩展程序升级 + let url = `https://${window.location.host.split(':')[0]}:${window.location.port + }/application/extend/hi-smart-perf-host-extend-update.zip`; + fetch(url).then(response => { + if (!response.ok) { + throw new Error("No corresponding upgrade compression package found"); + } + return response.arrayBuffer() + }).then((arrayBuffer) => { + this.send(TypeConstants.UPDATE_TYPE, Constants.UPDATE_CMD, new Uint8Array(arrayBuffer)); + }).catch((error) => { + console.error(error); + }) + } + // 登录 login(): void { this.websocket!.send(Utils.encode(Constants.LOGIN_PARAM)); @@ -102,7 +159,7 @@ export class WebSocketManager { // WebSocket是否登录成功 isReady(): boolean { - return this.ready + return this.ready; } /** @@ -125,6 +182,10 @@ export class WebSocketManager { if (!this.ready) {// 改判断条件 ready return; } + this.send(type, cmd, data) + } + + send(type: number, cmd?: number, data?: Uint8Array) { let message: MessageParam = { type: type, cmd: cmd, @@ -132,7 +193,7 @@ export class WebSocketManager { session: this.session!, data_lenght: data ? data.byteLength : undefined, data: data - } + }; let encode = Utils.encode(message); this.websocket!.send(encode!); } @@ -141,36 +202,36 @@ export class WebSocketManager { * 传递数据信息至webSocket * 模块调 */ - reconnect(event: unknown) { + reconnect(event: unknown): void { //@ts-ignore if (event.wasClean) {// 正常关闭 - return + return; } // 未连接成功打开定时器 setTimeout(() => { this.connectWebSocket(); - }, Constants.INTERVAL_TIME) + }, Constants.INTERVAL_TIME); } // 定时检查心跳 - sendHeartbeat() { + sendHeartbeat(): void { this.heartbeatInterval = window.setInterval(() => { - this.sendMessage(TypeConstants.HEARTBEAT_TYPE) - }, Constants.INTERVAL_TIME) + this.sendMessage(TypeConstants.HEARTBEAT_TYPE); + }, Constants.INTERVAL_TIME); } /** * 重连时初始化登录信息 * 在异常关闭时调用 */ - initLoginInfor() { + initLoginInfor(): void { this.ready = false; this.sessionId = null; this.session = null; } // 连接关闭时,清除心跳 - clearHeartbeat() { + clearHeartbeat(): void { if (this.heartbeatInterval) { clearInterval(this.heartbeatInterval); this.heartbeatInterval = null; diff --git a/trace_streamer/doc/compile_trace_streamer.md b/trace_streamer/doc/compile_trace_streamer.md index a3b728c612fb3cd50f6f389f4284479666abe7eb..dd38457f20becf6903883ec52699ba552f20fbe0 100755 --- a/trace_streamer/doc/compile_trace_streamer.md +++ b/trace_streamer/doc/compile_trace_streamer.md @@ -14,7 +14,7 @@ TraceStreamer可以编译为命令行下的可执行程序,或者WebAssembly | --- | --- | --- | |linux |clang/clang++| (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0| | macx |clang/clang++| 14.0.3 | -|windows |gcc.exe/g++.exe| (i686-posix-dwarf-rev0, Built by MinGW-W64 project) 8.1.0| +|windows |gcc.exe/g++.exe| gcc version 12.1.0 (x86_64-posix-sjlj-rev3, Built by MinGW-W64 project)| |wasm(linux下编译) |emcc/em++| 3.1.12| 对于wasm环境(目前只支持linux下编译),build.sh会自行配置环境。 diff --git a/trace_streamer/pare_third_party.sh b/trace_streamer/pare_third_party.sh index f48b1c1231f19ba42d0c803ac9d0f3274fc9bdce..2e2d29e3628d46bd53991b48e9f1e291568f0f50 100755 --- a/trace_streamer/pare_third_party.sh +++ b/trace_streamer/pare_third_party.sh @@ -102,7 +102,7 @@ if [ ! -d "perf_include/hiviewdfx/faultloggerd" ];then mkdir -p perf_include/hiviewdfx/faultloggerd/interfaces/innerkits git clone git@gitee.com:openharmony/hiviewdfx_faultloggerd.git cd hiviewdfx_faultloggerd - git reset --hard 7bd128c8fa91b79606c1bb21f20123879b351a4f + git reset --hard 7296f69c0d418cd9353638f3117296e4b494e4e5 cd .. mv hiviewdfx_faultloggerd/common/ perf_include/hiviewdfx/faultloggerd mv hiviewdfx_faultloggerd/interfaces/common/ perf_include/hiviewdfx/faultloggerd/interfaces @@ -140,35 +140,37 @@ if [ ! -f "hiperf/BUILD.gn" ];then rm -rf hiperf developtools_hiperf git clone git@gitee.com:openharmony/developtools_hiperf.git cd developtools_hiperf - git reset --hard 59eecf523796401740d02894f64b4d23f7d370a9 + git reset --hard 9d189f41d76c1ae6e8e12238aef5ef5b8cdbc09f cd .. if [ -d "developtools_hiperf" ];then mv developtools_hiperf hiperf $cp ../prebuilts/patch_hiperf/BUILD.gn ../third_party/hiperf/BUILD.gn $sed -i "/FRIEND_TEST/s/^\(.*\)$/\/\/\1/g" hiperf/include/virtual_thread.h - $sed -i "s/HIPERF_DEBUG/ALWAYSTRUE/g" hiperf/include/virtual_thread.h + # $sed -i "s/HIPERF_DEBUG/ALWAYSTRUE/g" hiperf/include/virtual_thread.h $sed -i "/#include \"report_json_file.h\"/s/^\(.*\)$/\/\/\1/g" hiperf/include/report.h $sed -i "/#include /s/^\(.*\)$/\/\/\1/g" hiperf/include/debug_logger.h $sed -i "/#include /s/^\(.*\)$/\/\/\1/g" hiperf/include/utilities.h $sed -i "/FRIEND_TEST/s/^\(.*\)$/\/\/\1/g" hiperf/include/virtual_thread.h $sed -i "/FRIEND_TEST/s/^\(.*\)$/\/\/\1/g" hiperf/include/callstack.h - $sed -i '/unwinder.h/s/^/\/\/ /' hiperf/include/callstack.h + # $sed -i '/unwinder.h/s/^/\/\/ /' hiperf/include/callstack.h $sed -i "/FRIEND_TEST/s/^\(.*\)$/\/\/\1/g" hiperf/include/symbols_file.h $sed -i "/FRIEND_TEST/s/^\(.*\)$/\/\/\1/g" hiperf/include/virtual_runtime.h $sed -i "/FRIEND_TEST/s/^\(.*\)$/\/\/\1/g" hiperf/include/report.h $sed -i "s/HIPERF_DEBUG/ALWAYSTRUE/g" hiperf/include/virtual_thread.h - $sed -i "/using __s8 = char;/a #define unw_word_t uint64_t" hiperf/include/nonlinux/linux/types.h - $sed -i '/^void Report::PrepareConsole(/,/^}/ s/^.*$/\/\/&/; /^void Report::PrepareConsole(/,/return;/ s/^[[:blank:]]*/ /' hiperf/src/report.cpp - $sed -i '/namespace HiPerf {/avoid Report::PrepareConsole(){ return;}' hiperf/src/report.cpp - $sed -i '/HITRACE_METER_NAME/s/^/\/\/ /' hiperf/src/callstack.cpp - $sed -i '/hitrace_meter.h/s/^/\/\/ /' hiperf/src/callstack.cpp - $sed -i '/dlfcn.h/s/^/\/\/ /' hiperf/src/callstack.cpp - $sed -i '/dfx_ark.h/s/^/\/\/ /' hiperf/src/callstack.cpp - $sed -i '/dfx_regs.h/s/^/\/\/ /' hiperf/src/callstack.cpp + # $sed -i "/using __s8 = char;/a #define unw_word_t uint64_t" hiperf/include/nonlinux/linux/types.h + # $sed -i '/^void Report::PrepareConsole(/,/^}/ s/^.*$/\/\/&/; /^void Report::PrepareConsole(/,/return;/ s/^[[:blank:]]*/ /' hiperf/src/report.cpp + # $sed -i '/namespace HiPerf {/avoid Report::PrepareConsole(){ return;}' hiperf/src/report.cpp + # $sed -i '/HITRACE_METER_NAME/s/^/\/\/ /' hiperf/src/callstack.cpp + # $sed -i '/hitrace_meter.h/s/^/\/\/ /' hiperf/src/callstack.cpp + # $sed -i '/dlfcn.h/s/^/\/\/ /' hiperf/src/callstack.cpp + # $sed -i '/dfx_ark.h/s/^/\/\/ /' hiperf/src/callstack.cpp + # $sed -i '/dfx_regs.h/s/^/\/\/ /' hiperf/src/callstack.cpp $sed -i '/return DoUnwind2/s/^/\/\/ /' hiperf/src/callstack.cpp - $sed -i '/#if defined(is_ohos) && is_ohos/s/defined(is_ohos) && is_ohos/true/g' hiperf/src/virtual_runtime.cpp - $sed -i '/#if defined(is_ohos) && is_ohos/s/defined(is_ohos) && is_ohos/true/g' hiperf/include/virtual_runtime.h - $sed -i '/symbolsTable, elfFile_, elfPath/s/symbolsTable, elfFile_, elfPath/symbolsTable, elfFile_, filePath_/g' hiperf/src/symbols_file.cpp + # $sed -i '/#if defined(is_ohos) && is_ohos/s/defined(is_ohos) && is_ohos/true/g' hiperf/src/virtual_runtime.cpp + # $sed -i '/#if defined(is_ohos) && is_ohos/s/defined(is_ohos) && is_ohos/true/g' hiperf/include/virtual_runtime.h + # $sed -i '/symbolsTable, elfFile_, elfPath/s/symbolsTable, elfFile_, elfPath/symbolsTable, elfFile_, filePath_/g' hiperf/src/symbols_file.cpp + $sed -i '/spe_decoder.h/s/^/\/\/ /' hiperf/src/virtual_runtime.cpp + $sed -i '/spe_decoder.h/s/^/\/\/ /' hiperf/src/perf_event_record.cpp fi fi diff --git a/trace_streamer/prebuilts/patch_bzip2/bzip2build.gn b/trace_streamer/prebuilts/patch_bzip2/bzip2build.gn index 4567043d0e89525d9bc54a1e8c5fc4b4f6a7d20e..98fe87bc6014e5da20314c6f15d3815b48bb2ba0 100644 --- a/trace_streamer/prebuilts/patch_bzip2/bzip2build.gn +++ b/trace_streamer/prebuilts/patch_bzip2/bzip2build.gn @@ -33,7 +33,7 @@ ohos_source_set("bzip2_src") { subsystem_name = "thirdparty" } -ohos_static_library("libbz2") { +ohos_source_set("libbz2") { deps = [ ":bzip2_src" ] public_configs = [ ":bzip2_config" ] diff --git a/trace_streamer/prebuilts/patch_hiperf/BUILD.gn b/trace_streamer/prebuilts/patch_hiperf/BUILD.gn index 4fcf8600e011ccf93b8be1b014821e4914871b05..02975a15832d6f4c2ded28d96329b4f9ff35f325 100644 --- a/trace_streamer/prebuilts/patch_hiperf/BUILD.gn +++ b/trace_streamer/prebuilts/patch_hiperf/BUILD.gn @@ -16,6 +16,7 @@ import("../../build/ts.gni") config("hiperf_config") { cflags = [ "-D ALWAYSTRUE", + "-D CONFIG_NO_HILOG", "-D is_mingw=${is_mingw}", ] } @@ -41,7 +42,6 @@ ohos_source_set("hiperf_src") { subsystem_name = "thirdparty" part_name = "hiperf" sources = [ - "src/callstack.cpp", "src/dwarf_encoding.cpp", "src/option.cpp", "src/perf_event_record.cpp", diff --git a/trace_streamer/prebuilts/patch_hiperf/hiviewdfx_BUILD.gn b/trace_streamer/prebuilts/patch_hiperf/hiviewdfx_BUILD.gn index 7e9651695b6d30241792d197fa8ae48d7d80fae5..5e5fbfc61ee72e0afe7e86ebaf98ec37d3866617 100644 --- a/trace_streamer/prebuilts/patch_hiperf/hiviewdfx_BUILD.gn +++ b/trace_streamer/prebuilts/patch_hiperf/hiviewdfx_BUILD.gn @@ -26,6 +26,7 @@ config("faultloggerd_public_config") { include_dirs = [ "faultloggerd/common/dfxlog", "faultloggerd/common/dfxutil", + "faultloggerd/common/trace/include", "faultloggerd/interfaces/common", "faultloggerd/interfaces/nonlinux", "faultloggerd/interfaces/innerkits/unwinder/include", @@ -42,8 +43,10 @@ config("faultloggerd_public_config") { ohos_source_set("libfaultloggerd") { sources = [ "faultloggerd/common/dfxutil/dfx_util.cpp", + "faultloggerd/common/trace/dfx_trace_dlsym.cpp", "faultloggerd/interfaces/innerkits/unwinder/dfx_elf.cpp", "faultloggerd/interfaces/innerkits/unwinder/dfx_elf_parser.cpp", + "faultloggerd/interfaces/innerkits/unwinder/dfx_hap.cpp", "faultloggerd/interfaces/innerkits/unwinder/dfx_map.cpp", "faultloggerd/interfaces/innerkits/unwinder/dfx_maps.cpp", "faultloggerd/interfaces/innerkits/unwinder/dfx_memory.cpp", diff --git a/trace_streamer/src/base/codec_cov.cpp b/trace_streamer/src/base/codec_cov.cpp index a1360fe6821b3d38373884e0f11c5e20abe498e1..7ccaaab7cd3b084061bedf938d6b94028c2af889 100644 --- a/trace_streamer/src/base/codec_cov.cpp +++ b/trace_streamer/src/base/codec_cov.cpp @@ -16,6 +16,7 @@ #include "codec_cov.h" #include +#include #ifdef _WIN32 #include #endif @@ -115,6 +116,50 @@ std::string GbkToUtf8(const char *srcStr) WideCharToMultiByte(CP_UTF8, 0, wstr.get(), -1, str.get(), len, NULL, NULL); return std::string(str.get()); } +std::string Utf8ToGbk(const char *srcStr) +{ + int32_t len = MultiByteToWideChar(CP_UTF8, 0, srcStr, -1, NULL, 0); + std::unique_ptr wstr = std::make_unique(len + 1); + MultiByteToWideChar(CP_UTF8, 0, srcStr, -1, wstr.get(), len); + len = WideCharToMultiByte(CP_ACP, 0, wstr.get(), -1, NULL, 0, NULL, NULL); + std::unique_ptr str = std::make_unique(len + 1); + WideCharToMultiByte(CP_ACP, 0, wstr.get(), -1, str.get(), len, NULL, NULL); + return std::string(str.get()); +} +/** @fn std::wstring String2WString(const std::string& strInput) + * @brief string转换为wstring + * @param (IN) const std::string& + * @return std::wstring + */ +std::wstring String2WString(const std::string &strInput) +{ + auto codePage = IsGBK(reinterpret_cast(strInput.c_str()), strInput.length()) ? CP_ACP : CP_UTF8; + if (strInput.empty()) { + std::cout << "strInput is empty" << std::endl; + return L""; + } + + // 获取待转换的数据的长度 + int len_in = MultiByteToWideChar(codePage, 0, (LPCSTR)strInput.c_str(), -1, NULL, 0); + if (len_in <= 0) { + std::cout << "The result of WideCharToMultiByte is Invalid!" << std::endl; + return L""; + } + + // 为输出数据申请空间 + std::wstring wstr_out; + wstr_out.resize(len_in - 1, L'\0'); + + // 数据格式转换 + int to_result = MultiByteToWideChar(codePage, 0, (LPCSTR)strInput.c_str(), -1, (LPWSTR)wstr_out.c_str(), len_in); + + // 判断转换结果 + if (0 == to_result) { + std::cout << "Can't transfer String to WString" << std::endl; + } + + return wstr_out; +} #endif } // namespace base } // namespace SysTuning diff --git a/trace_streamer/src/base/codec_cov.h b/trace_streamer/src/base/codec_cov.h index 076cc0bdcd2f75e85fdfcf1093fa830e910a37ef..2a4bf42c38ace7626d5c52318125384d8edc5e62 100644 --- a/trace_streamer/src/base/codec_cov.h +++ b/trace_streamer/src/base/codec_cov.h @@ -32,6 +32,8 @@ CODING GetCoding(const uint8_t *data, int32_t len); #ifdef _WIN32 std::string GbkToUtf8(const char *srcStr); +std::string Utf8ToGbk(const char *srcStr); +std::wstring String2WString(const std::string &strInput); #endif } // namespace base } // namespace SysTuning diff --git a/trace_streamer/src/base/file.cpp b/trace_streamer/src/base/file.cpp index b632aa1733039645963e6b7098f7abcc56568dac..f879ec211a2dd9a3fe080d708414eb284e9a3e9e 100644 --- a/trace_streamer/src/base/file.cpp +++ b/trace_streamer/src/base/file.cpp @@ -18,21 +18,17 @@ #include #include #include +#include #include #include #include "log.h" +#include "codec_cov.h" #if defined(_WIN32) #include #include #include #endif -#if defined(is_linux) || defined(_WIN32) -#include -#endif -#include "zlib.h" -#include "contrib/minizip/zip.h" -#include "contrib/minizip/unzip.h" namespace SysTuning { namespace base { @@ -82,7 +78,7 @@ std::string GetExecutionDirectoryPath() std::string str(currPath); return str.substr(0, str.find_last_of('/')); } -#if defined(is_linux) || defined(_WIN32) + std::vector GetFilesNameFromDir(const std::string &path, bool onlyFileName) { std::vector soFiles; @@ -102,128 +98,148 @@ std::vector GetFilesNameFromDir(const std::string &path, bool onlyF } return soFiles; } -#endif bool UnZipFile(const std::string &zipFile, std::string &traceFile) { - std::filesystem::path stdZipFile(zipFile); - // 检查文件是否存在 - if (!std::filesystem::exists(stdZipFile)) { - TS_LOGI("!std::filesystem::exists(dirPath), dirPath: %s\n", zipFile.data()); + LocalZip localZip(zipFile); + return localZip.Unzip(traceFile); +} + +LocalZip::LocalZip(const std::string &file) : filePath_(file) +{ + buf_ = std::make_unique(bufSize_); + tmpDir_ = std::filesystem::path(file).parent_path().append("ts_tmp").string(); +} + +// 检查文件是否存在 +bool LocalZip::IsFileExist() +{ +#ifdef _WIN32 + std::filesystem::path zipFile(String2WString(filePath_)); +#else + std::filesystem::path zipFile(filePath_); +#endif + if (!std::filesystem::exists(zipFile)) { + TS_LOGE("!std::filesystem::exists(zipFile), filePath: %s\n", filePath_.data()); return false; } - std::ifstream zipIfstream(stdZipFile); - char buf[2]; - zipIfstream.read(buf, 2); - if (buf[0] != 'P' || buf[1] != 'K') { - // 不是zip文件, 返回true走正常解析流程 - return true; - } else { - auto unzipDirPath = stdZipFile.parent_path().append("tmp").string(); - LocalUnzip(zipFile, unzipDirPath); - auto files = GetFilesNameFromDir(unzipDirPath, false); - if (files.size() == 1) { - traceFile = files[0]; + return true; +} + +// 检查是否为zip文件 +bool LocalZip::IsZipFile() +{ + std::ifstream zipIfstream(filePath_); + char buf[magicNumLen_]; + zipIfstream.read(buf, magicNumLen_); + return buf[0] == 'P' && buf[1] == 'K'; +} + +bool LocalZip::CreateDir(const std::filesystem::path &dirName, bool del) +{ + std::filesystem::path dir = dirName; + if (dirName.u8string().back() == '/' || dirName.u8string().back() == '\\') { + auto tmpStr = dirName.u8string().substr(0, dirName.u8string().size() - 1); +#ifdef _WIN32 + dir = std::filesystem::path(String2WString(tmpStr)); +#else + dir = std::filesystem::path(tmpStr); +#endif + } + if (std::filesystem::exists(dir)) { + if (del) { + std::filesystem::remove_all(dir); + } else { return true; } - return false; } + return std::filesystem::create_directories(dir); } -bool LocalUnzip(const std::string &zipFile, const std::string &dstDir) +bool LocalZip::WriteFile(const unzFile &uzf, const std::filesystem::path &fileName) { - int err = 0; - void *buf; - uInt size_buf; - // 创建 dstDir - if (std::filesystem::exists(dstDir)) { - std::filesystem::remove_all(dstDir); - std::filesystem::create_directories(dstDir); + if (unzOpenCurrentFile(uzf) != UNZ_OK) { + TS_LOGE("unzOpenCurrentFile error."); + } else { + auto parentPath = fileName.parent_path(); + if (!parentPath.empty()) { + CreateDir(parentPath); + } + auto err = unzReadCurrentFile(uzf, buf_.get(), bufSize_); + if (err < 0) { + TS_LOGE("unzReadCurrentFile error."); + return false; + } + if (err > 0) { +#ifdef _WIN32 + FILE *fout = fopen(Utf8ToGbk(fileName.u8string().c_str()).c_str(), "wb"); +#else + FILE *fout = fopen(fileName.c_str(), "wb"); +#endif + if (fwrite(buf_.get(), (unsigned)err, 1, fout) != 1) { + TS_LOGE("error in writing extracted filee."); + err = UNZ_ERRNO; + return false; + } + fclose(fout); + } + unzCloseCurrentFile(uzf); } + return true; +} +bool LocalZip::Unzip(std::string &traceFile) +{ + if (!IsFileExist() || !IsZipFile() || !CreateDir(tmpDir_, true)) { + return false; + } // 打开zip文件 - unzFile uf = unzOpen(zipFile.c_str()); - if (uf == NULL) { - std::cout << "unzOpen error." << std::endl; + unzFile uzf = unzOpen(filePath_.c_str()); + if (uzf == nullptr) { + TS_LOGE("unzOpen error."); return false; } - // 获取zip文件信息 - unz_global_info gi; - err = unzGetGlobalInfo(uf, &gi); - if (err != UNZ_OK) { - std::cout << "unzGetGlobalInfo error." << std::endl; + unz_global_info ugi; + if (unzGetGlobalInfo(uzf, &ugi) != UNZ_OK) { + TS_LOGE("unzGetGlobalInfo error."); return false; } - - size_buf = 512000000; - buf = (void *)malloc(size_buf); - - // 遍历zip - for (int i = 0; i < gi.number_entry; i++) { - char filename_inzip[256]; + for (int i = 0; i < ugi.number_entry; i++) { + char filenameInZip[256]; unz_file_info file_info; - uLong ratio = 0; - const char *string_method = ""; - char charCrypt = ' '; - err = unzGetCurrentFileInfo(uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0); - if (err != UNZ_OK) { - std::cout << "error " << err << " with zipfile in unzGetCurrentFileInfo." << std::endl; + if (unzGetCurrentFileInfo(uzf, &file_info, filenameInZip, sizeof(filenameInZip), NULL, 0, NULL, 0) != UNZ_OK) { + TS_LOGE("unzGetCurrentFileInfo error."); break; } - std::string isdir; - std::string filename = filename_inzip; - if (filename.back() == '/' || filename.back() == '\\') { - //* 是目录,则创建目录 - isdir = " is directory"; - std::string dir = dstDir + "/" + filename; - if (!std::filesystem::exists(dir)) { - std::filesystem::create_directories(dir); - } - } else { - //* 是文件,打开 -> 读取 -> 写入解压文件 -> 关闭 - isdir = " is file"; - - err = unzOpenCurrentFile(uf); - if (err != UNZ_OK) { - std::cout << "error " << err << " with zipfile in unzOpenCurrentFile." << std::endl; - } else { - std::string writefile = dstDir + "/" + filename; - std::filesystem::path fpath(writefile); - std::string par = fpath.parent_path().string(); - if (!fpath.parent_path().empty() && !std::filesystem::exists(fpath.parent_path())) { - std::filesystem::create_directories(fpath.parent_path()); - } - err = unzReadCurrentFile(uf, buf, size_buf); - if (err < 0) { - std::cout << "error " << err << " with zipfile in unzReadCurrentFile." << std::endl; - break; - } - if (err > 0) { - FILE *fout = fopen(writefile.c_str(), "wb"); - if (fwrite(buf, (unsigned)err, 1, fout) != 1) { - std::cout << "error in writing extracted filee." << std::endl; - err = UNZ_ERRNO; - break; - } - fclose(fout); - } - unzCloseCurrentFile(uf); - } +#ifdef _WIN32 + auto fileName = std::filesystem::path(tmpDir_).append(String2WString(filenameInZip)); +#else + auto fileName = std::filesystem::path(tmpDir_).append(filenameInZip); +#endif + // 是目录,则创建目录; 是文件,打开 -> 读取 -> 写入解压文件 -> 关闭 + auto isDir = fileName.string().back() == '/' || fileName.string().back() == '\\'; + if (!(isDir ? CreateDir(fileName) : WriteFile(uzf, fileName))) { + break; } - - if ((i + 1) < gi.number_entry) { - err = unzGoToNextFile(uf); - if (err != UNZ_OK) { - std::cout << "error " << err << " with zipfile in unzGoToNextFile." << std::endl; + // uzf迭代 + if ((i + 1) < ugi.number_entry) { + if (unzGoToNextFile(uzf) != UNZ_OK) { + TS_LOGE("unzGoToNextFile error."); break; } } } - - unzClose(uf); - - return true; + unzClose(uzf); + auto files = GetFilesNameFromDir(tmpDir_, false); + if (files.size() == 1) { + traceFile = files[0]; +#ifdef _WIN32 + traceFile = Utf8ToGbk(traceFile.c_str()); +#endif + return true; + } + return false; } } // namespace base } // namespace SysTuning diff --git a/trace_streamer/src/base/file.h b/trace_streamer/src/base/file.h index 1e66055b289dd6439cc85318fde68da7223d7311..d66b2aaa03e521c1d0921c33810e7d37acdec64f 100644 --- a/trace_streamer/src/base/file.h +++ b/trace_streamer/src/base/file.h @@ -16,8 +16,13 @@ #ifndef INCLUDE_TUNING_BASE_FILE_UTILS_H #define INCLUDE_TUNING_BASE_FILE_UTILS_H +#include +#include #include #include +#include + +#include "contrib/minizip/unzip.h" namespace SysTuning { namespace base { @@ -48,6 +53,24 @@ std::vector GetFilesNameFromDir(const std::string &path, bool onlyF bool UnZipFile(const std::string &zipFile, std::string &traceFile); bool LocalUnzip(const std::string &zipFile, const std::string &dstDir); + +class LocalZip { +public: + LocalZip(const std::string &file); + bool Unzip(std::string &traceFile); + +private: + bool IsFileExist(); + bool IsZipFile(); + static bool CreateDir(const std::filesystem::path &dirName, bool del = false); + bool WriteFile(const unzFile &uzf, const std::filesystem::path &fileName); + std::string filePath_; + std::string tmpDir_; + uint32_t bufSize_ = 512000000; + uint8_t magicNumLen_ = 2; + std::unique_ptr buf_; +}; + } // namespace base } // namespace SysTuning #endif // INCLUDE_TUNING_BASE_FILE_UTILS_H_ diff --git a/trace_streamer/src/main.cpp b/trace_streamer/src/main.cpp index d44ce2031c162684a17be068c426733024ad8caf..78c2ae0e6c65a0ccd7e0f112c40938e1bc7fe71b 100644 --- a/trace_streamer/src/main.cpp +++ b/trace_streamer/src/main.cpp @@ -272,9 +272,9 @@ bool SetFileSize(const std::string &traceFilePath) } int OpenAndParserFile(TraceStreamerSelector &ts, const std::string &traceFilePath) { - std::string filePath = traceFilePath; + std::string filePath; if (!UnZipFile(traceFilePath, filePath)) { - return 1; + filePath = traceFilePath; } if (!SetFileSize(filePath)) { return 0; diff --git a/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp b/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp index e82da207ba1e5c11e041dad23f5668f1261401a3..292b181607e51bb2f18fbee6524908de7737562c 100644 --- a/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp +++ b/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp @@ -582,7 +582,7 @@ void PerfDataParser::UpdateReportWorkloadInfo() const if (featureSection) { TS_LOGI("found HIPERF_META_WORKLOAD_CMD"); auto sectionString = static_cast(featureSection); - workloader = sectionString->toString(); + workloader = sectionString->ToString(); } else { TS_LOGW("NOT found HIPERF_META_WORKLOAD_CMD"); } diff --git a/trace_streamer/src/parser/pbreader_parser/arkts/BUILD.gn b/trace_streamer/src/parser/pbreader_parser/arkts/BUILD.gn index fc7f12436953e579ac583cb934091698db00f272..120403972e91d35f575270d33eb5d8d16d4a97d9 100644 --- a/trace_streamer/src/parser/pbreader_parser/arkts/BUILD.gn +++ b/trace_streamer/src/parser/pbreader_parser/arkts/BUILD.gn @@ -25,6 +25,7 @@ ohos_static_library("pbreader_arkts_parser") { "pbreader_js_memory_parser.cpp", ] public_deps = [ + "${OHOS_TRACE_STREAMER_PROTOS_DIR}/base:base", "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/services:ts_all_type_cpp", "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/js_memory:js_memory_data_reader", "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/js_memory:ts_js_memory_data_cpp", diff --git a/trace_streamer/src/parser/print_event_parser.cpp b/trace_streamer/src/parser/print_event_parser.cpp index 9c4998840069a9d300f017373fe024e383cbb2fe..4e23fc2a0ec738af3f2f3bbaf36d1d0e0495c1b6 100644 --- a/trace_streamer/src/parser/print_event_parser.cpp +++ b/trace_streamer/src/parser/print_event_parser.cpp @@ -319,6 +319,10 @@ bool PrintEventParser::ReciveVsync(size_t callStackRow, std::string &args, const } ++it; } + if (now == 0 || expectEnd == 0 || vsyncId == 0) { + TS_LOGE("Now,expectedEnd or vsyncId should not be 0!"); + return false; + } if (convertVsyncTs_ && traceType_ == TRACE_FILETYPE_H_TRACE) { if (now != INVALID_UINT64) { now = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_MONOTONIC, now); diff --git a/trace_streamer/src/trace_data/BUILD.gn b/trace_streamer/src/trace_data/BUILD.gn index 5489b73efc0a091b6235520c7547063ed1e71b34..48495aa3ec785ff27238b9cc290f88cf3c11ea36 100644 --- a/trace_streamer/src/trace_data/BUILD.gn +++ b/trace_streamer/src/trace_data/BUILD.gn @@ -92,7 +92,7 @@ ohos_source_set("trace_data") { deps = [ "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/smartperf_host:ts_all_sph_cpp", ] - + public_deps = [ "${SRC}/base:base" ] public_configs = [ "${SRC}/parser/ebpf_parser:ebpf_parser_cfg", "${SRC}/base/sqlite_ext:sqlite_ext_cfg", diff --git a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp index 02c32ffc0c03a298c8d58a95e0201dc5ef6d5cfd..b6663a6bb0e98721936fcfa56215fddaec6fb279 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp +++ b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp @@ -264,7 +264,7 @@ void TraceStreamerSelector::GetMarkPositionData(std::unique_ptr &data // Move the data pointer to the starting position of the remaining data // The remaining data size is equal to the data size minus the current markinfo size size -= curMarkSize; - auto remainingData = std::make_unique(size); + auto remainingData = std::make_unique(size); memcpy_s(remainingData.get(), size, data.get() + curMarkSize, size); data.reset(remainingData.release()); }