diff --git a/0001-feat-golang-ad.patch b/0001-feat-golang-ad.patch new file mode 100644 index 0000000000000000000000000000000000000000..61eb0698d55b26749ef91dc2733becfa0b080581 --- /dev/null +++ b/0001-feat-golang-ad.patch @@ -0,0 +1,165 @@ +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/server/main.go b/ide/server/main.go index 80a242fb8889f8f3dd94a01c3f16edf8bdd1b4a7..530ff115573a70338e10786ec5502b39091784da 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,79 @@ 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() { + defer func() { + if r := recover(); r != nil { + fmt.Printf("parseMsgPublishFile happen panic, content is %+v\n", r) + } + }() + msgPublishData.Mux.Lock() + defer msgPublishData.Mux.Unlock() + 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.RLock() + data := msgPublishData.Msg + msgPublishData.Mux.RUnlock() + 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 := 5 * time.Minute + timer := time.NewTimer(5 * time.Second) + 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.Lock() + msgPublishData.FilePath = sc.MsgPublishFile + msgPublishData.Mux.Unlock() + 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 0000000000000000000000000000000000000000..637b403495932e12805e858f50883d962caca8d4 --- /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 fde296819b41b01eef3ffaef5c795bd5ab2c9569..0000000000000000000000000000000000000000 --- 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/src/base-ui/chart/pie/LitChartPie.ts b/ide/src/base-ui/chart/pie/LitChartPie.ts index 560893146b932e392852f614dc61fb57d4416385..252a537038a97fbd0be9493eb92d511124cf5b18 100644 --- a/ide/src/base-ui/chart/pie/LitChartPie.ts +++ b/ide/src/base-ui/chart/pie/LitChartPie.ts @@ -179,11 +179,13 @@ export class LitChartPie extends BaseElement { } this.updateHoverItemStatus(it); if (it.hover) { - this.showTip( - this.centerX || 0, - this.centerY || 0, - this.litChartPieConfig!.tip ? this.litChartPieConfig!.tip(it) : `${it.key}: ${it.value}` - ); + if (this.centerX && this.centerX > 0 && this.centerY && this.centerY > 0) { + this.showTip( + this.centerX - 40 || 0, + this.centerY || 0, + this.litChartPieConfig!.tip ? this.litChartPieConfig!.tip(it) : `${it.key}: ${it.value}` + ); + } } }); if (!hasHover) { @@ -270,8 +272,8 @@ export class LitChartPie extends BaseElement { if (it.hover && this.litChartPieConfig) { this.litChartPieConfig.hoverHandler?.(it.obj); this.showTip( - ev.pageX - rect.left + 10, - ev.pageY - this.offsetTop - 10, + ev.pageX - rect.left > this.centerX! ? ev.pageX - rect.left - 165 : ev.pageX - rect.left + 10, + ev.pageY - this.offsetTop > this.centerY! ? ev.pageY - this.offsetTop - 50 : ev.pageY + (this.offsetTop - rect.top) - this.offsetTop + 20, this.litChartPieConfig.tip ? this.litChartPieConfig!.tip(it) : `${it.key}: ${it.value}` ); } diff --git a/ide/src/base-ui/loading/LitLoading.ts b/ide/src/base-ui/loading/LitLoading.ts new file mode 100644 index 0000000000000000000000000000000000000000..f0b3fd56ec075f103e51a63644305bff678f4cf3 --- /dev/null +++ b/ide/src/base-ui/loading/LitLoading.ts @@ -0,0 +1,177 @@ +import { BaseElement, element } from '../BaseElement' + +@element('lit-loading') +export class LitLoading extends BaseElement { + + initHtml(): string { + return ` + +
+
+
+
+
+
+
+
+
+
+
+
+ 加载中 ... +
+
+ `; + } + + initElements(): void { + } +} \ No newline at end of file diff --git a/ide/src/base-ui/menu/LitMainMenu.ts b/ide/src/base-ui/menu/LitMainMenu.ts index 89fa33020c8b5897c95d378e14488d07336d14fb..e5465cc75cf409c6e2bdbfcb113caeaeaeeab76c 100644 --- a/ide/src/base-ui/menu/LitMainMenu.ts +++ b/ide/src/base-ui/menu/LitMainMenu.ts @@ -95,6 +95,7 @@ const initHtmlStyle: string = ` cursor: pointer; height: 47px; width: 48px; + color: #1E4EEA; } `; diff --git a/ide/src/base-ui/select/LitSelect.ts b/ide/src/base-ui/select/LitSelect.ts index aad124e5c4d87417f569bb5ed2acf24fbeb63129..da9d3e108939c3e05f5f15476b50fb2f00c5b4bd 100644 --- a/ide/src/base-ui/select/LitSelect.ts +++ b/ide/src/base-ui/select/LitSelect.ts @@ -16,6 +16,7 @@ import { BaseElement, element } from '../BaseElement'; import { selectHtmlStr } from './LitSelectHtml'; import { LitSelectOption } from './LitSelectOption'; +import { SpSystemTrace } from '../../trace/component/SpSystemTrace'; @element('lit-select') export class LitSelect extends BaseElement { @@ -45,6 +46,7 @@ export class LitSelect extends BaseElement { 'border', 'mode', 'showSearchInput', + 'tabSelect' ]; } @@ -471,7 +473,12 @@ export class LitSelect extends BaseElement { setOnkeydown(): void { // @ts-ignore - this.selectInputEl.onkeydown = (ev: unknown): void => { + this.selectInputEl.onkeydown = (ev: KeyboardEvent): void => { + ev.stopPropagation(); + if (this.hasAttribute('tabselect')) { + // @ts-ignore + this.selectInputEl.readOnly = true; + } else { // @ts-ignore if (ev.key === 'Backspace') { if (this.isMultiple()) { @@ -513,11 +520,12 @@ export class LitSelect extends BaseElement { }) ); } - } // @ts-ignore + }// @ts-ignore } else if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { // @ts-ignore ev.preventDefault(); } + } }; } diff --git a/ide/src/base-ui/tabs/lit-tabs.ts b/ide/src/base-ui/tabs/lit-tabs.ts index 75935c8f16a7ac1aea3e34401dbeae8a3be5657b..e2014306dca5b203152552f46d74d7e00b08fedd 100644 --- a/ide/src/base-ui/tabs/lit-tabs.ts +++ b/ide/src/base-ui/tabs/lit-tabs.ts @@ -17,6 +17,7 @@ import { element } from '../BaseElement'; import { LitTabpane } from './lit-tabpane'; import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil'; import { LitTabsHtml } from './lit-tabs.html'; +import { shadowRootInput } from '../../trace/component/trace/base/shadowRootInput'; @element('lit-tabs') export class LitTabs extends HTMLElement { @@ -281,7 +282,6 @@ export class LitTabs extends HTMLElement { a.removeAttribute('data-selected'); } }); - let tbp = this.querySelector(`lit-tabpane[key='${key}']`); let panes = this.querySelectorAll('lit-tabpane'); panes.forEach((a) => { if (a.key === key) { @@ -292,8 +292,14 @@ export class LitTabs extends HTMLElement { a.style.display = 'none'; } }); + let tbp = this.querySelector(`lit-tabpane[key='${key}']`); + if (tbp) { + setTimeout(() => { + shadowRootInput.preventBubbling(tbp); + }, 500); + } } - + byKeyIsValid(isValid: boolean, a: Element): void { if (isValid) { let span = a.querySelector('span') as HTMLSpanElement; diff --git a/ide/src/doc/quickstart_parsing_ability.html b/ide/src/doc/quickstart_parsing_ability.html index b495caf5a293832896040d6f78c036d57f5181ca..45ee591a2622877f6a0bed6af3bb7688fec8876d 100644 --- a/ide/src/doc/quickstart_parsing_ability.html +++ b/ide/src/doc/quickstart_parsing_ability.html @@ -877,6 +877,196 @@ Single file max size: trace文件分割的大小。
GitHub Logo

+ +

+ Hangs抓取和展示说明 +

+

+ 挂起(hang)是离散用户交互中的明显延迟,并且它几乎总是主线程上长时间运行工作的结果。 + 仅当主线程在大约 50 毫秒到 100 毫秒或更长时间内无响应时,离散交互延迟才会开始变得明显。 +

+

Hangs的抓取

+

Hangs抓取配置参数

+

+ 进入Probes config页面,打开Record mode开关,勾选notification可以抓取Hangs数据(此选项为默认勾选)。 +

+
+ GitHub Logo +

+ 解析时需要打开Flags页面的Hangs Detection开关(Disabled切换为Enabled)。 +

+
+ GitHub Logo +

Hangs展示说明

+

+ 将抓取的trace文件导入到smartperf工具中,查看挂起的情况。 +

+

泳道图展示

+ GitHub Logo +

类型说明

+ GitHub Logo +

+ 点击Hangs Detection开关下的选项可以选择展示的不同类型。 +

+

+ 根据duration大小将hang划分为4个type,即Instant、Circumstantial、Micro、Severe。4个type分别对应时长为 + 33ms<d<100ms、100ms≤d<250ms、250ms≤d<500ms、500ms≤d。 +

+

+ 颜色按type由浅及深:Instant蓝色、Circumstantial黄色、Micro橙色、Severe红色。 +

+

+ 选择不同类型展示出的泳道会不一样: 选择Instant会显示Instant、Circumstantial、Micro、Severe,如图一; + 选择Circumstantial则显示Circumstantial、Micro、Severe,如图二,以此类推。 +

+ GitHub Logo +

+ 图一 +

+ GitHub Logo +

+ 图二 +

+

Hangs泳道图的点选功能

+

+ 可以对hangs的各个slice进行点选,点选后在最下方的弹出层中会展示点选数据的统计的tab页。点击Hang type右侧蓝色箭头,会跳转到该hang对应的trace点。 +

+ GitHub Logo +
+ GitHub Logo +

+ Trace点的name依次对应tab页的Sender tid、Send time、Expect handle time、Task name/ID、Prio、Sender。 +

+
    +
  • +
    +StartTime(Relative):开始时间(相对时间)。
    +
    +
  • +
  • +
    +StartTime(Absolute):开始时间(绝对时间)。
    +
    +
  • +
  • +
    +Duration:持续时间。
    +
    +
  • +
  • +
    +Hang Type:挂起类型。
    +
    +
  • +
  • +
    +Sender tid:发送event的线程ID。
    +
    +
  • +
  • +
    +Send time:事件发送时间。
    +
    +
  • +
  • +
    +Expect handle time:期望事件开始时间。
    +
    +
  • +
  • +
    +Task name/Id:事件名/事件ID。
    +
    +
  • +
  • +
    +Prio:优先级。
    +
    +
  • +
  • +
    +Sender:发送者。
    +
    +
  • +
+

Hangs泳道图的框选功能

+

+ 框选Hangs的泳道图,展示Hangs的tab页,右侧第一个下拉框可以选择类型,也能根据process ,sender去搜索。 +

+ GitHub Logo +
    +
  • +
    +StartTime:开始时间。
    +
    +
  • +
  • +
    +Duration:持续时间。
    +
    +
  • +
  • +
    +Hang Type:挂起类型。
    +
    +
  • +
  • +
    +Process:进程名。
    +
    +
  • +
  • +
    +Sender tid:发送event的线程ID。
    +
    +
  • +
  • +
    +Send time:事件发送时间。
    +
    +
  • +
  • +
    +Expect handle time:期望事件开始时间。
    +
    +
  • +
  • +
    +Task name/Id:事件名/事件ID。
    +
    +
  • +
  • +
    +Prio:优先级。
    +
    +
  • +
  • +
    +Sender:发送者。
    +
    +
  • +
+

+ 框选Hangs的泳道图,展示Summary的tab页。 +

+ GitHub Logo +
    +
  • +
    +Type/Process/Hang:根据类型显示挂起情况。
    +
    +
  • +
  • +
    +Count:各类型的数量。
    +
    +
  • +
+

Hangs归一化泳道

+

+ 为了方便查看hangs数据,对不同进程下的hangs泳道进行了归一化处理 +

+ GitHub Logo