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
|
@@ -37,7 +37,7 @@ import { NEUTRAL_METRIC_KEYS, } from './run-comparison.js
|
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
/** A change under this share of
|
|
40
|
+
/** A change under this share of the baseline's value reads as "about the same", for
|
|
41
41
|
* run time and cost metrics alike: run-to-run noise on a shared cluster easily
|
|
42
42
|
* moves a job a percent or two. */
|
|
43
43
|
export const SAME_CHANGE_SHARE = 0.02;
|
|
@@ -78,14 +78,14 @@ function namesWhere(net , keep )
|
|
|
78
78
|
return [...net].filter(([, change]) => keep(change)).map(([name]) => name);
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
/** "
|
|
82
|
-
* job failed" / "All 3 of
|
|
83
|
-
function jobsFailed(run
|
|
84
|
-
if (failedJobs < totalJobs) return `
|
|
85
|
-
return totalJobs === 1 ? `
|
|
81
|
+
/** "The candidate had 2 of 5 jobs fail", or, when every job failed, "The candidate's only
|
|
82
|
+
* job failed" / "All 3 of the candidate's jobs failed" rather than "1 of 1 jobs". */
|
|
83
|
+
function jobsFailed(run , { failedJobs, totalJobs } ) {
|
|
84
|
+
if (failedJobs < totalJobs) return `The ${run} had ${failedJobs} of ${totalJobs} jobs fail`;
|
|
85
|
+
return totalJobs === 1 ? `The ${run}'s only job failed` : `All ${totalJobs} of the ${run}'s jobs failed`;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
/**
|
|
88
|
+
/** The baseline's failures in the parenthesis after the candidate's. */
|
|
89
89
|
function baselineFailures({ failedJobs, totalJobs } ) {
|
|
90
90
|
if (failedJobs === 0) return 'none';
|
|
91
91
|
if (failedJobs < totalJobs) return `${failedJobs} of ${totalJobs}`;
|
|
@@ -93,18 +93,18 @@ function baselineFailures({ failedJobs, totalJobs } )
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
/** The headline when either run had failed jobs, as the run verdict leads
|
|
96
|
-
* with a failure: a faster
|
|
96
|
+
* with a failure: a faster candidate that dropped work is not an improvement,
|
|
97
97
|
* and with equal failure counts the tone stays neutral since a failing run
|
|
98
98
|
* that ends sooner may just have failed earlier. Null when both runs
|
|
99
99
|
* completed. */
|
|
100
100
|
function failureHeadline(base , cand ) {
|
|
101
101
|
if (base.failedJobs === 0 && cand.failedJobs === 0) return null;
|
|
102
102
|
const tone = cand.failedJobs > base.failedJobs ? 'worse' : cand.failedJobs < base.failedJobs ? 'better' : 'same';
|
|
103
|
-
if (cand.failedJobs === 0) return { title: `${jobsFailed('
|
|
104
|
-
return { title: `${jobsFailed('
|
|
103
|
+
if (cand.failedJobs === 0) return { title: `${jobsFailed('baseline', base)}; the candidate completed`, tone };
|
|
104
|
+
return { title: `${jobsFailed('candidate', cand)} (baseline: ${baselineFailures(base)})`, tone };
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
/** One plain answer to "did
|
|
107
|
+
/** One plain answer to "did the candidate get better or worse than the baseline", from the
|
|
108
108
|
* comparison's own whole-run metrics and finding-category tallies: run time
|
|
109
109
|
* first, then which cost metrics moved each way past run-to-run noise, then which finding
|
|
110
110
|
* categories appeared or went away. When either run had failed jobs, that
|
|
@@ -119,25 +119,25 @@ export function summarizeComparison(
|
|
|
119
119
|
jobs ,
|
|
120
120
|
) {
|
|
121
121
|
const wall = metrics.find((metric) => metric.key === 'wallClock');
|
|
122
|
-
let title = 'Run time could not be compared between
|
|
122
|
+
let title = 'Run time could not be compared between the baseline and the candidate';
|
|
123
123
|
let tone = 'unknown';
|
|
124
124
|
// A log with no end-of-run record stops where the run was cut off, so its
|
|
125
125
|
// shorter time is not a speed-up: say how much each log covers, neutrally.
|
|
126
|
-
const incompleteRuns = jobs ? (['
|
|
126
|
+
const incompleteRuns = jobs ? (['baseline', 'candidate'] ).filter((run) => jobs[run].incomplete) : [];
|
|
127
127
|
if (wall && wall.baseline != null && wall.baseline > 0 && wall.candidate != null && incompleteRuns.length > 0) {
|
|
128
128
|
const change = wall.candidate - wall.baseline;
|
|
129
129
|
title = Math.abs(change / wall.baseline) < SAME_CHANGE_SHARE
|
|
130
|
-
? "
|
|
131
|
-
: `
|
|
130
|
+
? "The candidate's log covers about as much run time as the baseline's"
|
|
131
|
+
: `The candidate's log covers ${formatDuration(Math.abs(change))} ${change < 0 ? 'less' : 'more'} run time than the baseline's`;
|
|
132
132
|
} else if (wall && wall.baseline != null && wall.baseline > 0 && wall.candidate != null) {
|
|
133
133
|
const change = wall.candidate - wall.baseline;
|
|
134
134
|
const share = change / wall.baseline;
|
|
135
135
|
if (Math.abs(share) < SAME_CHANGE_SHARE) {
|
|
136
|
-
title = '
|
|
136
|
+
title = 'The candidate took about as long as the baseline';
|
|
137
137
|
tone = 'same';
|
|
138
138
|
} else {
|
|
139
139
|
const faster = change < 0;
|
|
140
|
-
title = `
|
|
140
|
+
title = `The candidate finished ${formatDuration(Math.abs(change))} ${faster ? 'faster' : 'slower'} than the baseline (${Math.round(Math.abs(share) * 100)}%)`;
|
|
141
141
|
tone = faster ? 'better' : 'worse';
|
|
142
142
|
}
|
|
143
143
|
}
|
|
@@ -156,17 +156,17 @@ export function summarizeComparison(
|
|
|
156
156
|
if (incompleteRuns.length === 2) {
|
|
157
157
|
sentences.push('Neither log has an end-of-run record, so their times cover only what each log captured, not how long the runs took.');
|
|
158
158
|
} else if (incompleteRuns.length === 1) {
|
|
159
|
-
sentences.push(`
|
|
159
|
+
sentences.push(`The ${incompleteRuns[0]}'s log has no end-of-run record, so its time covers only what the log captured, not how long the run took.`);
|
|
160
160
|
}
|
|
161
|
-
if (worse.length > 0) sentences.push(`Worse in
|
|
162
|
-
if (better.length > 0) sentences.push(`Better in
|
|
161
|
+
if (worse.length > 0) sentences.push(`Worse in the candidate: ${worse.join(', ')}.`);
|
|
162
|
+
if (better.length > 0) sentences.push(`Better in the candidate: ${better.join(', ')}.`);
|
|
163
163
|
if (cost.length > 0 && worse.length === 0 && better.length === 0) sentences.push('Other measured cost metrics look about the same.');
|
|
164
164
|
|
|
165
165
|
const net = netByCategory(findings);
|
|
166
166
|
const introduced = namesWhere(net, (change) => change > 0);
|
|
167
167
|
const resolved = namesWhere(net, (change) => change < 0);
|
|
168
|
-
if (introduced.length > 0) sentences.push(`New or more frequent in
|
|
169
|
-
if (resolved.length > 0) sentences.push(`Less frequent in
|
|
168
|
+
if (introduced.length > 0) sentences.push(`New or more frequent in the candidate: ${introduced.join(', ')}.`);
|
|
169
|
+
if (resolved.length > 0) sentences.push(`Less frequent in the candidate: ${resolved.join(', ')}.`);
|
|
170
170
|
return { title, tone, sentences };
|
|
171
171
|
}
|
|
172
172
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
6e0ac29f74ae092b14c5700dfa86d3273fce7d1af59005c6e2e450a91da92d5e
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Delta write commands whose root node is a bare name in sparkPlanInfo on real logs. The parser keeps
|
|
2
|
+
// their `Arguments:` line (event-handlers.ts) and delta-targets.ts reads their target from it; the
|
|
3
|
+
// handler table there is typed by this list, so a command added here must get a handler.
|
|
4
|
+
export const DELTA_COMMANDS = [
|
|
5
|
+
'MergeIntoCommand', 'UpdateCommand', 'DeleteCommand', 'WriteIntoDelta', 'WriteIntoDeltaCommand',
|
|
6
|
+
'SaveIntoDataSourceCommand',
|
|
7
|
+
] ;
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export function isDeltaCommand(name ) {
|
|
12
|
+
return (DELTA_COMMANDS ).includes(name);
|
|
13
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// The `<table path>/_delta_log` paths that plans name: the only trace of which Delta table a command
|
|
2
|
+
// or API merge touched when its plan carries no target. A scan may read a source too, so callers
|
|
3
|
+
// take a path only when exactly one is named.
|
|
4
|
+
import { walkPlanTree } from './plan-tree-walk.js';
|
|
5
|
+
import { isCut, } from './write-target-args.js';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
// A URI or absolute path before `/_delta_log`, as printed in `... State #0 - <path>/_delta_log[cols]`
|
|
9
|
+
// scans and `DeltaLogFileIndex [<path>/_delta_log/<file>, ...]`.
|
|
10
|
+
const DELTA_LOG_PATH = /((?:[A-Za-z][A-Za-z0-9+.-]*:\/{1,3}|\/)[^\s,[\]()#]+?)\/_delta_log(?=[/[\],\s)]|$)/g;
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
// Every distinct table path named in the plans; `unreliable` when a plan is missing or a path cut.
|
|
15
|
+
function deltaLogPaths(executions ) {
|
|
16
|
+
const paths = new Set ();
|
|
17
|
+
let unreliable = false;
|
|
18
|
+
for (const exec of executions) {
|
|
19
|
+
if (!exec.planTree) { unreliable = true; continue; }
|
|
20
|
+
walkPlanTree(exec.planTree, (node) => {
|
|
21
|
+
for (const text of [node.name, node.detail ?? '']) {
|
|
22
|
+
const mentions = text.split('/_delta_log').length - 1;
|
|
23
|
+
if (mentions === 0) continue;
|
|
24
|
+
const matches = [...text.matchAll(DELTA_LOG_PATH)];
|
|
25
|
+
// A `/_delta_log` that is not read as a path is a table this set cannot name.
|
|
26
|
+
if (matches.length < mentions) unreliable = true;
|
|
27
|
+
for (const m of matches) {
|
|
28
|
+
if (isCut(m[1])) unreliable = true;
|
|
29
|
+
else paths.add(m[1].replace(/\/+$/, ''));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}, { dedupe: true });
|
|
33
|
+
}
|
|
34
|
+
return { paths, unreliable };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** The one table path the plans of `executions` name, or null for none, several or an unreadable plan. */
|
|
38
|
+
export function soleLogPath(executions ) {
|
|
39
|
+
const { paths, unreliable } = deltaLogPaths(executions);
|
|
40
|
+
const [path] = paths;
|
|
41
|
+
return !unreliable && paths.size === 1 ? { kind: 'path', target: path } : null;
|
|
42
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// Delta write targets that the plan node's simpleString does not carry. A Delta command node is a
|
|
2
|
+
// bare name in sparkPlanInfo on real logs; its target is read from the `Arguments:` line the parser
|
|
3
|
+
// keeps (SqlExecution.commandArguments, one reader per command in COMMANDS), and for a command that
|
|
4
|
+
// always scans its target (MERGE, UPDATE, DELETE) from the single `_delta_log` path of the executions
|
|
5
|
+
// sharing its root. A write command may read another Delta table as its source, so it never takes
|
|
6
|
+
// that step. Otherwise the target is null: a rule that cannot name exactly one target names none.
|
|
7
|
+
import { isDeltaCommand, } from './delta-commands.js';
|
|
8
|
+
import { soleLogPath } from './delta-log-paths.js';
|
|
9
|
+
import { isCut, splitArgs, tableName, } from './write-target-args.js';
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/** Executions grouped by rootExecutionId, each group excluding the root itself. */
|
|
18
|
+
export function indexByRoot(sql ) {
|
|
19
|
+
const byRoot = new Map ();
|
|
20
|
+
for (const exec of sql.values()) {
|
|
21
|
+
if (exec.rootExecutionId === undefined || exec.rootExecutionId === exec.id) continue;
|
|
22
|
+
const list = byRoot.get(exec.rootExecutionId);
|
|
23
|
+
if (list) list.push(exec);
|
|
24
|
+
else byRoot.set(exec.rootExecutionId, [exec]);
|
|
25
|
+
}
|
|
26
|
+
return byRoot;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// The text after `<Command>\nArguments: `, or null when the execution kept none for this command.
|
|
30
|
+
function argumentsOf(exec , command ) {
|
|
31
|
+
const kept = exec.commandArguments;
|
|
32
|
+
const head = `${command}\nArguments: `;
|
|
33
|
+
return kept !== undefined && kept.startsWith(head) ? kept.slice(head.length) : null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// A catalog table is printed as its quoted identifier, `catalog`.`db`.`t`, as one top-level
|
|
37
|
+
// argument. Two or more such arguments (or none) leave the table unnamed. The session catalog is
|
|
38
|
+
// implied by a Hive or V1 table name, so it is dropped: `spark_catalog`.`db`.`t` is db.t.
|
|
39
|
+
const QUOTED_TABLE = /^`[^`]+`(?:\.`[^`]+`){1,2}$/;
|
|
40
|
+
|
|
41
|
+
function tableFromArguments(args ) {
|
|
42
|
+
const candidates = splitArgs(args).filter((arg) => QUOTED_TABLE.test(arg.text));
|
|
43
|
+
if (candidates.length !== 1 || !candidates[0].terminated) return null;
|
|
44
|
+
const name = tableName(candidates[0].text);
|
|
45
|
+
if (!name || isCut(name)) return null;
|
|
46
|
+
const parts = name.split('.');
|
|
47
|
+
return { kind: 'table', target: parts.length === 3 && parts[0] === 'spark_catalog' ? parts.slice(1).join('.') : name };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// SaveIntoDataSourceCommand prints `<provider>@<hash>, [k=v, k2=v2], <mode>`. The target is the
|
|
51
|
+
// one `path` option of a Delta provider.
|
|
52
|
+
function pathFromSaveOptions(args ) {
|
|
53
|
+
const options = splitArgs(args)[1];
|
|
54
|
+
if (!options?.terminated || !/^\[[\s\S]*\]$/.test(options.text)) return null;
|
|
55
|
+
const body = options.text.slice(1, -1);
|
|
56
|
+
const keys = [...body.matchAll(/(?:^|, )([A-Za-z0-9_.-]+)=/g)];
|
|
57
|
+
const paths = keys.flatMap((key, i) => {
|
|
58
|
+
if (key[1].toLowerCase() !== 'path') return [];
|
|
59
|
+
return [body.slice(key.index + key[0].length, i + 1 < keys.length ? keys[i + 1].index : body.length)];
|
|
60
|
+
});
|
|
61
|
+
if (paths.length !== 1 || isCut(paths[0]) || /\*{5,}\(redacted\)/.test(paths[0])) return null;
|
|
62
|
+
return { kind: 'path', target: paths[0] };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
const tableCommand = { fromArguments: tableFromArguments, scansTarget: false };
|
|
73
|
+
const scanningTableCommand = { ...tableCommand, scansTarget: true };
|
|
74
|
+
|
|
75
|
+
// One entry per Delta command: a new command is added here (and to DELTA_COMMANDS), not in the resolver.
|
|
76
|
+
const COMMANDS = {
|
|
77
|
+
MergeIntoCommand: scanningTableCommand,
|
|
78
|
+
UpdateCommand: scanningTableCommand,
|
|
79
|
+
DeleteCommand: scanningTableCommand,
|
|
80
|
+
WriteIntoDelta: tableCommand,
|
|
81
|
+
WriteIntoDeltaCommand: tableCommand,
|
|
82
|
+
// Only the arguments say a save is a Delta one; a JDBC save with a Delta table in its source
|
|
83
|
+
// would otherwise take that table as its target.
|
|
84
|
+
SaveIntoDataSourceCommand: {
|
|
85
|
+
fromArguments: (args) => (args.includes('DeltaDataSource') ? pathFromSaveOptions(args) : null),
|
|
86
|
+
scansTarget: false,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/** Target of a Delta command whose simpleString names none; `node` must be the root of `exec`'s plan. */
|
|
91
|
+
export function resolveDeltaCommandTarget(
|
|
92
|
+
command , exec , node , byRoot ,
|
|
93
|
+
) {
|
|
94
|
+
if (!isDeltaCommand(command) || node !== exec.planTree) return null;
|
|
95
|
+
const handler = COMMANDS[command];
|
|
96
|
+
const args = argumentsOf(exec, command);
|
|
97
|
+
const found = args === null ? null : handler.fromArguments(args);
|
|
98
|
+
if (found || !handler.scansTarget) return found;
|
|
99
|
+
// Child executions are the root's own only when it is the root: a command run under another
|
|
100
|
+
// execution shares that execution's children, which may belong to unrelated work.
|
|
101
|
+
return exec.rootExecutionId === exec.id ? soleLogPath(byRoot.get(exec.id) ?? []) : null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// An append or overwrite of an existing Delta table (saveAsTable, INSERT INTO or OVERWRITE) is an
|
|
105
|
+
// `AppendDataExecV1` or `OverwriteByExpressionExecV1` whose first argument is the table object:
|
|
106
|
+
// `DeltaTableV2(<session>,<path>,Some(CatalogTable(\nCatalog: c\nDatabase: d\nTable: t\n...)),...)`.
|
|
107
|
+
// Its CatalogTable block names the table; a path-based table has `None` there and only the path.
|
|
108
|
+
const DELTA_TABLE_V2 = /^\w+ DeltaTableV2\([^,\s]*,([^,\n]*),(?:Some\(CatalogTable\(\n(?:Catalog: (\S+)\n)?Database: (\S+)\nTable: (\S+)\n|None,)/;
|
|
109
|
+
const SIMPLE_NAME = /^[A-Za-z0-9_$]+$/;
|
|
110
|
+
|
|
111
|
+
/** Target of a V1-fallback write on a DeltaTableV2 table, or null when the detail has another shape. */
|
|
112
|
+
export function parseDeltaTableV2(detail ) {
|
|
113
|
+
const m = DELTA_TABLE_V2.exec(detail);
|
|
114
|
+
if (!m) return null;
|
|
115
|
+
const [, path, catalog, database, table] = m;
|
|
116
|
+
if (table === undefined) return path && !isCut(path) ? { kind: 'path', target: path } : null;
|
|
117
|
+
if (![database, table, catalog ?? 'spark_catalog'].every((part) => SIMPLE_NAME.test(part))) return null;
|
|
118
|
+
// The session catalog is implied by a V1 name, so it is dropped (as for a Delta command).
|
|
119
|
+
const name = `${database}.${table}`;
|
|
120
|
+
return { kind: 'table', target: catalog === undefined || catalog === 'spark_catalog' ? name : `${catalog}.${name}` };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** The append a Delta CTAS or RTAS runs under its own root: its staged table has no name. */
|
|
124
|
+
export function isStagedDeltaWrite(write ) {
|
|
125
|
+
return (write.command === 'AppendDataExecV1' || write.command === 'OverwriteByExpressionExecV1')
|
|
126
|
+
&& /^\w+ \S*DeltaCatalog\$StagedDeltaTableV2@/.test(write.raw);
|
|
127
|
+
}
|