點(diǎn):把查詢結(jié)果發(fā)布為儀表盤數(shù)據(jù)源)
Perfetto Data Explorer 的 Export to Dashboard 節(jié)點(diǎn)把查詢結(jié)果發(fā)布為儀表盤數(shù)據(jù)源【免費(fèi)下載鏈接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.項(xiàng)目地址: https://gitcode.com/GitHub_Trending/pe/perfettoExport to Dashboard 是 Perfetto UI 的 Data Explorer數(shù)據(jù)探索器查詢圖Query Graph中的一種節(jié)點(diǎn)作用是把上游任意數(shù)據(jù)源表、過濾器、Join 等的查詢結(jié)果發(fā)布到全局儀表盤注冊(cè)表供 Dashboard 標(biāo)簽頁中的圖表直接引用。本文將以 dashboard.md 為核心結(jié)合 dashboard_node.ts、dashboard_registry.ts 等源碼講清該節(jié)點(diǎn)的配置項(xiàng)、工作流程、底層實(shí)現(xiàn)原理與使用建議讀完后你將能熟練地用它在 Data Explorer 中構(gòu)建“查詢圖 → 儀表盤”的完整數(shù)據(jù)鏈路。一、節(jié)點(diǎn)定位查詢圖與儀表盤之間的橋梁在 Perfetto Data Explorer 中用戶通過把多種節(jié)點(diǎn)Table Source、Filter、Join、Sort、Aggregation 等連接成一張有向無環(huán)圖來構(gòu)建數(shù)據(jù)管道最終結(jié)果既可以作為新表繼續(xù)參與后續(xù)處理也可以被“導(dǎo)出”到儀表盤進(jìn)行可視化。Export to Dashboard 節(jié)點(diǎn)節(jié)點(diǎn)類型kDashboard查詢節(jié)點(diǎn)定義正是承擔(dān)后者的橋梁它不改變數(shù)據(jù)本身只是把上游節(jié)點(diǎn)的輸入列finalCols原樣透?jìng)鞑l(fā)布出去發(fā)布后的數(shù)據(jù)源進(jìn)入全局儀表盤注冊(cè)表dashboardRegistry這是一個(gè)不依附于任何單個(gè)儀表盤、全局共享的單例池Dashboard 標(biāo)簽頁從該注冊(cè)表中讀取數(shù)據(jù)源列表用戶據(jù)此添加圖表。從 dashboard_node.ts 可以看到節(jié)點(diǎn)的finalCols直接返回primaryInput?.finalCols ?? []即導(dǎo)出節(jié)點(diǎn)的輸出列完全等于其輸入列自身不新增、不修改任何列——這是一個(gè)純粹的“發(fā)布publish”動(dòng)作。此外該節(jié)點(diǎn)沒有自己的結(jié)果面板customResultsPanel()返回一個(gè)空態(tài)提示“Data from this node is exported to dashboards.”明確告知用戶此處的數(shù)據(jù)去向是儀表盤而不是內(nèi)聯(lián)結(jié)果表。二、唯一配置項(xiàng)Export nameExport to Dashboard 節(jié)點(diǎn)只有一項(xiàng)配置Export name導(dǎo)出名稱一個(gè)人類可讀的標(biāo)簽會(huì)顯示在儀表盤圖表上以及 Data Explorer 的 Data 面板中。該名稱用于在儀表盤上標(biāo)識(shí)數(shù)據(jù)源因此在同一張圖中建議給出有區(qū)分度的名稱。2.1 名稱解析的優(yōu)先級(jí)鏈從 dashboard_node.ts 的getExportName()實(shí)現(xiàn)可以還原出完整的命名規(guī)則private getExportName(): string { return ( this.attrs.exportName?.trim() || this.primaryInput?.getTitle() || Unnamed export ); }解析順序?yàn)轱@式設(shè)置的exportName自動(dòng)去除首尾空白——最高優(yōu)先級(jí)上游節(jié)點(diǎn)的標(biāo)題如primaryInput.getTitle()通常是表名或節(jié)點(diǎn)標(biāo)題——當(dāng)未填寫導(dǎo)出名時(shí)作為默認(rèn)值兜底值Unnamed export——當(dāng)既沒有填寫導(dǎo)出名、也沒有連接輸入節(jié)點(diǎn)時(shí)使用。節(jié)點(diǎn)詳情面板 會(huì)實(shí)時(shí)顯示Exported as ${this.getExportName()}方便你隨時(shí)核對(duì)最終生效的導(dǎo)出名。2.2 修改即發(fā)布導(dǎo)出名稱的編輯框nodeSpecificModify()在值變化時(shí)會(huì)立即調(diào)用publishExportedSource()并觸發(fā)onchange回調(diào)也就是說無需手動(dòng)“保存”名稱的修改會(huì)立刻同步到儀表盤注冊(cè)表。該屬性存放在可序列化的DashboardNodeAttrs.exportName中隨查詢圖狀態(tài)一起被保存/恢復(fù)具體序列化邏輯見 state_serialization.ts 與 node_config.ts。三、工作流程三步把數(shù)據(jù)送上儀表盤原文檔給出了標(biāo)準(zhǔn)的三步流程下面結(jié)合源碼逐一展開。步驟 1連接上游節(jié)點(diǎn)將一個(gè)上游節(jié)點(diǎn)table、filter、join 等連接到 Export to Dashboard 節(jié)點(diǎn)的輸入端。此時(shí)節(jié)點(diǎn)會(huì)校驗(yàn)輸入是否有效未連接任何輸入時(shí)validate()報(bào)錯(cuò)No input connected輸入節(jié)點(diǎn)自身校驗(yàn)失敗時(shí)報(bào)錯(cuò)Input title is invalid錯(cuò)誤信息中帶上上游標(biāo)題便于定位是哪個(gè)節(jié)點(diǎn)出了問題。校驗(yàn)邏輯見 dashboard_node.ts對(duì)應(yīng)的單元測(cè)試覆蓋了上述全部錯(cuò)誤分支dashboard_node_unittest.ts。步驟 2節(jié)點(diǎn)把輸入列發(fā)布到全局儀表盤注冊(cè)表連接建立后onPrevNodesUpdated()會(huì)觸發(fā)發(fā)布動(dòng)作dashboard_node.ts。發(fā)布的數(shù)據(jù)源對(duì)象DashboardDataSource結(jié)構(gòu)如下dashboard_registry.tsinterface DashboardDataSource { readonly name: string; // 導(dǎo)出名稱用于展示與選擇 readonly nodeId: string; // 導(dǎo)出節(jié)點(diǎn) ID注冊(cè)表主鍵 readonly columns: ReadonlyArray{name: string; type?: PerfettoSqlType}; // 列名 類型 readonly graphId: string; // 所屬查詢圖標(biāo)簽頁的穩(wěn)定 ID tableName?: string; // 物化后的 SQL 表名執(zhí)行前為 undefined requestExecution?: () Promisevoid; // 觸發(fā)源節(jié)點(diǎn)執(zhí)行同步 物化 }發(fā)布時(shí)會(huì)把finalCols中每一列的名稱與類型快照進(jìn)columns。列信息是快照式的當(dāng)上游列發(fā)生變化例如修改了上游節(jié)點(diǎn)的列時(shí)節(jié)點(diǎn)會(huì)通過onPrevNodesUpdated()重新發(fā)布注冊(cè)表中對(duì)應(yīng)nodeId的數(shù)據(jù)源會(huì)被整體覆蓋更新而不會(huì)產(chǎn)生重復(fù)條目——這一點(diǎn)由單元測(cè)試顯式驗(yàn)證dashboard_node_unittest.ts。值得注意的是如果導(dǎo)出節(jié)點(diǎn)的輸入被斷開publishExportedSource()會(huì)調(diào)用dashboardRegistry.removeExportedSource(this.nodeId)主動(dòng)注銷該數(shù)據(jù)源儀表盤上引用它的圖表隨即變?yōu)椤皵?shù)據(jù)源已移除”的失聯(lián)狀態(tài)。步驟 3在 Dashboard 標(biāo)簽頁添加圖表打開 Dashboard 標(biāo)簽頁通過側(cè)邊欄的Add面板選擇圖表類型并添加圖表。圖表通過sourceNodeId關(guān)聯(lián)到具體的導(dǎo)出源dashboard_registry.tsinterface DashboardChart { readonly sourceNodeId: string; // 引用的導(dǎo)出源 nodeId config: ChartConfig; col?: number; row?: number; colSpan?: number; rowSpan?: number; }如果當(dāng)前沒有任何導(dǎo)出源Dashboard 畫布會(huì)顯示空態(tài)提示“Use the Export to Dashboard node in the graph to export data here.”dashboard.ts——這正是 Export to Dashboard 節(jié)點(diǎn)存在的意義。四、全局注冊(cè)表跨標(biāo)簽頁共享的數(shù)據(jù)源池4.1 為什么是全局單例dashboardRegistry是一個(gè)全局單例dashboard_registry.ts內(nèi)部用MapnodeId, DashboardDataSource維護(hù)所有導(dǎo)出源。源碼注釋說明了原因?qū)С龉?jié)點(diǎn)的發(fā)布動(dòng)作發(fā)生在查詢執(zhí)行過程中、Mithril 渲染循環(huán)之外因此必須使用全局單例保證任何時(shí)刻都能被可靠訪問而 Dashboard 標(biāo)簽頁則通過 DataExplorer 把數(shù)據(jù)源列表以 props 方式注入。4.2 提供的核心查詢能力注冊(cè)表暴露了以下方法方法作用setExportedSource(source)發(fā)布/覆蓋一個(gè)導(dǎo)出源以nodeId為鍵removeExportedSource(nodeId)刪除導(dǎo)出源例如節(jié)點(diǎn)被刪除或輸入斷開getExportedSource(nodeId)按節(jié)點(diǎn) ID 取單個(gè)導(dǎo)出源getAllExportedSources()取全部導(dǎo)出源getExportedSourcesForGraph(graphId)按查詢圖標(biāo)簽頁過濾clear()清空整個(gè)池測(cè)試與重置時(shí)使用每個(gè)導(dǎo)出源都記錄著所屬查詢圖標(biāo)簽頁的graphId因此多張查詢圖、多個(gè)導(dǎo)出節(jié)點(diǎn)可以共存互不干擾。4.3 與圖表數(shù)據(jù)聯(lián)動(dòng)Linked Columns注冊(cè)表中還有g(shù)etLinkedSourceNodeIds()工具函數(shù)給定一個(gè)源和一個(gè)列名返回所有“擁有同名列”的源節(jié)點(diǎn) ID含自身。這支撐了儀表盤的Linked columns關(guān)聯(lián)列面板——當(dāng)用戶在某個(gè)圖表上刷選brush時(shí)同名列的其他圖表可以聯(lián)動(dòng)過濾實(shí)現(xiàn)跨圖表交互分析。五、延遲物化表在首次使用時(shí)才執(zhí)行原文檔 Tips 中強(qiáng)調(diào)了兩點(diǎn)表在首次使用時(shí)才物化儀表盤會(huì)在源尚未運(yùn)行時(shí)自動(dòng)觸發(fā)執(zhí)行。這在源碼中有非常清晰的體現(xiàn)。5.1 tableName 的懶解析DashboardDataSource.tableName在發(fā)布時(shí)是undefined注釋明確寫著Undefined until the source node has been executed。發(fā)布動(dòng)作本身不會(huì)立即請(qǐng)求執(zhí)行——單元測(cè)試專門驗(yàn)證了“發(fā)布后getTableNameForNode尚未被調(diào)用”dashboard_node_unittest.ts。5.2 圖表渲染觸發(fā)執(zhí)行當(dāng)儀表盤上的圖表需要渲染數(shù)據(jù)時(shí)dashboard_chart_view.ts 會(huì)檢查source.tableName若為undefined且尚未請(qǐng)求過執(zhí)行則調(diào)用source.requestExecution()requestExecution內(nèi)部先請(qǐng)求上游節(jié)點(diǎn)執(zhí)行requestNodeExecution(parentNodeId)執(zhí)行完成后通過getTableNameForNode(parentNodeId)解析出物化的 SQL 表名寫回source.tableName并再次setExportedSource更新注冊(cè)表dashboard_node.ts表名就緒后圖表以SELECT * FROM ${tableName} ...的形式查詢數(shù)據(jù)dashboard_chart_view.ts。這一機(jī)制保證了只要圖表的引用源被觸發(fā)一次執(zhí)行后續(xù)渲染就復(fù)用已物化的表避免重復(fù)計(jì)算同時(shí)用戶無需手動(dòng)“先運(yùn)行查詢圖再開儀表盤”首次添加圖表即可自動(dòng)拉起數(shù)據(jù)。六、儀表盤畫布導(dǎo)出源如何被消費(fèi)導(dǎo)出源進(jìn)入注冊(cè)表后在 Dashboard 畫布上以圖表卡片的形式被消費(fèi)。了解畫布規(guī)則有助于理解“導(dǎo)出名”之外的設(shè)計(jì)畫布采用24 列網(wǎng)格GRID_COLUMNS 24圖表卡片默認(rèn)尺寸為DEFAULT_COL_SPAN 8、DEFAULT_ROW_SPAN 6最小不得小于 4×4dashboard_registry.ts卡片支持拖拽、縮放水平/垂直并強(qiáng)制保持至少 1 格間距checkOverlap/findNonOverlappingPosition除圖表外畫布還支持Label文本標(biāo)簽和Segment Divider分段分隔線分隔線上方的圖表是“驅(qū)動(dòng)者driver”其刷選brush選擇會(huì)過濾下方“消費(fèi)者consumer”圖表的數(shù)據(jù)而驅(qū)動(dòng)者自身不受過濾影響getDriversOf/getConsumersOf/isDriverChart若某個(gè)圖表引用的導(dǎo)出源被刪除節(jié)點(diǎn)被刪或輸入斷開該圖表會(huì)渲染為“Data source removed”失聯(lián)卡片提示用戶刪除或重新指派數(shù)據(jù)源dashboard.ts。在 Data 側(cè)邊欄面板中用戶可以查看全部導(dǎo)出源及其列并為圖表更換數(shù)據(jù)源每個(gè)圖表頭部都有數(shù)據(jù)源 Chip 和編輯按鈕。七、最佳實(shí)踐與提示結(jié)合原文檔 Tips 與源碼行為給出以下實(shí)操建議為導(dǎo)出起描述性名稱導(dǎo)出名會(huì)直接出現(xiàn)在儀表盤圖表頭部、數(shù)據(jù)源 Chip 和 Data 面板中。因?yàn)槟J(rèn)回退到上游節(jié)點(diǎn)標(biāo)題建議對(duì)上游節(jié)點(diǎn)命名足夠清晰或顯式填寫導(dǎo)出名空名稱或純空白會(huì)回退到上游標(biāo)題兩者皆無時(shí)才顯示Unnamed export。善用“修改即發(fā)布”導(dǎo)出名、上游列的任何變更都會(huì)即時(shí)同步到注冊(cè)表無需手動(dòng)刷新儀表盤但請(qǐng)留意列結(jié)構(gòu)變化后儀表盤上已配置圖表若引用了不存在的列會(huì)被自動(dòng)清理關(guān)聯(lián)的刷選過濾器見 dashboard_chart_view.ts。理解延遲執(zhí)行導(dǎo)出本身不觸發(fā)查詢執(zhí)行表在圖表首次渲染時(shí)才物化。想要預(yù)取數(shù)據(jù)可以在查詢圖中運(yùn)行上游節(jié)點(diǎn)或在儀表盤中先添加任意一個(gè)引用該源的圖表。一個(gè)節(jié)點(diǎn)對(duì)應(yīng)一個(gè)數(shù)據(jù)源每個(gè) Export to Dashboard 節(jié)點(diǎn)在注冊(cè)表中占據(jù)唯一nodeId鍵重復(fù)發(fā)布會(huì)覆蓋而不是疊加刪除節(jié)點(diǎn)或斷開輸入會(huì)自動(dòng)注銷數(shù)據(jù)源保持注冊(cè)表干凈??鐖D表聯(lián)動(dòng)利用 Linked Columns同名列關(guān)聯(lián)和 Segment Divider驅(qū)動(dòng)/消費(fèi)者分層可以把多個(gè)導(dǎo)出源組合成交互式分析儀表盤而不必把全部邏輯塞進(jìn)單個(gè)查詢。八、相關(guān)源碼與文檔索引節(jié)點(diǎn)說明文檔本文主體ui/src/assets/data_explorer/node_info/dashboard.md節(jié)點(diǎn)實(shí)現(xiàn)校驗(yàn)、命名、發(fā)布邏輯ui/src/plugins/dev.perfetto.DataExplorer/query_builder/nodes/dashboard_node.ts全局注冊(cè)表與數(shù)據(jù)源類型定義ui/src/plugins/dev.perfetto.DataExplorer/dashboard/dashboard_registry.tsDashboard 畫布組件空態(tài)、圖表卡片、驅(qū)動(dòng)/消費(fèi)者分隔ui/src/plugins/dev.perfetto.DataExplorer/dashboard/dashboard.ts圖表渲染與延遲執(zhí)行SELECT * FROM tableNameui/src/plugins/dev.perfetto.DataExplorer/dashboard/dashboard_chart_view.ts節(jié)點(diǎn)文檔加載器markdown 渲染與緩存ui/src/plugins/dev.perfetto.DataExplorer/query_builder/node_doc_loader.ts節(jié)點(diǎn)單元測(cè)試發(fā)布、回退命名、列變更、執(zhí)行解析全覆蓋ui/src/plugins/dev.perfetto.DataExplorer/query_builder/nodes/dashboard_node_unittest.ts同類節(jié)點(diǎn)文檔Filter、Join、Visualisation 等ui/src/assets/data_explorer/node_info/九、小結(jié)Export to Dashboard 節(jié)點(diǎn)是 Perfetto Data Explorer 中“查詢圖”與“可視化儀表盤”之間的關(guān)鍵樞紐它用最小的配置一個(gè)導(dǎo)出名把上游任意數(shù)據(jù)源發(fā)布到全局注冊(cè)表由儀表盤按需物化執(zhí)行并渲染圖表還通過全局單例注冊(cè)表、列快照更新、同名列聯(lián)動(dòng)等機(jī)制保證了多圖多源的協(xié)作與一致性。掌握這一節(jié)點(diǎn)你就打通了從 SQL 查詢構(gòu)建到交互式儀表盤可視化的完整鏈路。【免費(fèi)下載鏈接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.項(xiàng)目地址: https://gitcode.com/GitHub_Trending/pe/perfetto創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考