sparkforensics-server 0.1.0 → 0.2.0
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/README.md +6 -0
- package/index.js +40 -49
- package/lib/static-files.js +10 -6
- package/package.json +20 -1
- package/public/assets/AutoscalingChurn-CFJkiqxW.js +1 -0
- package/public/assets/CacheUtilization-kTKZBzDA.js +1 -0
- package/public/assets/CachingOpportunity-CU70EWcF.js +1 -0
- package/public/assets/ColdStart-hOI-WOvm.js +1 -0
- package/public/assets/ConfigAudit-B4oAksZY.js +1 -0
- package/public/assets/CoreUsageArea-D-dR3SQk.js +1 -0
- package/public/assets/Dashboard-MDhohsq4.js +4 -0
- package/public/assets/DuplicatePlanSubtree-54RKsfI7.js +1 -0
- package/public/assets/DurationHistogram-CviQyPNM.js +1 -0
- package/public/assets/EmptyState-v2ehFncc.js +1 -0
- package/public/assets/ExecutorUtilization-vHyFHgL6.js +1 -0
- package/public/assets/GcPressure-DINuhcno.js +1 -0
- package/public/assets/ImpactEstimate-C6GzFOY9.js +1 -0
- package/public/assets/IncompleteRun-a1kuCnU6.js +1 -0
- package/public/assets/JobFailures-CYwPfUhR.js +1 -0
- package/public/assets/MemoryUtilization-Dlfj0e_f.js +1 -0
- package/public/assets/OverBroadcast-BMu7Y8l9.js +1 -0
- package/public/assets/PartitionSizing-CvMGfSVB.js +1 -0
- package/public/assets/PlanExplorer-xYFme_Rx.js +1 -0
- package/public/assets/PlanGraphRoute-a3OGg6ET.js +1 -0
- package/public/assets/RetryWaste-JKRjOZ-J.js +1 -0
- package/public/assets/RowPagination-DypWbnic.js +1 -0
- package/public/assets/ShuffleIO-Mi8HiVu-.js +1 -0
- package/public/assets/Skew-C3iOScTC.js +1 -0
- package/public/assets/SlowHost-DKBg18v-.js +1 -0
- package/public/assets/SmallFiles-CCCB6AIu.js +1 -0
- package/public/assets/SpeculationWaste-DUNupw0_.js +1 -0
- package/public/assets/Spill-BlLdatik.js +1 -0
- package/public/assets/StageFailed-qtY7C7Yo.js +1 -0
- package/public/assets/StageFindingGroup-CoVdEZYs.js +1 -0
- package/public/assets/StageHeader-uDBLHgdg.js +1 -0
- package/public/assets/StagePill-CYCMdlIx.js +1 -0
- package/public/assets/StageShape-zs0mAjQJ.js +1 -0
- package/public/assets/StageSlowness-C7vg0u5Q.js +1 -0
- package/public/assets/Straggler-4BRGAQP4.js +1 -0
- package/public/assets/TaskFailures-CSjO23Kg.js +1 -0
- package/public/assets/TinyTask-6Zuovcn5.js +1 -0
- package/public/assets/UnderBroadcast-CePjo0ZV.js +1 -0
- package/public/assets/WidgetLeadSummary-DRNRVvn7.js +1 -0
- package/public/assets/{charts-vendor-NMqKV0H4.js → charts-vendor-Cf1-wzeH.js} +2 -2
- package/public/assets/downsample-D8XmJk6i.js +1 -0
- package/public/assets/finding-anchor-4TmpXd7j.js +1 -0
- package/public/assets/impact-sort-Cq6KOLqh.js +1 -0
- package/public/assets/inbox-DBFovbUX.js +1 -0
- package/public/assets/index-CHjV2-jB.js +9 -0
- package/public/assets/index-DMEtaP4u.css +1 -0
- package/public/assets/parser-worker-BMPPE37w.js +64 -0
- package/public/assets/plan-graph-vendor-B96a-e4N.js +7 -0
- package/public/assets/react-vendor-DA6opS-q.js +9 -0
- package/public/assets/select-D5fK-za0.js +1 -0
- package/public/assets/toggle-group-lbIXRG0W.js +1 -0
- package/public/assets/usePagedRows-CFoZrPr4.js +1 -0
- package/public/assets/useRecentFiles-BPGQ6XII.js +13 -0
- package/public/assets/useSortMode-BOPpfLhJ.js +1 -0
- package/public/docs/404.html +3 -3
- package/public/docs/assets/{app.Bxy4_HVA.js → app.BgzsaTS3.js} +1 -1
- package/public/docs/assets/aqe-loop.IwQSATHw.svg +1 -0
- package/public/docs/assets/aqe-loop.dark.DGbaxqJE.svg +1 -0
- package/public/docs/assets/broadcast-vs-shuffle.Db4WY1XK.svg +1 -0
- package/public/docs/assets/broadcast-vs-shuffle.dark.C7Bxs0mG.svg +1 -0
- package/public/docs/assets/cache-lifecycle.dark.B-hS7AgU.svg +1 -0
- package/public/docs/assets/cache-lifecycle.rEOVYQNU.svg +1 -0
- package/public/docs/assets/chunks/@localSearchIndexroot.PQ5JepCp.js +1 -0
- package/public/docs/assets/chunks/{VPLocalSearchBox.L5jNOIR3.js → VPLocalSearchBox.DOq3t-On.js} +1 -1
- package/public/docs/assets/chunks/duplicate-plan-subtree.dark.Cdp70QhV.js +1 -0
- package/public/docs/assets/chunks/{framework.CNDaxUod.js → framework.DSg0KOwT.js} +1 -1
- package/public/docs/assets/chunks/retry-escalation-ladder.dark.DHipdJgZ.js +1 -0
- package/public/docs/assets/chunks/theme.BP14rGBx.js +2 -0
- package/public/docs/assets/cold-start-timeline.DxC_Sc7w.svg +1 -0
- package/public/docs/assets/cold-start-timeline.dark.CZ17YcAG.svg +1 -0
- package/public/docs/assets/columnar-layout.PghGeOEA.svg +1 -0
- package/public/docs/assets/columnar-layout.dark.BVNlz0ff.svg +1 -0
- package/public/docs/assets/container-memory.DIO0AnIm.svg +1 -0
- package/public/docs/assets/container-memory.dark.CP-5zuCl.svg +1 -0
- package/public/docs/assets/contributor-guide_architecture_board-widgets.md.B-OsL91z.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_board-widgets.md.B-OsL91z.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_detector-contract.md.BOeH4d1J.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_detector-contract.md.BOeH4d1J.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_drill-down.md.BtPdlM7r.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_drill-down.md.BtPdlM7r.lean.js +1 -0
- package/public/docs/assets/{contributor-guide_architecture_impact-estimation.md.CzlXOnCq.js → contributor-guide_architecture_impact-estimation.md.DYCDPgkh.js} +1 -1
- package/public/docs/assets/{contributor-guide_architecture_impact-estimation.md.CzlXOnCq.lean.js → contributor-guide_architecture_impact-estimation.md.DYCDPgkh.lean.js} +1 -1
- package/public/docs/assets/{contributor-guide_architecture_index.md.94lNbF-4.js → contributor-guide_architecture_index.md.3TO9ic6w.js} +1 -1
- package/public/docs/assets/{contributor-guide_architecture_index.md.94lNbF-4.lean.js → contributor-guide_architecture_index.md.3TO9ic6w.lean.js} +1 -1
- package/public/docs/assets/{contributor-guide_architecture_overview.md.mQFlN66o.js → contributor-guide_architecture_overview.md.CehiRmGn.js} +1 -1
- package/public/docs/assets/{contributor-guide_architecture_overview.md.mQFlN66o.lean.js → contributor-guide_architecture_overview.md.CehiRmGn.lean.js} +1 -1
- package/public/docs/assets/contributor-guide_architecture_state-and-history.md.m3S3UdMk.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_state-and-history.md.m3S3UdMk.lean.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering.md.DbqPf2OT.js +1 -0
- package/public/docs/assets/contributor-guide_architecture_widget-rendering.md.DbqPf2OT.lean.js +1 -0
- package/public/docs/assets/{contributor-guide_architecture_worker-protocol.md.BaS_L10g.js → contributor-guide_architecture_worker-protocol.md.B93qJ_tT.js} +2 -2
- package/public/docs/assets/{contributor-guide_architecture_worker-protocol.md.BaS_L10g.lean.js → contributor-guide_architecture_worker-protocol.md.B93qJ_tT.lean.js} +1 -1
- package/public/docs/assets/contributor-guide_contributing.md.CvRsdr6J.js +1 -0
- package/public/docs/assets/contributor-guide_contributing.md.CvRsdr6J.lean.js +1 -0
- package/public/docs/assets/{contributor-guide_development-setup.md.CpUMVtIK.js → contributor-guide_development-setup.md.DvAN_9mK.js} +1 -1
- package/public/docs/assets/{contributor-guide_development-setup.md.CpUMVtIK.lean.js → contributor-guide_development-setup.md.DvAN_9mK.lean.js} +1 -1
- package/public/docs/assets/{contributor-guide_testing.md.C0q-BJfl.js → contributor-guide_testing.md.6rIKqSyY.js} +1 -1
- package/public/docs/assets/{contributor-guide_testing.md.C0q-BJfl.lean.js → contributor-guide_testing.md.6rIKqSyY.lean.js} +1 -1
- package/public/docs/assets/dag-stages.DSz_S937.svg +1 -0
- package/public/docs/assets/dag-stages.dark.F72UzxH4.svg +1 -0
- package/public/docs/assets/driver-executor.D5pQ7YN1.svg +1 -0
- package/public/docs/assets/driver-executor.dark.BmX9cPvh.svg +1 -0
- package/public/docs/assets/duplicate-plan-subtree.B4cvN6fj.svg +1 -0
- package/public/docs/assets/duplicate-plan-subtree.dark.Dw8wS0Ag.svg +1 -0
- package/public/docs/assets/{index.md.CETnDZzR.js → index.md.CHJVslga.js} +1 -1
- package/public/docs/assets/{index.md.CETnDZzR.lean.js → index.md.CHJVslga.lean.js} +1 -1
- package/public/docs/assets/join-strategy.C_FvrCEo.svg +1 -0
- package/public/docs/assets/join-strategy.dark.ChMLnNII.svg +1 -0
- package/public/docs/assets/memory-borrowing.BqQRJg0u.svg +1 -0
- package/public/docs/assets/memory-borrowing.dark.Yhh20O9C.svg +1 -0
- package/public/docs/assets/memory-regions.XHvO7jHG.svg +1 -0
- package/public/docs/assets/memory-regions.dark.D4TP9_08.svg +1 -0
- package/public/docs/assets/repartition-vs-coalesce.BovLRrpj.svg +1 -0
- package/public/docs/assets/repartition-vs-coalesce.dark.BhAczKZQ.svg +1 -0
- package/public/docs/assets/retry-escalation-ladder.DyTKJJmZ.svg +1 -0
- package/public/docs/assets/retry-escalation-ladder.dark.BdsabtU3.svg +1 -0
- package/public/docs/assets/shuffle-map-reduce.KuOEZVmg.svg +1 -0
- package/public/docs/assets/shuffle-map-reduce.dark.BgQZnFSb.svg +1 -0
- package/public/docs/assets/spill-classification.BU2euYDO.svg +1 -0
- package/public/docs/assets/spill-classification.dark.D7i1M40d.svg +1 -0
- package/public/docs/assets/{style.D2mY0HUs.css → style.DXOMCXxn.css} +1 -1
- package/public/docs/assets/tuning-reference_anti-patterns.md.Df1YMIHu.js +1 -0
- package/public/docs/assets/tuning-reference_anti-patterns.md.Df1YMIHu.lean.js +1 -0
- package/public/docs/assets/tuning-reference_aqe.md.BIsCtLzm.js +1 -0
- package/public/docs/assets/tuning-reference_aqe.md.BIsCtLzm.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-broadcast-sizing.md.CEstB3Ia.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-broadcast-sizing.md.CEstB3Ia.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-cold-start.md.CEuy-72y.js +7 -0
- package/public/docs/assets/tuning-reference_bottleneck-cold-start.md.CEuy-72y.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-duplicate-plan-subtree.md.CIohQDfn.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-duplicate-plan-subtree.md.CIohQDfn.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-failures.md.4z5BXGJ2.js +6 -0
- package/public/docs/assets/tuning-reference_bottleneck-failures.md.4z5BXGJ2.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-gc.md.DSxzZRK7.js +6 -0
- package/public/docs/assets/tuning-reference_bottleneck-gc.md.DSxzZRK7.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-job-failure-rate.md.BaJl__1W.js +8 -0
- package/public/docs/assets/tuning-reference_bottleneck-job-failure-rate.md.BaJl__1W.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-memory-utilization.md.DbP-SJZc.js +7 -0
- package/public/docs/assets/tuning-reference_bottleneck-memory-utilization.md.DbP-SJZc.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-retry-waste.md.D5JMjVOt.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-retry-waste.md.D5JMjVOt.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-shuffle.md.CM-nTmIH.js +12 -0
- package/public/docs/assets/tuning-reference_bottleneck-shuffle.md.CM-nTmIH.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-skew.md.BdUwiDhn.js +14 -0
- package/public/docs/assets/tuning-reference_bottleneck-skew.md.BdUwiDhn.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-slow-host.md.BlIo6UDW.js +7 -0
- package/public/docs/assets/tuning-reference_bottleneck-slow-host.md.BlIo6UDW.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-small-files.md.B8kloyx8.js +5 -0
- package/public/docs/assets/tuning-reference_bottleneck-small-files.md.B8kloyx8.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-spill.md.PNH7mITt.js +6 -0
- package/public/docs/assets/tuning-reference_bottleneck-spill.md.PNH7mITt.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-straggler.md.DY36fHN5.js +7 -0
- package/public/docs/assets/tuning-reference_bottleneck-straggler.md.DY36fHN5.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-tiny-tasks.md.QTV7O8kU.js +8 -0
- package/public/docs/assets/tuning-reference_bottleneck-tiny-tasks.md.QTV7O8kU.lean.js +1 -0
- package/public/docs/assets/tuning-reference_bottleneck-utilization.md.DTiueZC3.js +5 -0
- package/public/docs/assets/tuning-reference_bottleneck-utilization.md.DTiueZC3.lean.js +1 -0
- package/public/docs/assets/tuning-reference_caching.md.B7aQ8asB.js +1 -0
- package/public/docs/assets/tuning-reference_caching.md.B7aQ8asB.lean.js +1 -0
- package/public/docs/assets/tuning-reference_cluster-config.md.ZVmDGsQ3.js +1 -0
- package/public/docs/assets/tuning-reference_cluster-config.md.ZVmDGsQ3.lean.js +1 -0
- package/public/docs/assets/tuning-reference_config.md.UvveiWG3.js +1 -0
- package/public/docs/assets/tuning-reference_config.md.UvveiWG3.lean.js +1 -0
- package/public/docs/assets/tuning-reference_data-formats.md.bjCAWH3N.js +1 -0
- package/public/docs/assets/tuning-reference_data-formats.md.bjCAWH3N.lean.js +1 -0
- package/public/docs/assets/tuning-reference_index.md.BQ_NooMV.js +1 -0
- package/public/docs/assets/tuning-reference_index.md.BQ_NooMV.lean.js +1 -0
- package/public/docs/assets/tuning-reference_intro.md.CobD-lGB.js +1 -0
- package/public/docs/assets/tuning-reference_intro.md.CobD-lGB.lean.js +1 -0
- package/public/docs/assets/tuning-reference_joins.md.BtKs_CuW.js +1 -0
- package/public/docs/assets/tuning-reference_joins.md.BtKs_CuW.lean.js +1 -0
- package/public/docs/assets/tuning-reference_memory-model.md.DhT-n4y3.js +1 -0
- package/public/docs/assets/tuning-reference_memory-model.md.DhT-n4y3.lean.js +1 -0
- package/public/docs/assets/tuning-reference_metrics.md.mLOh7Apj.js +1 -0
- package/public/docs/assets/tuning-reference_metrics.md.mLOh7Apj.lean.js +1 -0
- package/public/docs/assets/tuning-reference_partitioning.md.q0zKF_8X.js +1 -0
- package/public/docs/assets/tuning-reference_partitioning.md.q0zKF_8X.lean.js +1 -0
- package/public/docs/assets/tuning-reference_pyspark.md.DDCfvN9t.js +6 -0
- package/public/docs/assets/tuning-reference_pyspark.md.DDCfvN9t.lean.js +1 -0
- package/public/docs/assets/tuning-reference_shuffle.md.BZZ7R4Ix.js +1 -0
- package/public/docs/assets/tuning-reference_shuffle.md.BZZ7R4Ix.lean.js +1 -0
- package/public/docs/assets/tuning-reference_spark-architecture.md.Dwzm5avO.js +1 -0
- package/public/docs/assets/tuning-reference_spark-architecture.md.Dwzm5avO.lean.js +1 -0
- package/public/docs/assets/tuning-reference_table-formats.md.D6wj-2dX.js +1 -0
- package/public/docs/assets/tuning-reference_table-formats.md.D6wj-2dX.lean.js +1 -0
- package/public/docs/assets/udf-execution-models.BUFDICuG.svg +1 -0
- package/public/docs/assets/udf-execution-models.dark.YTNS6GDq.svg +1 -0
- package/public/docs/assets/user-guide_alternative-log-retrieval.md.sU3KGarf.js +1 -0
- package/public/docs/assets/user-guide_alternative-log-retrieval.md.sU3KGarf.lean.js +1 -0
- package/public/docs/assets/user-guide_getting-started.md.DtEM37MK.js +3 -0
- package/public/docs/assets/user-guide_getting-started.md.DtEM37MK.lean.js +1 -0
- package/public/docs/assets/{user-guide_mcp-tools.md.DwYI1d6C.js → user-guide_mcp-tools.md.C8MiIu7F.js} +35 -5
- package/public/docs/assets/{user-guide_mcp-tools.md.DwYI1d6C.lean.js → user-guide_mcp-tools.md.C8MiIu7F.lean.js} +1 -1
- package/public/docs/assets/{user-guide_run-comparison.md.5-oaOfTu.js → user-guide_run-comparison.md.S0TWWmLY.js} +1 -1
- package/public/docs/assets/{user-guide_run-comparison.md.5-oaOfTu.lean.js → user-guide_run-comparison.md.S0TWWmLY.lean.js} +1 -1
- package/public/docs/assets/user-guide_understanding-findings.md.D0R_Y-R2.js +1 -0
- package/public/docs/assets/{user-guide_understanding-findings.md.CK2WZ0Tf.lean.js → user-guide_understanding-findings.md.D0R_Y-R2.lean.js} +1 -1
- package/public/docs/contributor-guide/architecture/board-widgets.html +7 -7
- package/public/docs/contributor-guide/architecture/detector-contract.html +7 -7
- package/public/docs/contributor-guide/architecture/drill-down.html +7 -7
- package/public/docs/contributor-guide/architecture/impact-estimation.html +7 -7
- package/public/docs/contributor-guide/architecture/index.html +7 -7
- package/public/docs/contributor-guide/architecture/overview.html +7 -7
- package/public/docs/contributor-guide/architecture/state-and-history.html +7 -7
- package/public/docs/contributor-guide/architecture/widget-rendering.html +7 -7
- package/public/docs/contributor-guide/architecture/worker-protocol.html +8 -8
- package/public/docs/contributor-guide/contributing.html +7 -7
- package/public/docs/contributor-guide/development-setup.html +7 -7
- package/public/docs/contributor-guide/testing.html +7 -7
- package/public/docs/hashmap.json +1 -1
- package/public/docs/index.html +7 -7
- package/public/docs/tuning-reference/anti-patterns.html +29 -0
- package/public/docs/tuning-reference/aqe.html +29 -0
- package/public/docs/tuning-reference/bottleneck-broadcast-sizing.html +29 -0
- package/public/docs/tuning-reference/bottleneck-cold-start.html +35 -0
- package/public/docs/tuning-reference/bottleneck-duplicate-plan-subtree.html +30 -0
- package/public/docs/tuning-reference/bottleneck-failures.html +35 -0
- package/public/docs/tuning-reference/bottleneck-gc.html +34 -0
- package/public/docs/tuning-reference/bottleneck-job-failure-rate.html +37 -0
- package/public/docs/tuning-reference/bottleneck-memory-utilization.html +35 -0
- package/public/docs/tuning-reference/bottleneck-retry-waste.html +30 -0
- package/public/docs/tuning-reference/bottleneck-shuffle.html +40 -0
- package/public/docs/tuning-reference/bottleneck-skew.html +42 -0
- package/public/docs/tuning-reference/bottleneck-slow-host.html +35 -0
- package/public/docs/tuning-reference/bottleneck-small-files.html +33 -0
- package/public/docs/tuning-reference/bottleneck-spill.html +34 -0
- package/public/docs/tuning-reference/bottleneck-straggler.html +35 -0
- package/public/docs/tuning-reference/bottleneck-tiny-tasks.html +36 -0
- package/public/docs/tuning-reference/bottleneck-utilization.html +34 -0
- package/public/docs/tuning-reference/caching.html +29 -0
- package/public/docs/tuning-reference/cluster-config.html +29 -0
- package/public/docs/tuning-reference/config.html +29 -0
- package/public/docs/tuning-reference/data-formats.html +29 -0
- package/public/docs/tuning-reference/index.html +29 -0
- package/public/docs/tuning-reference/intro.html +29 -0
- package/public/docs/tuning-reference/joins.html +29 -0
- package/public/docs/tuning-reference/memory-model.html +29 -0
- package/public/docs/tuning-reference/metrics.html +29 -0
- package/public/docs/tuning-reference/partitioning.html +29 -0
- package/public/docs/tuning-reference/pyspark.html +34 -0
- package/public/docs/tuning-reference/shuffle.html +29 -0
- package/public/docs/tuning-reference/spark-architecture.html +29 -0
- package/public/docs/tuning-reference/table-formats.html +29 -0
- package/public/docs/user-guide/alternative-log-retrieval.html +29 -0
- package/public/docs/user-guide/getting-started.html +8 -8
- package/public/docs/user-guide/mcp-tools.html +41 -11
- package/public/docs/user-guide/run-comparison.html +7 -7
- package/public/docs/user-guide/understanding-findings.html +7 -7
- package/public/index.html +6 -6
- package/vendor-core/analyzer.js +74 -74
- package/vendor-core/cli/budgets.js +13 -27
- package/vendor-core/cli/collect-run.js +43 -19
- package/vendor-core/core-count.js +25 -27
- package/vendor-core/core-locality-ratio.js +4 -11
- package/vendor-core/core-time-series.js +6 -12
- package/vendor-core/core-usage-locality.js +3 -4
- package/vendor-core/detectors.js +256 -375
- package/vendor-core/docs-config.js +69 -21
- package/vendor-core/docs-content/chapters/01-intro.md +32 -0
- package/vendor-core/docs-content/chapters/02-spark-architecture.md +76 -0
- package/vendor-core/docs-content/chapters/03-memory-model.md +73 -0
- package/vendor-core/docs-content/chapters/04-partitioning.md +65 -0
- package/vendor-core/docs-content/chapters/05-joins.md +62 -0
- package/vendor-core/docs-content/chapters/06-shuffle.md +59 -0
- package/vendor-core/docs-content/chapters/07-data-formats.md +81 -0
- package/vendor-core/docs-content/chapters/07b-table-formats.md +56 -0
- package/vendor-core/docs-content/chapters/08-caching.md +58 -0
- package/vendor-core/docs-content/chapters/09-pyspark.md +78 -0
- package/vendor-core/docs-content/chapters/10-aqe.md +167 -0
- package/vendor-core/docs-content/chapters/11-cluster-config.md +170 -0
- package/vendor-core/docs-content/chapters/12-anti-patterns.md +171 -0
- package/vendor-core/docs-content/chapters/14-metrics.md +87 -0
- package/vendor-core/docs-content/chapters/15-config.md +93 -0
- package/vendor-core/docs-content/chapters/nav-index.json +370 -0
- package/vendor-core/docs-content/detection/cache.md +6 -0
- package/vendor-core/docs-content/detection/cfg.md +15 -0
- package/vendor-core/docs-content/detection/chrn.md +7 -0
- package/vendor-core/docs-content/detection/cold.md +4 -0
- package/vendor-core/docs-content/detection/cstor.md +4 -0
- package/vendor-core/docs-content/detection/fail.md +5 -0
- package/vendor-core/docs-content/detection/gc.md +4 -0
- package/vendor-core/docs-content/detection/host.md +5 -0
- package/vendor-core/docs-content/detection/incmp.md +6 -0
- package/vendor-core/docs-content/detection/jobs.md +4 -0
- package/vendor-core/docs-content/detection/local.md +7 -0
- package/vendor-core/docs-content/detection/mem.md +10 -0
- package/vendor-core/docs-content/detection/part.md +5 -0
- package/vendor-core/docs-content/detection/plan.md +14 -0
- package/vendor-core/docs-content/detection/retry.md +4 -0
- package/vendor-core/docs-content/detection/sfail.md +5 -0
- package/vendor-core/docs-content/detection/shape.md +5 -0
- package/vendor-core/docs-content/detection/shfl.md +4 -0
- package/vendor-core/docs-content/detection/skew.md +6 -0
- package/vendor-core/docs-content/detection/slow.md +6 -0
- package/vendor-core/docs-content/detection/spec.md +7 -0
- package/vendor-core/docs-content/detection/spill.md +7 -0
- package/vendor-core/docs-content/detection/strag.md +5 -0
- package/vendor-core/docs-content/detection/tiny.md +4 -0
- package/vendor-core/docs-content/detection/util.md +4 -0
- package/vendor-core/docs-content/diagrams/aqe-loop.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/aqe-loop.svg +1 -0
- package/vendor-core/docs-content/diagrams/broadcast-vs-shuffle.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/broadcast-vs-shuffle.svg +1 -0
- package/vendor-core/docs-content/diagrams/cache-lifecycle.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/cache-lifecycle.svg +1 -0
- package/vendor-core/docs-content/diagrams/cold-start-timeline.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/cold-start-timeline.svg +1 -0
- package/vendor-core/docs-content/diagrams/columnar-layout.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/columnar-layout.svg +1 -0
- package/vendor-core/docs-content/diagrams/container-memory.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/container-memory.svg +1 -0
- package/vendor-core/docs-content/diagrams/dag-stages.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/dag-stages.svg +1 -0
- package/vendor-core/docs-content/diagrams/driver-executor.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/driver-executor.svg +1 -0
- package/vendor-core/docs-content/diagrams/duplicate-plan-subtree.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/duplicate-plan-subtree.svg +1 -0
- package/vendor-core/docs-content/diagrams/join-strategy.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/join-strategy.svg +1 -0
- package/vendor-core/docs-content/diagrams/memory-borrowing.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/memory-borrowing.svg +1 -0
- package/vendor-core/docs-content/diagrams/memory-regions.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/memory-regions.svg +1 -0
- package/vendor-core/docs-content/diagrams/repartition-vs-coalesce.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/repartition-vs-coalesce.svg +1 -0
- package/vendor-core/docs-content/diagrams/retry-escalation-ladder.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/retry-escalation-ladder.svg +1 -0
- package/vendor-core/docs-content/diagrams/shuffle-map-reduce.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/shuffle-map-reduce.svg +1 -0
- package/vendor-core/docs-content/diagrams/spill-classification.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/spill-classification.svg +1 -0
- package/vendor-core/docs-content/diagrams/udf-execution-models.dark.svg +1 -0
- package/vendor-core/docs-content/diagrams/udf-execution-models.svg +1 -0
- package/vendor-core/docs-content/tuning/broadcast-sizing.md +78 -0
- package/vendor-core/docs-content/tuning/cold-start.md +81 -0
- package/vendor-core/docs-content/tuning/duplicate-plan-subtree.md +45 -0
- package/vendor-core/docs-content/tuning/failures.md +124 -0
- package/vendor-core/docs-content/tuning/gc.md +110 -0
- package/vendor-core/docs-content/tuning/job-failure-rate.md +101 -0
- package/vendor-core/docs-content/tuning/memory-utilization.md +58 -0
- package/vendor-core/docs-content/tuning/retry-waste.md +90 -0
- package/vendor-core/docs-content/tuning/shuffle.md +154 -0
- package/vendor-core/docs-content/tuning/skew.md +123 -0
- package/vendor-core/docs-content/tuning/slow-host.md +117 -0
- package/vendor-core/docs-content/tuning/small-files.md +99 -0
- package/vendor-core/docs-content/tuning/spill.md +114 -0
- package/vendor-core/docs-content/tuning/straggler.md +103 -0
- package/vendor-core/docs-content/tuning/tiny-tasks.md +94 -0
- package/vendor-core/docs-content/tuning/utilization.md +90 -0
- package/vendor-core/docs-site-config.js +10 -17
- package/vendor-core/efficiency-model.js +7 -13
- package/vendor-core/etl-phases.js +3 -5
- package/vendor-core/event-handlers.js +232 -134
- package/vendor-core/event-schemas.js +48 -114
- package/vendor-core/evidence-availability.js +5 -10
- package/vendor-core/evidence-report.js +72 -122
- package/vendor-core/export-data.js +48 -0
- package/vendor-core/finding-action-label.js +4 -10
- package/vendor-core/finding-filter-predicate.js +3 -7
- package/vendor-core/finding-generic-recommendation.js +112 -0
- package/vendor-core/finding-names.js +51 -0
- package/vendor-core/format-utils.js +112 -38
- package/vendor-core/impact-band.js +18 -24
- package/vendor-core/impact-estimator.js +38 -74
- package/vendor-core/ingest.js +7 -13
- package/vendor-core/job-groups.js +3 -6
- package/vendor-core/list-runs.js +278 -0
- package/vendor-core/load-vendored.js +6 -12
- package/vendor-core/log-header-peek.js +81 -0
- package/vendor-core/lz4-block.js +4 -6
- package/vendor-core/mcp-server-factory.js +38 -8
- package/vendor-core/mcp-tools.js +105 -76
- package/vendor-core/model-assembler.js +8 -16
- package/vendor-core/occupancy.js +5 -9
- package/vendor-core/parser-worker.js +18 -27
- package/vendor-core/plan-dot.js +2 -5
- package/vendor-core/plan-duration-attribution.js +78 -29
- package/vendor-core/plan-graph-model.js +126 -69
- package/vendor-core/plan-node-detail.js +31 -17
- package/vendor-core/plan-summary.js +19 -8
- package/vendor-core/recommendation-rollup.js +35 -39
- package/vendor-core/redact.js +72 -16
- package/vendor-core/rolling-log-reassembly.js +4 -6
- package/vendor-core/run-comparison.js +65 -70
- package/vendor-core/scaling-sim.js +5 -7
- package/vendor-core/session-snapshot.js +1 -1
- package/vendor-core/shs-fetch.js +4 -6
- package/vendor-core/shs-load.js +9 -13
- package/vendor-core/shs-request.js +1 -1
- package/vendor-core/stage-quantiles.js +14 -0
- package/vendor-core/types.js +78 -18
- package/vendor-core/wasted-core-hours.js +7 -12
- package/public/assets/AutoscalingChurn-CP5OjN6v.js +0 -1
- package/public/assets/CacheUtilization-BjyawXL6.js +0 -1
- package/public/assets/CachingOpportunity-DV2ABG2G.js +0 -1
- package/public/assets/ConfigAudit-DMiBhAoG.js +0 -1
- package/public/assets/CoreUsageArea-CGYIgPnt.js +0 -1
- package/public/assets/Dashboard-D1_IrWRs.js +0 -12
- package/public/assets/ExecutorTimeline-DkaAGqQT.js +0 -1
- package/public/assets/Failures-Crngoicu.js +0 -1
- package/public/assets/GcPressure-CFXm4BnA.js +0 -1
- package/public/assets/IncompleteRun-BWEJTb13.js +0 -1
- package/public/assets/JobFailures-BmjxCA-h.js +0 -1
- package/public/assets/MemoryUtilization-Bu2uQJbd.js +0 -1
- package/public/assets/PlanExplorer-DKUwF0uz.js +0 -1
- package/public/assets/PlanGraphRoute-BjPSugIG.js +0 -1
- package/public/assets/ShuffleIO--Rur3neu.js +0 -1
- package/public/assets/Spill-DIMpt8c2.js +0 -1
- package/public/assets/TaskSkew-BDr1DbeI.js +0 -1
- package/public/assets/index-4id52G-A.js +0 -9
- package/public/assets/index-D9kwVYIO.css +0 -1
- package/public/assets/parser-worker-00O9WEQC.js +0 -65
- package/public/assets/plan-graph-vendor-vZQHG2EJ.js +0 -7
- package/public/assets/react-vendor-u4pyvC5Y.js +0 -9
- package/public/assets/useRecentFiles-46iBU9zJ.js +0 -5
- package/public/docs/assets/chunks/@localSearchIndexroot.DclgKtlT.js +0 -1
- package/public/docs/assets/chunks/theme.CoT6y5bf.js +0 -2
- package/public/docs/assets/contributor-guide_architecture_board-widgets.md.BtjoE_1k.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_board-widgets.md.BtjoE_1k.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_detector-contract.md.DQyCHQNM.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_detector-contract.md.DQyCHQNM.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_drill-down.md.BKfyDQck.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_drill-down.md.BKfyDQck.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_state-and-history.md.DaqttKgQ.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_state-and-history.md.DaqttKgQ.lean.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_widget-rendering.md.Bk6Iyj9S.js +0 -1
- package/public/docs/assets/contributor-guide_architecture_widget-rendering.md.Bk6Iyj9S.lean.js +0 -1
- package/public/docs/assets/contributor-guide_contributing.md.C-lKs70I.js +0 -1
- package/public/docs/assets/contributor-guide_contributing.md.C-lKs70I.lean.js +0 -1
- package/public/docs/assets/user-guide_getting-started.md.BJdD7a7_.js +0 -3
- package/public/docs/assets/user-guide_getting-started.md.BJdD7a7_.lean.js +0 -1
- package/public/docs/assets/user-guide_understanding-findings.md.CK2WZ0Tf.js +0 -1
- package/public/vendor/spark-doc/anchors.json +0 -205
- package/public/vendor/spark-doc/index.html +0 -4202
- package/public/vendor/spark-doc/landing.html +0 -418
- package/public/vendor/spark-doc/meta.html +0 -970
package/README.md
ADDED
package/index.js
CHANGED
|
@@ -4,27 +4,18 @@ import { realpathSync, existsSync } from 'node:fs';
|
|
|
4
4
|
import { dirname, join } from 'node:path';
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
6
6
|
import { resolveStaticRoot, serveStatic } from './lib/static-files.js';
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// mcp-server-factory imports it unconditionally too (vendored .js or repo
|
|
11
|
-
// .ts, either way), and packages/server/package.json
|
|
12
|
-
// (like the root package.json) declares '@modelcontextprotocol/sdk' as a direct
|
|
13
|
-
// dependency, so plain node module resolution finds it in both the published
|
|
14
|
-
// and monorepo-dev layouts.
|
|
7
|
+
// No install-mode fallback needed for the sdk package (unlike core below):
|
|
8
|
+
// packages/server/package.json declares '@modelcontextprotocol/sdk' as a direct
|
|
9
|
+
// dependency, so node resolution finds it in both published and monorepo layouts.
|
|
15
10
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
16
11
|
|
|
17
12
|
const DEFAULT_PORT = 4173;
|
|
18
13
|
const DEFAULT_HOST = '127.0.0.1';
|
|
19
14
|
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
// node_modules); in the monorepo it falls back to the real repo-root
|
|
25
|
-
// packages/core/src/ sibling directory. load-vendored.js itself is the one
|
|
26
|
-
// module this bootstrap has to locate by hand (see its own header comment);
|
|
27
|
-
// every other core module then loads through its exported loadVendored().
|
|
15
|
+
// vendor-core/ exists only in a published install (populated by vendor-core.mjs
|
|
16
|
+
// at publish time); the monorepo falls back to the packages/core/src/ sibling.
|
|
17
|
+
// load-vendored.js is the one module located by hand; the rest load through its
|
|
18
|
+
// exported loadVendored().
|
|
28
19
|
async function loadVendoredCore(dir, moduleName, opts) {
|
|
29
20
|
const vendoredHelper = join(dir, 'vendor-core', 'load-vendored.js');
|
|
30
21
|
const helperPath = existsSync(vendoredHelper) ? vendoredHelper : join(dir, '..', 'core', 'src', 'load-vendored.js');
|
|
@@ -45,12 +36,9 @@ async function loadHandleShsProxy(dir) {
|
|
|
45
36
|
export function createServer({
|
|
46
37
|
staticRoot,
|
|
47
38
|
fetchImpl = fetch,
|
|
48
|
-
// Test-only override
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
// swallowed by the no-op .catch() below, without racing the real
|
|
52
|
-
// packages/server/vendor-core/ directory that test/bin.test.js
|
|
53
|
-
// separately populates and tears down.
|
|
39
|
+
// Test-only override: lets test/index.test.js inject a rejecting promise to
|
|
40
|
+
// prove a real failure still surfaces as a /mcp error, not swallowed by the
|
|
41
|
+
// no-op .catch() below.
|
|
54
42
|
loadCreateMcpServer: loadCreateMcpServerImpl = loadCreateMcpServer,
|
|
55
43
|
} = {}) {
|
|
56
44
|
const dir = dirname(fileURLToPath(import.meta.url));
|
|
@@ -58,18 +46,10 @@ export function createServer({
|
|
|
58
46
|
const createMcpServerPromise = loadCreateMcpServerImpl(dir);
|
|
59
47
|
const handleShsProxyPromise = loadHandleShsProxy(dir);
|
|
60
48
|
handleShsProxyPromise.catch(() => {});
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
// transiently exists-but-is-mid-rewrite while test/bin.test.js's own real
|
|
66
|
-
// `npm pack` is running concurrently in another test file/worker), Node
|
|
67
|
-
// reports an unhandled rejection even though nothing actually needed the
|
|
68
|
-
// result yet. A promise's rejection is independently observable by every
|
|
69
|
-
// consumer that awaits/.catches it, so attaching this no-op handler here
|
|
70
|
-
// does not hide a real failure from the /mcp handler's own `await
|
|
71
|
-
// createMcpServerPromise` below; it only marks this one rejection as
|
|
72
|
-
// "handled" for Node's unhandledRejection bookkeeping.
|
|
49
|
+
// Only awaited later in the /mcp branch, so a request that never hits /mcp
|
|
50
|
+
// leaves it unconsumed; a rejection there would be an unhandled rejection.
|
|
51
|
+
// This no-op handler marks it handled without hiding the failure from the
|
|
52
|
+
// /mcp handler's own await (rejections are observable per-consumer).
|
|
73
53
|
createMcpServerPromise.catch(() => {});
|
|
74
54
|
|
|
75
55
|
return http.createServer(async (req, res) => {
|
|
@@ -79,16 +59,14 @@ export function createServer({
|
|
|
79
59
|
const handleShsProxy = await handleShsProxyPromise;
|
|
80
60
|
await handleShsProxy(req, res, { fetchImpl });
|
|
81
61
|
} else if (pathname === '/mcp') {
|
|
82
|
-
// Stateless mode (sessionIdGenerator: undefined)
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
// own simpleStatelessStreamableHttp.ts example).
|
|
62
|
+
// Stateless mode (sessionIdGenerator: undefined): a transport handles
|
|
63
|
+
// one request and the SDK throws on reuse, so make a fresh
|
|
64
|
+
// server+transport pair per request.
|
|
86
65
|
const createMcpServer = await createMcpServerPromise;
|
|
87
66
|
const mcpServer = createMcpServer();
|
|
88
|
-
// allowedHosts is matched against the raw Host header (host:port,
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
// port via listen(0, ...).
|
|
67
|
+
// allowedHosts is matched against the raw Host header (host:port), so
|
|
68
|
+
// derive the port from the actual socket, not a hardcode: tests bind to
|
|
69
|
+
// an ephemeral port via listen(0, ...).
|
|
92
70
|
const localPort = req.socket.localPort;
|
|
93
71
|
const mcpTransport = new StreamableHTTPServerTransport({
|
|
94
72
|
sessionIdGenerator: undefined,
|
|
@@ -135,13 +113,26 @@ function parsePort(argv) {
|
|
|
135
113
|
return DEFAULT_PORT;
|
|
136
114
|
}
|
|
137
115
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
116
|
+
const USAGE = `Usage: sparkforensics-server [--port <n>]
|
|
117
|
+
|
|
118
|
+
Serves the SparkForensics dashboard locally and proxies Spark History
|
|
119
|
+
Server fetches on your behalf (server-to-server, so no browser CORS
|
|
120
|
+
restriction). Binds to 127.0.0.1 only. Default port ${DEFAULT_PORT},
|
|
121
|
+
overridden by --port or the PORT env var.
|
|
122
|
+
|
|
123
|
+
See https://github.com/shuffle-works/sparkforensics#readme for details.
|
|
124
|
+
`;
|
|
125
|
+
|
|
126
|
+
// argv[1] is the bin symlink path via the published `.bin` entry, so
|
|
127
|
+
// realpath-resolve it before comparing against this module's real path.
|
|
141
128
|
const invokedDirectly = process.argv[1] && realpathSync(process.argv[1]) === fileURLToPath(import.meta.url);
|
|
142
129
|
if (invokedDirectly) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
130
|
+
if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
|
131
|
+
process.stderr.write(USAGE);
|
|
132
|
+
} else {
|
|
133
|
+
const port = parsePort(process.argv);
|
|
134
|
+
startServer({ port }).then(() => {
|
|
135
|
+
for (const line of serverStartupGuidance(port)) console.log(line);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
147
138
|
}
|
package/lib/static-files.js
CHANGED
|
@@ -15,16 +15,20 @@ const CONTENT_TYPES = {
|
|
|
15
15
|
|
|
16
16
|
export function resolveStaticRoot(dir) {
|
|
17
17
|
const bundled = join(dir, 'public');
|
|
18
|
-
|
|
18
|
+
// Monorepo dev fallback (no public/ yet): dir is packages/server, and the
|
|
19
|
+
// Vite build output lives at the repo root, two levels up.
|
|
20
|
+
return existsSync(bundled) ? bundled : join(dir, '..', '..', 'dist');
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
export async function serveStatic(req, res, root) {
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
// harmless 404 instead of being caught and rejected with 403.
|
|
24
|
+
// Deliberately not via `new URL()`: its dot-segment resolution collapses
|
|
25
|
+
// `/../../etc/passwd` before we see it, sailing a traversal past the guard
|
|
26
|
+
// below as a 404 instead of a 403.
|
|
26
27
|
const pathname = decodeURIComponent(req.url.split('?')[0]);
|
|
27
|
-
const
|
|
28
|
+
const stripped = pathname.replace(/^\/+/, '');
|
|
29
|
+
// Any directory-style request (trailing slash, including '/' itself) seeks
|
|
30
|
+
// that directory's index.html, same as a browser navigating to it directly.
|
|
31
|
+
const relative = pathname.endsWith('/') ? `${stripped}index.html` : stripped;
|
|
28
32
|
const target = normalize(join(root, relative));
|
|
29
33
|
|
|
30
34
|
// Path-traversal guard: the resolved path must stay within root.
|
package/package.json
CHANGED
|
@@ -1,7 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sparkforensics-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"description": "Local companion server for the SparkForensics dashboard: serves the app and proxies Spark History Server fetches to avoid browser CORS restrictions.",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/shuffle-works/sparkforensics.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/shuffle-works/sparkforensics/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/shuffle-works/sparkforensics#readme",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"apache-spark",
|
|
17
|
+
"spark",
|
|
18
|
+
"spark-history-server",
|
|
19
|
+
"server",
|
|
20
|
+
"proxy",
|
|
21
|
+
"cors",
|
|
22
|
+
"dashboard"
|
|
23
|
+
],
|
|
5
24
|
"bin": {
|
|
6
25
|
"sparkforensics-server": "index.js"
|
|
7
26
|
},
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as C,j as e}from"./react-vendor-DA6opS-q.js";import{W as k,T as A,I as T,D as B}from"./index-CHjV2-jB.js";import{I as E}from"./ImpactEstimate-C6GzFOY9.js";import{W as N}from"./WidgetLeadSummary-DRNRVvn7.js";import{j as w,C as f}from"./useRecentFiles-BPGQ6XII.js";import{d as I}from"./downsample-D8XmJk6i.js";import{k as R,C as K,X as L,Y as $,T as _,f as z,a as b,l as D}from"./charts-vendor-Cf1-wzeH.js";import"./plan-graph-vendor-B96a-e4N.js";const F=60,G=6e4,H=220;function O(t,s,a,c,r){if(t.length===0&&s.length===0)return[];const x=Math.max(r,c-a),l=Math.max(1,Math.ceil(x/r)),i=[];for(let n=0;n<l;n++)i.push({tStart:a+n*r,adds:0,removes:0});const u=n=>Math.min(l-1,Math.max(0,Math.floor((n-a)/r)));for(const n of t)i[u(n.timestamp)].adds++;for(const n of s)i[u(n.timestamp)].removes++;return i}function Y(t,s){const a=Math.max(1,s-t);return Math.max(G,Math.ceil(a/F))}function U(t){if(t<=0)return 1;const a=10**Math.floor(Math.log10(t)),c=t/a;return(c<=1?1:c<=2?2:c<=5?5:10)*a}function W(t){const s=t.reduce((c,r)=>Math.max(c,Math.abs(r.added),Math.abs(r.removed)),0),a=U(s);return{domain:[-a,a],ticks:[-a,-a/2,0,a/2,a]}}function M(t){return Math.abs(t.height)<1?null:e.jsx(D,{...t})}function X({finding:t}){return e.jsxs("div",{className:"flex flex-col gap-1 transition-colors",children:[e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Short-lived executors: ",e.jsxs("strong",{children:[t.value,"%"]})]}),e.jsx(E,{finding:t}),e.jsxs("p",{className:"flex flex-wrap items-start gap-2 text-sm",children:[e.jsx(T,{impactBand:t.impactBand,className:"mt-1.5"}),e.jsxs("span",{children:[t.recommendation," ",e.jsx(B,{anchor:"#config-autoscale-bounds",children:"Tuning executorIdleTimeout and the min/max bounds"}),"."]})]})]})}const se=C.memo(function({appModel:s,activeFileId:a,catalog:c=[],defaultCollapsed:r=!0}){const x=C.useMemo(()=>{const o=s.executors.added,m=s.executors.removed;if(o.length===0&&m.length===0)return{hasEvents:!1,added:o,removed:m};const g=s.app,h=g?.startTime??0,v=g?.endTime??h,S=Y(h,v),j=I(O(o,m,h,v,S)).map(p=>({t:`${Math.round((p.tStart-h)/1e3)}s`,added:p.adds,removed:-p.removes})),y=W(j);return{hasEvents:!0,added:o,removed:m,rows:j,yAxisScale:y}},[s,a]);if(!x.hasEvents)return e.jsx(k,{title:"Autoscaling Churn",summary:e.jsx("span",{className:"text-muted-foreground text-xs",children:"No executor add/remove events (static allocation)."}),children:e.jsx("p",{className:"text-muted-foreground text-xs",children:"No executor add/remove events (static allocation)."})});const{added:l,removed:i,rows:u,yAxisScale:n}=x,d=c.find(o=>o.type==="autoscalingChurn");return e.jsx(k,{title:"Autoscaling Churn",impactBand:d?.impactBand,badges:d&&e.jsx(A,{type:"autoscalingChurn",impactBand:d.impactBand}),defaultCollapsed:r,summary:e.jsx(N,{value:`${l.length} added / ${i.length} removed`,context:d?`${d.value}% short-lived executors, ${d.impactBand}`:"executor churn events"}),children:e.jsxs("div",{className:"space-y-2",children:[d&&e.jsx(X,{finding:d}),e.jsx("p",{className:"text-muted-foreground text-xs",children:"executors added / removed over time"}),e.jsx(w,{ariaLabel:"Executor added and removed counts per time bucket over the run.",height:H,table:{caption:"Executor added/removed counts by time bucket",columns:["Time","Executors added","Executors removed"],rows:u.map(o=>[o.t,o.added,Math.abs(o.removed)]),align:["right","right","right"]},children:e.jsxs(R,{data:u,children:[e.jsx(K,{stroke:f.muted,strokeOpacity:.2}),e.jsx(L,{dataKey:"t",tick:{fontSize:10}}),e.jsx($,{tick:{fontSize:10},width:32,domain:n.domain,ticks:n.ticks}),e.jsx(_,{formatter:(o,m)=>[Math.abs(Number(o)),m]}),e.jsx(z,{wrapperStyle:{fontSize:10}}),e.jsx(b,{dataKey:"added",name:"Added",stackId:"churn",fill:f.clean,shape:M}),e.jsx(b,{dataKey:"removed",name:"Removed",stackId:"churn",fill:f.muted,shape:M})]})})]})})});export{se as AutoscalingChurn,O as bucketChurn};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as o,j as s}from"./react-vendor-DA6opS-q.js";import{L as v,at as C,W as M,P as $,Z as L,H as P,_ as c,Q as A,J as d,I as R,n as j,j as l,T as F,D as E,S as _,A as H,ar as U,as as W}from"./index-CHjV2-jB.js";import{u as O}from"./finding-anchor-4TmpXd7j.js";import{I as V}from"./ImpactEstimate-C6GzFOY9.js";import{R as S}from"./RowPagination-DypWbnic.js";import{u as D}from"./usePagedRows-CFoZrPr4.js";import{W as G}from"./WidgetLeadSummary-DRNRVvn7.js";import"./charts-vendor-Cf1-wzeH.js";import"./plan-graph-vendor-B96a-e4N.js";const z=70;function J(a){if(!a)return"—";const t=[];return a.useMemory&&t.push("Memory"),a.useDisk&&t.push("Disk"),a.deserialized?t.push("Deserialized"):(a.useMemory||a.useDisk)&&t.push("Serialized"),(a.replication??1)>1&&t.push(`x${a.replication}`),t.join(" · ")||"—"}function k(a){return a.name||`RDD ${a.id}`}function Q(a){const t=_(k(a));return t.length<=z?t:`${t.slice(0,z)}…`}function X(a){const t=U("pct",W(a));return a.variant==="diskSpillover"?`${t} spilled to disk: ${l(a.diskSize??0)} disk / ${l(a.memorySize??0)} memory`:`${t} cached (${a.numCachedPartitions??0}/${a.numPartitions??0} partitions)`}function Z({finding:a}){const t=O([a]),m=a.rddName??`RDD ${a.rddId}`;return s.jsxs("div",{ref:t.ref,tabIndex:t.tabIndex,"data-flashed":t.dataFlashed,className:`space-y-1 transition-colors ${t.flashClassName}`,children:[s.jsxs("p",{className:"flex flex-wrap items-start gap-2",children:[s.jsx(R,{impactBand:a.impactBand,className:"mt-1.5"}),s.jsx("span",{children:m})]}),s.jsx(H,{children:s.jsx("p",{className:"text-xs text-muted-foreground",children:X(a)})}),s.jsx(V,{finding:a}),s.jsx("p",{className:"text-sm",children:a.recommendation})]})}const re=o.memo(function({appModel:t,catalog:m}){const[b,h]=o.useState(0),[w,u]=o.useState(0),x=t.app?.rddInfo,r=o.useMemo(()=>x?[...x.values()].filter(e=>(e.storageLevel?.useMemory||e.storageLevel?.useDisk)&&(e.numCachedPartitions??0)>0).sort((e,i)=>(i.memorySize??0)+(i.diskSize??0)-((e.memorySize??0)+(e.diskSize??0))):[],[x]),n=o.useMemo(()=>m.filter(e=>e.type==="cacheUtilization").sort((e,i)=>v[e.impactBand]-v[i.impactBand]),[m]),p=D(r,b,h),f=C(),B=f?n.findIndex(e=>e===f.finding):null,g=D(n,w,u,B);if(r.length===0)return null;const I=e=>n.filter(i=>i.rddId===e),T=r.reduce((e,i)=>e+(i.memorySize??0)+(i.diskSize??0),0);return s.jsx("div",{"data-widget":"cache-utilization",children:s.jsxs(M,{title:"Cache Storage",impactBand:j(n),badges:s.jsxs(s.Fragment,{children:[n.length>0?s.jsx(F,{type:"cacheUtilization",impactBand:j(n)??"info"}):null,s.jsxs("span",{className:"text-xs text-muted-foreground",children:[r.length," cached RDD",r.length===1?"":"s",", see"," ",s.jsx(E,{anchor:"#memory-model",children:"how Spark accounts cached memory"})]})]}),defaultCollapsed:!0,summary:s.jsx(G,{value:l(T),context:"cached across memory + disk"}),children:[s.jsxs($,{children:[s.jsx(L,{children:s.jsxs(P,{children:[s.jsx(c,{children:"RDD"}),s.jsx(c,{children:"Storage level"}),s.jsx(c,{className:"text-right",children:"Cached partitions"}),s.jsx(c,{className:"text-right",children:"Memory"}),s.jsx(c,{className:"text-right",children:"Disk"})]})}),s.jsx(A,{children:p.visible.map(e=>{const i=k(e),N=Q(e),y=I(e.id);return s.jsxs(P,{children:[s.jsxs(d,{className:"max-w-80 truncate",title:i!==N?i:void 0,children:[N,y.length>0&&s.jsx(R,{impactBand:j(y)??"info",className:"ml-1.5"})]}),s.jsx(d,{children:J(e.storageLevel)}),s.jsxs(d,{className:"text-right",children:[e.numCachedPartitions," / ",e.numPartitions]}),s.jsx(d,{className:"text-right",children:l(e.memorySize??0)}),s.jsx(d,{className:"text-right",children:l(e.diskSize??0)})]},e.id)})})]}),s.jsx(S,{page:p.effectivePage,totalPages:p.totalPages,onPrev:()=>h(e=>e-1),onNext:()=>h(e=>e+1)}),n.length>0?s.jsxs("div",{className:"mt-3 space-y-2 text-sm",children:[g.visible.map(e=>s.jsx(Z,{finding:e},e.id)),s.jsx(S,{page:g.effectivePage,totalPages:g.totalPages,onPrev:()=>u(e=>e-1),onNext:()=>u(e=>e+1)})]}):null]})})});export{re as CacheUtilization};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as x,j as e}from"./react-vendor-DA6opS-q.js";import{c as R,at as v,W as b,P as N,Z as w,H as h,_ as l,Q as C,A as T,T as B,J as d,Y as u,j as I}from"./index-CHjV2-jB.js";import{u as $}from"./finding-anchor-4TmpXd7j.js";import{I as P}from"./ImpactEstimate-C6GzFOY9.js";import{R as k}from"./RowPagination-DypWbnic.js";import{u as O}from"./usePagedRows-CFoZrPr4.js";import{W}from"./WidgetLeadSummary-DRNRVvn7.js";import{R as A}from"./useRecentFiles-BPGQ6XII.js";import"./charts-vendor-Cf1-wzeH.js";import"./plan-graph-vendor-B96a-e4N.js";const E=[["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"}]],H=R("git-merge",E);function M({relations:a,operator:t}){const r=t==="union"?"union":"join";return e.jsx("span",{className:"inline-flex flex-wrap items-baseline",children:a.map((i,o)=>e.jsxs("span",{children:[o>0?e.jsxs(e.Fragment,{children:[" ",e.jsx("span",{className:"mx-1 font-semibold uppercase text-xs tracking-wide text-primary",children:r})," "]}):null,i.relation]},i.relation))})}function S({finding:a}){const t=$([a]),r=a.variant==="composite";return e.jsxs(h,{ref:t.ref,tabIndex:t.tabIndex,"data-flashed":t.dataFlashed,className:`transition-colors ${t.flashClassName}`,children:[e.jsx(d,{children:e.jsxs("span",{className:"inline-flex items-center gap-2",children:[r?e.jsx(H,{className:"size-3.5 text-muted-foreground","aria-hidden":"true"}):null,r&&a.relations&&a.relations.length>0?e.jsx(M,{relations:a.relations,operator:a.operator}):e.jsx("span",{children:a.relation}),r?e.jsx(u,{variant:"outline",className:"text-xs uppercase border-dashed",children:a.operator?.toUpperCase()}):e.jsx(u,{variant:"secondary",className:"text-xs uppercase",children:a.format})]})}),e.jsxs(d,{children:[a.value," queries"]}),e.jsx(d,{className:"text-right",children:I(a.totalReadBytes??0)}),e.jsxs(d,{children:[e.jsx(P,{finding:a}),e.jsx("p",{className:"mt-1",children:a.recommendation})]})]})}const U=x.memo(function({catalog:t,defaultCollapsed:r=!0}){const[i,o]=x.useState(0),c=x.useMemo(()=>t.filter(s=>s.type==="cachingOpportunity").sort((s,n)=>(n.totalReadBytes??0)-(s.totalReadBytes??0)||(typeof n.value=="number"?n.value:0)-(typeof s.value=="number"?s.value:0)),[t]),p=v(),j=p?c.findIndex(s=>s===p.finding):null,{totalPages:y,effectivePage:f,visible:g}=O(c,i,o,j);if(c.length===0)return null;const m=c[0];return e.jsx(b,{title:"Caching Opportunities",impactBand:"info",badges:e.jsx(B,{type:"cachingOpportunity",impactBand:"info"}),defaultCollapsed:r,summary:e.jsx(W,{value:`${m.value}×`,context:`read by ${m.value} queries: ${m.relation}`}),children:e.jsxs("div",{className:"space-y-3",children:[e.jsxs(N,{children:[e.jsx(w,{children:e.jsxs(h,{children:[e.jsx(l,{children:"Relation"}),e.jsx(l,{children:"Read by"}),e.jsx(l,{className:"text-right",children:"Data read"}),e.jsx(l,{children:"Recommendation"})]})}),e.jsx(C,{children:g.map((s,n)=>e.jsx(S,{finding:s},`${s.format}:${s.relation}:${(s.executionIds??[]).join(",")}:${n}`))})]}),e.jsxs(T,{children:[e.jsx(A,{confidence:"low"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Reuse is inferred from plan structure, not confirmed by execution. Verify before caching."})]}),e.jsx(k,{page:f,totalPages:y,onPrev:()=>o(s=>s-1),onNext:()=>o(s=>s+1)})]})})});export{U as CachingOpportunity};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as n,j as e}from"./react-vendor-DA6opS-q.js";import{L as d,at as C,W as v,T as y,I as N}from"./index-CHjV2-jB.js";import{W as P}from"./WidgetLeadSummary-DRNRVvn7.js";import{u as T}from"./finding-anchor-4TmpXd7j.js";import{c as b}from"./impact-sort-Cq6KOLqh.js";import{I as w}from"./ImpactEstimate-C6GzFOY9.js";import{u as M,S as A}from"./useSortMode-BOPpfLhJ.js";import{R as E}from"./RowPagination-DypWbnic.js";import{u as O}from"./usePagedRows-CFoZrPr4.js";import"./charts-vendor-Cf1-wzeH.js";import"./plan-graph-vendor-B96a-e4N.js";import"./toggle-group-lbIXRG0W.js";import"./useRecentFiles-BPGQ6XII.js";function l(s){return`${s.value}s`}function W({finding:s}){const o=T([s]);return e.jsxs("li",{ref:o.ref,tabIndex:o.tabIndex,"data-flashed":o.dataFlashed,className:`space-y-1 text-sm transition-colors ${o.flashClassName}`,children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(N,{impactBand:s.impactBand}),e.jsx("strong",{children:l(s)})]}),e.jsx(w,{finding:s}),e.jsx("p",{className:"text-muted-foreground pt-1",children:s.recommendation})]})}const U=n.memo(function({catalog:o,defaultCollapsed:p=!0}){const{sortMode:u,setSortMode:g,orderBy:x}=M(),[m,f]=n.useState(!p),[h,r]=n.useState(0),a=o.filter(t=>t.type==="coldStart").slice().sort((t,R)=>d[t.impactBand]-d[R.impactBand]),c=x(a,t=>[t],t=>t.stageId??null),i=C(),j=i?c.findIndex(t=>t===i.finding):null,{totalPages:S,effectivePage:I,visible:B}=O(c,h,r,j);return a.length===0?null:e.jsxs(v,{title:"Cold Start",impactBand:a[0].impactBand,badges:e.jsxs(e.Fragment,{children:[e.jsx(y,{type:"coldStart",impactBand:a[0].impactBand}),b(a,a.length,m)?e.jsx(A,{mode:u,onChange:g}):null]}),open:m,onOpenChange:f,summary:e.jsx(P,{value:l(a[0]),context:`${a.length} issue${a.length===1?"":"s"} flagged`}),children:[e.jsx("ul",{className:"space-y-2",children:B.map(t=>e.jsx(W,{finding:t},t.id))}),e.jsx(E,{page:I,totalPages:S,onPrev:()=>r(t=>t-1),onNext:()=>r(t=>t+1)})]})});export{U as ColdStart};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as m,j as e}from"./react-vendor-DA6opS-q.js";import{ag as A,L as g,at as I,A as r,W as f,n as R,T as k,I as B,D as b}from"./index-CHjV2-jB.js";import{R as c}from"./useRecentFiles-BPGQ6XII.js";import{u as w}from"./finding-anchor-4TmpXd7j.js";import{I as P}from"./ImpactEstimate-C6GzFOY9.js";import{R as S}from"./RowPagination-DypWbnic.js";import{u as D}from"./usePagedRows-CFoZrPr4.js";import{W as T}from"./WidgetLeadSummary-DRNRVvn7.js";import"./charts-vendor-Cf1-wzeH.js";import"./plan-graph-vendor-B96a-e4N.js";function W({finding:n}){const t=w([n]);return e.jsxs("li",{ref:t.ref,tabIndex:t.tabIndex,"data-flashed":t.dataFlashed,className:`space-y-1 transition-colors ${t.flashClassName}`,children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(B,{impactBand:n.impactBand}),e.jsx("code",{className:"text-xs",children:n.property}),e.jsx("span",{className:"text-xs text-muted-foreground",children:"="}),e.jsx("code",{className:"rounded bg-accent/10 px-1.5 py-0.5 font-mono text-xs text-accent",children:String(n.value)})]}),e.jsx(P,{finding:n}),e.jsxs("p",{className:"text-sm",children:[n.recommendation,n.docAnchor?e.jsxs(e.Fragment,{children:[" ",e.jsxs(b,{anchor:n.docAnchor,children:["Why ",n.property," matters"]})]}):null]})]})}const H=m.memo(function({appModel:t,configFindings:l,defaultCollapsed:h=!0}){const[j,d]=m.useState(0),o=m.useMemo(()=>(l??A(t.app)).filter(s=>s.type==="configAudit").slice().sort((s,a)=>g[s.impactBand]-g[a.impactBand]),[l,t]),u=I(),y=u?o.findIndex(s=>s===u.finding):null,{totalPages:v,effectivePage:C,visible:N}=D(o,j,d,y);if(o.length===0){const s=t.evidenceAvailability?.entries.find(i=>i.key==="sparkConfiguration");let a;if(s)s.state==="present"?a="No misconfigurations detected.":s.state==="unknown"&&s.reasonCode==="parseIncomplete"?a=e.jsxs(e.Fragment,{children:[e.jsxs("span",{children:[s.summary," "]}),e.jsx(r,{children:e.jsx(c,{evidenceKey:"sparkConfiguration"})})]}):a=e.jsxs(e.Fragment,{children:[e.jsx("span",{children:"No environment info captured in this log. "}),e.jsx(r,{children:e.jsx(c,{evidenceKey:"sparkConfiguration"})})]});else{const i=t.app?.evidenceInputs;a=(i?i.environmentUpdates>0:Object.keys(t.app?.config??{}).length>0||!!t.app?.resources)?"No misconfigurations detected.":e.jsxs(e.Fragment,{children:[e.jsx("span",{children:"No environment info captured in this log. "}),e.jsx(r,{children:e.jsx(c,{evidenceKey:"sparkConfiguration"})})]})}const p=e.jsx("p",{className:"text-muted-foreground text-xs",children:a});return e.jsx(f,{title:"Config Sanity",compact:!0,summary:p,children:p})}const x=R(o);return e.jsxs(f,{title:"Config Sanity",impactBand:x,badges:e.jsx(k,{type:"configAudit",impactBand:x??"info"}),statusBadge:e.jsx(r,{children:e.jsx(c,{evidenceKey:"sparkConfiguration"})}),defaultCollapsed:h,summary:e.jsx(T,{value:`${o.length}`,context:`misconfiguration${o.length===1?"":"s"} flagged`}),children:[e.jsx("ul",{className:"space-y-4",children:N.map(s=>e.jsx(W,{finding:s},s.id))}),e.jsx(S,{page:C,totalPages:v,onPrev:()=>d(s=>s-1),onNext:()=>d(s=>s+1)})]})});export{H as ConfigAudit};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as O,j as e}from"./react-vendor-DA6opS-q.js";import{az as G,W as B,A as T,D as q,I as X,T as W}from"./index-CHjV2-jB.js";import{R as $,j as J,C as l}from"./useRecentFiles-BPGQ6XII.js";import{d as Q}from"./downsample-D8XmJk6i.js";import{E as V}from"./EmptyState-v2ehFncc.js";import{I as Z}from"./ImpactEstimate-C6GzFOY9.js";import{R as tt}from"./RowPagination-DypWbnic.js";import{u as et}from"./usePagedRows-CFoZrPr4.js";import{W as at}from"./WidgetLeadSummary-DRNRVvn7.js";import{I as ot}from"./inbox-DBFovbUX.js";import{A as st,C as nt,X as it,Y as rt,T as ct,f as lt,b as mt}from"./charts-vendor-Cf1-wzeH.js";import"./plan-graph-vendor-B96a-e4N.js";const D=["PROCESS_LOCAL","NODE_LOCAL","RACK_LOCAL","NO_PREF","ANY"];function dt(M,{bucketWidthMs:n=6e4,tiers:y=D}={}){const m=M.filter(a=>(a.completedAt??0)>(a.submittedAt??0)&&(a.executorRunTime??0)>0);if(m.length===0)return{labels:[],series:{}};const x=m.reduce((a,s)=>Math.min(a,s.submittedAt??a),1/0),v=m.reduce((a,s)=>Math.max(a,s.completedAt??a),-1/0),c=Math.max(1,Math.ceil((v-x)/n)),i={};for(const a of y)i[a]=new Array(c).fill(0);const g=new Array(c).fill(0);for(const a of m){const s=a.completedAt??0,h=a.submittedAt??0,u=s-h,S=(a.executorRunTime??0)/u,b=(a.localityStats??[]).reduce((t,d)=>t+d.count,0)||1,N=new Map((a.localityStats??[]).map(t=>[t.locality,t.count/b]));for(let t=0;t<c;t++){const d=x+t*n,L=d+n,p=Math.min(s,L)-Math.max(h,d);if(p<=0)continue;const k=p/n;for(const[C,I]of N){const f=S*I*k;i[C]?i[C][t]+=f:g[t]+=f}}}g.some(a=>a>0)&&(i.OTHER=g);const o=new Array(c).fill(0);for(const a of Object.keys(i))for(let s=0;s<c;s++)o[s]+=i[a][s];const E=o.reduce((a,s)=>Math.max(a,s),0);i.idle=o.map(a=>Math.max(0,E-a));const A=[];for(let a=0;a<c;a++)A.push(x+a*n);return{labels:A,series:i}}const ut=240,pt=60,z={PROCESS_LOCAL:"Process-local",NODE_LOCAL:"Node-local",RACK_LOCAL:"Rack-local",NO_PREF:"No preference",ANY:"Any",OTHER:"Other",idle:"Idle"},H={PROCESS_LOCAL:l.clean,NODE_LOCAL:l.accent,RACK_LOCAL:l.warning,NO_PREF:l.muted,ANY:l.critical,OTHER:l.muted,idle:l.muted},F="Core Usage by Locality",vt=O.memo(function({appModel:n,catalog:y,activeFileId:m,defaultCollapsed:x=!0}){const[v,c]=O.useState(0),i=O.useMemo(()=>{const t=[...n.stages.values()];if(!t.some(r=>(r.executorRunTime??0)>0&&(r.completedAt??0)>(r.submittedAt??0)))return{hasActivity:!1};const L=n.app,p=L?.startTime??0,k=L?.endTime??p,C=Math.max(6e4,Math.ceil(Math.max(1,k-p)/pt)),{labels:I,series:f}=dt(t,{bucketWidthMs:C}),w=[...D.filter(r=>f[r]),...f.OTHER?["OTHER"]:[],"idle"],P=I.map((r,_)=>{const j={t:Math.round((r-p)/1e3)};for(const R of w)j[R]=f[R]?.[_]??0;return j}),K=Q(P),U=w.filter(r=>r!=="idle"),Y=P.reduce((r,_)=>Math.max(r,U.reduce((j,R)=>j+_[R],0)),0);return{hasActivity:!0,order:w,points:P,sampled:K,peakCores:Y}},[n,m]),g=O.useMemo(()=>G([...n.stages.values()],{topN:1/0}),[n,m]),o=y.find(t=>t.type==="coreLocality"),E=y.some(t=>t.type==="memoryUtilization"&&t.variant==="idleCores"),A=g.topStages.filter(t=>t.nonLocalTasks>0),{totalPages:a,effectivePage:s,visible:h}=et(A,v,c);if(!i.hasActivity)return e.jsx(B,{title:F,summary:e.jsx("span",{className:"text-muted-foreground text-xs",children:"No stage activity to plot."}),children:e.jsx(V,{tone:"neutral",icon:ot,title:"No stage activity to plot."})});const{order:u,points:S,sampled:b,peakCores:N}=i;return e.jsx(B,{title:F,impactBand:o?.impactBand,badges:o?e.jsx(W,{type:"coreLocality",impactBand:o.impactBand}):null,defaultCollapsed:x,summary:e.jsx(at,{value:`${Math.round(N)} cores`,context:"peak concurrent, by locality"}),children:e.jsxs("div",{className:"space-y-2",children:[e.jsx(T,{children:e.jsxs("p",{className:"text-muted-foreground text-xs",children:["approximate: stage-level attribution",o?null:e.jsxs(e.Fragment,{children:[", see ",e.jsx(q,{anchor:"#bottleneck-utilization",children:"how utilization is measured"})]})]})}),o?e.jsxs("p",{className:"flex flex-wrap items-start gap-2 text-sm",children:[e.jsx(X,{impactBand:o.impactBand,className:"mt-1.5"}),e.jsxs("span",{children:[e.jsxs("strong",{children:[o.value,"% non-local"]}),": ",o.recommendation]})]}):null,o?e.jsx(Z,{finding:o}):null,e.jsx(T,{children:o?e.jsx($,{confidence:o.confidence,validationRequired:o.validationRequired}):null}),e.jsx(J,{ariaLabel:"Approximate concurrent core usage over time, stacked by task locality tier, with idle capacity shown. See the legend for tier colors.",height:ut,table:{caption:"Concurrent core usage over time by locality tier",columns:["Time (s)",...u.map(t=>z[t]??t)],rows:S.map(t=>[t.t,...u.map(d=>Math.round(t[d]))]),align:Array.from({length:u.length+1},()=>"right")},children:e.jsxs(st,{data:b,children:[e.jsx(nt,{vertical:!1,stroke:l.muted,strokeOpacity:.2}),e.jsx(it,{dataKey:"t",tick:{fontSize:10},label:{value:"seconds from app start",position:"insideBottom",offset:-2,fontSize:10}}),e.jsx(rt,{tick:{fontSize:10},width:36,label:{value:"avg concurrent cores",angle:-90,position:"insideLeft",fontSize:10}}),e.jsx(ct,{}),e.jsx(lt,{wrapperStyle:{fontSize:10}}),u.map(t=>e.jsx(mt,{type:"monotone",dataKey:t,name:z[t]??t,stackId:"cores",stroke:H[t]??l.muted,fill:H[t]??l.muted,fillOpacity:t==="idle"?.15:.8,isAnimationActive:!1},t))]})}),e.jsx(T,{children:h.length>0?e.jsxs(e.Fragment,{children:[e.jsx("ul",{className:"space-y-1 text-xs text-muted-foreground",children:h.map(t=>e.jsxs("li",{children:["Stage ",t.stageId,": ",Math.round(t.ratio*100),"% non-local (",t.nonLocalTasks,"/",t.taskCount," tasks)"]},t.stageId))}),e.jsx(tt,{page:s,totalPages:a,onPrev:()=>c(t=>t-1),onNext:()=>c(t=>t+1)})]}):null}),e.jsx(T,{children:E?e.jsx("p",{className:"text-xs text-muted-foreground",children:"Idle cores also flagged → see Memory Utilization widget"}):null})]})})});export{vt as CoreUsageArea};
|