@64mb/freelens-power 1.0.3 → 1.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 (47) hide show
  1. package/README.md +5 -1
  2. package/out/main/common/monitoring-history.js +52 -0
  3. package/out/main/common/monitoring-history.js.map +1 -0
  4. package/out/main/common/store/monitoring-preferences-store.js +25 -2
  5. package/out/main/common/store/monitoring-preferences-store.js.map +1 -1
  6. package/out/main/dashboard-views.js +132 -28
  7. package/out/main/dashboard-views.js.map +1 -1
  8. package/out/main/index.js +2 -0
  9. package/out/main/index.js.map +1 -1
  10. package/out/main/monitoring-history-database.js +103 -0
  11. package/out/main/monitoring-history-database.js.map +1 -0
  12. package/out/main/monitoring-history-worker.js +61 -0
  13. package/out/main/monitoring-history-worker.js.map +1 -0
  14. package/out/main/monitoring-history.js +100 -0
  15. package/out/main/monitoring-history.js.map +1 -0
  16. package/out/renderer/_virtual/_global-external_mobx.js +2 -1
  17. package/out/renderer/diagnostics.js +647 -0
  18. package/out/renderer/diagnostics.js.map +1 -0
  19. package/out/renderer/index.js +28 -1
  20. package/out/renderer/index.js.map +1 -1
  21. package/out/renderer/monitoring-collector.js +202 -0
  22. package/out/renderer/monitoring-collector.js.map +1 -0
  23. package/out/renderer/monitoring-history-collection.js +184 -0
  24. package/out/renderer/monitoring-history-collection.js.map +1 -0
  25. package/out/renderer/monitoring-history-view.js +150 -0
  26. package/out/renderer/monitoring-history-view.js.map +1 -0
  27. package/out/renderer/monitoring-history.js +19 -0
  28. package/out/renderer/monitoring-history.js.map +1 -0
  29. package/out/renderer/monitoring.js +98 -125
  30. package/out/renderer/monitoring.js.map +1 -1
  31. package/out/renderer/node-monitoring.js +116 -0
  32. package/out/renderer/node-monitoring.js.map +1 -0
  33. package/out/renderer/pod-monitoring.js +39 -8
  34. package/out/renderer/pod-monitoring.js.map +1 -1
  35. package/out/renderer/preferences/monitoring-preferences.js +55 -10
  36. package/out/renderer/preferences/monitoring-preferences.js.map +1 -1
  37. package/out/renderer/src/common/monitoring-history.js +15 -0
  38. package/out/renderer/src/common/monitoring-history.js.map +1 -0
  39. package/out/renderer/src/common/monitoring-math.js +98 -0
  40. package/out/renderer/src/common/monitoring-math.js.map +1 -0
  41. package/out/renderer/src/common/resource-diagnostics.js +227 -0
  42. package/out/renderer/src/common/resource-diagnostics.js.map +1 -0
  43. package/out/renderer/src/common/store/monitoring-preferences-store.js +25 -2
  44. package/out/renderer/src/common/store/monitoring-preferences-store.js.map +1 -1
  45. package/out/renderer/welcome.js +3 -1
  46. package/out/renderer/welcome.js.map +1 -1
  47. package/package.json +1 -1
@@ -4,96 +4,10 @@ const require_monitoring_preferences_store = require("./src/common/store/monitor
4
4
  const require__global_external_react = require("./_virtual/_global-external_react.js");
5
5
  const require__global_external_react_dom = require("./_virtual/_global-external_react-dom.js");
6
6
  const require_jsx_runtime = require("./_virtual/_global-external_react/jsx-runtime.js");
7
+ const require_monitoring_math = require("./src/common/monitoring-math.js");
8
+ const require_monitoring_collector = require("./monitoring-collector.js");
9
+ const require_monitoring_history_view = require("./monitoring-history-view.js");
7
10
  //#region src/renderer/monitoring.tsx
8
- function effectivePodResource(pod, metric, kind) {
9
- const read = (resources) => {
10
- const raw = resources?.[kind]?.[metric];
11
- if (raw !== void 0) return parseQuantity(raw, metric === "memory");
12
- if (kind === "requests" && resources?.limits?.[metric] !== void 0) return parseQuantity(resources.limits[metric], metric === "memory");
13
- return kind === "requests" ? 0 : Infinity;
14
- };
15
- const spec = pod.spec;
16
- if (!spec?.containers?.length) throw new Error("Missing pod containers");
17
- let sidecars = 0;
18
- let initPeak = 0;
19
- for (const container of spec.initContainers ?? []) {
20
- const value = read(container.resources);
21
- if (container.restartPolicy === "Always") {
22
- sidecars += value;
23
- initPeak = Math.max(initPeak, sidecars);
24
- } else initPeak = Math.max(initPeak, sidecars + value);
25
- }
26
- let effective = Math.max(initPeak, sidecars + spec.containers.reduce((sum, container) => sum + read(container.resources), 0));
27
- if (spec.resources?.[kind]?.[metric] !== void 0) effective = read(spec.resources);
28
- const overhead = spec.overhead?.[metric];
29
- if (overhead !== void 0 && (kind === "requests" || effective > 0)) effective += parseQuantity(overhead, metric === "memory");
30
- return effective;
31
- }
32
- function aggregateResources(nodes, pods) {
33
- if (!nodes.length || nodes.some((node) => !node.metadata?.name)) throw new Error("Missing node inventory");
34
- const names = new Set(nodes.map((node) => node.metadata.name));
35
- const scheduled = pods?.filter((pod) => pod.spec?.nodeName && names.has(pod.spec.nodeName) && pod.status?.phase !== "Succeeded" && pod.status?.phase !== "Failed");
36
- const sum = (metric) => {
37
- const capacity = nodes.reduce((total, node) => total + parseQuantity(node.status?.capacity?.[metric] ?? "", metric === "memory"), 0);
38
- const allocatable = nodes.reduce((total, node) => total + parseQuantity(node.status?.allocatable?.[metric] ?? "", metric === "memory"), 0);
39
- const requests = scheduled?.reduce((total, pod) => total + effectivePodResource(pod, metric, "requests"), 0);
40
- const limits = scheduled?.reduce((total, pod) => total + effectivePodResource(pod, metric, "limits"), 0);
41
- return {
42
- capacity,
43
- allocatable,
44
- requests,
45
- limits: limits === Infinity ? void 0 : limits,
46
- unbounded: limits === Infinity
47
- };
48
- };
49
- return {
50
- cpu: sum("cpu"),
51
- memory: sum("memory")
52
- };
53
- }
54
- var INTERVAL = 3e4;
55
- function parseQuantity(raw, memory = false) {
56
- const match = /^(\d+(?:\.\d*)?|\.\d+)([eE][+-]?\d+|n|u|m|Ki|Mi|Gi|Ti|Pi|Ei|k|K|M|G|T|P|E)?$/.exec(raw);
57
- if (!match) throw new Error("Invalid metrics quantity");
58
- const suffix = match[2] ?? "";
59
- const value = Number(match[1]) * (suffix.endsWith("i") ? 1024 ** ([
60
- "Ki",
61
- "Mi",
62
- "Gi",
63
- "Ti",
64
- "Pi",
65
- "Ei"
66
- ].indexOf(suffix) + 1) : /^[eE][+-]?\d+$/.test(suffix) ? 10 ** Number(suffix.slice(1)) : {
67
- n: 1e-9,
68
- u: 1e-6,
69
- m: .001,
70
- k: 1e3,
71
- K: 1e3,
72
- M: 1e6,
73
- G: 1e9,
74
- T: 0xe8d4a51000,
75
- P: 0x38d7ea4c68000,
76
- E: 0xde0b6b3a7640000
77
- }[suffix] ?? 1);
78
- if (!Number.isFinite(value) || !memory && suffix.endsWith("i")) throw new Error("Invalid metrics quantity");
79
- return value;
80
- }
81
- function aggregateMetrics(nodes, now = Date.now()) {
82
- if (!nodes.length) throw new Error("No node metrics available");
83
- let cpu = 0;
84
- let memory = 0;
85
- for (const node of nodes) {
86
- const timestamp = Date.parse(node.timestamp);
87
- if (!Number.isFinite(timestamp) || now - timestamp > 12e4 || timestamp > now + 3e4) throw new Error("Node metrics are stale");
88
- cpu += parseQuantity(node.usage.cpu);
89
- memory += parseQuantity(node.usage.memory, true);
90
- }
91
- return {
92
- time: now,
93
- cpu,
94
- memory
95
- };
96
- }
97
11
  function formatMonitoringTime(time) {
98
12
  return new Date(time).toLocaleTimeString([], {
99
13
  hour: "2-digit",
@@ -198,10 +112,10 @@ function MetricChart({ metric, samples, status, scope = "node" }) {
198
112
  value: (sample) => sample.resources?.[metric][key]
199
113
  }))];
200
114
  const visibleSeries = scope === "pod" ? series.filter((line) => line.key === "usage" || line.key === "requests") : series;
201
- const max = Math.max(...samples.flatMap((sample) => visibleSeries.map((line) => line.value(sample) ?? 0)), .001) * 1.1;
115
+ const max = Math.max(...samples.flatMap((sample) => [...visibleSeries.map((line) => line.value(sample) ?? 0), sample.historical?.[metric]?.max ?? 0]), .001) * 1.1;
202
116
  const end = last?.time ?? Date.now();
203
117
  const start = samples[0]?.time ?? end;
204
- const duration = Math.max(end - start, INTERVAL);
118
+ const duration = Math.max(end - start, require_monitoring_math.MONITORING_INTERVAL);
205
119
  const x = (sample) => 88 + (sample.time - start) / duration * plotWidth;
206
120
  const y = (sample) => 208 - sample[metric] / max * 184;
207
121
  const selectNearest = (event) => {
@@ -298,12 +212,26 @@ function MetricChart({ metric, samples, status, scope = "node" }) {
298
212
  fontSize: "11",
299
213
  children: format(max * fraction)
300
214
  })] }, fraction)),
215
+ samples.map((sample) => {
216
+ const summary = sample.historical?.[metric];
217
+ if (!summary || summary.min === summary.max) return null;
218
+ return /* @__PURE__ */ require_jsx_runtime.jsx("line", {
219
+ "data-monitoring-extrema": "",
220
+ x1: x(sample),
221
+ x2: x(sample),
222
+ y1: 208 - summary.max / max * 184,
223
+ y2: 208 - summary.min / max * 184,
224
+ stroke: "#c93dce",
225
+ strokeOpacity: .35,
226
+ strokeWidth: 4
227
+ }, `range:${sample.time}`);
228
+ }),
301
229
  visibleSeries.map((line) => /* @__PURE__ */ require_jsx_runtime.jsx("path", {
302
230
  "data-monitoring-series": line.key,
303
231
  d: samples.reduce((path, sample, index) => {
304
232
  const value = line.value(sample);
305
233
  if (value === void 0) return path;
306
- return `${path} ${(index ? line.value(samples[index - 1]) : void 0) === void 0 ? "M" : "L"}${x(sample)},${208 - value / max * 184}`;
234
+ return `${path} ${(index ? line.value(samples[index - 1]) : void 0) === void 0 || sample.breakBefore || sample.time - samples[index - 1].time > 1.8 * Math.max(sample.historical?.[metric]?.resolution ?? 3e4, samples[index - 1].historical?.[metric]?.resolution ?? 3e4) ? "M" : "L"}${x(sample)},${208 - value / max * 184}`;
307
235
  }, ""),
308
236
  fill: "none",
309
237
  stroke: line.color,
@@ -371,6 +299,18 @@ function MetricChart({ metric, samples, status, scope = "node" }) {
371
299
  line.value(selected) === void 0 ? "Unavailable" : format(line.value(selected))
372
300
  ]
373
301
  }, line.key)),
302
+ selected.historical?.[metric] && /* @__PURE__ */ require_jsx_runtime.jsxs("div", { children: [
303
+ "Min: ",
304
+ format(selected.historical[metric].min),
305
+ " · Max: ",
306
+ format(selected.historical[metric].max),
307
+ /* @__PURE__ */ require_jsx_runtime.jsx("br", {}),
308
+ selected.historical[metric].count,
309
+ " samples ·",
310
+ " ",
311
+ Math.round(selected.historical[metric].resolution / 1e3),
312
+ "s bucket"
313
+ ] }),
374
314
  /* @__PURE__ */ require_jsx_runtime.jsx("div", {
375
315
  style: {
376
316
  color: "var(--textColorSecondary)",
@@ -617,9 +557,16 @@ function ResourceDonut({ metric, sample, status }) {
617
557
  });
618
558
  }
619
559
  function MonitoringCharts({ samples, status }) {
560
+ const clusterId = require_extensions.Renderer.Catalog.activeCluster.get()?.metadata.uid;
561
+ const history = require_monitoring_history_view.useMonitoringHistory(clusterId ? {
562
+ clusterId,
563
+ scope: "cluster",
564
+ uid: clusterId
565
+ } : void 0, samples);
620
566
  return /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
621
567
  style: { containerType: "inline-size" },
622
- children: [/* @__PURE__ */ require_jsx_runtime.jsx("style", { children: `
568
+ children: [
569
+ /* @__PURE__ */ require_jsx_runtime.jsx("style", { children: `
623
570
  [data-monitoring-layout] { display:grid; grid-template-columns:minmax(0,1.6fr) minmax(0,1.6fr) minmax(0,1fr) minmax(0,1fr); gap:16px; align-items:stretch }
624
571
  [data-monitoring-trends], [data-monitoring-summaries] { display:contents }
625
572
  @container (min-width: 961px) {
@@ -633,27 +580,45 @@ function MonitoringCharts({ samples, status }) {
633
580
  [data-monitoring-layout] { grid-template-columns:minmax(0,1fr) }
634
581
  .power-ai-overview-actions + [data-testid="cluster-overview-page"] [data-monitoring-trends] > section:not(:first-child) { --power-monitoring-trend-top:16px }
635
582
  }
636
- ` }), /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
637
- "data-monitoring-layout": "",
638
- children: [/* @__PURE__ */ require_jsx_runtime.jsx("div", {
639
- "data-monitoring-trends": "",
640
- children: ["cpu", "memory"].map((metric) => /* @__PURE__ */ require_jsx_runtime.jsx(MetricChart, {
641
- metric,
642
- samples,
643
- status
644
- }, metric))
645
- }), /* @__PURE__ */ require_jsx_runtime.jsx("div", {
646
- "data-monitoring-summaries": "",
647
- children: ["cpu", "memory"].map((metric) => /* @__PURE__ */ require_jsx_runtime.jsx(ResourceDonut, {
648
- metric,
649
- sample: samples.at(-1),
650
- status
651
- }, metric))
652
- })]
653
- })]
583
+ ` }),
584
+ /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
585
+ style: {
586
+ display: "flex",
587
+ alignItems: "center",
588
+ gap: 12,
589
+ marginBottom: 8
590
+ },
591
+ children: [/* @__PURE__ */ require_jsx_runtime.jsx(require_monitoring_history_view.MonitoringHistoryRange, {
592
+ range: history.range,
593
+ onChange: history.setRange
594
+ }), /* @__PURE__ */ require_jsx_runtime.jsx("small", {
595
+ role: "status",
596
+ children: history.status
597
+ })]
598
+ }),
599
+ /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
600
+ "data-monitoring-layout": "",
601
+ children: [/* @__PURE__ */ require_jsx_runtime.jsx("div", {
602
+ "data-monitoring-trends": "",
603
+ children: ["cpu", "memory"].map((metric) => /* @__PURE__ */ require_jsx_runtime.jsx(MetricChart, {
604
+ metric,
605
+ samples: history.samples,
606
+ status
607
+ }, metric))
608
+ }), /* @__PURE__ */ require_jsx_runtime.jsx("div", {
609
+ "data-monitoring-summaries": "",
610
+ children: ["cpu", "memory"].map((metric) => /* @__PURE__ */ require_jsx_runtime.jsx(ResourceDonut, {
611
+ metric,
612
+ sample: samples.at(-1),
613
+ status
614
+ }, metric))
615
+ })]
616
+ })
617
+ ]
654
618
  });
655
619
  }
656
620
  function startMonitoring() {
621
+ const release = require_monitoring_collector.retainMonitoringCollector();
657
622
  const preferences = require_monitoring_preferences_store.MonitoringPreferencesStore.getInstanceOrCreate();
658
623
  let stopCurrent;
659
624
  const stop = require__global_external_mobx.reaction(() => preferences.enabled, (enabled) => {
@@ -663,6 +628,7 @@ function startMonitoring() {
663
628
  return () => {
664
629
  stop();
665
630
  stopCurrent?.();
631
+ release();
666
632
  };
667
633
  }
668
634
  function mountMonitoring() {
@@ -713,7 +679,7 @@ function mountMonitoring() {
713
679
  cluster = currentCluster;
714
680
  overview = currentOverview;
715
681
  }
716
- const cutoff = Date.now() - 60 * INTERVAL;
682
+ const cutoff = Date.now() - 60 * require_monitoring_math.MONITORING_INTERVAL;
717
683
  if (samples.length && samples[0].time < cutoff) samples = samples.filter((sample) => sample.time >= cutoff);
718
684
  if (!overview || !cluster || document.visibilityState === "hidden") return;
719
685
  if (!host) {
@@ -761,21 +727,30 @@ function mountMonitoring() {
761
727
  render();
762
728
  if (pendingGeneration === generation || Date.now() < nextSample) return;
763
729
  pendingGeneration = generation;
764
- nextSample = Date.now() + INTERVAL;
730
+ nextSample = Date.now() + require_monitoring_math.MONITORING_INTERVAL;
765
731
  const requestGeneration = generation;
766
732
  const isCurrent = () => !stopped && requestGeneration === generation && document.visibilityState !== "hidden" && overview?.isConnected === true && require_extensions.Renderer.Catalog.activeCluster.get()?.metadata.uid === cluster;
767
733
  try {
768
- const [metrics, inventory, pods] = await Promise.allSettled([
769
- require_extensions.Renderer.K8sApi.nodesMetricsApi.list(),
770
- Promise.resolve().then(() => require_extensions.Renderer.K8sApi.nodesApi.list()),
771
- Promise.resolve().then(() => require_extensions.Renderer.K8sApi.podsApi.list())
772
- ]);
734
+ const collected = await require_monitoring_collector.getMonitoringSnapshot();
735
+ const metrics = collected.nodeMetrics === void 0 ? { status: "rejected" } : {
736
+ status: "fulfilled",
737
+ value: collected.nodeMetrics
738
+ };
739
+ const inventory = collected.nodes === void 0 ? { status: "rejected" } : {
740
+ status: "fulfilled",
741
+ value: collected.nodes
742
+ };
743
+ const pods = collected.pods === void 0 ? { status: "rejected" } : {
744
+ status: "fulfilled",
745
+ value: collected.pods
746
+ };
773
747
  if (!isCurrent()) return;
774
748
  if (metrics.status !== "fulfilled") throw new Error("Metrics unavailable");
775
- const sample = aggregateMetrics(metrics.value ?? []);
749
+ const sample = require_monitoring_math.aggregateMetrics(metrics.value ?? []);
750
+ sample.time = Math.min(...metrics.value.map((item) => Date.parse(item.timestamp)));
776
751
  const warnings = [];
777
752
  if (inventory.status === "fulfilled") try {
778
- sample.resources = aggregateResources(inventory.value ?? [], pods.status === "fulfilled" ? pods.value ?? void 0 : void 0);
753
+ sample.resources = require_monitoring_math.aggregateResources(inventory.value ?? [], pods.status === "fulfilled" ? pods.value ?? void 0 : void 0);
779
754
  const expected = new Set((inventory.value ?? []).map((node) => node.metadata.name));
780
755
  const observed = new Set((metrics.value ?? []).map((node) => node.metadata.name));
781
756
  sample.completeUsage = expected.size > 0 && expected.size === observed.size && [...expected].every((name) => observed.has(name));
@@ -786,7 +761,7 @@ function mountMonitoring() {
786
761
  else warnings.push("Node inventory unavailable or access denied; usage coverage unverified, capacity unavailable");
787
762
  if (pods.status !== "fulfilled") warnings.push("Cluster-wide Pods unavailable or access denied; requests unavailable");
788
763
  sample.resourceStatus = warnings.join(". ");
789
- samples = [...samples, sample].slice(-60);
764
+ samples = [...samples.filter((entry) => entry.time !== sample.time), sample].sort((a, b) => a.time - b.time).slice(-60);
790
765
  status = "";
791
766
  } catch {
792
767
  if (!isCurrent()) return;
@@ -819,11 +794,9 @@ function mountMonitoring() {
819
794
  }
820
795
  //#endregion
821
796
  exports.MetricChart = MetricChart;
822
- exports.aggregateMetrics = aggregateMetrics;
823
- exports.aggregateResources = aggregateResources;
824
- exports.effectivePodResource = effectivePodResource;
797
+ exports.effectivePodResource = require_monitoring_math.effectivePodResource;
825
798
  exports.formatMonitoringTime = formatMonitoringTime;
826
- exports.parseQuantity = parseQuantity;
799
+ exports.parseQuantity = require_monitoring_math.parseQuantity;
827
800
  exports.startMonitoring = startMonitoring;
828
801
 
829
802
  //# sourceMappingURL=monitoring.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"monitoring.js","names":[],"sources":["../../src/renderer/monitoring.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { reaction } from \"mobx\";\nimport { type CSSProperties, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { MonitoringPreferencesStore } from \"../common/store/monitoring-preferences-store\";\n\ntype ResourceValues = { requests?: Partial<Record<string, string>>; limits?: Partial<Record<string, string>> };\ntype ResourceContainer = { resources?: ResourceValues; restartPolicy?: string };\nexport type MonitoringPod = {\n spec?: {\n nodeName?: string;\n containers?: ResourceContainer[];\n initContainers?: ResourceContainer[];\n overhead?: Partial<Record<string, string>>;\n resources?: ResourceValues;\n };\n status?: { phase?: string };\n};\nexport type MonitoringNode = {\n metadata: { name: string };\n status?: { capacity?: Partial<Record<string, string>>; allocatable?: Partial<Record<string, string>> };\n};\ntype ResourceTotals = {\n capacity?: number;\n allocatable?: number;\n requests?: number;\n limits?: number;\n unbounded?: boolean;\n};\nexport type MonitoringSample = {\n time: number;\n cpu: number;\n memory: number;\n resources?: Record<\"cpu\" | \"memory\", ResourceTotals>;\n resourceStatus?: string;\n completeUsage?: boolean;\n};\n\nexport function effectivePodResource(\n pod: MonitoringPod,\n metric: \"cpu\" | \"memory\",\n kind: \"requests\" | \"limits\",\n): number {\n const read = (resources?: ResourceValues) => {\n const raw = resources?.[kind]?.[metric];\n if (raw !== undefined) return parseQuantity(raw, metric === \"memory\");\n if (kind === \"requests\" && resources?.limits?.[metric] !== undefined)\n return parseQuantity(resources.limits[metric], metric === \"memory\");\n return kind === \"requests\" ? 0 : Infinity;\n };\n const spec = pod.spec;\n if (!spec?.containers?.length) throw new Error(\"Missing pod containers\");\n let sidecars = 0;\n let initPeak = 0;\n for (const container of spec.initContainers ?? []) {\n const value = read(container.resources);\n if (container.restartPolicy === \"Always\") {\n sidecars += value;\n initPeak = Math.max(initPeak, sidecars);\n } else initPeak = Math.max(initPeak, sidecars + value);\n }\n let effective = Math.max(\n initPeak,\n sidecars + spec.containers.reduce((sum, container) => sum + read(container.resources), 0),\n );\n if (spec.resources?.[kind]?.[metric] !== undefined) effective = read(spec.resources);\n const overhead = spec.overhead?.[metric];\n if (overhead !== undefined && (kind === \"requests\" || effective > 0))\n effective += parseQuantity(overhead, metric === \"memory\");\n return effective;\n}\n\nexport function aggregateResources(\n nodes: MonitoringNode[],\n pods?: MonitoringPod[],\n): Record<\"cpu\" | \"memory\", ResourceTotals> {\n if (!nodes.length || nodes.some((node) => !node.metadata?.name)) throw new Error(\"Missing node inventory\");\n const names = new Set(nodes.map((node) => node.metadata.name));\n const scheduled = pods?.filter(\n (pod) =>\n pod.spec?.nodeName &&\n names.has(pod.spec.nodeName) &&\n pod.status?.phase !== \"Succeeded\" &&\n pod.status?.phase !== \"Failed\",\n );\n const sum = (metric: \"cpu\" | \"memory\"): ResourceTotals => {\n const capacity = nodes.reduce(\n (total, node) => total + parseQuantity(node.status?.capacity?.[metric] ?? \"\", metric === \"memory\"),\n 0,\n );\n const allocatable = nodes.reduce(\n (total, node) => total + parseQuantity(node.status?.allocatable?.[metric] ?? \"\", metric === \"memory\"),\n 0,\n );\n const requests = scheduled?.reduce((total, pod) => total + effectivePodResource(pod, metric, \"requests\"), 0);\n const limits = scheduled?.reduce((total, pod) => total + effectivePodResource(pod, metric, \"limits\"), 0);\n return {\n capacity,\n allocatable,\n requests,\n limits: limits === Infinity ? undefined : limits,\n unbounded: limits === Infinity,\n };\n };\n return { cpu: sum(\"cpu\"), memory: sum(\"memory\") };\n}\nconst INTERVAL = 30_000;\nexport const MAX_SAMPLES = 60;\n\nexport function parseQuantity(raw: string, memory = false): number {\n const match = /^(\\d+(?:\\.\\d*)?|\\.\\d+)([eE][+-]?\\d+|n|u|m|Ki|Mi|Gi|Ti|Pi|Ei|k|K|M|G|T|P|E)?$/.exec(raw);\n if (!match) throw new Error(\"Invalid metrics quantity\");\n const suffix = match[2] ?? \"\";\n const factors: Record<string, number> = {\n n: 1e-9,\n u: 1e-6,\n m: 1e-3,\n k: 1e3,\n K: 1e3,\n M: 1e6,\n G: 1e9,\n T: 1e12,\n P: 1e15,\n E: 1e18,\n };\n const value =\n Number(match[1]) *\n (suffix.endsWith(\"i\")\n ? 1024 ** ([\"Ki\", \"Mi\", \"Gi\", \"Ti\", \"Pi\", \"Ei\"].indexOf(suffix) + 1)\n : /^[eE][+-]?\\d+$/.test(suffix)\n ? 10 ** Number(suffix.slice(1))\n : (factors[suffix] ?? 1));\n if (!Number.isFinite(value) || (!memory && suffix.endsWith(\"i\"))) throw new Error(\"Invalid metrics quantity\");\n return value;\n}\n\nexport function aggregateMetrics(\n nodes: { usage: { cpu: string; memory: string }; timestamp: string }[],\n now = Date.now(),\n): MonitoringSample {\n if (!nodes.length) throw new Error(\"No node metrics available\");\n let cpu = 0;\n let memory = 0;\n for (const node of nodes) {\n const timestamp = Date.parse(node.timestamp);\n if (!Number.isFinite(timestamp) || now - timestamp > 120_000 || timestamp > now + 30_000)\n throw new Error(\"Node metrics are stale\");\n cpu += parseQuantity(node.usage.cpu);\n memory += parseQuantity(node.usage.memory, true);\n }\n return { time: now, cpu, memory };\n}\n\nexport function formatMonitoringTime(time: number): string {\n return new Date(time).toLocaleTimeString([], {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hourCycle: \"h23\",\n });\n}\n\nfunction ResourceTitle({ metric, label }: { metric: \"cpu\" | \"memory\"; label?: string }) {\n return (\n <strong style={{ display: \"inline-flex\", alignItems: \"center\", gap: 6 }}>\n <span className=\"Icon material\" aria-hidden=\"true\" style={{ \"--size\": \"18px\", fontWeight: 400 } as CSSProperties}>\n <span className=\"icon\">{metric === \"cpu\" ? \"developer_board\" : \"memory\"}</span>\n </span>\n {label ?? (metric === \"cpu\" ? \"CPU\" : \"Memory\")}\n </strong>\n );\n}\n\nexport function MetricChart({\n metric,\n samples,\n status,\n scope = \"node\",\n}: {\n metric: \"cpu\" | \"memory\";\n samples: MonitoringSample[];\n status: string;\n scope?: \"node\" | \"pod\";\n}) {\n const [selectedTime, setSelectedTime] = useState<number>();\n const [pinned, setPinned] = useState(false);\n const previousMetric = useRef(metric);\n useEffect(() => {\n if (\n previousMetric.current !== metric ||\n (selectedTime !== undefined && !samples.some((sample) => sample.time === selectedTime))\n ) {\n setPinned(false);\n setSelectedTime(undefined);\n }\n previousMetric.current = metric;\n }, [metric, samples, selectedTime]);\n useEffect(() => {\n if (!pinned) return;\n const escape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n event.stopPropagation();\n setPinned(false);\n setSelectedTime(undefined);\n }\n };\n document.addEventListener(\"keydown\", escape, true);\n return () => document.removeEventListener(\"keydown\", escape, true);\n }, [pinned]);\n const chartRef = useRef<SVGSVGElement>(null);\n const [width, setWidth] = useState(600);\n useLayoutEffect(() => {\n const chart = chartRef.current;\n if (!chart) return;\n const measure = () => {\n const measured = chart.getBoundingClientRect().width;\n if (measured > 0) setWidth(measured);\n };\n measure();\n const observer = typeof ResizeObserver === \"undefined\" ? undefined : new ResizeObserver(measure);\n observer?.observe(chart);\n window.addEventListener(\"resize\", measure);\n return () => {\n observer?.disconnect();\n window.removeEventListener(\"resize\", measure);\n };\n }, []);\n const plotWidth = Math.max(1, width - 112);\n const last = samples.at(-1);\n const selected = samples.find((sample) => sample.time === selectedTime);\n const label = metric === \"cpu\" ? \"CPU\" : \"Memory\";\n const format = (value: number) =>\n metric === \"cpu\" ? `${value.toFixed(2)} cores` : `${(value / 1024 ** 3).toFixed(2)} GiB`;\n const series = [\n { key: \"usage\", label: \"Usage\", color: \"#c93dce\", value: (sample: MonitoringSample) => sample[metric] },\n ...([\"requests\", \"allocatable\", \"capacity\"] as const).map((key) => ({\n key,\n label: { requests: \"Requests\", allocatable: \"Allocatable Capacity\", capacity: \"Capacity\" }[key],\n color: { requests: \"#4caf50\", allocatable: \"#5486b5\", capacity: \"var(--textColorSecondary)\" }[key],\n value: (sample: MonitoringSample) => sample.resources?.[metric][key],\n })),\n ];\n const visibleSeries =\n scope === \"pod\" ? series.filter((line) => line.key === \"usage\" || line.key === \"requests\") : series;\n const max =\n Math.max(...samples.flatMap((sample) => visibleSeries.map((line) => line.value(sample) ?? 0)), 0.001) * 1.1;\n const end = last?.time ?? Date.now();\n const start = samples[0]?.time ?? end;\n const duration = Math.max(end - start, INTERVAL);\n const x = (sample: MonitoringSample) => 88 + ((sample.time - start) / duration) * plotWidth;\n const y = (sample: MonitoringSample) => 208 - (sample[metric] / max) * 184;\n const selectNearest = (event: React.MouseEvent<SVGSVGElement>) => {\n const bounds = event.currentTarget.getBoundingClientRect();\n if (!bounds.width || !samples.length) return;\n const scale = Math.min(bounds.width / width, (bounds.height || 250) / 250);\n const offset = (bounds.width - width * scale) / 2;\n const position = (event.clientX - bounds.left - offset) / scale;\n const time = start + ((position - 88) / plotWidth) * duration;\n const nearest = samples.reduce((nearest, sample) =>\n Math.abs(sample.time - time) < Math.abs(nearest.time - time) ? sample : nearest,\n ).time;\n setSelectedTime(nearest);\n return nearest;\n };\n return (\n <section\n aria-label={`${label} metrics-server usage`}\n style={{\n padding: \"var(--power-monitoring-trend-top, 16px) 16px 16px\",\n background: \"var(--contentColor)\",\n minWidth: 0,\n minHeight: 280,\n position: \"relative\",\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 12 }}>\n <ResourceTitle metric={metric} />\n <span>{status ? \"Unavailable\" : last ? format(last[metric]) : \"Collecting…\"}</span>\n </div>\n <svg\n ref={chartRef}\n data-monitoring-trend=\"\"\n viewBox={`0 0 ${width} 250`}\n role=\"img\"\n tabIndex={0}\n aria-label={`${label} usage over collected samples. Use arrow keys to inspect samples. Click or press Enter to pin the tooltip, Escape to dismiss`}\n onMouseMove={(event) => {\n if (!pinned) selectNearest(event);\n }}\n onClick={(event) => {\n if (pinned) setPinned(false);\n else if (samples.length) {\n if (selectNearest(event) === undefined && !selected) setSelectedTime(last?.time);\n setPinned(true);\n }\n }}\n onMouseLeave={() => {\n if (!pinned) setSelectedTime(undefined);\n }}\n onFocus={() => {\n if (!pinned) setSelectedTime(last?.time);\n }}\n onBlur={() => {\n if (!pinned) setSelectedTime(undefined);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n if (samples.length) {\n if (!selected) setSelectedTime(last?.time);\n setPinned(!pinned);\n }\n return;\n }\n if (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\") return;\n event.preventDefault();\n const index = samples.findIndex((sample) => sample.time === selectedTime);\n setSelectedTime(\n samples[\n Math.max(\n 0,\n Math.min(\n samples.length - 1,\n (index < 0 ? samples.length - 1 : index) + (event.key === \"ArrowLeft\" ? -1 : 1),\n ),\n )\n ]?.time,\n );\n }}\n style={{ width: \"100%\", height: 250, color: \"#c93dce\", display: \"block\" }}\n >\n <title>Click to pin tooltip · click again or Escape to unpin</title>\n {[0, 0.5, 1].map((fraction) => (\n <g key={fraction}>\n <line\n x1=\"88\"\n x2={width - 24}\n y1={208 - fraction * 184}\n y2={208 - fraction * 184}\n stroke=\"var(--borderFaintColor)\"\n />\n <text x=\"80\" y={212 - fraction * 184} textAnchor=\"end\" fill=\"var(--textColorSecondary)\" fontSize=\"11\">\n {format(max * fraction)}\n </text>\n </g>\n ))}\n {visibleSeries.map((line) => (\n <path\n key={line.key}\n data-monitoring-series={line.key}\n d={samples.reduce((path, sample, index) => {\n const value = line.value(sample);\n if (value === undefined) return path;\n const previous = index ? line.value(samples[index - 1]) : undefined;\n return `${path} ${previous === undefined ? \"M\" : \"L\"}${x(sample)},${208 - (value / max) * 184}`;\n }, \"\")}\n fill=\"none\"\n stroke={line.color}\n strokeWidth=\"2\"\n strokeDasharray={line.key === \"capacity\" || line.key === \"allocatable\" ? \"5 3\" : undefined}\n />\n ))}\n {samples.map((sample) => (\n <circle key={sample.time} cx={x(sample)} cy={y(sample)} r=\"2\" fill=\"currentColor\">\n <title>\n {formatMonitoringTime(sample.time)}: {format(sample[metric])}\n </title>\n </circle>\n ))}\n {samples.length > 0 &&\n [0, 0.5, 1].map((fraction) => (\n <text\n key={fraction}\n x={88 + fraction * plotWidth}\n y=\"235\"\n textAnchor={fraction === 0 ? \"start\" : fraction === 1 ? \"end\" : \"middle\"}\n fill=\"var(--textColorSecondary)\"\n fontSize=\"11\"\n >\n {formatMonitoringTime(start + fraction * duration)}\n </text>\n ))}\n {selected && (\n <line\n data-monitoring-crosshair=\"\"\n x1={x(selected)}\n x2={x(selected)}\n y1=\"24\"\n y2=\"208\"\n stroke=\"var(--textColorSecondary)\"\n strokeDasharray=\"4 3\"\n />\n )}\n </svg>\n <style>{`\n @keyframes freelens-power-metric-tooltip-enter { from { opacity:0; transform:translateY(2px) } to { opacity:1; transform:translateY(0) } }\n [data-monitoring-tooltip] { animation:freelens-power-metric-tooltip-enter 140ms ease-out }\n @media (prefers-reduced-motion:reduce) { [data-monitoring-tooltip] { animation:none } }\n `}</style>\n {selected && (\n <div\n data-monitoring-tooltip=\"\"\n role=\"tooltip\"\n style={{\n position: \"absolute\",\n top: 44,\n right: 24,\n padding: 8,\n background: \"var(--contentColor)\",\n border: \"1px solid var(--borderFaintColor)\",\n pointerEvents: \"none\",\n }}\n >\n <div>\n {formatMonitoringTime(selected.time)}\n {pinned ? \" · Pinned\" : \"\"}\n </div>\n {visibleSeries.map((line) => (\n <div key={line.key} style={{ color: line.color }}>\n {line.label}: {line.value(selected) === undefined ? \"Unavailable\" : format(line.value(selected)!)}\n </div>\n ))}\n <div style={{ color: \"var(--textColorSecondary)\", marginTop: 4, fontSize: 10 }}>\n {pinned ? \"Click chart or Escape to unpin\" : \"Click or Enter to pin\"}\n </div>\n </div>\n )}\n <div\n aria-label={`${label} chart legend`}\n style={{ display: \"flex\", flexWrap: \"wrap\", gap: \"6px 16px\", marginBottom: 8 }}\n >\n {visibleSeries.map((line) => (\n <span key={line.key}>\n <span style={{ color: line.color }}>●</span> {line.label}\n </span>\n ))}\n </div>\n {last?.resourceStatus && (\n <div role=\"status\" style={{ color: \"var(--textColorSecondary)\", marginBottom: 8 }}>\n {last.resourceStatus}\n </div>\n )}\n {(scope === \"node\" || status || !samples.length) && (\n <div\n style={{ fontSize: 11, color: \"var(--textColorSecondary)\", display: \"flex\", alignItems: \"center\", gap: 4 }}\n role=\"status\"\n aria-label={`${scope} metrics status`}\n >\n {scope === \"node\" && (\n <sup aria-hidden=\"true\" style={{ fontSize: 12 }}>\n *\n </sup>\n )}\n <span>{status || (samples.length ? \"metrics-server data\" : \"Waiting for metrics-server data\")}</span>\n </div>\n )}\n </section>\n );\n}\n\nfunction ResourceDonut({\n metric,\n sample,\n status,\n}: {\n metric: \"cpu\" | \"memory\";\n sample?: MonitoringSample;\n status: string;\n}) {\n const [activeRing, setActiveRing] = useState<number>();\n useEffect(() => {\n if (activeRing === undefined) return;\n const dismiss = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") return;\n event.preventDefault();\n event.stopPropagation();\n setActiveRing(undefined);\n };\n document.addEventListener(\"keydown\", dismiss, true);\n return () => document.removeEventListener(\"keydown\", dismiss, true);\n }, [activeRing]);\n const label = metric === \"cpu\" ? \"CPU\" : \"Memory\";\n const totals = sample?.resources?.[metric];\n const format = (value: number) =>\n metric === \"cpu\" ? `${value.toFixed(2)} cores` : `${(value / 1024 ** 3).toFixed(2)} GiB`;\n const available = (value?: number) => (value === undefined ? \"Unavailable\" : format(value));\n const denominator = totals?.allocatable;\n const rings = [\n { label: \"Usage\", color: \"#c93dce\", value: sample?.[metric] },\n { label: \"Requests\", color: \"#4caf50\", value: totals?.requests },\n ];\n const percentage = (value?: number) =>\n value !== undefined && denominator !== undefined && denominator > 0 ? (value / denominator) * 100 : undefined;\n const usagePercent = percentage(sample?.[metric]);\n const unused =\n sample?.completeUsage && denominator !== undefined ? format(denominator - sample[metric]) : \"Unavailable\";\n const unrequested =\n denominator !== undefined && totals?.requests !== undefined ? format(denominator - totals.requests) : \"Unavailable\";\n const allocationDetail = `Allocatable: ${available(denominator)}. Schedulable capacity after system reservations, used as the denominator for both rings. Physical Capacity: ${available(totals?.capacity)}. Unused allocatable (usage): ${unused}. Unrequested: ${unrequested}`;\n const hovered = activeRing === undefined ? undefined : rings[activeRing];\n const tooltipId = `power-monitoring-${metric}-donut-tooltip`;\n return (\n <section\n aria-label={`${label} resource summary`}\n style={{\n padding: \"var(--power-monitoring-summary-top, 16px) 16px 16px\",\n minWidth: 0,\n background: \"var(--contentColor)\",\n position: \"relative\",\n overflow: \"visible\",\n }}\n >\n <ResourceTitle metric={metric} label={metric === \"memory\" ? \"RAM\" : \"CPU\"} />\n <svg\n data-monitoring-donut=\"\"\n viewBox=\"0 0 200 200\"\n role=\"img\"\n aria-label={`${label} usage and requests relative to allocatable capacity`}\n style={{ display: \"block\", width: \"100%\", height: 200 }}\n >\n {rings.map((ring, index) => {\n const radius = 76 - index * 18;\n const percent = percentage(ring.value);\n const detail = `${ring.label}: ${available(ring.value)}${percent === undefined ? \"\" : ` (${percent.toFixed(1)}% of allocatable${percent > 100 ? \", over allocatable\" : \"\"})`}`;\n return (\n <g\n key={ring.label}\n tabIndex={0}\n role=\"img\"\n aria-label={detail}\n aria-describedby={activeRing === index ? tooltipId : undefined}\n onMouseEnter={() => setActiveRing(index)}\n onMouseMove={() => setActiveRing(index)}\n onMouseLeave={() => setActiveRing(undefined)}\n onFocus={() => setActiveRing(index)}\n onBlur={() => setActiveRing(undefined)}\n >\n <circle cx=\"100\" cy=\"100\" r={radius} fill=\"none\" stroke=\"var(--borderFaintColor)\" strokeWidth=\"12\" />\n {percent !== undefined && (\n <circle\n data-monitoring-ring={ring.label}\n cx=\"100\"\n cy=\"100\"\n r={radius}\n fill=\"none\"\n stroke={ring.color}\n strokeWidth=\"12\"\n pathLength=\"100\"\n strokeDasharray={`${Math.min(100, Math.max(0, percent))} 100`}\n transform=\"rotate(-90 100 100)\"\n />\n )}\n </g>\n );\n })}\n <text\n data-monitoring-usage-percentage=\"\"\n x=\"100\"\n y=\"100\"\n textAnchor=\"middle\"\n fill=\"var(--textColorPrimary)\"\n fontSize=\"26\"\n fontWeight=\"600\"\n >\n {usagePercent === undefined ? \"N/A\" : `${usagePercent.toFixed(1)}%`}\n </text>\n <text x=\"100\" y=\"120\" textAnchor=\"middle\" fill=\"var(--textColorPrimary)\" fontSize=\"12\">\n Usage\n </text>\n </svg>\n {hovered && (\n <div\n id={tooltipId}\n data-monitoring-tooltip=\"\"\n role=\"tooltip\"\n style={{\n position: \"absolute\",\n top: 48,\n left: 8,\n right: 8,\n zIndex: 20,\n padding: 8,\n border: \"1px solid var(--borderFaintColor)\",\n background: \"var(--contentColor)\",\n pointerEvents: \"none\",\n overflowWrap: \"anywhere\",\n boxShadow: \"0 3px 12px #0003\",\n }}\n >\n <div style={{ color: hovered.color }}>\n {hovered.label}: {available(hovered.value)}\n </div>\n <div>\n {percentage(hovered.value) === undefined\n ? \"Percentage unavailable\"\n : `${percentage(hovered.value)!.toFixed(1)}% of allocatable${percentage(hovered.value)! > 100 ? \" (over allocatable)\" : \"\"}`}\n </div>\n <div>Allocatable: {available(denominator)}</div>\n </div>\n )}\n <div aria-label={`${label} resource totals`} style={{ display: \"grid\", gap: 6, fontSize: 12 }}>\n {rings.map((ring) => (\n <div\n key={ring.label}\n title={`${ring.label} relative to allocatable capacity. ${ring.label === \"Usage\" ? `Unused allocatable (usage): ${unused}` : `Unrequested: ${unrequested}`}`}\n >\n <span style={{ color: ring.color }}>●</span> {ring.label}: {available(ring.value)}\n {percentage(ring.value) !== undefined && <span> ({percentage(ring.value)!.toFixed(1)}%)</span>}\n </div>\n ))}\n <div title={allocationDetail}>\n <span style={{ color: \"#5486b5\" }}>●</span> Allocatable: {available(denominator)}\n </div>\n </div>\n {(status || sample?.resourceStatus) && (\n <div role=\"status\" style={{ color: \"var(--textColorSecondary)\", fontSize: 11, marginTop: 8 }}>\n {status || sample?.resourceStatus}\n </div>\n )}\n </section>\n );\n}\n\nfunction MonitoringCharts({ samples, status }: { samples: MonitoringSample[]; status: string }) {\n return (\n <div style={{ containerType: \"inline-size\" }}>\n <style>{`\n [data-monitoring-layout] { display:grid; grid-template-columns:minmax(0,1.6fr) minmax(0,1.6fr) minmax(0,1fr) minmax(0,1fr); gap:16px; align-items:stretch }\n [data-monitoring-trends], [data-monitoring-summaries] { display:contents }\n @container (min-width: 961px) {\n [data-monitoring-summaries] > section { --power-monitoring-summary-top:16px }\n }\n @container (max-width: 960px) {\n [data-monitoring-layout] { grid-template-columns:repeat(2,minmax(0,1fr)) }\n .power-ai-overview-actions + [data-testid=\"cluster-overview-page\"] [data-monitoring-trends] > section { --power-monitoring-trend-top:56px }\n }\n @container (max-width: 580px) {\n [data-monitoring-layout] { grid-template-columns:minmax(0,1fr) }\n .power-ai-overview-actions + [data-testid=\"cluster-overview-page\"] [data-monitoring-trends] > section:not(:first-child) { --power-monitoring-trend-top:16px }\n }\n `}</style>\n <div data-monitoring-layout=\"\">\n <div data-monitoring-trends=\"\">\n {([\"cpu\", \"memory\"] as const).map((metric) => (\n <MetricChart key={metric} metric={metric} samples={samples} status={status} />\n ))}\n </div>\n <div data-monitoring-summaries=\"\">\n {([\"cpu\", \"memory\"] as const).map((metric) => (\n <ResourceDonut key={metric} metric={metric} sample={samples.at(-1)} status={status} />\n ))}\n </div>\n </div>\n </div>\n );\n}\n\nexport function startMonitoring(): () => void {\n const preferences = MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>();\n let stopCurrent: (() => void) | undefined;\n const stop = reaction(\n () => preferences.enabled,\n (enabled) => {\n stopCurrent?.();\n stopCurrent = enabled ? mountMonitoring() : undefined;\n },\n { fireImmediately: true },\n );\n return () => {\n stop();\n stopCurrent?.();\n };\n}\n\nfunction mountMonitoring(): () => void {\n const suppression = document.createElement(\"style\");\n suppression.setAttribute(\"data-freelens-power-native-metrics-suppression\", \"\");\n suppression.textContent = `\n [data-testid=\"cluster-overview-page\"] > [class*=\"ClusterMetrics\"],\n [data-testid=\"cluster-overview-page\"] > :has([class*=\"ClusterMetrics\"]),\n [data-testid=\"cluster-overview-page\"] > :is([class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"]):not(:has(.PieChart)),\n [data-testid=\"cluster-overview-page\"] > :has([class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"], [class*=\"cluster-pie-charts\"][class*=\"empty\"]):not(:has(.PieChart)) {\n display:none !important;\n }\n `;\n document.head.append(suppression);\n let host: HTMLElement | undefined;\n let overview: Element | null = null;\n let samples: MonitoringSample[] = [];\n let status = \"\";\n let renderedSamples: MonitoringSample[] | undefined;\n let renderedStatus: string | undefined;\n let cluster: string | undefined;\n let stopped = false;\n let pendingGeneration: number | undefined;\n let generation = 0;\n let nextSample = 0;\n const hidden = new Map<HTMLElement, string | null>();\n const restore = () => {\n for (const [element, original] of hidden) {\n if (original === null) element.removeAttribute(\"style\");\n else element.setAttribute(\"style\", original);\n }\n hidden.clear();\n if (host) {\n ReactDOM.unmountComponentAtNode(host);\n host.remove();\n host = undefined;\n renderedSamples = undefined;\n renderedStatus = undefined;\n }\n };\n const update = async () => {\n const currentCluster = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n const currentOverview = document.querySelector('[data-testid=\"cluster-overview-page\"]');\n if (cluster !== currentCluster || overview !== currentOverview) {\n generation++;\n restore();\n samples = [];\n status = \"\";\n nextSample = 0;\n cluster = currentCluster;\n overview = currentOverview;\n }\n const cutoff = Date.now() - MAX_SAMPLES * INTERVAL;\n if (samples.length && samples[0].time < cutoff) samples = samples.filter((sample) => sample.time >= cutoff);\n if (!overview || !cluster || document.visibilityState === \"hidden\") return;\n if (!host) {\n host = document.createElement(\"div\");\n host.setAttribute(\"data-freelens-power-monitoring\", \"\");\n host.style.gridColumn = \"1 / -1\";\n hidden.set(overview as HTMLElement, overview.getAttribute(\"style\"));\n Object.assign((overview as HTMLElement).style, {\n gridTemplateAreas: \"none\",\n gridTemplateColumns: \"minmax(0, 1fr)\",\n gridTemplateRows: \"none\",\n height: \"auto\",\n });\n overview.prepend(host);\n }\n for (const title of overview.querySelectorAll<HTMLElement>(\".PieChart > .chart-title\")) {\n if (title.textContent !== \"CPU\" && title.textContent !== \"Memory\") continue;\n const panel = title.closest(\".PieChart\")?.parentElement;\n if (panel && panel.style.display !== \"none\") {\n if (!hidden.has(panel)) hidden.set(panel, panel.getAttribute(\"style\"));\n panel.style.display = \"none\";\n }\n }\n // native CSS modules retain [ClusterMetrics] in the generated class name\n for (const child of overview.children) {\n if (!(child instanceof HTMLElement) || child === host) continue;\n const nativeMetrics =\n child.matches('[class*=\"ClusterMetrics\"]') || child.querySelector('[class*=\"ClusterMetrics\"]');\n const unavailablePies =\n (child.matches('[class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"]') ||\n child.querySelector(\n '[class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"], [class*=\"cluster-pie-charts\"][class*=\"empty\"]',\n )) &&\n !child.querySelector(\".PieChart\");\n if ((nativeMetrics || unavailablePies) && child.style.display !== \"none\") {\n if (!hidden.has(child)) hidden.set(child, child.getAttribute(\"style\"));\n child.style.display = \"none\";\n }\n if (!hidden.has(child)) hidden.set(child, child.getAttribute(\"style\"));\n child.style.gridArea = \"auto\";\n }\n const render = () => {\n if (host && (renderedSamples !== samples || renderedStatus !== status)) {\n ReactDOM.render(<MonitoringCharts samples={samples} status={status} />, host);\n renderedSamples = samples;\n renderedStatus = status;\n }\n };\n render();\n if (pendingGeneration === generation || Date.now() < nextSample) return;\n pendingGeneration = generation;\n nextSample = Date.now() + INTERVAL;\n const requestGeneration = generation;\n const isCurrent = () =>\n !stopped &&\n requestGeneration === generation &&\n document.visibilityState !== \"hidden\" &&\n overview?.isConnected === true &&\n Renderer.Catalog.activeCluster.get()?.metadata.uid === cluster;\n try {\n const [metrics, inventory, pods] = await Promise.allSettled([\n Renderer.K8sApi.nodesMetricsApi.list(),\n Promise.resolve().then(() => Renderer.K8sApi.nodesApi.list()),\n Promise.resolve().then(() => Renderer.K8sApi.podsApi.list()),\n ]);\n if (!isCurrent()) return;\n if (metrics.status !== \"fulfilled\") throw new Error(\"Metrics unavailable\");\n const sample = aggregateMetrics(metrics.value ?? []);\n const warnings: string[] = [];\n if (inventory.status === \"fulfilled\") {\n try {\n sample.resources = aggregateResources(\n inventory.value ?? [],\n pods.status === \"fulfilled\" ? (pods.value ?? undefined) : undefined,\n );\n const expected = new Set((inventory.value ?? []).map((node) => node.metadata.name));\n const observed = new Set((metrics.value ?? []).map((node) => node.metadata.name));\n sample.completeUsage =\n expected.size > 0 && expected.size === observed.size && [...expected].every((name) => observed.has(name));\n if (!sample.completeUsage)\n warnings.push(\n \"Partial node metrics coverage: usage is the reported subset; unused allocatable unavailable\",\n );\n } catch {\n warnings.push(\"Resource totals unavailable: incomplete or invalid node/pod data\");\n }\n } else\n warnings.push(\"Node inventory unavailable or access denied; usage coverage unverified, capacity unavailable\");\n if (pods.status !== \"fulfilled\")\n warnings.push(\"Cluster-wide Pods unavailable or access denied; requests unavailable\");\n sample.resourceStatus = warnings.join(\". \");\n samples = [...samples, sample].slice(-MAX_SAMPLES);\n status = \"\";\n } catch {\n if (!isCurrent()) return;\n status = \"Node metrics unavailable, stale or access denied. Last collected samples remain visible.\";\n } finally {\n if (pendingGeneration === requestGeneration) pendingGeneration = undefined;\n }\n if (!stopped && requestGeneration === generation) render();\n };\n const observer = new MutationObserver(() => {\n void update();\n });\n observer.observe(document.body, { childList: true, subtree: true });\n const timer = window.setInterval(() => {\n void update();\n }, 1000);\n void update();\n return () => {\n stopped = true;\n generation++;\n window.clearInterval(timer);\n observer.disconnect();\n suppression.remove();\n restore();\n samples = [];\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"monitoring.js","names":[],"sources":["../../src/renderer/monitoring.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { reaction } from \"mobx\";\nimport { type CSSProperties, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport {\n aggregateMetrics,\n aggregateResources,\n MONITORING_INTERVAL as INTERVAL,\n MAX_SAMPLES,\n type MonitoringSample,\n} from \"../common/monitoring-math\";\nimport { MonitoringPreferencesStore } from \"../common/store/monitoring-preferences-store\";\nimport { getMonitoringSnapshot, retainMonitoringCollector } from \"./monitoring-collector\";\nimport { MonitoringHistoryRange, useMonitoringHistory } from \"./monitoring-history-view\";\n\nexport {\n aggregateMetrics,\n aggregateResources,\n effectivePodResource,\n MAX_SAMPLES,\n type MonitoringNode,\n type MonitoringPod,\n type MonitoringSample,\n parseQuantity,\n} from \"../common/monitoring-math\";\n\nexport function formatMonitoringTime(time: number): string {\n return new Date(time).toLocaleTimeString([], {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hourCycle: \"h23\",\n });\n}\n\nfunction ResourceTitle({ metric, label }: { metric: \"cpu\" | \"memory\"; label?: string }) {\n return (\n <strong style={{ display: \"inline-flex\", alignItems: \"center\", gap: 6 }}>\n <span className=\"Icon material\" aria-hidden=\"true\" style={{ \"--size\": \"18px\", fontWeight: 400 } as CSSProperties}>\n <span className=\"icon\">{metric === \"cpu\" ? \"developer_board\" : \"memory\"}</span>\n </span>\n {label ?? (metric === \"cpu\" ? \"CPU\" : \"Memory\")}\n </strong>\n );\n}\n\nexport function MetricChart({\n metric,\n samples,\n status,\n scope = \"node\",\n}: {\n metric: \"cpu\" | \"memory\";\n samples: MonitoringSample[];\n status: string;\n scope?: \"node\" | \"pod\";\n}) {\n const [selectedTime, setSelectedTime] = useState<number>();\n const [pinned, setPinned] = useState(false);\n const previousMetric = useRef(metric);\n useEffect(() => {\n if (\n previousMetric.current !== metric ||\n (selectedTime !== undefined && !samples.some((sample) => sample.time === selectedTime))\n ) {\n setPinned(false);\n setSelectedTime(undefined);\n }\n previousMetric.current = metric;\n }, [metric, samples, selectedTime]);\n useEffect(() => {\n if (!pinned) return;\n const escape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n event.stopPropagation();\n setPinned(false);\n setSelectedTime(undefined);\n }\n };\n document.addEventListener(\"keydown\", escape, true);\n return () => document.removeEventListener(\"keydown\", escape, true);\n }, [pinned]);\n const chartRef = useRef<SVGSVGElement>(null);\n const [width, setWidth] = useState(600);\n useLayoutEffect(() => {\n const chart = chartRef.current;\n if (!chart) return;\n const measure = () => {\n const measured = chart.getBoundingClientRect().width;\n if (measured > 0) setWidth(measured);\n };\n measure();\n const observer = typeof ResizeObserver === \"undefined\" ? undefined : new ResizeObserver(measure);\n observer?.observe(chart);\n window.addEventListener(\"resize\", measure);\n return () => {\n observer?.disconnect();\n window.removeEventListener(\"resize\", measure);\n };\n }, []);\n const plotWidth = Math.max(1, width - 112);\n const last = samples.at(-1);\n const selected = samples.find((sample) => sample.time === selectedTime);\n const label = metric === \"cpu\" ? \"CPU\" : \"Memory\";\n const format = (value: number) =>\n metric === \"cpu\" ? `${value.toFixed(2)} cores` : `${(value / 1024 ** 3).toFixed(2)} GiB`;\n const series = [\n { key: \"usage\", label: \"Usage\", color: \"#c93dce\", value: (sample: MonitoringSample) => sample[metric] },\n ...([\"requests\", \"allocatable\", \"capacity\"] as const).map((key) => ({\n key,\n label: { requests: \"Requests\", allocatable: \"Allocatable Capacity\", capacity: \"Capacity\" }[key],\n color: { requests: \"#4caf50\", allocatable: \"#5486b5\", capacity: \"var(--textColorSecondary)\" }[key],\n value: (sample: MonitoringSample) => sample.resources?.[metric][key],\n })),\n ];\n const visibleSeries =\n scope === \"pod\" ? series.filter((line) => line.key === \"usage\" || line.key === \"requests\") : series;\n const max =\n Math.max(\n ...samples.flatMap((sample) => [\n ...visibleSeries.map((line) => line.value(sample) ?? 0),\n sample.historical?.[metric]?.max ?? 0,\n ]),\n 0.001,\n ) * 1.1;\n const end = last?.time ?? Date.now();\n const start = samples[0]?.time ?? end;\n const duration = Math.max(end - start, INTERVAL);\n const x = (sample: MonitoringSample) => 88 + ((sample.time - start) / duration) * plotWidth;\n const y = (sample: MonitoringSample) => 208 - (sample[metric] / max) * 184;\n const selectNearest = (event: React.MouseEvent<SVGSVGElement>) => {\n const bounds = event.currentTarget.getBoundingClientRect();\n if (!bounds.width || !samples.length) return;\n const scale = Math.min(bounds.width / width, (bounds.height || 250) / 250);\n const offset = (bounds.width - width * scale) / 2;\n const position = (event.clientX - bounds.left - offset) / scale;\n const time = start + ((position - 88) / plotWidth) * duration;\n const nearest = samples.reduce((nearest, sample) =>\n Math.abs(sample.time - time) < Math.abs(nearest.time - time) ? sample : nearest,\n ).time;\n setSelectedTime(nearest);\n return nearest;\n };\n return (\n <section\n aria-label={`${label} metrics-server usage`}\n style={{\n padding: \"var(--power-monitoring-trend-top, 16px) 16px 16px\",\n background: \"var(--contentColor)\",\n minWidth: 0,\n minHeight: 280,\n position: \"relative\",\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 12 }}>\n <ResourceTitle metric={metric} />\n <span>{status ? \"Unavailable\" : last ? format(last[metric]) : \"Collecting…\"}</span>\n </div>\n <svg\n ref={chartRef}\n data-monitoring-trend=\"\"\n viewBox={`0 0 ${width} 250`}\n role=\"img\"\n tabIndex={0}\n aria-label={`${label} usage over collected samples. Use arrow keys to inspect samples. Click or press Enter to pin the tooltip, Escape to dismiss`}\n onMouseMove={(event) => {\n if (!pinned) selectNearest(event);\n }}\n onClick={(event) => {\n if (pinned) setPinned(false);\n else if (samples.length) {\n if (selectNearest(event) === undefined && !selected) setSelectedTime(last?.time);\n setPinned(true);\n }\n }}\n onMouseLeave={() => {\n if (!pinned) setSelectedTime(undefined);\n }}\n onFocus={() => {\n if (!pinned) setSelectedTime(last?.time);\n }}\n onBlur={() => {\n if (!pinned) setSelectedTime(undefined);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n if (samples.length) {\n if (!selected) setSelectedTime(last?.time);\n setPinned(!pinned);\n }\n return;\n }\n if (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\") return;\n event.preventDefault();\n const index = samples.findIndex((sample) => sample.time === selectedTime);\n setSelectedTime(\n samples[\n Math.max(\n 0,\n Math.min(\n samples.length - 1,\n (index < 0 ? samples.length - 1 : index) + (event.key === \"ArrowLeft\" ? -1 : 1),\n ),\n )\n ]?.time,\n );\n }}\n style={{ width: \"100%\", height: 250, color: \"#c93dce\", display: \"block\" }}\n >\n <title>Click to pin tooltip · click again or Escape to unpin</title>\n {[0, 0.5, 1].map((fraction) => (\n <g key={fraction}>\n <line\n x1=\"88\"\n x2={width - 24}\n y1={208 - fraction * 184}\n y2={208 - fraction * 184}\n stroke=\"var(--borderFaintColor)\"\n />\n <text x=\"80\" y={212 - fraction * 184} textAnchor=\"end\" fill=\"var(--textColorSecondary)\" fontSize=\"11\">\n {format(max * fraction)}\n </text>\n </g>\n ))}\n {samples.map((sample) => {\n const summary = sample.historical?.[metric];\n if (!summary || summary.min === summary.max) return null;\n return (\n <line\n key={`range:${sample.time}`}\n data-monitoring-extrema=\"\"\n x1={x(sample)}\n x2={x(sample)}\n y1={208 - (summary.max / max) * 184}\n y2={208 - (summary.min / max) * 184}\n stroke=\"#c93dce\"\n strokeOpacity={0.35}\n strokeWidth={4}\n />\n );\n })}\n {visibleSeries.map((line) => (\n <path\n key={line.key}\n data-monitoring-series={line.key}\n d={samples.reduce((path, sample, index) => {\n const value = line.value(sample);\n if (value === undefined) return path;\n const previous = index ? line.value(samples[index - 1]) : undefined;\n return `${path} ${previous === undefined || sample.breakBefore || sample.time - samples[index - 1].time > 1.8 * Math.max(sample.historical?.[metric]?.resolution ?? INTERVAL, samples[index - 1].historical?.[metric]?.resolution ?? INTERVAL) ? \"M\" : \"L\"}${x(sample)},${208 - (value / max) * 184}`;\n }, \"\")}\n fill=\"none\"\n stroke={line.color}\n strokeWidth=\"2\"\n strokeDasharray={line.key === \"capacity\" || line.key === \"allocatable\" ? \"5 3\" : undefined}\n />\n ))}\n {samples.map((sample) => (\n <circle key={sample.time} cx={x(sample)} cy={y(sample)} r=\"2\" fill=\"currentColor\">\n <title>\n {formatMonitoringTime(sample.time)}: {format(sample[metric])}\n </title>\n </circle>\n ))}\n {samples.length > 0 &&\n [0, 0.5, 1].map((fraction) => (\n <text\n key={fraction}\n x={88 + fraction * plotWidth}\n y=\"235\"\n textAnchor={fraction === 0 ? \"start\" : fraction === 1 ? \"end\" : \"middle\"}\n fill=\"var(--textColorSecondary)\"\n fontSize=\"11\"\n >\n {formatMonitoringTime(start + fraction * duration)}\n </text>\n ))}\n {selected && (\n <line\n data-monitoring-crosshair=\"\"\n x1={x(selected)}\n x2={x(selected)}\n y1=\"24\"\n y2=\"208\"\n stroke=\"var(--textColorSecondary)\"\n strokeDasharray=\"4 3\"\n />\n )}\n </svg>\n <style>{`\n @keyframes freelens-power-metric-tooltip-enter { from { opacity:0; transform:translateY(2px) } to { opacity:1; transform:translateY(0) } }\n [data-monitoring-tooltip] { animation:freelens-power-metric-tooltip-enter 140ms ease-out }\n @media (prefers-reduced-motion:reduce) { [data-monitoring-tooltip] { animation:none } }\n `}</style>\n {selected && (\n <div\n data-monitoring-tooltip=\"\"\n role=\"tooltip\"\n style={{\n position: \"absolute\",\n top: 44,\n right: 24,\n padding: 8,\n background: \"var(--contentColor)\",\n border: \"1px solid var(--borderFaintColor)\",\n pointerEvents: \"none\",\n }}\n >\n <div>\n {formatMonitoringTime(selected.time)}\n {pinned ? \" · Pinned\" : \"\"}\n </div>\n {visibleSeries.map((line) => (\n <div key={line.key} style={{ color: line.color }}>\n {line.label}: {line.value(selected) === undefined ? \"Unavailable\" : format(line.value(selected)!)}\n </div>\n ))}\n {selected.historical?.[metric] && (\n <div>\n Min: {format(selected.historical[metric]!.min)} · Max: {format(selected.historical[metric]!.max)}\n <br />\n {selected.historical[metric]!.count} samples ·{\" \"}\n {Math.round(selected.historical[metric]!.resolution / 1000)}s bucket\n </div>\n )}\n <div style={{ color: \"var(--textColorSecondary)\", marginTop: 4, fontSize: 10 }}>\n {pinned ? \"Click chart or Escape to unpin\" : \"Click or Enter to pin\"}\n </div>\n </div>\n )}\n <div\n aria-label={`${label} chart legend`}\n style={{ display: \"flex\", flexWrap: \"wrap\", gap: \"6px 16px\", marginBottom: 8 }}\n >\n {visibleSeries.map((line) => (\n <span key={line.key}>\n <span style={{ color: line.color }}>●</span> {line.label}\n </span>\n ))}\n </div>\n {last?.resourceStatus && (\n <div role=\"status\" style={{ color: \"var(--textColorSecondary)\", marginBottom: 8 }}>\n {last.resourceStatus}\n </div>\n )}\n {(scope === \"node\" || status || !samples.length) && (\n <div\n style={{ fontSize: 11, color: \"var(--textColorSecondary)\", display: \"flex\", alignItems: \"center\", gap: 4 }}\n role=\"status\"\n aria-label={`${scope} metrics status`}\n >\n {scope === \"node\" && (\n <sup aria-hidden=\"true\" style={{ fontSize: 12 }}>\n *\n </sup>\n )}\n <span>{status || (samples.length ? \"metrics-server data\" : \"Waiting for metrics-server data\")}</span>\n </div>\n )}\n </section>\n );\n}\n\nfunction ResourceDonut({\n metric,\n sample,\n status,\n}: {\n metric: \"cpu\" | \"memory\";\n sample?: MonitoringSample;\n status: string;\n}) {\n const [activeRing, setActiveRing] = useState<number>();\n useEffect(() => {\n if (activeRing === undefined) return;\n const dismiss = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\") return;\n event.preventDefault();\n event.stopPropagation();\n setActiveRing(undefined);\n };\n document.addEventListener(\"keydown\", dismiss, true);\n return () => document.removeEventListener(\"keydown\", dismiss, true);\n }, [activeRing]);\n const label = metric === \"cpu\" ? \"CPU\" : \"Memory\";\n const totals = sample?.resources?.[metric];\n const format = (value: number) =>\n metric === \"cpu\" ? `${value.toFixed(2)} cores` : `${(value / 1024 ** 3).toFixed(2)} GiB`;\n const available = (value?: number) => (value === undefined ? \"Unavailable\" : format(value));\n const denominator = totals?.allocatable;\n const rings = [\n { label: \"Usage\", color: \"#c93dce\", value: sample?.[metric] },\n { label: \"Requests\", color: \"#4caf50\", value: totals?.requests },\n ];\n const percentage = (value?: number) =>\n value !== undefined && denominator !== undefined && denominator > 0 ? (value / denominator) * 100 : undefined;\n const usagePercent = percentage(sample?.[metric]);\n const unused =\n sample?.completeUsage && denominator !== undefined ? format(denominator - sample[metric]) : \"Unavailable\";\n const unrequested =\n denominator !== undefined && totals?.requests !== undefined ? format(denominator - totals.requests) : \"Unavailable\";\n const allocationDetail = `Allocatable: ${available(denominator)}. Schedulable capacity after system reservations, used as the denominator for both rings. Physical Capacity: ${available(totals?.capacity)}. Unused allocatable (usage): ${unused}. Unrequested: ${unrequested}`;\n const hovered = activeRing === undefined ? undefined : rings[activeRing];\n const tooltipId = `power-monitoring-${metric}-donut-tooltip`;\n return (\n <section\n aria-label={`${label} resource summary`}\n style={{\n padding: \"var(--power-monitoring-summary-top, 16px) 16px 16px\",\n minWidth: 0,\n background: \"var(--contentColor)\",\n position: \"relative\",\n overflow: \"visible\",\n }}\n >\n <ResourceTitle metric={metric} label={metric === \"memory\" ? \"RAM\" : \"CPU\"} />\n <svg\n data-monitoring-donut=\"\"\n viewBox=\"0 0 200 200\"\n role=\"img\"\n aria-label={`${label} usage and requests relative to allocatable capacity`}\n style={{ display: \"block\", width: \"100%\", height: 200 }}\n >\n {rings.map((ring, index) => {\n const radius = 76 - index * 18;\n const percent = percentage(ring.value);\n const detail = `${ring.label}: ${available(ring.value)}${percent === undefined ? \"\" : ` (${percent.toFixed(1)}% of allocatable${percent > 100 ? \", over allocatable\" : \"\"})`}`;\n return (\n <g\n key={ring.label}\n tabIndex={0}\n role=\"img\"\n aria-label={detail}\n aria-describedby={activeRing === index ? tooltipId : undefined}\n onMouseEnter={() => setActiveRing(index)}\n onMouseMove={() => setActiveRing(index)}\n onMouseLeave={() => setActiveRing(undefined)}\n onFocus={() => setActiveRing(index)}\n onBlur={() => setActiveRing(undefined)}\n >\n <circle cx=\"100\" cy=\"100\" r={radius} fill=\"none\" stroke=\"var(--borderFaintColor)\" strokeWidth=\"12\" />\n {percent !== undefined && (\n <circle\n data-monitoring-ring={ring.label}\n cx=\"100\"\n cy=\"100\"\n r={radius}\n fill=\"none\"\n stroke={ring.color}\n strokeWidth=\"12\"\n pathLength=\"100\"\n strokeDasharray={`${Math.min(100, Math.max(0, percent))} 100`}\n transform=\"rotate(-90 100 100)\"\n />\n )}\n </g>\n );\n })}\n <text\n data-monitoring-usage-percentage=\"\"\n x=\"100\"\n y=\"100\"\n textAnchor=\"middle\"\n fill=\"var(--textColorPrimary)\"\n fontSize=\"26\"\n fontWeight=\"600\"\n >\n {usagePercent === undefined ? \"N/A\" : `${usagePercent.toFixed(1)}%`}\n </text>\n <text x=\"100\" y=\"120\" textAnchor=\"middle\" fill=\"var(--textColorPrimary)\" fontSize=\"12\">\n Usage\n </text>\n </svg>\n {hovered && (\n <div\n id={tooltipId}\n data-monitoring-tooltip=\"\"\n role=\"tooltip\"\n style={{\n position: \"absolute\",\n top: 48,\n left: 8,\n right: 8,\n zIndex: 20,\n padding: 8,\n border: \"1px solid var(--borderFaintColor)\",\n background: \"var(--contentColor)\",\n pointerEvents: \"none\",\n overflowWrap: \"anywhere\",\n boxShadow: \"0 3px 12px #0003\",\n }}\n >\n <div style={{ color: hovered.color }}>\n {hovered.label}: {available(hovered.value)}\n </div>\n <div>\n {percentage(hovered.value) === undefined\n ? \"Percentage unavailable\"\n : `${percentage(hovered.value)!.toFixed(1)}% of allocatable${percentage(hovered.value)! > 100 ? \" (over allocatable)\" : \"\"}`}\n </div>\n <div>Allocatable: {available(denominator)}</div>\n </div>\n )}\n <div aria-label={`${label} resource totals`} style={{ display: \"grid\", gap: 6, fontSize: 12 }}>\n {rings.map((ring) => (\n <div\n key={ring.label}\n title={`${ring.label} relative to allocatable capacity. ${ring.label === \"Usage\" ? `Unused allocatable (usage): ${unused}` : `Unrequested: ${unrequested}`}`}\n >\n <span style={{ color: ring.color }}>●</span> {ring.label}: {available(ring.value)}\n {percentage(ring.value) !== undefined && <span> ({percentage(ring.value)!.toFixed(1)}%)</span>}\n </div>\n ))}\n <div title={allocationDetail}>\n <span style={{ color: \"#5486b5\" }}>●</span> Allocatable: {available(denominator)}\n </div>\n </div>\n {(status || sample?.resourceStatus) && (\n <div role=\"status\" style={{ color: \"var(--textColorSecondary)\", fontSize: 11, marginTop: 8 }}>\n {status || sample?.resourceStatus}\n </div>\n )}\n </section>\n );\n}\n\nfunction MonitoringCharts({ samples, status }: { samples: MonitoringSample[]; status: string }) {\n const clusterId = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n const history = useMonitoringHistory(\n clusterId ? { clusterId, scope: \"cluster\", uid: clusterId } : undefined,\n samples,\n );\n return (\n <div style={{ containerType: \"inline-size\" }}>\n <style>{`\n [data-monitoring-layout] { display:grid; grid-template-columns:minmax(0,1.6fr) minmax(0,1.6fr) minmax(0,1fr) minmax(0,1fr); gap:16px; align-items:stretch }\n [data-monitoring-trends], [data-monitoring-summaries] { display:contents }\n @container (min-width: 961px) {\n [data-monitoring-summaries] > section { --power-monitoring-summary-top:16px }\n }\n @container (max-width: 960px) {\n [data-monitoring-layout] { grid-template-columns:repeat(2,minmax(0,1fr)) }\n .power-ai-overview-actions + [data-testid=\"cluster-overview-page\"] [data-monitoring-trends] > section { --power-monitoring-trend-top:56px }\n }\n @container (max-width: 580px) {\n [data-monitoring-layout] { grid-template-columns:minmax(0,1fr) }\n .power-ai-overview-actions + [data-testid=\"cluster-overview-page\"] [data-monitoring-trends] > section:not(:first-child) { --power-monitoring-trend-top:16px }\n }\n `}</style>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 12, marginBottom: 8 }}>\n <MonitoringHistoryRange range={history.range} onChange={history.setRange} />\n <small role=\"status\">{history.status}</small>\n </div>\n <div data-monitoring-layout=\"\">\n <div data-monitoring-trends=\"\">\n {([\"cpu\", \"memory\"] as const).map((metric) => (\n <MetricChart key={metric} metric={metric} samples={history.samples} status={status} />\n ))}\n </div>\n <div data-monitoring-summaries=\"\">\n {([\"cpu\", \"memory\"] as const).map((metric) => (\n <ResourceDonut key={metric} metric={metric} sample={samples.at(-1)} status={status} />\n ))}\n </div>\n </div>\n </div>\n );\n}\n\nexport function startMonitoring(): () => void {\n const release = retainMonitoringCollector();\n const preferences = MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>();\n let stopCurrent: (() => void) | undefined;\n const stop = reaction(\n () => preferences.enabled,\n (enabled) => {\n stopCurrent?.();\n stopCurrent = enabled ? mountMonitoring() : undefined;\n },\n { fireImmediately: true },\n );\n return () => {\n stop();\n stopCurrent?.();\n release();\n };\n}\n\nfunction mountMonitoring(): () => void {\n const suppression = document.createElement(\"style\");\n suppression.setAttribute(\"data-freelens-power-native-metrics-suppression\", \"\");\n suppression.textContent = `\n [data-testid=\"cluster-overview-page\"] > [class*=\"ClusterMetrics\"],\n [data-testid=\"cluster-overview-page\"] > :has([class*=\"ClusterMetrics\"]),\n [data-testid=\"cluster-overview-page\"] > :is([class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"]):not(:has(.PieChart)),\n [data-testid=\"cluster-overview-page\"] > :has([class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"], [class*=\"cluster-pie-charts\"][class*=\"empty\"]):not(:has(.PieChart)) {\n display:none !important;\n }\n `;\n document.head.append(suppression);\n let host: HTMLElement | undefined;\n let overview: Element | null = null;\n let samples: MonitoringSample[] = [];\n let status = \"\";\n let renderedSamples: MonitoringSample[] | undefined;\n let renderedStatus: string | undefined;\n let cluster: string | undefined;\n let stopped = false;\n let pendingGeneration: number | undefined;\n let generation = 0;\n let nextSample = 0;\n const hidden = new Map<HTMLElement, string | null>();\n const restore = () => {\n for (const [element, original] of hidden) {\n if (original === null) element.removeAttribute(\"style\");\n else element.setAttribute(\"style\", original);\n }\n hidden.clear();\n if (host) {\n ReactDOM.unmountComponentAtNode(host);\n host.remove();\n host = undefined;\n renderedSamples = undefined;\n renderedStatus = undefined;\n }\n };\n const update = async () => {\n const currentCluster = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n const currentOverview = document.querySelector('[data-testid=\"cluster-overview-page\"]');\n if (cluster !== currentCluster || overview !== currentOverview) {\n generation++;\n restore();\n samples = [];\n status = \"\";\n nextSample = 0;\n cluster = currentCluster;\n overview = currentOverview;\n }\n const cutoff = Date.now() - MAX_SAMPLES * INTERVAL;\n if (samples.length && samples[0].time < cutoff) samples = samples.filter((sample) => sample.time >= cutoff);\n if (!overview || !cluster || document.visibilityState === \"hidden\") return;\n if (!host) {\n host = document.createElement(\"div\");\n host.setAttribute(\"data-freelens-power-monitoring\", \"\");\n host.style.gridColumn = \"1 / -1\";\n hidden.set(overview as HTMLElement, overview.getAttribute(\"style\"));\n Object.assign((overview as HTMLElement).style, {\n gridTemplateAreas: \"none\",\n gridTemplateColumns: \"minmax(0, 1fr)\",\n gridTemplateRows: \"none\",\n height: \"auto\",\n });\n overview.prepend(host);\n }\n for (const title of overview.querySelectorAll<HTMLElement>(\".PieChart > .chart-title\")) {\n if (title.textContent !== \"CPU\" && title.textContent !== \"Memory\") continue;\n const panel = title.closest(\".PieChart\")?.parentElement;\n if (panel && panel.style.display !== \"none\") {\n if (!hidden.has(panel)) hidden.set(panel, panel.getAttribute(\"style\"));\n panel.style.display = \"none\";\n }\n }\n // native CSS modules retain [ClusterMetrics] in the generated class name\n for (const child of overview.children) {\n if (!(child instanceof HTMLElement) || child === host) continue;\n const nativeMetrics =\n child.matches('[class*=\"ClusterMetrics\"]') || child.querySelector('[class*=\"ClusterMetrics\"]');\n const unavailablePies =\n (child.matches('[class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"]') ||\n child.querySelector(\n '[class*=\"noMetrics\"], [data-testid=\"no-metrics-message\"], [class*=\"cluster-pie-charts\"][class*=\"empty\"]',\n )) &&\n !child.querySelector(\".PieChart\");\n if ((nativeMetrics || unavailablePies) && child.style.display !== \"none\") {\n if (!hidden.has(child)) hidden.set(child, child.getAttribute(\"style\"));\n child.style.display = \"none\";\n }\n if (!hidden.has(child)) hidden.set(child, child.getAttribute(\"style\"));\n child.style.gridArea = \"auto\";\n }\n const render = () => {\n if (host && (renderedSamples !== samples || renderedStatus !== status)) {\n ReactDOM.render(<MonitoringCharts samples={samples} status={status} />, host);\n renderedSamples = samples;\n renderedStatus = status;\n }\n };\n render();\n if (pendingGeneration === generation || Date.now() < nextSample) return;\n pendingGeneration = generation;\n nextSample = Date.now() + INTERVAL;\n const requestGeneration = generation;\n const isCurrent = () =>\n !stopped &&\n requestGeneration === generation &&\n document.visibilityState !== \"hidden\" &&\n overview?.isConnected === true &&\n Renderer.Catalog.activeCluster.get()?.metadata.uid === cluster;\n try {\n const collected = await getMonitoringSnapshot();\n const metrics =\n collected.nodeMetrics === undefined\n ? { status: \"rejected\" as const }\n : { status: \"fulfilled\" as const, value: collected.nodeMetrics };\n const inventory =\n collected.nodes === undefined\n ? { status: \"rejected\" as const }\n : { status: \"fulfilled\" as const, value: collected.nodes };\n const pods =\n collected.pods === undefined\n ? { status: \"rejected\" as const }\n : { status: \"fulfilled\" as const, value: collected.pods };\n if (!isCurrent()) return;\n if (metrics.status !== \"fulfilled\") throw new Error(\"Metrics unavailable\");\n const sample = aggregateMetrics(metrics.value ?? []);\n sample.time = Math.min(...metrics.value.map((item) => Date.parse(item.timestamp)));\n const warnings: string[] = [];\n if (inventory.status === \"fulfilled\") {\n try {\n sample.resources = aggregateResources(\n inventory.value ?? [],\n pods.status === \"fulfilled\" ? (pods.value ?? undefined) : undefined,\n );\n const expected = new Set((inventory.value ?? []).map((node) => node.metadata.name));\n const observed = new Set((metrics.value ?? []).map((node) => node.metadata.name));\n sample.completeUsage =\n expected.size > 0 && expected.size === observed.size && [...expected].every((name) => observed.has(name));\n if (!sample.completeUsage)\n warnings.push(\n \"Partial node metrics coverage: usage is the reported subset; unused allocatable unavailable\",\n );\n } catch {\n warnings.push(\"Resource totals unavailable: incomplete or invalid node/pod data\");\n }\n } else\n warnings.push(\"Node inventory unavailable or access denied; usage coverage unverified, capacity unavailable\");\n if (pods.status !== \"fulfilled\")\n warnings.push(\"Cluster-wide Pods unavailable or access denied; requests unavailable\");\n sample.resourceStatus = warnings.join(\". \");\n samples = [...samples.filter((entry) => entry.time !== sample.time), sample]\n .sort((a, b) => a.time - b.time)\n .slice(-MAX_SAMPLES);\n status = \"\";\n } catch {\n if (!isCurrent()) return;\n status = \"Node metrics unavailable, stale or access denied. Last collected samples remain visible.\";\n } finally {\n if (pendingGeneration === requestGeneration) pendingGeneration = undefined;\n }\n if (!stopped && requestGeneration === generation) render();\n };\n const observer = new MutationObserver(() => {\n void update();\n });\n observer.observe(document.body, { childList: true, subtree: true });\n const timer = window.setInterval(() => {\n void update();\n }, 1000);\n void update();\n return () => {\n stopped = true;\n generation++;\n window.clearInterval(timer);\n observer.disconnect();\n suppression.remove();\n restore();\n samples = [];\n };\n}\n"],"mappings":"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"}