sparkforensics-server 0.1.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.
Files changed (167) hide show
  1. package/index.js +147 -0
  2. package/lib/static-files.js +50 -0
  3. package/package.json +28 -0
  4. package/public/assets/AutoscalingChurn-CP5OjN6v.js +1 -0
  5. package/public/assets/CacheUtilization-BjyawXL6.js +1 -0
  6. package/public/assets/CachingOpportunity-DV2ABG2G.js +1 -0
  7. package/public/assets/ConfigAudit-DMiBhAoG.js +1 -0
  8. package/public/assets/CoreUsageArea-CGYIgPnt.js +1 -0
  9. package/public/assets/Dashboard-D1_IrWRs.js +12 -0
  10. package/public/assets/ExecutorTimeline-DkaAGqQT.js +1 -0
  11. package/public/assets/Failures-Crngoicu.js +1 -0
  12. package/public/assets/GcPressure-CFXm4BnA.js +1 -0
  13. package/public/assets/IncompleteRun-BWEJTb13.js +1 -0
  14. package/public/assets/JobFailures-BmjxCA-h.js +1 -0
  15. package/public/assets/MemoryUtilization-Bu2uQJbd.js +1 -0
  16. package/public/assets/PlanExplorer-DKUwF0uz.js +1 -0
  17. package/public/assets/PlanGraphRoute-BjPSugIG.js +1 -0
  18. package/public/assets/ShuffleIO--Rur3neu.js +1 -0
  19. package/public/assets/Spill-DIMpt8c2.js +1 -0
  20. package/public/assets/TaskSkew-BDr1DbeI.js +1 -0
  21. package/public/assets/charts-vendor-NMqKV0H4.js +59 -0
  22. package/public/assets/index-4id52G-A.js +9 -0
  23. package/public/assets/index-D9kwVYIO.css +1 -0
  24. package/public/assets/parser-worker-00O9WEQC.js +65 -0
  25. package/public/assets/plan-graph-vendor-BnuhLJ6X.css +1 -0
  26. package/public/assets/plan-graph-vendor-vZQHG2EJ.js +7 -0
  27. package/public/assets/react-vendor-u4pyvC5Y.js +9 -0
  28. package/public/assets/useRecentFiles-46iBU9zJ.js +5 -0
  29. package/public/docs/404.html +26 -0
  30. package/public/docs/assets/app.Bxy4_HVA.js +1 -0
  31. package/public/docs/assets/chunks/@localSearchIndexroot.DclgKtlT.js +1 -0
  32. package/public/docs/assets/chunks/VPLocalSearchBox.L5jNOIR3.js +9 -0
  33. package/public/docs/assets/chunks/framework.CNDaxUod.js +20 -0
  34. package/public/docs/assets/chunks/theme.CoT6y5bf.js +2 -0
  35. package/public/docs/assets/contributor-guide_architecture_board-widgets.md.BtjoE_1k.js +1 -0
  36. package/public/docs/assets/contributor-guide_architecture_board-widgets.md.BtjoE_1k.lean.js +1 -0
  37. package/public/docs/assets/contributor-guide_architecture_detector-contract.md.DQyCHQNM.js +1 -0
  38. package/public/docs/assets/contributor-guide_architecture_detector-contract.md.DQyCHQNM.lean.js +1 -0
  39. package/public/docs/assets/contributor-guide_architecture_drill-down.md.BKfyDQck.js +1 -0
  40. package/public/docs/assets/contributor-guide_architecture_drill-down.md.BKfyDQck.lean.js +1 -0
  41. package/public/docs/assets/contributor-guide_architecture_impact-estimation.md.CzlXOnCq.js +1 -0
  42. package/public/docs/assets/contributor-guide_architecture_impact-estimation.md.CzlXOnCq.lean.js +1 -0
  43. package/public/docs/assets/contributor-guide_architecture_index.md.94lNbF-4.js +1 -0
  44. package/public/docs/assets/contributor-guide_architecture_index.md.94lNbF-4.lean.js +1 -0
  45. package/public/docs/assets/contributor-guide_architecture_overview.md.mQFlN66o.js +1 -0
  46. package/public/docs/assets/contributor-guide_architecture_overview.md.mQFlN66o.lean.js +1 -0
  47. package/public/docs/assets/contributor-guide_architecture_state-and-history.md.DaqttKgQ.js +1 -0
  48. package/public/docs/assets/contributor-guide_architecture_state-and-history.md.DaqttKgQ.lean.js +1 -0
  49. package/public/docs/assets/contributor-guide_architecture_widget-rendering.md.Bk6Iyj9S.js +1 -0
  50. package/public/docs/assets/contributor-guide_architecture_widget-rendering.md.Bk6Iyj9S.lean.js +1 -0
  51. package/public/docs/assets/contributor-guide_architecture_worker-protocol.md.BaS_L10g.js +6 -0
  52. package/public/docs/assets/contributor-guide_architecture_worker-protocol.md.BaS_L10g.lean.js +1 -0
  53. package/public/docs/assets/contributor-guide_contributing.md.C-lKs70I.js +1 -0
  54. package/public/docs/assets/contributor-guide_contributing.md.C-lKs70I.lean.js +1 -0
  55. package/public/docs/assets/contributor-guide_development-setup.md.CpUMVtIK.js +12 -0
  56. package/public/docs/assets/contributor-guide_development-setup.md.CpUMVtIK.lean.js +1 -0
  57. package/public/docs/assets/contributor-guide_testing.md.C0q-BJfl.js +1 -0
  58. package/public/docs/assets/contributor-guide_testing.md.C0q-BJfl.lean.js +1 -0
  59. package/public/docs/assets/index.md.CETnDZzR.js +1 -0
  60. package/public/docs/assets/index.md.CETnDZzR.lean.js +1 -0
  61. package/public/docs/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
  62. package/public/docs/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
  63. package/public/docs/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
  64. package/public/docs/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
  65. package/public/docs/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
  66. package/public/docs/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
  67. package/public/docs/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
  68. package/public/docs/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
  69. package/public/docs/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
  70. package/public/docs/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
  71. package/public/docs/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
  72. package/public/docs/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
  73. package/public/docs/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
  74. package/public/docs/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
  75. package/public/docs/assets/style.D2mY0HUs.css +1 -0
  76. package/public/docs/assets/user-guide_getting-started.md.BJdD7a7_.js +3 -0
  77. package/public/docs/assets/user-guide_getting-started.md.BJdD7a7_.lean.js +1 -0
  78. package/public/docs/assets/user-guide_mcp-tools.md.DwYI1d6C.js +95 -0
  79. package/public/docs/assets/user-guide_mcp-tools.md.DwYI1d6C.lean.js +1 -0
  80. package/public/docs/assets/user-guide_run-comparison.md.5-oaOfTu.js +1 -0
  81. package/public/docs/assets/user-guide_run-comparison.md.5-oaOfTu.lean.js +1 -0
  82. package/public/docs/assets/user-guide_understanding-findings.md.CK2WZ0Tf.js +1 -0
  83. package/public/docs/assets/user-guide_understanding-findings.md.CK2WZ0Tf.lean.js +1 -0
  84. package/public/docs/contributor-guide/architecture/board-widgets.html +29 -0
  85. package/public/docs/contributor-guide/architecture/detector-contract.html +29 -0
  86. package/public/docs/contributor-guide/architecture/drill-down.html +29 -0
  87. package/public/docs/contributor-guide/architecture/impact-estimation.html +29 -0
  88. package/public/docs/contributor-guide/architecture/index.html +29 -0
  89. package/public/docs/contributor-guide/architecture/overview.html +29 -0
  90. package/public/docs/contributor-guide/architecture/state-and-history.html +29 -0
  91. package/public/docs/contributor-guide/architecture/widget-rendering.html +29 -0
  92. package/public/docs/contributor-guide/architecture/worker-protocol.html +34 -0
  93. package/public/docs/contributor-guide/contributing.html +29 -0
  94. package/public/docs/contributor-guide/development-setup.html +40 -0
  95. package/public/docs/contributor-guide/testing.html +29 -0
  96. package/public/docs/favicon.svg +4 -0
  97. package/public/docs/hashmap.json +1 -0
  98. package/public/docs/index.html +29 -0
  99. package/public/docs/user-guide/getting-started.html +31 -0
  100. package/public/docs/user-guide/mcp-tools.html +123 -0
  101. package/public/docs/user-guide/run-comparison.html +29 -0
  102. package/public/docs/user-guide/understanding-findings.html +29 -0
  103. package/public/docs/vp-icons.css +0 -0
  104. package/public/favicon.svg +4 -0
  105. package/public/index.html +36 -0
  106. package/public/vendor/spark-doc/anchors.json +205 -0
  107. package/public/vendor/spark-doc/index.html +4202 -0
  108. package/public/vendor/spark-doc/landing.html +418 -0
  109. package/public/vendor/spark-doc/meta.html +970 -0
  110. package/vendor-core/analyzer.js +167 -0
  111. package/vendor-core/assert-never.js +3 -0
  112. package/vendor-core/cli/budgets.js +203 -0
  113. package/vendor-core/cli/collect-run.js +107 -0
  114. package/vendor-core/core-count.js +68 -0
  115. package/vendor-core/core-locality-ratio.js +54 -0
  116. package/vendor-core/core-time-series.js +92 -0
  117. package/vendor-core/core-usage-locality.js +70 -0
  118. package/vendor-core/detectors.js +1989 -0
  119. package/vendor-core/docs-config.js +72 -0
  120. package/vendor-core/docs-site-config.js +23 -0
  121. package/vendor-core/efficiency-model.js +62 -0
  122. package/vendor-core/etl-phases.js +28 -0
  123. package/vendor-core/event-handlers.js +906 -0
  124. package/vendor-core/event-schemas.js +405 -0
  125. package/vendor-core/evidence-availability.js +121 -0
  126. package/vendor-core/evidence-report.js +459 -0
  127. package/vendor-core/finding-action-label.js +97 -0
  128. package/vendor-core/finding-filter-predicate.js +38 -0
  129. package/vendor-core/format-utils.js +167 -0
  130. package/vendor-core/impact-band.js +50 -0
  131. package/vendor-core/impact-estimator.js +428 -0
  132. package/vendor-core/ingest.js +139 -0
  133. package/vendor-core/job-groups.js +30 -0
  134. package/vendor-core/load-vendored.js +24 -0
  135. package/vendor-core/lz4-block.js +135 -0
  136. package/vendor-core/mcp-error.js +3 -0
  137. package/vendor-core/mcp-server-factory.js +115 -0
  138. package/vendor-core/mcp-tools.js +331 -0
  139. package/vendor-core/model-assembler.js +76 -0
  140. package/vendor-core/occupancy.js +202 -0
  141. package/vendor-core/parser-worker.js +249 -0
  142. package/vendor-core/plan-dot.js +25 -0
  143. package/vendor-core/plan-duration-attribution.js +185 -0
  144. package/vendor-core/plan-graph-model.js +171 -0
  145. package/vendor-core/plan-node-detail.js +159 -0
  146. package/vendor-core/plan-summary.js +233 -0
  147. package/vendor-core/plan-tree-walk.js +29 -0
  148. package/vendor-core/proxy.js +157 -0
  149. package/vendor-core/recommendation-rollup.js +197 -0
  150. package/vendor-core/redact.js +175 -0
  151. package/vendor-core/rolling-log-reassembly.js +52 -0
  152. package/vendor-core/run-aggregates.js +44 -0
  153. package/vendor-core/run-comparison.js +458 -0
  154. package/vendor-core/scaling-sim.js +73 -0
  155. package/vendor-core/session-snapshot.js +79 -0
  156. package/vendor-core/shs-fetch.js +196 -0
  157. package/vendor-core/shs-load.js +121 -0
  158. package/vendor-core/shs-request.js +101 -0
  159. package/vendor-core/shs-schemas.js +13 -0
  160. package/vendor-core/snappy-block.js +140 -0
  161. package/vendor-core/stage-quantiles.js +199 -0
  162. package/vendor-core/threshold-summary.js +35 -0
  163. package/vendor-core/types.js +286 -0
  164. package/vendor-core/vendor/fflate.js +2695 -0
  165. package/vendor-core/vendor/fzstd.js +768 -0
  166. package/vendor-core/wall-clock.js +36 -0
  167. package/vendor-core/wasted-core-hours.js +68 -0
@@ -0,0 +1,92 @@
1
+ // Sweep-line "busy cores over time" computation. Pure and side-effect-free so
2
+ // it can run inside parser-worker.js (over retained task launch/finish
3
+ // timestamps) or on the main thread (scaling simulator). One core per task:
4
+ // Spark's default task-to-core mapping.
5
+ //
6
+ // `hypotheticalCores` clamps the concurrent busy-core count to N (the
7
+ // deterministic "utilization at N cores" curve). It does NOT re-schedule tasks;
8
+ // makespan re-estimation is the scaling simulator's job, layered on this signal.
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+ function buildStepFunction(intervals , hypotheticalCores ) {
22
+ // Emit +1 at launch, -1 at finish. Skip empty/negative intervals.
23
+ const events = [];
24
+ for (const { launch, finish } of intervals) {
25
+ if (!(finish > launch)) continue;
26
+ events.push({ t: launch, delta: 1 });
27
+ events.push({ t: finish, delta: -1 });
28
+ }
29
+ // Sort by time; at equal time process -1 before +1 so [launch, finish) is
30
+ // half-open (a task finishing exactly as another launches does not overlap).
31
+ events.sort((a, b) => (a.t - b.t) || (a.delta - b.delta));
32
+
33
+ // Walk consecutive timestamps, emitting the busy level held on each interval.
34
+ const segments = [];
35
+ let busy = 0;
36
+ for (let i = 0; i < events.length; i++) {
37
+ const cur = events[i];
38
+ busy += cur.delta;
39
+ const next = events[i + 1];
40
+ if (!next || next.t === cur.t) continue;
41
+ const effective = hypotheticalCores != null ? Math.min(busy, hypotheticalCores) : busy;
42
+ segments.push({ tStart: cur.t, tEnd: next.t, busy: effective });
43
+ }
44
+ return segments;
45
+ }
46
+
47
+ export function computeCoreTimeSeries(intervals , {
48
+ bucketBy = 'time',
49
+ bucketWidthMs = 1000,
50
+ hypotheticalCores = null,
51
+ }
52
+
53
+
54
+
55
+ = {})
56
+
57
+
58
+
59
+
60
+
61
+ {
62
+ const segments = buildStepFunction(intervals, hypotheticalCores);
63
+
64
+ if (bucketBy === 'coreCount') {
65
+ const histogram = [];
66
+ for (const seg of segments) {
67
+ histogram[seg.busy] = (histogram[seg.busy] ?? 0) + (seg.tEnd - seg.tStart);
68
+ }
69
+ // Fill sparse holes with 0 so the array reads as a dense histogram.
70
+ for (let k = 0; k < histogram.length; k++) if (histogram[k] === undefined) histogram[k] = 0;
71
+ return { mode: 'coreCount', histogram };
72
+ }
73
+
74
+ // bucketBy === 'time'
75
+ if (segments.length === 0) {
76
+ return { mode: 'time', bucketWidthMs, startTime: null, endTime: null, buckets: [] };
77
+ }
78
+ const startTime = segments[0].tStart;
79
+ const endTime = segments[segments.length - 1].tEnd;
80
+ const buckets = [];
81
+ for (let tStart = startTime; tStart < endTime; tStart += bucketWidthMs) {
82
+ const tEnd = tStart + bucketWidthMs;
83
+ let busyCoreMs = 0;
84
+ for (const seg of segments) {
85
+ const lo = Math.max(seg.tStart, tStart);
86
+ const hi = Math.min(seg.tEnd, tEnd);
87
+ if (hi > lo) busyCoreMs += seg.busy * (hi - lo);
88
+ }
89
+ buckets.push({ tStart, tEnd, busyCoreMs, avgBusyCores: busyCoreMs / bucketWidthMs });
90
+ }
91
+ return { mode: 'time', bucketWidthMs, startTime, endTime, buckets };
92
+ }
@@ -0,0 +1,70 @@
1
+ // Stage-granular approximation of core-usage-by-locality over time. See the
2
+ // plan's Task 6 DEVIATION note: per-task locality is not retained, so this
3
+ // distributes each stage's executorRunTime across its wall-clock window,
4
+ // split by localityStats proportions. Not exact; approximate by construction.
5
+ export const LOCALITY_TIERS = ['PROCESS_LOCAL', 'NODE_LOCAL', 'RACK_LOCAL', 'NO_PREF', 'ANY'];
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+ export function computeLocalityAreaSeries(
25
+ stages ,
26
+ { bucketWidthMs = 60_000, tiers = LOCALITY_TIERS } = {},
27
+ ) {
28
+ const valid = stages.filter(s => (s.completedAt ?? 0) > (s.submittedAt ?? 0) && (s.executorRunTime ?? 0) > 0);
29
+ if (valid.length === 0) return { labels: [], series: {} };
30
+ const startTime = valid.reduce((m, s) => Math.min(m, s.submittedAt ?? m), Infinity);
31
+ const endTime = valid.reduce((m, s) => Math.max(m, s.completedAt ?? m), -Infinity);
32
+ const nBuckets = Math.max(1, Math.ceil((endTime - startTime) / bucketWidthMs));
33
+
34
+ const series = {};
35
+ for (const tier of tiers) series[tier] = new Array(nBuckets).fill(0);
36
+ const other = new Array(nBuckets).fill(0); // localities not in the fixed tier list
37
+
38
+ for (const s of valid) {
39
+ const completedAt = s.completedAt ?? 0;
40
+ const submittedAt = s.submittedAt ?? 0;
41
+ const wall = completedAt - submittedAt;
42
+ const avgCores = (s.executorRunTime ?? 0) / wall; // core-time / wall-time = avg concurrent cores
43
+ const total = (s.localityStats ?? []).reduce((a, l) => a + l.count, 0) || 1;
44
+ const props = new Map((s.localityStats ?? []).map(l => [l.locality, l.count / total]));
45
+ // spread avgCores over the buckets this stage overlaps, weighted by overlap fraction
46
+ for (let b = 0; b < nBuckets; b++) {
47
+ const bStart = startTime + b * bucketWidthMs;
48
+ const bEnd = bStart + bucketWidthMs;
49
+ const overlap = Math.min(completedAt, bEnd) - Math.max(submittedAt, bStart);
50
+ if (overlap <= 0) continue;
51
+ const frac = overlap / bucketWidthMs; // portion of the bucket this stage covers
52
+ for (const [loc, p] of props) {
53
+ const add = avgCores * p * frac;
54
+ if (series[loc]) series[loc][b] += add;
55
+ else other[b] += add;
56
+ }
57
+ }
58
+ }
59
+ if (other.some(v => v > 0)) series.OTHER = other;
60
+
61
+ // idle = peak total busy across buckets, minus each bucket's total busy.
62
+ const totals = new Array(nBuckets).fill(0);
63
+ for (const tier of Object.keys(series)) for (let b = 0; b < nBuckets; b++) totals[b] += series[tier][b];
64
+ const peak = totals.reduce((m, v) => Math.max(m, v), 0);
65
+ series.idle = totals.map(v => Math.max(0, peak - v));
66
+
67
+ const labels = [];
68
+ for (let b = 0; b < nBuckets; b++) labels.push(startTime + b * bucketWidthMs);
69
+ return { labels, series };
70
+ }