sparkforensics-server 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +3 -0
- package/package.json +3 -3
- package/public/assets/AutoscalingChurn-5hDGIXi4.js +1 -0
- package/public/assets/CacheUtilization-CT2SCnJJ.js +1 -0
- package/public/assets/CachingOpportunity-D_O_WkbH.js +1 -0
- package/public/assets/ColdStart-B38OiAOp.js +1 -0
- package/public/assets/ConfigAudit-BoplryCH.js +1 -0
- package/public/assets/CoreUsageArea-csgwNxkl.js +1 -0
- package/public/assets/Dashboard-BgKodJl2.js +2 -0
- package/public/assets/DisclosureContext-B0siMVdg.js +1 -0
- package/public/assets/DuplicatePlanSubtree-BqS2A2j4.js +1 -0
- package/public/assets/ExecutorUtilization-Dp52QGWo.js +1 -0
- package/public/assets/GcPressure-CT1yzR_s.js +1 -0
- package/public/assets/IncompleteRun-C7Qkjtjn.js +1 -0
- package/public/assets/JobFailures-WHl3ELfh.js +1 -0
- package/public/assets/MemoryUtilization-D8IUDHJI.js +1 -0
- package/public/assets/OverBroadcast-6oSSAQ_R.js +1 -0
- package/public/assets/PartitionHint-CUvbnnxy.js +1 -0
- package/public/assets/PartitionSizing-BwdFL-mw.js +1 -0
- package/public/assets/{PlanExplorer-DdmPkKO1.js → PlanExplorer-DcxmiQWL.js} +1 -1
- package/public/assets/PlanGraphRoute-pqnHTt4i.js +1 -0
- package/public/assets/RetryWaste-BTbeHkJc.js +1 -0
- package/public/assets/ShuffleIO-CRhrYNE0.js +1 -0
- package/public/assets/Skew-DSNXRG9V.js +1 -0
- package/public/assets/SlowHost-B7Lwu2EU.js +1 -0
- package/public/assets/SmallFiles-C082c2rd.js +1 -0
- package/public/assets/SpeculationWaste-BS2vpadr.js +1 -0
- package/public/assets/Spill-B4DVKHXx.js +1 -0
- package/public/assets/StageFailed-D3ac9Sou.js +1 -0
- package/public/assets/StageFindingGroup-D9naK109.js +1 -0
- package/public/assets/{StageHeader-BSV8ALhT.js → StageHeader-pI1nTwVf.js} +1 -1
- package/public/assets/StageShape-eO5le8iG.js +1 -0
- package/public/assets/StageSlowness-BaNyfNvL.js +1 -0
- package/public/assets/Straggler-D5Fnok_y.js +1 -0
- package/public/assets/TaskFailures-BWnC-K_G.js +1 -0
- package/public/assets/{TinyTask-CIPRxWfT.js → TinyTask-8_5lpq_2.js} +1 -1
- package/public/assets/UnderBroadcast-DJ0XSwth.js +1 -0
- package/public/assets/{finding-anchor-DF1cSHO1.js → finding-anchor-Cys8Z6Yn.js} +1 -1
- package/public/assets/{impact-sort-7z0ZcBZf.js → impact-sort-BTQndbof.js} +1 -1
- package/public/assets/index-DCeWge12.js +13 -0
- package/public/assets/parser-worker-DmeCnLWU.js +122 -0
- package/public/assets/{plan-graph-vendor-B0sEms9Z.js → plan-graph-vendor-BYl-AzN5.js} +1 -1
- package/public/assets/{react-vendor-BAKt3vny.js → react-vendor-DEdfrRTJ.js} +1 -1
- package/public/assets/{select-Cy5pmbrh.js → select-DIYN6D3y.js} +1 -1
- package/public/assets/{usePagedRows-BjPOpUU8.js → usePagedRows-BxvdFnPk.js} +1 -1
- package/public/assets/useRecentFiles-C3Ov47U7.js +11 -0
- package/public/assets/{useSortMode-CU0vzThu.js → useSortMode-B8SRfAoG.js} +1 -1
- package/public/docs/404.html +4 -3
- package/public/docs/assets/{app.C6w47a9W.js → app.D2GqAkhy.js} +1 -1
- package/public/docs/assets/chunks/@localSearchIndexroot.D4OdkQjy.js +1 -0
- package/public/docs/assets/chunks/{VPLocalSearchBox.BcTNvT55.js → VPLocalSearchBox.BS4cSmtW.js} +1 -1
- package/public/docs/assets/chunks/{theme.D-mE6j02.js → theme.BuxVpb0H.js} +2 -2
- package/public/docs/assets/contributor-guide_architecture_board-widgets.md.YQcj5EI4.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_board-widgets.md.YQcj5EI4.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_board-widgets_caching-and-memory.md.8bH1HnZp.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_board-widgets_caching-and-memory.md.8bH1HnZp.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_board-widgets_plan-advisor.md.RlzvUmNm.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_board-widgets_plan-advisor.md.RlzvUmNm.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_board-widgets_visual-system-and-templating.md.DYgUpIJB.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_board-widgets_visual-system-and-templating.md.DYgUpIJB.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_detector-contract.md.wj6Et6UD.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_detector-contract.md.wj6Et6UD.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_detector-contract_plan-attribution.md.yNex4bys.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_detector-contract_plan-attribution.md.yNex4bys.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_detector-contract_threshold-tables.md.fkPBXsU2.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_detector-contract_threshold-tables.md.fkPBXsU2.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_drill-down.md.CqZPrdo9.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_drill-down.md.CqZPrdo9.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_drill-down_plan-graph.md.DwOozIEs.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_drill-down_plan-graph.md.DwOozIEs.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_impact-estimation.md.CZv_ZGOp.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_impact-estimation.md.CZv_ZGOp.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_impact-estimation_caveats-tuning-and-coverage.md.BUucRc0A.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_impact-estimation_caveats-tuning-and-coverage.md.BUucRc0A.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_impact-estimation_stage-union-rollup.md.DdCGtAGu.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_impact-estimation_stage-union-rollup.md.DdCGtAGu.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_index.md.tymxf1Fh.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_index.md.tymxf1Fh.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_overview.md.C1sSvm9i.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_overview.md.C1sSvm9i.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_state-and-history.md.DyCBdjuM.js +1 -0
- package/public/docs/assets/{contributor-guide_architecture_state-and-history.md.DOTVHjTV.lean.js → contributor-guide_architecture_state-and-history.md.DyCBdjuM.lean.js} +1 -1
- package/public/docs/assets/contributor-guide_architecture_state-and-history_history-server-intake.md.C298hrHZ.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_state-and-history_history-server-intake.md.C298hrHZ.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_state-and-history_run-comparison-internals.md.uuAKpY0Y.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_state-and-history_run-comparison-internals.md.uuAKpY0Y.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering.md.BOZ1azXG.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering.md.BOZ1azXG.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering_findings-tab.md.BQXycK6G.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering_findings-tab.md.BQXycK6G.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering_investigation-routing.md.BGdiyElu.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering_investigation-routing.md.BGdiyElu.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering_list-sort-mode.md.BuHKgH0C.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering_list-sort-mode.md.BuHKgH0C.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering_reference-section.md.DWqC80bN.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering_reference-section.md.DWqC80bN.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering_row-expand-contract.md.ZT89u9f1.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering_row-expand-contract.md.ZT89u9f1.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_worker-protocol.md.BAnhi2-d.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_worker-protocol.md.BAnhi2-d.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_worker-protocol_cli-and-mcp.md.Dk08VS7n.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_worker-protocol_cli-and-mcp.md.Dk08VS7n.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_worker-protocol_core-and-event-validation.md.DSVFPpWb.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_worker-protocol_core-and-event-validation.md.DSVFPpWb.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_worker-protocol_evidence-availability.md.CjimIDBY.js +6 -0
- package/public/docs/assets/contributor-guide_architecture_worker-protocol_evidence-availability.md.CjimIDBY.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_worker-protocol_evidence-report.md.DVGZOWvW.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_worker-protocol_evidence-report.md.DVGZOWvW.lean.js +1 -0
- package/public/docs/assets/contributor-guide_contributing.md.CQMvGwFt.js +1 -0
- package/public/docs/assets/{contributor-guide_contributing.md.B2E9ni79.lean.js → contributor-guide_contributing.md.CQMvGwFt.lean.js} +1 -1
- package/public/docs/assets/contributor-guide_development-setup.md.D9bu4j_c.js +15 -0
- package/public/docs/assets/contributor-guide_development-setup.md.D9bu4j_c.lean.js +1 -0
- package/public/docs/assets/contributor-guide_testing.md.By6XGR9a.js +1 -0
- package/public/docs/assets/{contributor-guide_testing.md.DTwhpoN2.lean.js → contributor-guide_testing.md.By6XGR9a.lean.js} +1 -1
- package/public/docs/assets/{style.DSixAiZE.css → style.tmDhD3c8.css} +1 -1
- package/public/docs/assets/user-guide_alternative-log-retrieval.md.CJpYvHGo.js +4 -0
- package/public/docs/assets/user-guide_alternative-log-retrieval.md.CJpYvHGo.lean.js +1 -0
- package/public/docs/assets/user-guide_alternative-log-retrieval_managed-platforms.md.DvDwHNtC.js +4 -0
- package/public/docs/assets/user-guide_alternative-log-retrieval_managed-platforms.md.DvDwHNtC.lean.js +1 -0
- package/public/docs/assets/user-guide_alternative-log-retrieval_ssh-bastion.md.Gszzlplv.js +1 -0
- package/public/docs/assets/user-guide_alternative-log-retrieval_ssh-bastion.md.Gszzlplv.lean.js +1 -0
- package/public/docs/assets/user-guide_getting-started.md.DYHHHkQR.js +1 -0
- package/public/docs/assets/user-guide_getting-started.md.DYHHHkQR.lean.js +1 -0
- package/public/docs/assets/user-guide_getting-started_ci-and-automation.md.DpnfKz3x.js +22 -0
- package/public/docs/assets/user-guide_getting-started_ci-and-automation.md.DpnfKz3x.lean.js +1 -0
- package/public/docs/assets/user-guide_getting-started_reading-the-dashboard.md.Obf3W3__.js +1 -0
- package/public/docs/assets/user-guide_getting-started_reading-the-dashboard.md.Obf3W3__.lean.js +1 -0
- package/public/docs/assets/user-guide_getting-started_regression-metric-keys.md.B_gzr2Mw.js +1 -0
- package/public/docs/assets/user-guide_getting-started_regression-metric-keys.md.B_gzr2Mw.lean.js +1 -0
- package/public/docs/assets/user-guide_getting-started_tuning-thresholds.md.B_MyjyZm.js +4 -0
- package/public/docs/assets/user-guide_getting-started_tuning-thresholds.md.B_MyjyZm.lean.js +1 -0
- package/public/docs/assets/user-guide_mcp-tools.md.C65SjWUL.js +16 -0
- package/public/docs/assets/user-guide_mcp-tools.md.C65SjWUL.lean.js +1 -0
- package/public/docs/assets/user-guide_mcp-tools_compare-runs.md.CPowlb2q.js +55 -0
- package/public/docs/assets/user-guide_mcp-tools_compare-runs.md.CPowlb2q.lean.js +1 -0
- package/public/docs/assets/user-guide_mcp-tools_diagnose-run.md.BP1vnHA5.js +23 -0
- package/public/docs/assets/user-guide_mcp-tools_diagnose-run.md.BP1vnHA5.lean.js +1 -0
- package/public/docs/assets/user-guide_mcp-tools_evaluate-budgets.md.Dq5Azk8G.js +26 -0
- package/public/docs/assets/user-guide_mcp-tools_evaluate-budgets.md.Dq5Azk8G.lean.js +1 -0
- package/public/docs/assets/user-guide_mcp-tools_get-finding-documentation.md.BtTTHNV6.js +14 -0
- package/public/docs/assets/user-guide_mcp-tools_get-finding-documentation.md.BtTTHNV6.lean.js +1 -0
- package/public/docs/assets/user-guide_mcp-tools_get-finding-evidence.md.rKyu4wts.js +20 -0
- package/public/docs/assets/user-guide_mcp-tools_get-finding-evidence.md.rKyu4wts.lean.js +1 -0
- package/public/docs/assets/user-guide_mcp-tools_get-reference-doc.md.Yac4tH3u.js +5 -0
- package/public/docs/assets/user-guide_mcp-tools_get-reference-doc.md.Yac4tH3u.lean.js +1 -0
- package/public/docs/assets/user-guide_mcp-tools_get-run-summary.md.DpxZ4ZNp.js +15 -0
- package/public/docs/assets/user-guide_mcp-tools_get-run-summary.md.DpxZ4ZNp.lean.js +1 -0
- package/public/docs/assets/user-guide_mcp-tools_list-runs.md.DpQPeCM3.js +12 -0
- package/public/docs/assets/user-guide_mcp-tools_list-runs.md.DpQPeCM3.lean.js +1 -0
- package/public/docs/assets/user-guide_run-comparison.md.B6aNtDYF.js +1 -0
- package/public/docs/assets/user-guide_run-comparison.md.B6aNtDYF.lean.js +1 -0
- package/public/docs/assets/user-guide_run-comparison_how-stages-are-matched.md.XBzQ1oEU.js +1 -0
- package/public/docs/assets/user-guide_run-comparison_how-stages-are-matched.md.XBzQ1oEU.lean.js +1 -0
- package/public/docs/assets/user-guide_understanding-findings.md.Dqt2H_C1.js +1 -0
- package/public/docs/contributor-guide/architecture/board-widgets/caching-and-memory.html +30 -0
- package/public/docs/contributor-guide/architecture/board-widgets/plan-advisor.html +30 -0
- package/public/docs/contributor-guide/architecture/board-widgets/visual-system-and-templating.html +30 -0
- package/public/docs/contributor-guide/architecture/board-widgets.html +7 -6
- package/public/docs/contributor-guide/architecture/detector-contract/plan-attribution.html +30 -0
- package/public/docs/contributor-guide/architecture/detector-contract/threshold-tables.html +30 -0
- package/public/docs/contributor-guide/architecture/detector-contract.html +7 -6
- package/public/docs/contributor-guide/architecture/drill-down/plan-graph.html +30 -0
- package/public/docs/contributor-guide/architecture/drill-down.html +7 -6
- package/public/docs/contributor-guide/architecture/impact-estimation/caveats-tuning-and-coverage.html +30 -0
- package/public/docs/contributor-guide/architecture/impact-estimation/stage-union-rollup.html +30 -0
- package/public/docs/contributor-guide/architecture/impact-estimation.html +7 -6
- package/public/docs/contributor-guide/architecture/index.html +7 -6
- package/public/docs/contributor-guide/architecture/overview.html +7 -6
- package/public/docs/contributor-guide/architecture/state-and-history/history-server-intake.html +30 -0
- package/public/docs/contributor-guide/architecture/state-and-history/run-comparison-internals.html +30 -0
- package/public/docs/contributor-guide/architecture/state-and-history.html +7 -6
- package/public/docs/contributor-guide/architecture/widget-rendering/findings-tab.html +30 -0
- package/public/docs/contributor-guide/architecture/widget-rendering/investigation-routing.html +30 -0
- package/public/docs/contributor-guide/architecture/widget-rendering/list-sort-mode.html +30 -0
- package/public/docs/contributor-guide/architecture/widget-rendering/reference-section.html +30 -0
- package/public/docs/contributor-guide/architecture/widget-rendering/row-expand-contract.html +30 -0
- package/public/docs/contributor-guide/architecture/widget-rendering.html +7 -6
- package/public/docs/contributor-guide/architecture/worker-protocol/cli-and-mcp.html +30 -0
- package/public/docs/contributor-guide/architecture/worker-protocol/core-and-event-validation.html +30 -0
- package/public/docs/contributor-guide/architecture/worker-protocol/evidence-availability.html +35 -0
- package/public/docs/contributor-guide/architecture/worker-protocol/evidence-report.html +30 -0
- package/public/docs/contributor-guide/architecture/worker-protocol.html +7 -11
- package/public/docs/contributor-guide/contributing.html +7 -6
- package/public/docs/contributor-guide/development-setup.html +11 -10
- package/public/docs/contributor-guide/testing.html +7 -6
- package/public/docs/hashmap.json +1 -1
- package/public/docs/index.html +5 -4
- package/public/docs/tuning-reference/anti-patterns.html +5 -4
- package/public/docs/tuning-reference/aqe.html +5 -4
- package/public/docs/tuning-reference/bottleneck-broadcast-sizing.html +5 -4
- package/public/docs/tuning-reference/bottleneck-cold-start.html +5 -4
- package/public/docs/tuning-reference/bottleneck-duplicate-plan-subtree.html +5 -4
- package/public/docs/tuning-reference/bottleneck-failures.html +5 -4
- package/public/docs/tuning-reference/bottleneck-gc.html +5 -4
- package/public/docs/tuning-reference/bottleneck-job-failure-rate.html +5 -4
- package/public/docs/tuning-reference/bottleneck-memory-utilization.html +5 -4
- package/public/docs/tuning-reference/bottleneck-retry-waste.html +5 -4
- package/public/docs/tuning-reference/bottleneck-shuffle.html +5 -4
- package/public/docs/tuning-reference/bottleneck-skew.html +5 -4
- package/public/docs/tuning-reference/bottleneck-slow-host.html +5 -4
- package/public/docs/tuning-reference/bottleneck-small-files.html +5 -4
- package/public/docs/tuning-reference/bottleneck-spill.html +5 -4
- package/public/docs/tuning-reference/bottleneck-straggler.html +5 -4
- package/public/docs/tuning-reference/bottleneck-tiny-tasks.html +5 -4
- package/public/docs/tuning-reference/bottleneck-utilization.html +5 -4
- package/public/docs/tuning-reference/caching.html +5 -4
- package/public/docs/tuning-reference/cluster-config.html +5 -4
- package/public/docs/tuning-reference/config.html +5 -4
- package/public/docs/tuning-reference/data-formats.html +5 -4
- package/public/docs/tuning-reference/index.html +5 -4
- package/public/docs/tuning-reference/intro.html +5 -4
- package/public/docs/tuning-reference/joins.html +5 -4
- package/public/docs/tuning-reference/memory-model.html +5 -4
- package/public/docs/tuning-reference/metrics.html +5 -4
- package/public/docs/tuning-reference/partitioning.html +5 -4
- package/public/docs/tuning-reference/pyspark.html +5 -4
- package/public/docs/tuning-reference/shuffle.html +5 -4
- package/public/docs/tuning-reference/spark-architecture.html +5 -4
- package/public/docs/tuning-reference/table-formats.html +5 -4
- package/public/docs/user-guide/alternative-log-retrieval/managed-platforms.html +33 -0
- package/public/docs/user-guide/alternative-log-retrieval/ssh-bastion.html +30 -0
- package/public/docs/user-guide/alternative-log-retrieval.html +11 -7
- package/public/docs/user-guide/getting-started/ci-and-automation.html +51 -0
- package/public/docs/user-guide/getting-started/reading-the-dashboard.html +30 -0
- package/public/docs/user-guide/getting-started/regression-metric-keys.html +30 -0
- package/public/docs/user-guide/getting-started/tuning-thresholds.html +33 -0
- package/public/docs/user-guide/getting-started.html +7 -11
- package/public/docs/user-guide/mcp-tools/compare-runs.html +84 -0
- package/public/docs/user-guide/mcp-tools/diagnose-run.html +52 -0
- package/public/docs/user-guide/mcp-tools/evaluate-budgets.html +55 -0
- package/public/docs/user-guide/mcp-tools/get-finding-documentation.html +43 -0
- package/public/docs/user-guide/mcp-tools/get-finding-evidence.html +49 -0
- package/public/docs/user-guide/mcp-tools/get-reference-doc.html +34 -0
- package/public/docs/user-guide/mcp-tools/get-run-summary.html +44 -0
- package/public/docs/user-guide/mcp-tools/list-runs.html +41 -0
- package/public/docs/user-guide/mcp-tools.html +12 -126
- package/public/docs/user-guide/run-comparison/how-stages-are-matched.html +30 -0
- package/public/docs/user-guide/run-comparison.html +7 -6
- package/public/docs/user-guide/understanding-findings.html +7 -6
- package/public/export-template.html +44 -44
- package/public/index.html +4 -4
- package/vendor-core/allocation.js +106 -0
- package/vendor-core/analyzer.js +13 -13
- package/vendor-core/api-merge-writes.js +80 -0
- package/vendor-core/cli/budgets.js +23 -9
- package/vendor-core/cli/collect-run.js +11 -4
- package/vendor-core/cli/regression-budgets.js +83 -0
- package/vendor-core/comparison-output.js +49 -0
- package/vendor-core/comparison-verdict.js +22 -22
- package/vendor-core/core-source-hash.txt +1 -1
- package/vendor-core/delta-commands.js +13 -0
- package/vendor-core/delta-log-paths.js +42 -0
- package/vendor-core/delta-targets.js +127 -0
- package/vendor-core/detectors.js +202 -68
- package/vendor-core/docs-content/detection/cache.md +3 -2
- package/vendor-core/docs-content/detection/cfg.md +9 -8
- package/vendor-core/docs-content/detection/chrn.md +1 -2
- package/vendor-core/docs-content/detection/cold.md +4 -2
- package/vendor-core/docs-content/detection/fail.md +3 -2
- package/vendor-core/docs-content/detection/gc.md +3 -2
- package/vendor-core/docs-content/detection/host.md +2 -1
- package/vendor-core/docs-content/detection/local.md +1 -1
- package/vendor-core/docs-content/detection/mem.md +5 -2
- package/vendor-core/docs-content/detection/plan.md +2 -1
- package/vendor-core/docs-content/detection/sfail.md +2 -1
- package/vendor-core/docs-content/detection/shape.md +5 -4
- package/vendor-core/docs-content/detection/skew.md +3 -1
- package/vendor-core/docs-content/detection/slow.md +2 -2
- package/vendor-core/docs-content/detection/spec.md +2 -3
- package/vendor-core/docs-content/detection/spill.md +1 -1
- package/vendor-core/docs-site-config.js +1 -1
- package/vendor-core/effective-conf.js +107 -0
- package/vendor-core/efficiency-model.js +8 -6
- package/vendor-core/event-handlers.js +255 -56
- package/vendor-core/event-schemas.js +5 -1
- package/vendor-core/evidence-report.js +31 -14
- package/vendor-core/finding-generic-recommendation.js +20 -1
- package/vendor-core/finding-names.js +7 -0
- package/vendor-core/finding-presentation.js +61 -26
- package/vendor-core/finding-tag-help.js +1 -1
- package/vendor-core/finding-types.js +12 -0
- package/vendor-core/format-utils.js +4 -3
- package/vendor-core/impact-estimator.js +20 -2
- package/vendor-core/impact-format.js +14 -13
- package/vendor-core/impact-model.js +27 -5
- package/vendor-core/ingest.js +4 -2
- package/vendor-core/list-runs.js +5 -2
- package/vendor-core/mcp-server-factory.js +13 -6
- package/vendor-core/mcp-tools.js +43 -34
- package/vendor-core/model-assembler.js +23 -1
- package/vendor-core/parser-worker.js +1 -1
- package/vendor-core/plan-graph-model.js +1 -1
- package/vendor-core/plan-summary.js +13 -10
- package/vendor-core/proxy.js +3 -1
- package/vendor-core/python-stage.js +25 -0
- package/vendor-core/recommendation-rollup.js +16 -9
- package/vendor-core/redact.js +51 -10
- package/vendor-core/remediation.js +20 -0
- package/vendor-core/run-comparison.js +118 -140
- package/vendor-core/run-interpretation.js +2 -1
- package/vendor-core/run-metrics.js +198 -0
- package/vendor-core/run-output.js +26 -0
- package/vendor-core/run-totals.js +24 -0
- package/vendor-core/run-verdict.js +3 -4
- package/vendor-core/scorecard-estimates.js +1 -0
- package/vendor-core/session-snapshot.js +7 -0
- package/vendor-core/shs-schemas.js +2 -2
- package/vendor-core/spark-memory.js +17 -0
- package/vendor-core/stage-alignment.js +262 -0
- package/vendor-core/stage-identity.js +112 -0
- package/vendor-core/stage-plan-nodes.js +18 -0
- package/vendor-core/stage-quantiles.js +4 -0
- package/vendor-core/types.js +54 -1
- package/vendor-core/wasted-core-hours.js +10 -7
- package/vendor-core/write-target-args.js +48 -0
- package/vendor-core/write-targets.js +295 -0
- package/public/assets/AutoscalingChurn-CUSIvvab.js +0 -1
- package/public/assets/CacheUtilization-Ce0K6_X2.js +0 -1
- package/public/assets/CachingOpportunity-Cn-LmRA4.js +0 -1
- package/public/assets/ColdStart-BoiYzEyV.js +0 -1
- package/public/assets/ConfigAudit-BoJc6PAw.js +0 -1
- package/public/assets/CoreUsageArea-BFfXKu7K.js +0 -1
- package/public/assets/Dashboard-Bo_1jGqH.js +0 -2
- package/public/assets/DisclosureContext-LYzHroHO.js +0 -1
- package/public/assets/DuplicatePlanSubtree-BaAuGAoo.js +0 -1
- package/public/assets/ExecutorUtilization-OE6VMFkG.js +0 -1
- package/public/assets/GcPressure-AoL_ZNrV.js +0 -1
- package/public/assets/IncompleteRun-Bv6IzgsQ.js +0 -1
- package/public/assets/JobFailures-DF3U2z1f.js +0 -1
- package/public/assets/MemoryUtilization-B65OVZlq.js +0 -1
- package/public/assets/OverBroadcast-DXbJREDl.js +0 -1
- package/public/assets/PartitionSizing-DZLnjy0d.js +0 -1
- package/public/assets/PlanGraphRoute-C-BGmC6j.js +0 -1
- package/public/assets/RetryWaste-BbEPsdMw.js +0 -1
- package/public/assets/ShuffleIO-wZB94LS8.js +0 -1
- package/public/assets/Skew-SpQE7zeJ.js +0 -1
- package/public/assets/SlowHost-DwDBCTvr.js +0 -1
- package/public/assets/SmallFiles-yjY_6sT1.js +0 -1
- package/public/assets/SpeculationWaste-73PDmj0c.js +0 -1
- package/public/assets/Spill-DEw0Kd1i.js +0 -1
- package/public/assets/StageFailed-BEfXdEJc.js +0 -1
- package/public/assets/StageFindingGroup-Bzm2TY03.js +0 -1
- package/public/assets/StageShape-CzR4jHOt.js +0 -1
- package/public/assets/StageSlowness-vMPsnAaa.js +0 -1
- package/public/assets/Straggler-Cf__OGl5.js +0 -1
- package/public/assets/TaskFailures-BZ8kLZiO.js +0 -1
- package/public/assets/UnderBroadcast-CBm8ZPoS.js +0 -1
- package/public/assets/index-CEM9bz_x.js +0 -13
- package/public/assets/parser-worker-Q5KCPdKT.js +0 -122
- package/public/assets/useRecentFiles-BrBl-AP1.js +0 -11
- package/public/docs/assets/chunks/@localSearchIndexroot.DbZy5EtM.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_board-widgets.md.VTcYTH4d.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_board-widgets.md.VTcYTH4d.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_detector-contract.md.CsqZHz_T.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_detector-contract.md.CsqZHz_T.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_drill-down.md.CFNCE8JB.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_drill-down.md.CFNCE8JB.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_impact-estimation.md.HT9IJGIl.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_impact-estimation.md.HT9IJGIl.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_index.md.3TO9ic6w.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_index.md.3TO9ic6w.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_overview.md.CTEqVeV4.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_overview.md.CTEqVeV4.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_state-and-history.md.DOTVHjTV.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_widget-rendering.md.BmpARZve.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_widget-rendering.md.BmpARZve.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_worker-protocol.md.21pTYhFF.js +0 -6
- package/public/docs/assets/contributor-guide_architecture_worker-protocol.md.21pTYhFF.lean.js +0 -1
- package/public/docs/assets/contributor-guide_contributing.md.B2E9ni79.js +0 -1
- package/public/docs/assets/contributor-guide_development-setup.md.CjgZJwjK.js +0 -15
- package/public/docs/assets/contributor-guide_development-setup.md.CjgZJwjK.lean.js +0 -1
- package/public/docs/assets/contributor-guide_testing.md.DTwhpoN2.js +0 -1
- package/public/docs/assets/user-guide_alternative-log-retrieval.md.ZHPSbBkF.js +0 -1
- package/public/docs/assets/user-guide_alternative-log-retrieval.md.ZHPSbBkF.lean.js +0 -1
- package/public/docs/assets/user-guide_getting-started.md.CEa2ZX-l.js +0 -6
- package/public/docs/assets/user-guide_getting-started.md.CEa2ZX-l.lean.js +0 -1
- package/public/docs/assets/user-guide_mcp-tools.md.dQwIvdTF.js +0 -131
- package/public/docs/assets/user-guide_mcp-tools.md.dQwIvdTF.lean.js +0 -1
- package/public/docs/assets/user-guide_run-comparison.md.ChLI3MK0.js +0 -1
- package/public/docs/assets/user-guide_run-comparison.md.ChLI3MK0.lean.js +0 -1
- package/public/docs/assets/user-guide_understanding-findings.md.D1ccs60C.js +0 -1
- /package/public/docs/assets/{user-guide_understanding-findings.md.D1ccs60C.lean.js → user-guide_understanding-findings.md.Dqt2H_C1.lean.js} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// the memoryUtilization detector's idle-cores math uses: capacity core-time vs.
|
|
3
3
|
// core-time that actually ran tasks. Feeds a report widget only, no detector.
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { computePeakConcurrentCores } from './core-count.js';
|
|
6
6
|
import { MS_PER_CORE_HOUR } from './format-utils.js';
|
|
7
7
|
|
|
8
8
|
const TOP_N = 5;
|
|
@@ -30,21 +30,24 @@ const EMPTY = {
|
|
|
30
30
|
|
|
31
31
|
// `app`/`runAggregates` are nullable because real callers pass null (app is
|
|
32
32
|
// SparkAppInfo | null before parsing completes), which the guard below already
|
|
33
|
-
// tolerates. `resources` is on app's shape so the
|
|
34
|
-
// type-checks; real app objects always carry it.
|
|
33
|
+
// tolerates. `resources` is on app's shape so the computePeakConcurrentCores
|
|
34
|
+
// pass-through type-checks; real app objects always carry it. An omitted
|
|
35
|
+
// `executorsRemoved` means no executor left, where peak cores equal the sum.
|
|
35
36
|
export function computeWastedCoreHours(
|
|
36
37
|
app ,
|
|
37
|
-
executorsAdded
|
|
38
|
+
executorsAdded = [],
|
|
38
39
|
runAggregates ,
|
|
40
|
+
executorsRemoved = [],
|
|
39
41
|
) {
|
|
40
42
|
// Nullish (not falsy) guard on times: a literal startTime:0 is valid.
|
|
41
43
|
if (!runAggregates || app?.startTime == null || app?.endTime == null) return EMPTY;
|
|
42
44
|
const appDurationMs = app.endTime - app.startTime;
|
|
43
45
|
if (appDurationMs <= 0) return EMPTY;
|
|
44
46
|
|
|
45
|
-
// Total cores:
|
|
46
|
-
// configured cores
|
|
47
|
-
|
|
47
|
+
// Total cores: peak concurrent Executor-Added Total Cores, else peak executors ×
|
|
48
|
+
// configured cores. Same capacity as the memoryUtilization detector, so an
|
|
49
|
+
// executor replaced mid-run is not counted twice.
|
|
50
|
+
const totalCores = computePeakConcurrentCores(app, executorsAdded, executorsRemoved);
|
|
48
51
|
if (totalCores <= 0) return EMPTY;
|
|
49
52
|
|
|
50
53
|
const totalCoreHours = (totalCores * appDurationMs) / MS_PER_CORE_HOUR;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Argument and identifier helpers shared by the write-target parsers (write-targets.ts) and the
|
|
2
|
+
// Delta command resolver (delta-targets.ts).
|
|
3
|
+
const IDENT_PART = String.raw`(?:\`(?:[^\`]|\`\`)*\`|[A-Za-z0-9_$]+)`;
|
|
4
|
+
const IDENTIFIER = new RegExp(`^${IDENT_PART}(?:\\.${IDENT_PART})*$`);
|
|
5
|
+
export const IDENT_PARTS = new RegExp(IDENT_PART, 'g');
|
|
6
|
+
const TRUNCATION_MARKER = /\.\.\.(?:\s*\d+ more fields)?/;
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
// Splits at top-level commas, ignoring commas inside (), [], {} and backticks. `terminated` is
|
|
11
|
+
// true when a comma follows the arg: the last arg of a cut-off string is never terminated.
|
|
12
|
+
export function splitArgs(args ) {
|
|
13
|
+
const out = [];
|
|
14
|
+
let depth = 0;
|
|
15
|
+
let quoted = false;
|
|
16
|
+
let start = 0;
|
|
17
|
+
for (let i = 0; i < args.length; i++) {
|
|
18
|
+
const c = args[i];
|
|
19
|
+
if (c === '`') quoted = !quoted;
|
|
20
|
+
else if (quoted) continue;
|
|
21
|
+
else if (c === '(' || c === '[' || c === '{') depth++;
|
|
22
|
+
else if (c === ')' || c === ']' || c === '}') depth--;
|
|
23
|
+
else if (c === ',' && depth === 0) {
|
|
24
|
+
out.push({ text: args.slice(start, i).trim(), terminated: true });
|
|
25
|
+
start = i + 1;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
out.push({ text: args.slice(start).trim(), terminated: false });
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function isCut(text ) {
|
|
33
|
+
return text === '' || TRUNCATION_MARKER.test(text);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// `db`.`t` or db.t -> db.t. A part that itself contains a dot or backtick keeps its quoting.
|
|
37
|
+
export function tableName(ident ) {
|
|
38
|
+
if (!IDENTIFIER.test(ident)) return null;
|
|
39
|
+
const parts = (ident.match(IDENT_PARTS) ?? []).map((p) => {
|
|
40
|
+
if (!p.startsWith('`')) return p;
|
|
41
|
+
const inner = p.slice(1, -1).replace(/``/g, '`');
|
|
42
|
+
return /[.`]/.test(inner) ? p : inner;
|
|
43
|
+
});
|
|
44
|
+
return parts.join('.');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** A write target found without parsing the node's simpleString. */
|
|
48
|
+
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
// Write targets: every SQL write command in a run's plans, with the path or table it writes to.
|
|
2
|
+
// Read by automation that halts a session when a target leaves its sandbox, so every rule here
|
|
3
|
+
// fails toward "target unknown" (null), never toward a guessed or partial target:
|
|
4
|
+
// - a write node whose target cannot be parsed is still reported, with target null and its raw
|
|
5
|
+
// simpleString;
|
|
6
|
+
// - a target Spark cut short (no delimiter after it, or a "..." marker in it) is unparseable;
|
|
7
|
+
// - a write-like node outside the known list is reported as an unrecognized write;
|
|
8
|
+
// - an execution whose plan is not in the model (or whose start event could not be read) is
|
|
9
|
+
// listed, never skipped, and the count of unreadable log lines is reported;
|
|
10
|
+
// - a Delta target is set only when exactly one table or path is named (delta-targets.ts,
|
|
11
|
+
// api-merge-writes.ts).
|
|
12
|
+
// Targets are verbatim from the simpleString: nothing is resolved (relative paths, ${var}
|
|
13
|
+
// placeholders, catalog-relative table names all pass through as the log states them).
|
|
14
|
+
import { walkPlanTree } from './plan-tree-walk.js';
|
|
15
|
+
import { apiMergeWrites } from './api-merge-writes.js';
|
|
16
|
+
import { indexByRoot, isStagedDeltaWrite, parseDeltaTableV2, resolveDeltaCommandTarget, } from './delta-targets.js';
|
|
17
|
+
import { IDENT_PARTS, isCut, splitArgs, tableName, } from './write-target-args.js';
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
// Write-like detection: a known command, any CamelCase word of the operator name in this set, or a
|
|
59
|
+
// TableAsSelect name.
|
|
60
|
+
const WRITE_WORDS = new Set([
|
|
61
|
+
'Write', 'Insert', 'Save', 'Overwrite', 'Append', 'Merge', 'Update', 'Delete', 'Truncate', 'Replace', 'Drop',
|
|
62
|
+
'Load', 'Vacuum', 'Convert', 'Clone', 'Restore', 'Optimize', 'Alter', 'Reorg', 'Rename', 'Call',
|
|
63
|
+
]);
|
|
64
|
+
// Names that contain no write word of their own: ADD/DROP/RENAME PARTITION (which can name a LOCATION).
|
|
65
|
+
const WRITE_SUBSTRINGS = ['TableAsSelect', 'AddPartition', 'DropPartition', 'RenamePartition', 'RecoverPartitions'];
|
|
66
|
+
// Plan nodes whose name matches a write word but which write no user data: WriteFiles is the child
|
|
67
|
+
// of a write command (the command is the write), the rest are query or streaming-state operators.
|
|
68
|
+
// Any join (SortMergeJoin) is excluded by name in isWriteLike.
|
|
69
|
+
const NOT_WRITES = new Set([
|
|
70
|
+
'WriteFiles', 'AppendColumns', 'AppendColumnsWithObject', 'MergeRows', 'StateStoreSave',
|
|
71
|
+
'StateStoreRestore', 'SessionWindowStateStoreSave', 'SessionWindowStateStoreRestore',
|
|
72
|
+
'UpdateEventTimeWatermarkColumn',
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
function commandOf(nodeName ) {
|
|
76
|
+
return nodeName.replace(/^Execute\s+/, '').trim().replace(/Exec$/, '');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Only the operator name (the first word) is classified: a scan's node name goes on to print its
|
|
80
|
+
// relation and table, whose identifiers can hold a write word (Scan JDBCRelation(dbo.PriceUpdate)).
|
|
81
|
+
function isWriteLike(command ) {
|
|
82
|
+
if (isKnownWrite(command)) return true;
|
|
83
|
+
const operator = command.split(/\s/, 1)[0];
|
|
84
|
+
if (NOT_WRITES.has(operator) || operator.includes('Join')) return false;
|
|
85
|
+
if (WRITE_SUBSTRINGS.some((part) => operator.includes(part))) return true;
|
|
86
|
+
return (operator.match(/[A-Z][a-z0-9]*/g) ?? []).some((word) => WRITE_WORDS.has(word));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Text after the command name in the simpleString. Empty when the simpleString does not start
|
|
90
|
+
// with the command (so nothing after it can be trusted).
|
|
91
|
+
function argsOf(detail , command ) {
|
|
92
|
+
const m = /^(?:Execute\s+)?(\S+)\s*([\s\S]*)$/.exec(detail.trim());
|
|
93
|
+
if (!m || commandOf(m[1]) !== command) return '';
|
|
94
|
+
return m[2];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// First arg of a path-writing command. The next arg must be the boolean that follows it in
|
|
98
|
+
// InsertIntoHadoopFsRelationCommand, or the static-partition map (INSERT OVERWRITE ... PARTITION
|
|
99
|
+
// (dt='x')) that precedes that boolean, which Spark prints as `[dt=x]` (or `Map(dt -> x)`); this also rejects a path Spark printed with ", " inside.
|
|
100
|
+
function parseHadoopFsPath(args ) {
|
|
101
|
+
const [path, second, third] = args;
|
|
102
|
+
const flag = second && /^(Map\(.*\)|\[.*\])$/s.test(second.text) && second.terminated ? third : second;
|
|
103
|
+
if (!path?.terminated || isCut(path.text) || !flag || !/^(true|false)$/.test(flag.text)) return null;
|
|
104
|
+
return { kind: 'path', target: path.text };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// A quoted or plain identifier, or the `[Database: d, TableName: t, ...]` form Hive commands print.
|
|
108
|
+
function parseTableArg(args ) {
|
|
109
|
+
const first = args[0];
|
|
110
|
+
if (!first) return null;
|
|
111
|
+
const hive = /^\[Database: ([^,\]]+), TableName: ([^,\]]+)[,\]]/.exec(first.text);
|
|
112
|
+
if (hive && /\]$/.test(first.text)) {
|
|
113
|
+
const name = tableName(`${hive[1].trim()}.${hive[2].trim()}`);
|
|
114
|
+
return name && !isCut(name) ? { kind: 'table', target: name } : null;
|
|
115
|
+
}
|
|
116
|
+
if (!first.terminated || isCut(first.text)) return null;
|
|
117
|
+
const name = tableName(first.text);
|
|
118
|
+
return name ? { kind: 'table', target: name } : null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Options of `Map(k -> v, k2 -> v2)`, or null when the Map is missing or not closed.
|
|
122
|
+
function parseOptionMap(text ) {
|
|
123
|
+
const m = /^Map\(([\s\S]*)\)$/.exec(text);
|
|
124
|
+
if (!m) return null;
|
|
125
|
+
const body = m[1];
|
|
126
|
+
const keys = [...body.matchAll(/(?:^|, )([A-Za-z0-9_.\-]+) -> /g)];
|
|
127
|
+
const options = new Map ();
|
|
128
|
+
keys.forEach((key, i) => {
|
|
129
|
+
const valueStart = key.index + key[0].length;
|
|
130
|
+
const valueEnd = i + 1 < keys.length ? keys[i + 1].index : body.length;
|
|
131
|
+
options.set(key[1].toLowerCase(), body.slice(valueStart, valueEnd));
|
|
132
|
+
});
|
|
133
|
+
return options;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// SaveIntoDataSourceCommand: `<provider>, Map(options), <mode>`. The target is the `path` option or
|
|
137
|
+
// the JDBC `dbtable`/`table` option; a redacted or missing value, or both options, is unparseable.
|
|
138
|
+
function parseSaveIntoDataSource(args ) {
|
|
139
|
+
const [, options, mode] = args;
|
|
140
|
+
if (!options?.terminated || !mode || mode.text === '') return null;
|
|
141
|
+
const map = parseOptionMap(options.text);
|
|
142
|
+
if (!map) return null;
|
|
143
|
+
const path = map.get('path');
|
|
144
|
+
const table = map.get('dbtable') ?? map.get('table');
|
|
145
|
+
if ((path === undefined) === (table === undefined)) return null;
|
|
146
|
+
const value = (path ?? table) ;
|
|
147
|
+
if (isCut(value) || /\*{5,}\(redacted\)/.test(value)) return null;
|
|
148
|
+
return path !== undefined ? { kind: 'path', target: value } : { kind: 'jdbcTable', target: value };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// The one target every match of `pattern` names, or null when there is none, when they name
|
|
152
|
+
// different targets, or when one of them is cut: a string that also prints another plan (a
|
|
153
|
+
// subquery) cannot tell which match is written. `pattern` captures the target, then its closing
|
|
154
|
+
// delimiter; a match without the delimiter was cut before it.
|
|
155
|
+
function soleMatch(detail , pattern , normalize ) {
|
|
156
|
+
const targets = new Set ();
|
|
157
|
+
for (const m of detail.matchAll(pattern)) targets.add(m[2] === undefined || isCut(m[1]) ? null : normalize(m[1]));
|
|
158
|
+
const [target] = targets;
|
|
159
|
+
return targets.size === 1 ? target : null;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// A V2 name states its catalog only as a leading part (catalog.namespace.table). With two parts or
|
|
163
|
+
// fewer the catalog is implicit, so a database check on the name alone could match another catalog.
|
|
164
|
+
function v2Table(name ) {
|
|
165
|
+
if (!name) return null;
|
|
166
|
+
const parts = name.match(IDENT_PARTS)?.length ?? 0;
|
|
167
|
+
return { kind: parts >= 3 ? 'table' : 'unqualifiedTable', target: name };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// DataSource V2 writes print the connector's Write object; Iceberg's is IcebergWrite(table=t, ...).
|
|
171
|
+
function parseV2Write(detail ) {
|
|
172
|
+
return v2Table(soleMatch(detail, /\b\w*Write\(table=([^,()\s]*)([,)])?/g, tableName));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// V2 CTAS/RTAS: `<catalog>@<hash>, <identifier>, <query plan>, ...`. The catalog shape is checked
|
|
176
|
+
// so a plan printed in a different layout is not misread.
|
|
177
|
+
function parseV2TableAsSelect(args ) {
|
|
178
|
+
const [catalog, ident] = args;
|
|
179
|
+
if (!catalog?.terminated || !/^[\w.$]+@[0-9a-f]+$/.test(catalog.text)) return null;
|
|
180
|
+
if (!ident?.terminated || isCut(ident.text)) return null;
|
|
181
|
+
return v2Table(tableName(ident.text));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Delta prints a path-based table as delta.`<path>`. Only the command's own first argument is the
|
|
185
|
+
// written table: later arguments print other plans (a source relation, a condition's subquery).
|
|
186
|
+
function parseDeltaPath(args ) {
|
|
187
|
+
const [first] = args;
|
|
188
|
+
const m = first?.terminated ? /^delta\.`([^`]*)`$/.exec(first.text) : null;
|
|
189
|
+
return m && !isCut(m[1]) ? { kind: 'path', target: m[1] } : null;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const V2_WRITES = new Set([
|
|
193
|
+
'AppendData', 'OverwriteByExpression', 'OverwritePartitionsDynamic', 'ReplaceData', 'WriteDelta',
|
|
194
|
+
'WriteToDataSourceV2',
|
|
195
|
+
// V1-fallback writers (Delta tables): their node names keep the V1 suffix, not ending in Exec.
|
|
196
|
+
'AppendDataExecV1', 'OverwriteByExpressionExecV1',
|
|
197
|
+
]);
|
|
198
|
+
const V2_TABLE_AS_SELECT = new Set([
|
|
199
|
+
'CreateTableAsSelect', 'AtomicCreateTableAsSelect', 'ReplaceTableAsSelect', 'AtomicReplaceTableAsSelect',
|
|
200
|
+
]);
|
|
201
|
+
const DELTA_COMMANDS = new Set([
|
|
202
|
+
'WriteIntoDelta', 'WriteIntoDeltaCommand', 'MergeIntoCommand', 'UpdateCommand', 'DeleteCommand',
|
|
203
|
+
'CreateDeltaTableCommand', 'OptimizeTableCommand', 'RestoreTableCommand', 'DeltaReorgTableCommand',
|
|
204
|
+
]);
|
|
205
|
+
|
|
206
|
+
const ARG_PARSERS = {
|
|
207
|
+
InsertIntoHadoopFsRelationCommand: parseHadoopFsPath,
|
|
208
|
+
InsertIntoHiveTable: parseTableArg,
|
|
209
|
+
CreateHiveTableAsSelectCommand: parseTableArg,
|
|
210
|
+
OptimizedCreateHiveTableAsSelectCommand: parseTableArg,
|
|
211
|
+
CreateDataSourceTableAsSelectCommand: parseTableArg,
|
|
212
|
+
SaveIntoDataSourceCommand: parseSaveIntoDataSource,
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
function isKnownWrite(command ) {
|
|
216
|
+
return command in ARG_PARSERS || V2_WRITES.has(command) || V2_TABLE_AS_SELECT.has(command) || DELTA_COMMANDS.has(command);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// [recognized, parsed target or null] for one write-like node.
|
|
220
|
+
function parseWrite(command , detail ) {
|
|
221
|
+
const argParser = ARG_PARSERS[command];
|
|
222
|
+
if (argParser) return [true, argParser(splitArgs(argsOf(detail, command)))];
|
|
223
|
+
if (V2_WRITES.has(command)) return [true, parseDeltaTableV2(detail) ?? parseV2Write(detail)];
|
|
224
|
+
if (V2_TABLE_AS_SELECT.has(command)) return [true, parseV2TableAsSelect(splitArgs(argsOf(detail, command)))];
|
|
225
|
+
// A MERGE prints its source relation too, so a delta. path in it may be the source, not the target.
|
|
226
|
+
// Its target comes from resolveDeltaCommandTarget alone.
|
|
227
|
+
if (command === 'MergeIntoCommand') return [true, null];
|
|
228
|
+
if (DELTA_COMMANDS.has(command)) return [true, parseDeltaPath(splitArgs(argsOf(detail, command)))];
|
|
229
|
+
return [false, null];
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function outputRowsOf(node ) {
|
|
233
|
+
const metric = node.metrics?.find((m) => m.name === 'number of output rows');
|
|
234
|
+
return metric !== undefined && Number.isFinite(metric.value) ? metric.value : null;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function collectWrites(exec , root , byRoot , out ) {
|
|
238
|
+
walkPlanTree(root, (node) => {
|
|
239
|
+
const command = commandOf(node.name);
|
|
240
|
+
if (!isWriteLike(command)) return;
|
|
241
|
+
const detail = node.detail ?? '';
|
|
242
|
+
const [recognized, parsedFromDetail] = parseWrite(command, detail);
|
|
243
|
+
// A Delta command's simpleString is bare on real logs: its target is found elsewhere.
|
|
244
|
+
const parsed = parsedFromDetail ?? resolveDeltaCommandTarget(command, exec, node, byRoot);
|
|
245
|
+
out.push({
|
|
246
|
+
sqlExecutionId: exec.id,
|
|
247
|
+
nodeId: node.id ?? null,
|
|
248
|
+
command,
|
|
249
|
+
recognized,
|
|
250
|
+
kind: parsed?.kind ?? null,
|
|
251
|
+
target: parsed?.target ?? null,
|
|
252
|
+
outputRows: outputRowsOf(node),
|
|
253
|
+
raw: detail !== '' ? detail : node.name,
|
|
254
|
+
});
|
|
255
|
+
}, { dedupe: true });
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// A staged Delta write writes the table its root's CTAS/RTAS node names, when it has exactly one.
|
|
259
|
+
function attributeStagedWrites(writes , sql ) {
|
|
260
|
+
for (const write of writes) {
|
|
261
|
+
if (write.target !== null || !isStagedDeltaWrite(write)) continue;
|
|
262
|
+
const root = sql.get(write.sqlExecutionId)?.rootExecutionId;
|
|
263
|
+
if (root === undefined || root === write.sqlExecutionId) continue;
|
|
264
|
+
const parents = writes.filter((w) => w.sqlExecutionId === root && V2_TABLE_AS_SELECT.has(w.command));
|
|
265
|
+
if (parents.length === 1 && parents[0].target !== null) {
|
|
266
|
+
write.kind = parents[0].kind;
|
|
267
|
+
write.target = parents[0].target;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
export function extractWriteTargets(sql , input = {}) {
|
|
279
|
+
const writes = [];
|
|
280
|
+
const withoutPlan = new Map ();
|
|
281
|
+
for (const id of input.unreadableSqlExecutions ?? []) if (!sql.get(id)?.planTree) withoutPlan.set(id, 'unreadableStart');
|
|
282
|
+
const byRoot = indexByRoot(sql);
|
|
283
|
+
for (const id of [...sql.keys()].sort((a, b) => a - b)) {
|
|
284
|
+
const exec = sql.get(id) ;
|
|
285
|
+
if (!exec.planTree) withoutPlan.set(id, withoutPlan.get(id) ?? 'noPlan');
|
|
286
|
+
else collectWrites(exec, exec.planTree, byRoot, writes);
|
|
287
|
+
}
|
|
288
|
+
// DeltaTable API merges run no command node: they are found by their executions' descriptions.
|
|
289
|
+
attributeStagedWrites(writes, sql);
|
|
290
|
+
writes.push(...apiMergeWrites(sql));
|
|
291
|
+
writes.sort((a, b) => a.sqlExecutionId - b.sqlExecutionId);
|
|
292
|
+
const executionsWithoutPlan = [...withoutPlan].sort((a, b) => a[0] - b[0])
|
|
293
|
+
.map(([sqlExecutionId, reason]) => ({ sqlExecutionId, reason }));
|
|
294
|
+
return { writes, executionsWithoutPlan, skippedLines: input.skippedLines ?? null };
|
|
295
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{M as t,T as n,f as r,l as i,o as a,s as o,t as s,v as c,w as l}from"./charts-vendor-0VMaLVLN.js";import{S as u,d,u as f}from"./DisclosureContext-LYzHroHO.js";import{p}from"./plan-graph-vendor-B0sEms9Z.js";import{_ as m,b as h}from"./useRecentFiles-BrBl-AP1.js";import{S as g}from"./index-CEM9bz_x.js";import{o as _,s as v,t as y}from"./Dashboard-Bo_1jGqH.js";var b=e(t(),1),x=p(),S=60,C=6e4,w=220;function T(e,t,n,r,i){if(e.length===0&&t.length===0)return[];let a=Math.max(i,r-n),o=Math.max(1,Math.ceil(a/i)),s=[];for(let e=0;e<o;e++)s.push({tStart:n+e*i,adds:0,removes:0});let c=e=>Math.min(o-1,Math.max(0,Math.floor((e-n)/i)));for(let t of e)s[c(t.timestamp)].adds++;for(let e of t)s[c(e.timestamp)].removes++;return s}function E(e,t){let n=Math.max(1,t-e);return Math.max(C,Math.ceil(n/S))}function D(e){if(e<=0)return 1;let t=10**Math.floor(Math.log10(e)),n=e/t;return(n<=1?1:n<=2?2:n<=5?5:10)*t}function O(e){let t=D(e.reduce((e,t)=>Math.max(e,Math.abs(t.added),Math.abs(t.removed)),0));return{domain:[-t,t],ticks:[-t,-t/2,0,t/2,t]}}function k(e){return Math.abs(e.height)<1?null:(0,x.jsx)(l,{...e})}function A({finding:e}){return(0,x.jsxs)(`div`,{className:`flex flex-col gap-1 transition-colors`,children:[(0,x.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Short-lived executors: `,(0,x.jsxs)(`strong`,{children:[e.value,`%`]})]}),(0,x.jsx)(y,{finding:e}),(0,x.jsxs)(`p`,{className:`flex flex-wrap items-start gap-2 text-sm`,children:[(0,x.jsx)(f,{impactBand:e.impactBand,className:`mt-1.5`}),(0,x.jsxs)(`span`,{children:[e.recommendation,` `,(0,x.jsx)(u,{anchor:`#config-autoscale-bounds`,children:`Tuning executorIdleTimeout and the min/max bounds`}),`.`]})]})]})}var j=(0,b.memo)(function({appModel:e,activeFileId:t,catalog:l=[],defaultCollapsed:u=!0}){let f=(0,b.useMemo)(()=>{let t=e.executors.added,n=e.executors.removed;if(t.length===0&&n.length===0)return{hasEvents:!1,added:t,removed:n};let r=e.app,i=r?.startTime??0,a=r?.endTime??i,o=E(i,a),s=v(T(t,n,i,a,o)).map(e=>({t:`${Math.round((e.tStart-i)/1e3)}s`,added:e.adds,removed:-e.removes}));return{hasEvents:!0,added:t,removed:n,rows:s,yAxisScale:O(s)}},[e,t]);if(!f.hasEvents)return(0,x.jsx)(g,{title:`Autoscaling Churn`,summary:(0,x.jsx)(`span`,{className:`text-muted-foreground text-xs`,children:`No executor add/remove events (static allocation).`}),children:(0,x.jsx)(`p`,{className:`text-muted-foreground text-xs`,children:`No executor add/remove events (static allocation).`})});let{added:p,removed:y,rows:S,yAxisScale:C}=f,D=l.find(e=>e.type===`autoscalingChurn`);return(0,x.jsx)(g,{title:`Autoscaling Churn`,impactBand:D?.impactBand,badges:D&&(0,x.jsx)(d,{type:`autoscalingChurn`,impactBand:D.impactBand}),defaultCollapsed:u,summary:(0,x.jsx)(_,{value:`${p.length} added / ${y.length} removed`,context:D?`${D.value}% short-lived executors, ${D.impactBand}`:`executor churn events`}),children:(0,x.jsxs)(`div`,{className:`space-y-2`,children:[D&&(0,x.jsx)(A,{finding:D}),(0,x.jsx)(`p`,{className:`text-muted-foreground text-xs`,children:`executors added / removed over time`}),(0,x.jsx)(h,{ariaLabel:`Executor added and removed counts per time bucket over the run.`,height:w,table:{caption:`Executor added/removed counts by time bucket`,columns:[`Time`,`Executors added`,`Executors removed`],rows:S.map(e=>[e.t,e.added,Math.abs(e.removed)]),align:[`right`,`right`,`right`]},children:(0,x.jsxs)(s,{data:S,children:[(0,x.jsx)(r,{stroke:m.muted,strokeOpacity:.2}),(0,x.jsx)(o,{dataKey:`t`,tick:{fontSize:10}}),(0,x.jsx)(a,{tick:{fontSize:10},width:32,domain:C.domain,ticks:C.ticks}),(0,x.jsx)(c,{formatter:(e,t)=>[Math.abs(Number(e)),t]}),(0,x.jsx)(n,{wrapperStyle:{fontSize:10}}),(0,x.jsx)(i,{dataKey:`added`,name:`Added`,stackId:`churn`,fill:m.clean,shape:k}),(0,x.jsx)(i,{dataKey:`removed`,name:`Removed`,stackId:`churn`,fill:m.muted,shape:k})]})})]})})});export{j as AutoscalingChurn};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{M as t}from"./charts-vendor-0VMaLVLN.js";import{$ as n,J as r,R as i,S as a,W as o,at as s,d as c,et as l,p as u,u as d}from"./DisclosureContext-LYzHroHO.js";import{p as f}from"./plan-graph-vendor-B0sEms9Z.js";import{m as p}from"./useRecentFiles-BrBl-AP1.js";import{D as m,F as h,I as g,L as _,M as v,P as y,S as b,j as x}from"./index-CEM9bz_x.js";import{o as S,r as C,t as w}from"./Dashboard-Bo_1jGqH.js";import{n as T}from"./finding-anchor-DF1cSHO1.js";import{t as E}from"./usePagedRows-BjPOpUU8.js";var D=e(t(),1),O=f(),k=70;function A(e){if(!e)return`—`;let t=[];return e.useMemory&&t.push(`Memory`),e.useDisk&&t.push(`Disk`),e.deserialized?t.push(`Deserialized`):(e.useMemory||e.useDisk)&&t.push(`Serialized`),(e.replication??1)>1&&t.push(`x${e.replication}`),t.join(` · `)||`—`}function j(e){return e.name||`RDD ${e.id}`}function M(e){let t=l(j(e));return t.length<=k?t:`${t.slice(0,k)}…`}function N(e){if(e.variant===`storageUnobserved`)return`No block updates logged: cached partition counts and sizes are unknown`;let t=r(`pct`,n(e));return e.variant===`diskSpillover`?`${t} spilled to disk: ${o(e.diskSize??0)} disk / ${o(e.memorySize??0)} memory`:`${t} cached (${e.numCachedPartitions??0}/${e.numPartitions??0} partitions)`}function P({finding:e}){let t=T([e]),n=e.dataUnavailable?`Cache storage not logged`:e.rddName??`RDD ${e.rddId}`;return(0,O.jsxs)(`div`,{ref:t.ref,tabIndex:t.tabIndex,"data-flashed":t.dataFlashed,className:`space-y-1 transition-colors ${t.flashClassName}`,children:[(0,O.jsxs)(`p`,{className:`flex flex-wrap items-start gap-2`,children:[(0,O.jsx)(d,{impactBand:e.impactBand,className:`mt-1.5`}),(0,O.jsx)(`span`,{children:n})]}),(0,O.jsx)(u,{children:(0,O.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:N(e)})}),(0,O.jsx)(w,{finding:e}),(0,O.jsx)(`p`,{className:`text-sm`,children:e.recommendation})]})}var F=(0,D.memo)(function({appModel:e,catalog:t}){let[r,l]=(0,D.useState)(0),[u,f]=(0,D.useState)(0),w=e.app?.rddInfo,T=(0,D.useMemo)(()=>w?[...w.values()].filter(e=>(e.storageLevel?.useMemory||e.storageLevel?.useDisk)&&(e.numCachedPartitions??0)>0).sort((e,t)=>(t.memorySize??0)+(t.diskSize??0)-((e.memorySize??0)+(e.diskSize??0))):[],[w]),k=(0,D.useMemo)(()=>p(t,`cacheUtilization`).sort((e,t)=>i[e.impactBand]-i[t.impactBand]),[t]),N=E(T,r,l),F=m(),I=F?k.findIndex(e=>e===F.finding):null,L=E(k,u,f,I),R=k.find(e=>e.dataUnavailable);if(T.length===0&&!R)return null;let z=e=>k.filter(t=>t.rddId===e),B=T.reduce((e,t)=>e+(t.memorySize??0)+(t.diskSize??0),0);return(0,O.jsx)(`div`,{"data-widget":`cache-utilization`,children:(0,O.jsxs)(b,{title:`Cache Storage`,impactBand:s(k),badges:(0,O.jsxs)(O.Fragment,{children:[k.length>0?(0,O.jsx)(c,{type:`cacheUtilization`,impactBand:s(k)??`info`}):null,(0,O.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[T.length>0?`${T.length} cached RDD${T.length===1?``:`s`}`:`cache storage not logged`,`, see`,` `,(0,O.jsx)(a,{anchor:`#memory-model`,children:`how Spark accounts cached memory`})]})]}),defaultCollapsed:!0,summary:T.length>0?(0,O.jsx)(S,{value:o(B),context:`cached across memory + disk`}):(0,O.jsx)(S,{value:`Unknown`,context:`${n(R)} persisted, no block updates`}),children:[T.length>0?(0,O.jsxs)(O.Fragment,{children:[(0,O.jsxs)(x,{children:[(0,O.jsx)(g,{children:(0,O.jsxs)(_,{children:[(0,O.jsx)(h,{children:`RDD`}),(0,O.jsx)(h,{children:`Storage level`}),(0,O.jsx)(h,{className:`text-right`,children:`Cached partitions`}),(0,O.jsx)(h,{className:`text-right`,children:`Memory`}),(0,O.jsx)(h,{className:`text-right`,children:`Disk`})]})}),(0,O.jsx)(v,{children:N.visible.map(e=>{let t=j(e),n=M(e),r=z(e.id);return(0,O.jsxs)(_,{children:[(0,O.jsxs)(y,{className:`max-w-80 truncate`,title:t===n?void 0:t,children:[n,r.length>0&&(0,O.jsx)(d,{impactBand:s(r)??`info`,className:`ml-1.5`})]}),(0,O.jsx)(y,{children:A(e.storageLevel)}),(0,O.jsxs)(y,{className:`text-right`,children:[e.numCachedPartitions,` / `,e.numPartitions]}),(0,O.jsx)(y,{className:`text-right`,children:o(e.memorySize??0)}),(0,O.jsx)(y,{className:`text-right`,children:o(e.diskSize??0)})]},e.id)})})]}),(0,O.jsx)(C,{page:N.effectivePage,totalPages:N.totalPages,onPrev:()=>l(e=>e-1),onNext:()=>l(e=>e+1)})]}):null,k.length>0?(0,O.jsxs)(`div`,{className:`mt-3 space-y-2 text-sm`,children:[L.visible.map(e=>(0,O.jsx)(P,{finding:e},e.id)),(0,O.jsx)(C,{page:L.effectivePage,totalPages:L.totalPages,onPrev:()=>f(e=>e-1),onNext:()=>f(e=>e+1)})]}):null]})})});export{F as CacheUtilization};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{M as t}from"./charts-vendor-0VMaLVLN.js";import{E as n,W as r,d as i,dt as a,p as o}from"./DisclosureContext-LYzHroHO.js";import{p as s}from"./plan-graph-vendor-B0sEms9Z.js";import{h as c,m as l}from"./useRecentFiles-BrBl-AP1.js";import{D as u,F as d,I as f,L as p,M as m,P as h,S as g,j as _}from"./index-CEM9bz_x.js";import{o as v,r as y,t as b}from"./Dashboard-Bo_1jGqH.js";import{n as x}from"./finding-anchor-DF1cSHO1.js";import{t as S}from"./usePagedRows-BjPOpUU8.js";var C={name:`git-merge`,size:24,node:[[`circle`,{cx:`18`,cy:`18`,r:`3`,key:`1xkwt0`}],[`circle`,{cx:`6`,cy:`6`,r:`3`,key:`1lh9wr`}],[`path`,{d:`M6 21V9a9 9 0 0 0 9 9`,key:`7kw0sc`}]]};C.node;var w=a(C),T=e(t(),1),E=s();function D({relations:e,operator:t}){let n=t===`union`?`union`:`join`;return(0,E.jsx)(`span`,{className:`inline-flex flex-wrap items-baseline`,children:e.map((e,t)=>(0,E.jsxs)(`span`,{children:[t>0?(0,E.jsxs)(E.Fragment,{children:[` `,(0,E.jsx)(`span`,{className:`mx-1 font-semibold uppercase text-xs tracking-wide text-primary`,children:n}),` `]}):null,e.relation]},e.relation))})}function O({finding:e}){let t=x([e]),i=e.variant===`composite`;return(0,E.jsxs)(p,{ref:t.ref,tabIndex:t.tabIndex,"data-flashed":t.dataFlashed,className:`transition-colors ${t.flashClassName}`,children:[(0,E.jsx)(h,{children:(0,E.jsxs)(`span`,{className:`inline-flex items-center gap-2`,children:[i?(0,E.jsx)(w,{className:`size-3.5 text-muted-foreground`,"aria-hidden":`true`}):null,i&&e.relations&&e.relations.length>0?(0,E.jsx)(D,{relations:e.relations,operator:e.operator}):(0,E.jsx)(`span`,{children:e.relation}),i?(0,E.jsx)(n,{variant:`outline`,className:`text-xs uppercase border-dashed`,children:e.operator?.toUpperCase()}):(0,E.jsx)(n,{variant:`secondary`,className:`text-xs uppercase`,children:e.format})]})}),(0,E.jsxs)(h,{children:[e.value,` queries`]}),(0,E.jsx)(h,{className:`text-right`,children:r(e.totalReadBytes)}),(0,E.jsxs)(h,{children:[(0,E.jsx)(b,{finding:e}),(0,E.jsx)(`p`,{className:`mt-1`,children:e.recommendation}),(0,E.jsx)(o,{children:(0,E.jsx)(c,{confidence:e.confidence,validationRequired:e.validationRequired})})]})]})}var k=(0,T.memo)(function({catalog:e,defaultCollapsed:t=!0}){let[n,r]=(0,T.useState)(0),a=(0,T.useMemo)(()=>l(e,`cachingOpportunity`).sort((e,t)=>t.totalReadBytes-e.totalReadBytes||(t.value??0)-(e.value??0)),[e]),s=u(),c=s?a.findIndex(e=>e===s.finding):null,{totalPages:h,effectivePage:b,visible:x}=S(a,n,r,c);if(a.length===0)return null;let C=a[0];return(0,E.jsx)(g,{title:`Caching Opportunities`,impactBand:`info`,badges:(0,E.jsx)(i,{type:`cachingOpportunity`,impactBand:`info`}),defaultCollapsed:t,summary:(0,E.jsx)(v,{value:`${C.value}×`,context:`read by ${C.value} queries: ${C.relation}`}),children:(0,E.jsxs)(`div`,{className:`space-y-3`,children:[(0,E.jsxs)(_,{children:[(0,E.jsx)(f,{children:(0,E.jsxs)(p,{children:[(0,E.jsx)(d,{children:`Relation`}),(0,E.jsx)(d,{children:`Read by`}),(0,E.jsx)(d,{className:`text-right`,children:`Data read`}),(0,E.jsx)(d,{children:`Recommendation`})]})}),(0,E.jsx)(m,{children:x.map((e,t)=>(0,E.jsx)(O,{finding:e},`${e.format}:${e.relation}:${(e.executionIds??[]).join(`,`)}:${t}`))})]}),(0,E.jsx)(o,{children:(0,E.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Reuse is inferred from plan structure, not confirmed by execution. Verify before caching.`})}),(0,E.jsx)(y,{page:b,totalPages:h,onPrev:()=>r(e=>e-1),onNext:()=>r(e=>e+1)})]})})});export{k as CachingOpportunity};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{M as t}from"./charts-vendor-0VMaLVLN.js";import{R as n,d as r,u as i}from"./DisclosureContext-LYzHroHO.js";import{p as a}from"./plan-graph-vendor-B0sEms9Z.js";import{D as o,S as s}from"./index-CEM9bz_x.js";import{o as c,r as l,t as u}from"./Dashboard-Bo_1jGqH.js";import{r as d}from"./impact-sort-7z0ZcBZf.js";import{n as f}from"./finding-anchor-DF1cSHO1.js";import{t as p}from"./usePagedRows-BjPOpUU8.js";import{n as m,t as h}from"./useSortMode-CU0vzThu.js";var g=e(t(),1),_=a();function v(e){return`${e.value}s`}function y({finding:e}){let t=f([e]);return(0,_.jsxs)(`li`,{ref:t.ref,tabIndex:t.tabIndex,"data-flashed":t.dataFlashed,className:`space-y-1 text-sm transition-colors ${t.flashClassName}`,children:[(0,_.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,_.jsx)(i,{impactBand:e.impactBand}),(0,_.jsx)(`strong`,{children:v(e)})]}),(0,_.jsx)(u,{finding:e}),(0,_.jsx)(`p`,{className:`text-muted-foreground pt-1`,children:e.recommendation})]})}var b=(0,g.memo)(function({catalog:e,defaultCollapsed:t=!0}){let{sortMode:i,setSortMode:a,orderBy:u}=h(),[f,b]=(0,g.useState)(!t),[x,S]=(0,g.useState)(0),C=e.filter(e=>e.type===`coldStart`).slice().sort((e,t)=>n[e.impactBand]-n[t.impactBand]),w=u(C,e=>[e],e=>e.stageId??null),T=o(),E=T?w.findIndex(e=>e===T.finding):null,{totalPages:D,effectivePage:O,visible:k}=p(w,x,S,E);return C.length===0?null:(0,_.jsxs)(s,{title:`Cold Start`,impactBand:C[0].impactBand,badges:(0,_.jsxs)(_.Fragment,{children:[(0,_.jsx)(r,{type:`coldStart`,impactBand:C[0].impactBand}),d(C,C.length,f)?(0,_.jsx)(m,{mode:i,onChange:a}):null]}),open:f,onOpenChange:b,summary:(0,_.jsx)(c,{value:v(C[0]),context:`${C.length} issue${C.length===1?``:`s`} flagged`}),children:[(0,_.jsx)(`ul`,{className:`space-y-2`,children:k.map(e=>(0,_.jsx)(y,{finding:e},e.id))}),(0,_.jsx)(l,{page:O,totalPages:D,onPrev:()=>S(e=>e-1),onNext:()=>S(e=>e+1)})]})});export{b as ColdStart};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{M as t}from"./charts-vendor-0VMaLVLN.js";import{R as n,S as r,at as i,d as a,j as o,p as s,u as c}from"./DisclosureContext-LYzHroHO.js";import{p as l}from"./plan-graph-vendor-B0sEms9Z.js";import{h as u,m as d}from"./useRecentFiles-BrBl-AP1.js";import{D as f,S as p}from"./index-CEM9bz_x.js";import{o as m,r as h,t as g}from"./Dashboard-Bo_1jGqH.js";import{n as _}from"./finding-anchor-DF1cSHO1.js";import{t as v}from"./usePagedRows-BjPOpUU8.js";var y=e(t(),1),b=l();function x({finding:e}){let t=_([e]);return(0,b.jsxs)(`li`,{ref:t.ref,tabIndex:t.tabIndex,"data-flashed":t.dataFlashed,className:`space-y-1 transition-colors ${t.flashClassName}`,children:[(0,b.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,b.jsx)(c,{impactBand:e.impactBand}),(0,b.jsx)(`code`,{className:`text-xs`,children:e.property}),(0,b.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:`=`}),(0,b.jsx)(`code`,{className:`rounded bg-accent/10 px-1.5 py-0.5 font-mono text-xs text-accent`,children:e.valueText})]}),(0,b.jsx)(g,{finding:e}),(0,b.jsxs)(`p`,{className:`text-sm`,children:[e.recommendation,e.docAnchor?(0,b.jsxs)(b.Fragment,{children:[` `,(0,b.jsxs)(r,{anchor:e.docAnchor,children:[`Why `,e.property,` matters`]})]}):null]})]})}var S=(0,y.memo)(function({appModel:e,configFindings:t,defaultCollapsed:r=!0}){let[c,l]=(0,y.useState)(0),g=(0,y.useMemo)(()=>d(t??[],`configAudit`).sort((e,t)=>n[e.impactBand]-n[t.impactBand]),[t]),_=f(),S=_?g.findIndex(e=>e===_.finding):null,{totalPages:C,effectivePage:w,visible:T}=v(g,c,l,S);if(g.length===0){let t=e.evidenceAvailability?.entries.find(e=>e.key===`sparkConfiguration`),n;if(t)n=t.state===`present`?`No misconfigurations detected.`:t.state===`unknown`&&t.reasonCode===`parseIncomplete`?(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)(`span`,{children:[t.summary,` `]}),(0,b.jsx)(s,{children:(0,b.jsx)(u,{evidenceKey:`sparkConfiguration`})})]}):(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(`span`,{children:`No environment info captured in this log. `}),(0,b.jsx)(s,{children:(0,b.jsx)(u,{evidenceKey:`sparkConfiguration`})})]});else{let t=e.app?.evidenceInputs;n=(t?t.environmentUpdates>0:Object.keys(e.app?.config??{}).length>0||e.app?.resources)?`No misconfigurations detected.`:(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(`span`,{children:`No environment info captured in this log. `}),(0,b.jsx)(s,{children:(0,b.jsx)(u,{evidenceKey:`sparkConfiguration`})})]})}let r=(0,b.jsx)(`p`,{className:`text-muted-foreground text-xs`,children:n});return(0,b.jsx)(p,{title:`Config Audit`,compact:!0,summary:r,children:r})}let E=i(g);return(0,b.jsxs)(p,{title:`Config Audit`,impactBand:E,badges:(0,b.jsx)(a,{type:`configAudit`,impactBand:E??`info`,docAnchor:o(g)}),statusBadge:(0,b.jsx)(s,{children:(0,b.jsx)(u,{evidenceKey:`sparkConfiguration`})}),defaultCollapsed:r,summary:(0,b.jsx)(m,{value:`${g.length}`,context:`misconfiguration${g.length===1?``:`s`} flagged`}),children:[(0,b.jsx)(`ul`,{className:`space-y-4`,children:T.map(e=>(0,b.jsx)(x,{finding:e},e.id))}),(0,b.jsx)(h,{page:w,totalPages:C,onPrev:()=>l(e=>e-1),onNext:()=>l(e=>e+1)})]})});export{S as ConfigAudit};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{M as t,T as n,f as r,n as i,o as a,s as o,u as s,v as c}from"./charts-vendor-0VMaLVLN.js";import{G as l,S as u,b as d,d as f,p,u as m}from"./DisclosureContext-LYzHroHO.js";import{p as h}from"./plan-graph-vendor-B0sEms9Z.js";import{_ as g,b as _,h as v,y}from"./useRecentFiles-BrBl-AP1.js";import{S as b}from"./index-CEM9bz_x.js";import{d as x,f as S,o as C,r as w,s as T,t as E}from"./Dashboard-Bo_1jGqH.js";import{t as D}from"./usePagedRows-BjPOpUU8.js";var O=e(t(),1),k=h(),A=240,j={PROCESS_LOCAL:`Process-local`,NODE_LOCAL:`Node-local`,RACK_LOCAL:`Rack-local`,NO_PREF:`No preference`,ANY:`Any`,OTHER:`Other`,idle:`Idle`},M={PROCESS_LOCAL:g.clean,NODE_LOCAL:g.accent,RACK_LOCAL:g.warning,NO_PREF:g.muted,ANY:g.critical,OTHER:g.muted,idle:g.muted},N=`Core Usage by Locality`,P=(0,O.memo)(function({catalog:e,defaultCollapsed:t=!0}){let[h,P]=(0,O.useState)(0),F=d()?.data.coreLocality,I=(0,O.useMemo)(()=>{let e=F?.chart??{hasActivity:!1};return e.hasActivity?{...e,sampled:T(e.points)}:e},[F]),L=F?.ratio.topStages??[],R=e.find(e=>e.type===`coreLocality`),z=e.some(e=>e.type===`memoryUtilization`&&e.variant===`idleCores`),B=L.filter(e=>e.nonLocalTasks>0),{totalPages:V,effectivePage:H,visible:U}=D(B,h,P);if(!I.hasActivity)return(0,k.jsx)(b,{title:N,summary:(0,k.jsx)(`span`,{className:`text-muted-foreground text-xs`,children:`No stage activity to plot.`}),children:(0,k.jsx)(x,{tone:`neutral`,icon:S,title:`No stage activity to plot.`})});let{order:W,points:G,sampled:K,peakCores:q}=I;return(0,k.jsx)(b,{title:N,impactBand:R?.impactBand,badges:R?(0,k.jsx)(f,{type:`coreLocality`,impactBand:R.impactBand}):null,defaultCollapsed:t,summary:(0,k.jsx)(C,{value:`${l(q)} cores`,context:`busy at the peak`}),children:(0,k.jsxs)(`div`,{className:`space-y-2`,children:[(0,k.jsx)(p,{children:(0,k.jsxs)(`p`,{className:`text-muted-foreground text-xs`,children:[`approximate: stage-level attribution`,R?null:(0,k.jsxs)(k.Fragment,{children:[`, see `,(0,k.jsx)(u,{anchor:`#bottleneck-utilization`,children:`how utilization is measured`})]})]})}),R?(0,k.jsxs)(`p`,{className:`flex flex-wrap items-start gap-2 text-sm`,children:[(0,k.jsx)(m,{impactBand:R.impactBand,className:`mt-1.5`}),(0,k.jsxs)(`span`,{children:[(0,k.jsxs)(`strong`,{children:[R.value,`% non-local`]}),`: `,R.recommendation]})]}):null,R?(0,k.jsx)(E,{finding:R}):null,(0,k.jsx)(p,{children:R?(0,k.jsx)(v,{confidence:R.confidence,validationRequired:R.validationRequired}):null}),(0,k.jsx)(_,{ariaLabel:`Approximate concurrent core usage over time, stacked by task locality tier, with idle capacity shown. See the legend for tier colors.`,height:A,table:{caption:`Concurrent core usage over time by locality tier`,columns:[`Time (s)`,...W.map(e=>j[e]??e)],rows:G.map(e=>[e.t,...W.map(t=>Math.round(e[t]))]),align:Array.from({length:W.length+1},()=>`right`)},children:(0,k.jsxs)(i,{data:K,children:[(0,k.jsx)(r,{vertical:!1,stroke:g.muted,strokeOpacity:.2}),(0,k.jsx)(o,{dataKey:`t`,tick:{fontSize:10},label:{value:`seconds from app start`,position:`insideBottom`,offset:-2,fontSize:10}}),(0,k.jsx)(a,{tick:{fontSize:10},width:36,label:{value:`avg concurrent cores`,angle:-90,position:`insideLeft`,fontSize:10}}),(0,k.jsx)(c,{...y}),(0,k.jsx)(n,{wrapperStyle:{fontSize:10}}),W.map(e=>(0,k.jsx)(s,{type:`monotone`,dataKey:e,name:j[e]??e,stackId:`cores`,stroke:M[e]??g.muted,fill:M[e]??g.muted,fillOpacity:e===`idle`?.15:.8,isAnimationActive:!1},e))]})}),(0,k.jsx)(p,{children:U.length>0?(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`ul`,{className:`space-y-1 text-xs text-muted-foreground`,children:U.map(e=>(0,k.jsxs)(`li`,{children:[`Stage `,e.stageId,`: `,Math.round(e.ratio*100),`% non-local (`,e.nonLocalTasks,`/`,e.taskCount,` tasks)`]},e.stageId))}),(0,k.jsx)(w,{page:H,totalPages:V,onPrev:()=>P(e=>e-1),onNext:()=>P(e=>e+1)})]}):null}),(0,k.jsx)(p,{children:z?(0,k.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Idle cores also flagged → see Memory Utilization widget`}):null})]})})});export{P as CoreUsageArea};
|