@64mb/freelens-power 1.5.0 → 1.6.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 (71) hide show
  1. package/README.md +4 -1
  2. package/out/main/ai-ipc.js +34 -3
  3. package/out/main/ai-ipc.js.map +1 -1
  4. package/out/main/common/power-logs-limits.js +227 -0
  5. package/out/main/common/power-logs-limits.js.map +1 -0
  6. package/out/main/common/power-logs.js +32 -0
  7. package/out/main/common/power-logs.js.map +1 -0
  8. package/out/main/common/store/logs-preferences-store.js +45 -0
  9. package/out/main/common/store/logs-preferences-store.js.map +1 -0
  10. package/out/main/dashboard-icon-cache.js +1 -1
  11. package/out/main/index.js +4 -0
  12. package/out/main/index.js.map +1 -1
  13. package/out/main/power-logs-budget.js +126 -0
  14. package/out/main/power-logs-budget.js.map +1 -0
  15. package/out/main/power-logs-child.js +86 -0
  16. package/out/main/power-logs-child.js.map +1 -0
  17. package/out/main/power-logs-database.js +179 -0
  18. package/out/main/power-logs-database.js.map +1 -0
  19. package/out/main/power-logs-ipc.js +275 -0
  20. package/out/main/power-logs-ipc.js.map +1 -0
  21. package/out/main/power-logs-query-child.js +23 -0
  22. package/out/main/power-logs-query-child.js.map +1 -0
  23. package/out/main/power-logs-query.js +127 -0
  24. package/out/main/power-logs-query.js.map +1 -0
  25. package/out/main/power-logs-worker.js +215 -0
  26. package/out/main/power-logs-worker.js.map +1 -0
  27. package/out/main/resource-search.js +1 -1
  28. package/out/renderer/ai-logs-sql.js +27 -0
  29. package/out/renderer/ai-logs-sql.js.map +1 -0
  30. package/out/renderer/ai-message.js +48 -27
  31. package/out/renderer/ai-message.js.map +1 -1
  32. package/out/renderer/ai-terminal-context.js +50 -40
  33. package/out/renderer/ai-terminal-context.js.map +1 -1
  34. package/out/renderer/ai.js +15 -2
  35. package/out/renderer/ai.js.map +1 -1
  36. package/out/renderer/appearance.js +1 -0
  37. package/out/renderer/appearance.js.map +1 -1
  38. package/out/renderer/index.js +67 -29
  39. package/out/renderer/index.js.map +1 -1
  40. package/out/renderer/power-log-json.js +29 -0
  41. package/out/renderer/power-log-json.js.map +1 -0
  42. package/out/renderer/power-logs-client.js +35 -0
  43. package/out/renderer/power-logs-client.js.map +1 -0
  44. package/out/renderer/power-logs-collector.js +316 -0
  45. package/out/renderer/power-logs-collector.js.map +1 -0
  46. package/out/renderer/power-logs-entrypoints.js +201 -0
  47. package/out/renderer/power-logs-entrypoints.js.map +1 -0
  48. package/out/renderer/power-logs-sql-row.js +52 -0
  49. package/out/renderer/power-logs-sql-row.js.map +1 -0
  50. package/out/renderer/power-logs-transport.js +122 -0
  51. package/out/renderer/power-logs-transport.js.map +1 -0
  52. package/out/renderer/power-logs.css.js +116 -0
  53. package/out/renderer/power-logs.css.js.map +1 -0
  54. package/out/renderer/power-logs.js +1352 -0
  55. package/out/renderer/power-logs.js.map +1 -0
  56. package/out/renderer/preferences/logs-preferences.js +93 -0
  57. package/out/renderer/preferences/logs-preferences.js.map +1 -0
  58. package/out/renderer/preferences/preferences.js +23 -9
  59. package/out/renderer/preferences/preferences.js.map +1 -1
  60. package/out/renderer/resource-relationships.js +1 -1
  61. package/out/renderer/src/common/power-log-parser.js +114 -0
  62. package/out/renderer/src/common/power-log-parser.js.map +1 -0
  63. package/out/renderer/src/common/power-logs-ai.js +56 -0
  64. package/out/renderer/src/common/power-logs-ai.js.map +1 -0
  65. package/out/renderer/src/common/power-logs-limits.js +227 -0
  66. package/out/renderer/src/common/power-logs-limits.js.map +1 -0
  67. package/out/renderer/src/common/power-logs.js +32 -0
  68. package/out/renderer/src/common/power-logs.js.map +1 -0
  69. package/out/renderer/src/common/store/logs-preferences-store.js +45 -0
  70. package/out/renderer/src/common/store/logs-preferences-store.js.map +1 -0
  71. package/package.json +4 -2
@@ -10,6 +10,7 @@ const require_ai_preferences_store = require("./src/common/store/ai-preferences-
10
10
  const require_ai_shortcuts_store = require("./src/common/store/ai-shortcuts-store.js");
11
11
  const require_appearance_preferences_store = require("./src/common/store/appearance-preferences-store.js");
12
12
  const require_dashboard_preferences_store = require("./src/common/store/dashboard-preferences-store.js");
13
+ const require_logs_preferences_store = require("./src/common/store/logs-preferences-store.js");
13
14
  const require_monitoring_preferences_store = require("./src/common/store/monitoring-preferences-store.js");
14
15
  const require_node_shell_preferences_store = require("./src/common/store/node-shell-preferences-store.js");
15
16
  const require_power_preferences_store = require("./src/common/store/power-preferences-store.js");
@@ -33,6 +34,8 @@ const require_monitoring = require("./monitoring.js");
33
34
  const require_monitoring_history_collection = require("./monitoring-history-collection.js");
34
35
  const require_node_monitoring = require("./node-monitoring.js");
35
36
  const require_pod_monitoring = require("./pod-monitoring.js");
37
+ const require_power_logs_entrypoints = require("./power-logs-entrypoints.js");
38
+ const require_power_logs = require("./power-logs.js");
36
39
  const require_preferences = require("./preferences/preferences.js");
37
40
  const require_read_only = require("./read-only.js");
38
41
  const require_resource_relationships = require("./resource-relationships.js");
@@ -59,6 +62,7 @@ var FreelensPowerRenderer = class extends require_extensions.Renderer.LensExtens
59
62
  onActivate() {
60
63
  const power = require_power_preferences_store.PowerPreferencesStore.getInstanceOrCreate();
61
64
  power.loadExtension(this);
65
+ require_logs_preferences_store.LogsPreferencesStore.getInstanceOrCreate().loadExtension(this);
62
66
  require_ai_preferences_store.AiPreferencesStore.getInstanceOrCreate().loadExtension(this);
63
67
  require_ai_shortcuts_store.AiShortcutsStore.getInstanceOrCreate().loadExtension(this);
64
68
  require_read_only_preferences_store.ReadOnlyPreferencesStore.getInstanceOrCreate().loadExtension(this);
@@ -81,7 +85,8 @@ var FreelensPowerRenderer = class extends require_extensions.Renderer.LensExtens
81
85
  require_appearance.startAppearanceOverride,
82
86
  require_welcome.startWelcomeOverride,
83
87
  require_ai.startAiChat,
84
- require_resource_search.startResourceSearch
88
+ require_resource_search.startResourceSearch,
89
+ require_power_logs_entrypoints.startPowerLogsEntrypoints
85
90
  ]) try {
86
91
  disposers.push(start());
87
92
  } catch {
@@ -113,33 +118,54 @@ var FreelensPowerRenderer = class extends require_extensions.Renderer.LensExtens
113
118
  id: "dashboard",
114
119
  components: { Page: () => /* @__PURE__ */ require_jsx_runtime.jsx(PowerEnabled, { children: /* @__PURE__ */ require_jsx_runtime.jsx(require_dashboard.DashboardPage, { onOpenPreferences: () => this.navigateToPreferences() }) }) }
115
120
  }];
116
- clusterPages = [{
117
- id: "relationships",
118
- components: { Page: () => /* @__PURE__ */ require_jsx_runtime.jsx(RelationshipsPage, {}) }
119
- }, {
120
- id: "diagnostics",
121
- components: { Page: () => /* @__PURE__ */ require_jsx_runtime.jsx(PowerEnabled, { children: /* @__PURE__ */ require_jsx_runtime.jsx(require_diagnostics.DiagnosticsPage, {}) }) }
122
- }];
123
- clusterPageMenus = [{
124
- visible: require__global_external_mobx.computed(() => require_power_preferences_store.PowerPreferencesStore.getInstanceOrCreate().enabled && require_monitoring_preferences_store.MonitoringPreferencesStore.getInstanceOrCreate().diagnosticsVisible),
125
- target: { pageId: "diagnostics" },
126
- title: "Diagnostics",
127
- orderNumber: 5,
128
- components: { Icon: () => /* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Icon, {
129
- material: "insights",
130
- tooltip: "Resource diagnostics"
131
- }) }
132
- }, {
133
- visible: require__global_external_mobx.computed(() => require_power_preferences_store.PowerPreferencesStore.getInstanceOrCreate().enabled && require_monitoring_preferences_store.MonitoringPreferencesStore.getInstanceOrCreate().relationshipsVisible),
134
- id: "relationships",
135
- target: { pageId: "relationships" },
136
- title: "Relationships",
137
- orderNumber: 6,
138
- components: { Icon: () => /* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Icon, {
139
- material: "account_tree",
140
- tooltip: "Resource relationships"
141
- }) }
142
- }];
121
+ clusterPages = [
122
+ {
123
+ id: "power-logs",
124
+ components: { Page: () => /* @__PURE__ */ require_jsx_runtime.jsx(PowerEnabled, { children: /* @__PURE__ */ require_jsx_runtime.jsx(require_power_logs.PowerLogsPage, {}) }) }
125
+ },
126
+ {
127
+ id: "relationships",
128
+ components: { Page: () => /* @__PURE__ */ require_jsx_runtime.jsx(RelationshipsPage, {}) }
129
+ },
130
+ {
131
+ id: "diagnostics",
132
+ components: { Page: () => /* @__PURE__ */ require_jsx_runtime.jsx(PowerEnabled, { children: /* @__PURE__ */ require_jsx_runtime.jsx(require_diagnostics.DiagnosticsPage, {}) }) }
133
+ }
134
+ ];
135
+ clusterPageMenus = [
136
+ {
137
+ visible: require__global_external_mobx.computed(() => require_power_preferences_store.PowerPreferencesStore.getInstanceOrCreate().enabled && require_monitoring_preferences_store.MonitoringPreferencesStore.getInstanceOrCreate().diagnosticsVisible),
138
+ target: { pageId: "diagnostics" },
139
+ title: "Diagnostics",
140
+ orderNumber: 5,
141
+ components: { Icon: () => /* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Icon, {
142
+ material: "insights",
143
+ tooltip: "Resource diagnostics"
144
+ }) }
145
+ },
146
+ {
147
+ visible: require__global_external_mobx.computed(() => require_power_preferences_store.PowerPreferencesStore.getInstanceOrCreate().enabled && require_monitoring_preferences_store.MonitoringPreferencesStore.getInstanceOrCreate().relationshipsVisible),
148
+ id: "relationships",
149
+ target: { pageId: "relationships" },
150
+ title: "Relationships",
151
+ orderNumber: 6,
152
+ components: { Icon: () => /* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Icon, {
153
+ material: "account_tree",
154
+ tooltip: "Resource relationships"
155
+ }) }
156
+ },
157
+ {
158
+ id: "power-logs",
159
+ visible: require__global_external_mobx.computed(() => require_power_preferences_store.PowerPreferencesStore.getInstanceOrCreate().enabled && require_logs_preferences_store.LogsPreferencesStore.getInstanceOrCreate().enabled),
160
+ target: { pageId: "power-logs" },
161
+ title: "Power Logs",
162
+ orderNumber: 7,
163
+ components: { Icon: () => /* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Icon, {
164
+ material: "subject",
165
+ tooltip: "Workload logs and SQL captures"
166
+ }) }
167
+ }
168
+ ];
143
169
  topBarItems = [{ components: { Item: () => /* @__PURE__ */ require_jsx_runtime.jsx(PowerEnabled, { children: /* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Icon, {
144
170
  material: "battery_charging_full",
145
171
  className: "freelens-power-settings-icon",
@@ -213,7 +239,19 @@ var FreelensPowerRenderer = class extends require_extensions.Renderer.LensExtens
213
239
  }) }) }
214
240
  }
215
241
  ];
216
- kubeObjectMenuItems = [{
242
+ kubeObjectMenuItems = [...[
243
+ "Pod",
244
+ "Deployment",
245
+ "DaemonSet",
246
+ "StatefulSet",
247
+ "ReplicaSet",
248
+ "Job",
249
+ "CronJob"
250
+ ].map((kind) => ({
251
+ kind,
252
+ apiVersions: kind === "Pod" ? ["v1"] : kind === "Job" || kind === "CronJob" ? ["batch/v1"] : ["apps/v1"],
253
+ components: { MenuItem: (props) => /* @__PURE__ */ require_jsx_runtime.jsx(PowerEnabled, { children: /* @__PURE__ */ require_jsx_runtime.jsx(require_power_logs_entrypoints.PowerLogsMenu, { ...props }) }) }
254
+ })), {
217
255
  kind: "Node",
218
256
  apiVersions: ["v1"],
219
257
  components: { MenuItem: (props) => /* @__PURE__ */ require_jsx_runtime.jsx(PowerEnabled, { children: /* @__PURE__ */ require_jsx_runtime.jsx(require_secure_node_shell_menu.SecureNodeShellMenu, { ...props }) }) }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/renderer/index.tsx"],"sourcesContent":["/**\n * Copyright (c) Freelens Authors. All rights reserved.\n * Licensed under MIT License. See THIRD_PARTY_LICENSES for more information.\n */\n\nimport { Common, Renderer } from \"@freelensapp/extensions\";\nimport { computed, reaction } from \"mobx\";\nimport { observer } from \"mobx-react\";\nimport { EXTENSION_DISPLAY_NAME, EXTENSION_ID } from \"../common/extension-info\";\nimport { AiPreferencesStore } from \"../common/store/ai-preferences-store\";\nimport { AiShortcutsStore } from \"../common/store/ai-shortcuts-store\";\nimport { AppearancePreferencesStore } from \"../common/store/appearance-preferences-store\";\nimport { DashboardPreferencesStore } from \"../common/store/dashboard-preferences-store\";\nimport { MonitoringPreferencesStore } from \"../common/store/monitoring-preferences-store\";\nimport { NodeShellPreferencesStore } from \"../common/store/node-shell-preferences-store\";\nimport { PowerPreferencesStore } from \"../common/store/power-preferences-store\";\nimport { ReadOnlyPreferencesStore } from \"../common/store/read-only-preferences-store\";\nimport { startAiChat } from \"./ai\";\nimport { startAppearanceOverride } from \"./appearance\";\nimport { startPowerButtonStyles } from \"./button-styles\";\nimport { ClusterIconsPage } from \"./cluster-icons\";\nimport { DashboardPage } from \"./dashboard\";\nimport { HpaDiagnosticsDetails } from \"./details/hpa-diagnostics-details\";\nimport { NamespaceHealthDetails } from \"./details/namespace-health-details\";\nimport { ResourceHealthDetails } from \"./details/resource-health-details\";\nimport { SecretCertificateDetails } from \"./details/secret-certificate-details\";\nimport { ServiceDiagnosticsDetails } from \"./details/service-diagnostics-details\";\nimport { DiagnosticsPage } from \"./diagnostics\";\nimport { type DiagnosticsResourceScope, focusDiagnosticsNamespace } from \"./diagnostics-state\";\nimport { SecureNodeShellMenu } from \"./menus/secure-node-shell-menu\";\nimport { startMonitoring } from \"./monitoring\";\nimport { startMonitoringCollector } from \"./monitoring-collector\";\nimport { startMonitoringHistoryCollection } from \"./monitoring-history-collection\";\nimport { NodeMonitoringDetails } from \"./node-monitoring\";\nimport { startPodMonitoring } from \"./pod-monitoring\";\nimport { PowerPreferences } from \"./preferences/preferences\";\nimport { startReadOnlyMode } from \"./read-only\";\nimport { ResourceRelationshipsPage } from \"./resource-relationships\";\nimport { startResourceSearch } from \"./resource-search\";\nimport { startWelcomeOverride } from \"./welcome\";\n\nimport type { ReactNode } from \"react\";\n\nconst PowerEnabled = observer(({ children }: { children: ReactNode }) =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled ? <>{children}</> : null,\n);\n\nconst RelationshipsPage = observer(() => (\n <PowerEnabled>\n <ResourceRelationshipsPage\n enabled={MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().relationshipsVisible}\n />\n </PowerEnabled>\n));\n\nexport default class FreelensPowerRenderer extends Renderer.LensExtension {\n get name() {\n return EXTENSION_DISPLAY_NAME;\n }\n get sanitizedExtensionId() {\n return EXTENSION_ID;\n }\n get storeName() {\n return this.manifest.storeName || EXTENSION_ID;\n }\n\n private stopFeatures?: () => void;\n\n onActivate() {\n const power = PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>();\n power.loadExtension(this);\n AiPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AiShortcutsStore.getInstanceOrCreate().loadExtension(this);\n ReadOnlyPreferencesStore.getInstanceOrCreate().loadExtension(this);\n NodeShellPreferencesStore.getInstanceOrCreate().loadExtension(this);\n MonitoringPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AppearancePreferencesStore.getInstanceOrCreate().loadExtension(this);\n DashboardPreferencesStore.getInstanceOrCreate().loadExtension(this);\n this.stopFeatures?.();\n let disposers: (() => void)[] = [];\n const stop = reaction(\n () => power.enabled,\n (enabled) => {\n for (const dispose of disposers) dispose();\n disposers = [];\n if (enabled) {\n for (const start of [\n startReadOnlyMode,\n startMonitoringCollector,\n startMonitoringHistoryCollection,\n startMonitoring,\n startPodMonitoring,\n startPowerButtonStyles,\n startAppearanceOverride,\n startWelcomeOverride,\n startAiChat,\n startResourceSearch,\n ]) {\n try {\n disposers.push(start());\n } catch {\n Common.logger.warn(\"[Freelens Power] feature could not start\", { feature: start.name });\n }\n }\n }\n },\n { fireImmediately: true },\n );\n this.stopFeatures = () => {\n stop();\n for (const dispose of disposers) dispose();\n disposers = [];\n };\n }\n\n onDeactivate() {\n this.stopFeatures?.();\n this.stopFeatures = undefined;\n }\n\n appPreferences = [\n {\n id: \"freelens-power-settings\",\n title: \"\",\n components: { Input: PowerPreferences, Hint: () => null },\n },\n ];\n\n globalPages = [\n {\n id: \"cluster-icons\",\n components: {\n Page: () => (\n <PowerEnabled>\n <ClusterIconsPage />\n </PowerEnabled>\n ),\n },\n },\n {\n id: \"dashboard\",\n components: {\n Page: () => (\n <PowerEnabled>\n <DashboardPage onOpenPreferences={() => this.navigateToPreferences()} />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n clusterPages = [\n { id: \"relationships\", components: { Page: () => <RelationshipsPage /> } },\n {\n id: \"diagnostics\",\n components: {\n Page: () => (\n <PowerEnabled>\n <DiagnosticsPage />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n clusterPageMenus = [\n {\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().diagnosticsVisible,\n ),\n target: { pageId: \"diagnostics\" },\n title: \"Diagnostics\",\n orderNumber: 5,\n components: { Icon: () => <Renderer.Component.Icon material=\"insights\" tooltip=\"Resource diagnostics\" /> },\n },\n {\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().relationshipsVisible,\n ),\n id: \"relationships\",\n target: { pageId: \"relationships\" },\n title: \"Relationships\",\n orderNumber: 6,\n components: {\n Icon: () => <Renderer.Component.Icon material=\"account_tree\" tooltip=\"Resource relationships\" />,\n },\n },\n ];\n\n topBarItems = [\n {\n components: {\n Item: () => (\n <PowerEnabled>\n <Renderer.Component.Icon\n material=\"battery_charging_full\"\n className=\"freelens-power-settings-icon\"\n tooltip=\"Freelens Power settings\"\n onClick={() => this.navigateToPreferences()}\n />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n private openDiagnostics = (namespace?: string, resourceScope?: DiagnosticsResourceScope) => {\n const clusterId = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n if (clusterId && (namespace || resourceScope)) focusDiagnosticsNamespace(clusterId, namespace, resourceScope);\n void this.navigate(\"diagnostics\");\n };\n\n kubeObjectDetailItems: Renderer.LensExtension[\"kubeObjectDetailItems\"] = [\n ...[\"Pod\", \"Deployment\", \"StatefulSet\", \"DaemonSet\", \"Node\"].map((kind) => ({\n kind,\n apiVersions: kind === \"Pod\" || kind === \"Node\" ? [\"v1\"] : [\"apps/v1\"],\n priority: 320,\n components: {\n Details: (props: Renderer.Component.KubeObjectDetailsProps) => (\n <PowerEnabled>\n <ResourceHealthDetails {...props} onOpenDiagnostics={this.openDiagnostics} />\n </PowerEnabled>\n ),\n },\n })),\n {\n kind: \"Namespace\",\n apiVersions: [\"v1\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <NamespaceHealthDetails {...props} onOpenDiagnostics={this.openDiagnostics} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Service\",\n apiVersions: [\"v1\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <ServiceDiagnosticsDetails {...props} object={props.object as Renderer.K8sApi.Service} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"HorizontalPodAutoscaler\",\n apiVersions: [\"autoscaling/v1\", \"autoscaling/v2\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <HpaDiagnosticsDetails {...props} object={props.object as Renderer.K8sApi.HorizontalPodAutoscaler} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Node\",\n apiVersions: [\"v1\"],\n // host order is [300 - priority], before native metrics at [-1]\n priority: 310,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <NodeMonitoringDetails {...props} object={props.object as Renderer.K8sApi.Node} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Secret\",\n apiVersions: [\"v1\"],\n priority: 10,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <SecretCertificateDetails {...props} object={props.object as Renderer.K8sApi.Secret} />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n kubeObjectMenuItems = [\n {\n kind: \"Node\",\n apiVersions: [\"v1\"],\n components: {\n MenuItem: (props: Renderer.Component.KubeObjectMenuProps<Renderer.K8sApi.Node>) => (\n <PowerEnabled>\n <SecureNodeShellMenu {...props} />\n </PowerEnabled>\n ),\n },\n },\n ];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/renderer/index.tsx"],"sourcesContent":["/**\n * Copyright (c) Freelens Authors. All rights reserved.\n * Licensed under MIT License. See THIRD_PARTY_LICENSES for more information.\n */\n\nimport { Common, Renderer } from \"@freelensapp/extensions\";\nimport { computed, reaction } from \"mobx\";\nimport { observer } from \"mobx-react\";\nimport { EXTENSION_DISPLAY_NAME, EXTENSION_ID } from \"../common/extension-info\";\nimport { AiPreferencesStore } from \"../common/store/ai-preferences-store\";\nimport { AiShortcutsStore } from \"../common/store/ai-shortcuts-store\";\nimport { AppearancePreferencesStore } from \"../common/store/appearance-preferences-store\";\nimport { DashboardPreferencesStore } from \"../common/store/dashboard-preferences-store\";\nimport { LogsPreferencesStore } from \"../common/store/logs-preferences-store\";\nimport { MonitoringPreferencesStore } from \"../common/store/monitoring-preferences-store\";\nimport { NodeShellPreferencesStore } from \"../common/store/node-shell-preferences-store\";\nimport { PowerPreferencesStore } from \"../common/store/power-preferences-store\";\nimport { ReadOnlyPreferencesStore } from \"../common/store/read-only-preferences-store\";\nimport { startAiChat } from \"./ai\";\nimport { startAppearanceOverride } from \"./appearance\";\nimport { startPowerButtonStyles } from \"./button-styles\";\nimport { ClusterIconsPage } from \"./cluster-icons\";\nimport { DashboardPage } from \"./dashboard\";\nimport { HpaDiagnosticsDetails } from \"./details/hpa-diagnostics-details\";\nimport { NamespaceHealthDetails } from \"./details/namespace-health-details\";\nimport { ResourceHealthDetails } from \"./details/resource-health-details\";\nimport { SecretCertificateDetails } from \"./details/secret-certificate-details\";\nimport { ServiceDiagnosticsDetails } from \"./details/service-diagnostics-details\";\nimport { DiagnosticsPage } from \"./diagnostics\";\nimport { type DiagnosticsResourceScope, focusDiagnosticsNamespace } from \"./diagnostics-state\";\nimport { SecureNodeShellMenu } from \"./menus/secure-node-shell-menu\";\nimport { startMonitoring } from \"./monitoring\";\nimport { startMonitoringCollector } from \"./monitoring-collector\";\nimport { startMonitoringHistoryCollection } from \"./monitoring-history-collection\";\nimport { NodeMonitoringDetails } from \"./node-monitoring\";\nimport { startPodMonitoring } from \"./pod-monitoring\";\nimport { PowerLogsPage } from \"./power-logs\";\nimport { PowerLogsMenu, startPowerLogsEntrypoints } from \"./power-logs-entrypoints\";\nimport { PowerPreferences } from \"./preferences/preferences\";\nimport { startReadOnlyMode } from \"./read-only\";\nimport { ResourceRelationshipsPage } from \"./resource-relationships\";\nimport { startResourceSearch } from \"./resource-search\";\nimport { startWelcomeOverride } from \"./welcome\";\n\nimport type { ReactNode } from \"react\";\n\nconst PowerEnabled = observer(({ children }: { children: ReactNode }) =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled ? <>{children}</> : null,\n);\n\nconst RelationshipsPage = observer(() => (\n <PowerEnabled>\n <ResourceRelationshipsPage\n enabled={MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().relationshipsVisible}\n />\n </PowerEnabled>\n));\n\nexport default class FreelensPowerRenderer extends Renderer.LensExtension {\n get name() {\n return EXTENSION_DISPLAY_NAME;\n }\n get sanitizedExtensionId() {\n return EXTENSION_ID;\n }\n get storeName() {\n return this.manifest.storeName || EXTENSION_ID;\n }\n\n private stopFeatures?: () => void;\n\n onActivate() {\n const power = PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>();\n power.loadExtension(this);\n LogsPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AiPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AiShortcutsStore.getInstanceOrCreate().loadExtension(this);\n ReadOnlyPreferencesStore.getInstanceOrCreate().loadExtension(this);\n NodeShellPreferencesStore.getInstanceOrCreate().loadExtension(this);\n MonitoringPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AppearancePreferencesStore.getInstanceOrCreate().loadExtension(this);\n DashboardPreferencesStore.getInstanceOrCreate().loadExtension(this);\n this.stopFeatures?.();\n let disposers: (() => void)[] = [];\n const stop = reaction(\n () => power.enabled,\n (enabled) => {\n for (const dispose of disposers) dispose();\n disposers = [];\n if (enabled) {\n for (const start of [\n startReadOnlyMode,\n startMonitoringCollector,\n startMonitoringHistoryCollection,\n startMonitoring,\n startPodMonitoring,\n startPowerButtonStyles,\n startAppearanceOverride,\n startWelcomeOverride,\n startAiChat,\n startResourceSearch,\n startPowerLogsEntrypoints,\n ]) {\n try {\n disposers.push(start());\n } catch {\n Common.logger.warn(\"[Freelens Power] feature could not start\", { feature: start.name });\n }\n }\n }\n },\n { fireImmediately: true },\n );\n this.stopFeatures = () => {\n stop();\n for (const dispose of disposers) dispose();\n disposers = [];\n };\n }\n\n onDeactivate() {\n this.stopFeatures?.();\n this.stopFeatures = undefined;\n }\n\n appPreferences = [\n {\n id: \"freelens-power-settings\",\n title: \"\",\n components: { Input: PowerPreferences, Hint: () => null },\n },\n ];\n\n globalPages = [\n {\n id: \"cluster-icons\",\n components: {\n Page: () => (\n <PowerEnabled>\n <ClusterIconsPage />\n </PowerEnabled>\n ),\n },\n },\n {\n id: \"dashboard\",\n components: {\n Page: () => (\n <PowerEnabled>\n <DashboardPage onOpenPreferences={() => this.navigateToPreferences()} />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n clusterPages = [\n {\n id: \"power-logs\",\n components: {\n Page: () => (\n <PowerEnabled>\n <PowerLogsPage />\n </PowerEnabled>\n ),\n },\n },\n { id: \"relationships\", components: { Page: () => <RelationshipsPage /> } },\n {\n id: \"diagnostics\",\n components: {\n Page: () => (\n <PowerEnabled>\n <DiagnosticsPage />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n clusterPageMenus = [\n {\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().diagnosticsVisible,\n ),\n target: { pageId: \"diagnostics\" },\n title: \"Diagnostics\",\n orderNumber: 5,\n components: { Icon: () => <Renderer.Component.Icon material=\"insights\" tooltip=\"Resource diagnostics\" /> },\n },\n {\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>().relationshipsVisible,\n ),\n id: \"relationships\",\n target: { pageId: \"relationships\" },\n title: \"Relationships\",\n orderNumber: 6,\n components: {\n Icon: () => <Renderer.Component.Icon material=\"account_tree\" tooltip=\"Resource relationships\" />,\n },\n },\n {\n id: \"power-logs\",\n visible: computed(\n () =>\n PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>().enabled &&\n LogsPreferencesStore.getInstanceOrCreate<LogsPreferencesStore>().enabled,\n ),\n target: { pageId: \"power-logs\" },\n title: \"Power Logs\",\n orderNumber: 7,\n components: {\n Icon: () => <Renderer.Component.Icon material=\"subject\" tooltip=\"Workload logs and SQL captures\" />,\n },\n },\n ];\n\n topBarItems = [\n {\n components: {\n Item: () => (\n <PowerEnabled>\n <Renderer.Component.Icon\n material=\"battery_charging_full\"\n className=\"freelens-power-settings-icon\"\n tooltip=\"Freelens Power settings\"\n onClick={() => this.navigateToPreferences()}\n />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n private openDiagnostics = (namespace?: string, resourceScope?: DiagnosticsResourceScope) => {\n const clusterId = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n if (clusterId && (namespace || resourceScope)) focusDiagnosticsNamespace(clusterId, namespace, resourceScope);\n void this.navigate(\"diagnostics\");\n };\n\n kubeObjectDetailItems: Renderer.LensExtension[\"kubeObjectDetailItems\"] = [\n ...[\"Pod\", \"Deployment\", \"StatefulSet\", \"DaemonSet\", \"Node\"].map((kind) => ({\n kind,\n apiVersions: kind === \"Pod\" || kind === \"Node\" ? [\"v1\"] : [\"apps/v1\"],\n priority: 320,\n components: {\n Details: (props: Renderer.Component.KubeObjectDetailsProps) => (\n <PowerEnabled>\n <ResourceHealthDetails {...props} onOpenDiagnostics={this.openDiagnostics} />\n </PowerEnabled>\n ),\n },\n })),\n {\n kind: \"Namespace\",\n apiVersions: [\"v1\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <NamespaceHealthDetails {...props} onOpenDiagnostics={this.openDiagnostics} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Service\",\n apiVersions: [\"v1\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <ServiceDiagnosticsDetails {...props} object={props.object as Renderer.K8sApi.Service} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"HorizontalPodAutoscaler\",\n apiVersions: [\"autoscaling/v1\", \"autoscaling/v2\"],\n priority: 320,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <HpaDiagnosticsDetails {...props} object={props.object as Renderer.K8sApi.HorizontalPodAutoscaler} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Node\",\n apiVersions: [\"v1\"],\n // host order is [300 - priority], before native metrics at [-1]\n priority: 310,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <NodeMonitoringDetails {...props} object={props.object as Renderer.K8sApi.Node} />\n </PowerEnabled>\n ),\n },\n },\n {\n kind: \"Secret\",\n apiVersions: [\"v1\"],\n priority: 10,\n components: {\n Details: (props) => (\n <PowerEnabled>\n <SecretCertificateDetails {...props} object={props.object as Renderer.K8sApi.Secret} />\n </PowerEnabled>\n ),\n },\n },\n ];\n\n kubeObjectMenuItems = [\n ...([\"Pod\", \"Deployment\", \"DaemonSet\", \"StatefulSet\", \"ReplicaSet\", \"Job\", \"CronJob\"] as const).map((kind) => ({\n kind,\n apiVersions: kind === \"Pod\" ? [\"v1\"] : kind === \"Job\" || kind === \"CronJob\" ? [\"batch/v1\"] : [\"apps/v1\"],\n components: {\n MenuItem: (props: Renderer.Component.KubeObjectMenuProps<Renderer.K8sApi.KubeObject>) => (\n <PowerEnabled>\n <PowerLogsMenu {...props} />\n </PowerEnabled>\n ),\n },\n })),\n {\n kind: \"Node\",\n apiVersions: [\"v1\"],\n components: {\n MenuItem: (props: Renderer.Component.KubeObjectMenuProps<Renderer.K8sApi.Node>) => (\n <PowerEnabled>\n <SecureNodeShellMenu {...props} />\n </PowerEnabled>\n ),\n },\n },\n ];\n}\n"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ const require_jsx_runtime = require("./_virtual/_global-external_react/jsx-runtime.js");
2
+ //#region src/renderer/power-log-json.tsx
3
+ function LogJson({ text }) {
4
+ const tokens = [];
5
+ const pattern = /"(?:\\.|[^"\\])*"(?:\s*:)?|\b(?:true|false|null)\b|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/g;
6
+ let cursor = 0;
7
+ for (const match of text.matchAll(pattern)) {
8
+ const start = match.index;
9
+ tokens.push(text.slice(cursor, start));
10
+ const value = match[0];
11
+ const key = value.startsWith("\"") && value.endsWith(":");
12
+ const kind = key ? "key" : value.startsWith("\"") ? "string" : /^(true|false|null)$/.test(value) ? "literal" : "number";
13
+ tokens.push(/* @__PURE__ */ require_jsx_runtime.jsx("span", {
14
+ "data-token": kind,
15
+ children: key ? value.slice(0, -1) : value
16
+ }, start));
17
+ if (key) tokens.push(":");
18
+ cursor = start + value.length;
19
+ }
20
+ tokens.push(text.slice(cursor));
21
+ return /* @__PURE__ */ require_jsx_runtime.jsx("pre", {
22
+ className: "power-log-json",
23
+ children: tokens
24
+ });
25
+ }
26
+ //#endregion
27
+ exports.LogJson = LogJson;
28
+
29
+ //# sourceMappingURL=power-log-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"power-log-json.js","names":[],"sources":["../../src/renderer/power-log-json.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\n\nexport function LogJson({ text }: { text: string }) {\n const tokens: ReactNode[] = [];\n const pattern = /\"(?:\\\\.|[^\"\\\\])*\"(?:\\s*:)?|\\b(?:true|false|null)\\b|-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?/g;\n let cursor = 0;\n for (const match of text.matchAll(pattern)) {\n const start = match.index!;\n tokens.push(text.slice(cursor, start));\n const value = match[0];\n const key = value.startsWith('\"') && value.endsWith(\":\");\n const kind = key\n ? \"key\"\n : value.startsWith('\"')\n ? \"string\"\n : /^(true|false|null)$/.test(value)\n ? \"literal\"\n : \"number\";\n tokens.push(\n <span key={start} data-token={kind}>\n {key ? value.slice(0, -1) : value}\n </span>,\n );\n if (key) tokens.push(\":\");\n cursor = start + value.length;\n }\n tokens.push(text.slice(cursor));\n return <pre className=\"power-log-json\">{tokens}</pre>;\n}\n"],"mappings":";;AAEA,SAAgB,QAAQ,EAAE,QAA0B;CAClD,MAAM,SAAsB,CAAC;CAC7B,MAAM,UAAU;CAChB,IAAI,SAAS;CACb,KAAK,MAAM,SAAS,KAAK,SAAS,OAAO,GAAG;EAC1C,MAAM,QAAQ,MAAM;EACpB,OAAO,KAAK,KAAK,MAAM,QAAQ,KAAK,CAAC;EACrC,MAAM,QAAQ,MAAM;EACpB,MAAM,MAAM,MAAM,WAAW,IAAG,KAAK,MAAM,SAAS,GAAG;EACvD,MAAM,OAAO,MACT,QACA,MAAM,WAAW,IAAG,IAClB,WACA,sBAAsB,KAAK,KAAK,IAC9B,YACA;EACR,OAAO,KACL,oCAAA,IAAC,QAAD;GAAkB,cAAY;aAC3B,MAAM,MAAM,MAAM,GAAG,EAAE,IAAI;EACxB,GAFK,KAEL,CACR;EACA,IAAI,KAAK,OAAO,KAAK,GAAG;EACxB,SAAS,QAAQ,MAAM;CACzB;CACA,OAAO,KAAK,KAAK,MAAM,MAAM,CAAC;CAC9B,OAAO,oCAAA,IAAC,OAAD;EAAK,WAAU;YAAkB;CAAY,CAAA;AACtD"}
@@ -0,0 +1,35 @@
1
+ const require_power_logs = require("./src/common/power-logs.js");
2
+ let electron = require("electron");
3
+ //#region src/renderer/power-logs-client.ts
4
+ function createPowerLogsClient(partition) {
5
+ const invoke = (operation, fields = {}) => electron.ipcRenderer.invoke(require_power_logs.POWER_LOGS_CHANNEL, {
6
+ ...partition,
7
+ operation,
8
+ ...fields
9
+ });
10
+ return {
11
+ list: () => invoke("list"),
12
+ create: (target) => invoke("create", { target }),
13
+ append: (captureId, records) => invoke("append", {
14
+ captureId,
15
+ records
16
+ }),
17
+ finish: (captureId, partial, notes) => invoke("finish", {
18
+ captureId,
19
+ partial,
20
+ notes
21
+ }),
22
+ delete: (captureId) => invoke("delete", { captureId }),
23
+ query: (captureId, queryId, sql) => invoke("query", {
24
+ captureId,
25
+ queryId,
26
+ sql
27
+ }),
28
+ cancel: (queryId) => invoke("cancel", { queryId }),
29
+ export: (captureId) => invoke("export", { captureId })
30
+ };
31
+ }
32
+ //#endregion
33
+ exports.createPowerLogsClient = createPowerLogsClient;
34
+
35
+ //# sourceMappingURL=power-logs-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"power-logs-client.js","names":[],"sources":["../../src/renderer/power-logs-client.ts"],"sourcesContent":["import { ipcRenderer } from \"electron\";\nimport {\n type LogCapture,\n type LogPartition,\n type LogQueryResult,\n type LogRecord,\n type LogTarget,\n POWER_LOGS_CHANNEL,\n} from \"../common/power-logs\";\n\nexport function createPowerLogsClient(partition: LogPartition) {\n const invoke = <T>(operation: string, fields: object = {}): Promise<T> =>\n ipcRenderer.invoke(POWER_LOGS_CHANNEL, { ...partition, operation, ...fields });\n return {\n list: () => invoke<LogCapture[]>(\"list\"),\n create: (target: LogTarget) => invoke<LogCapture>(\"create\", { target }),\n append: (captureId: string, records: LogRecord[]) => invoke<LogCapture>(\"append\", { captureId, records }),\n finish: (captureId: string, partial: boolean, notes: string[]) =>\n invoke<LogCapture>(\"finish\", { captureId, partial, notes }),\n delete: (captureId: string) => invoke<boolean>(\"delete\", { captureId }),\n query: (captureId: string, queryId: string, sql: string) =>\n invoke<LogQueryResult>(\"query\", { captureId, queryId, sql }),\n cancel: (queryId: string) => invoke<boolean>(\"cancel\", { queryId }),\n export: (captureId: string) => invoke<boolean>(\"export\", { captureId }),\n };\n}\n"],"mappings":";;;AAUA,SAAgB,sBAAsB,WAAyB;CAC7D,MAAM,UAAa,WAAmB,SAAiB,CAAC,MACtD,SAAA,YAAY,OAAO,mBAAA,oBAAoB;EAAE,GAAG;EAAW;EAAW,GAAG;CAAO,CAAC;CAC/E,OAAO;EACL,YAAY,OAAqB,MAAM;EACvC,SAAS,WAAsB,OAAmB,UAAU,EAAE,OAAO,CAAC;EACtE,SAAS,WAAmB,YAAyB,OAAmB,UAAU;GAAE;GAAW;EAAQ,CAAC;EACxG,SAAS,WAAmB,SAAkB,UAC5C,OAAmB,UAAU;GAAE;GAAW;GAAS;EAAM,CAAC;EAC5D,SAAS,cAAsB,OAAgB,UAAU,EAAE,UAAU,CAAC;EACtE,QAAQ,WAAmB,SAAiB,QAC1C,OAAuB,SAAS;GAAE;GAAW;GAAS;EAAI,CAAC;EAC7D,SAAS,YAAoB,OAAgB,UAAU,EAAE,QAAQ,CAAC;EAClE,SAAS,cAAsB,OAAgB,UAAU,EAAE,UAAU,CAAC;CACxE;AACF"}
@@ -0,0 +1,316 @@
1
+ const require_power_logs = require("./src/common/power-logs.js");
2
+ const require_power_log_parser = require("./src/common/power-log-parser.js");
3
+ let node_crypto = require("node:crypto");
4
+ //#region src/renderer/power-logs-collector.ts
5
+ var resources = {
6
+ Pod: ["/api/v1", "pods"],
7
+ Deployment: ["/apis/apps/v1", "deployments"],
8
+ ReplicaSet: ["/apis/apps/v1", "replicasets"],
9
+ DaemonSet: ["/apis/apps/v1", "daemonsets"],
10
+ StatefulSet: ["/apis/apps/v1", "statefulsets"],
11
+ Job: ["/apis/batch/v1", "jobs"],
12
+ CronJob: ["/apis/batch/v1", "cronjobs"]
13
+ };
14
+ var pathFor = (kind, namespace) => `${resources[kind][0]}/namespaces/${encodeURIComponent(namespace)}/${resources[kind][1]}`;
15
+ var canceled = () => /* @__PURE__ */ new Error("Log collection canceled");
16
+ function check(signal) {
17
+ if (signal?.aborted) throw canceled();
18
+ }
19
+ async function delay(ms, signal) {
20
+ check(signal);
21
+ await new Promise((resolve, reject) => {
22
+ const abort = () => {
23
+ clearTimeout(timer);
24
+ reject(canceled());
25
+ };
26
+ const timer = setTimeout(() => {
27
+ signal?.removeEventListener("abort", abort);
28
+ resolve();
29
+ }, ms);
30
+ signal?.addEventListener("abort", abort, { once: true });
31
+ });
32
+ }
33
+ var nextStart = 0;
34
+ var nextBytes = 0;
35
+ async function permit(signal) {
36
+ const start = Math.max(Date.now(), nextStart);
37
+ nextStart = start + 1e3 / require_power_logs.POWER_LOGS_LIMITS.requestsPerSecond;
38
+ await delay(Math.max(0, start - Date.now()), signal);
39
+ }
40
+ async function bytesPermit(bytes, signal) {
41
+ const start = Math.max(Date.now(), nextBytes);
42
+ nextBytes = start + bytes / require_power_logs.POWER_LOGS_LIMITS.bytesPerSecond * 1e3;
43
+ await delay(Math.max(0, start - Date.now()), signal);
44
+ }
45
+ async function request(operation, signal) {
46
+ for (let attempt = 0;; attempt++) {
47
+ await permit(signal);
48
+ try {
49
+ return await operation();
50
+ } catch (error) {
51
+ check(signal);
52
+ const value = error;
53
+ if (attempt >= 2 || ![429, 503].includes(value.status ?? 0)) throw new Error("Log API request failed");
54
+ const seconds = Number(value.retryAfter);
55
+ const wait = Number.isFinite(seconds) ? seconds * 1e3 : Date.parse(value.retryAfter ?? "") - Date.now();
56
+ await delay(Math.min(5e3, Math.max(500, Number.isFinite(wait) ? wait : 1e3)), signal);
57
+ }
58
+ }
59
+ }
60
+ async function resolveLogSources(target, transport, signal) {
61
+ const root = await request(() => transport.get(`${pathFor(target.kind, target.namespace)}/${encodeURIComponent(target.name)}`, void 0, signal), signal);
62
+ if (root.metadata?.uid !== target.uid) throw new Error("The selected workload has changed");
63
+ const notes = [];
64
+ async function list(kind) {
65
+ const items = [];
66
+ let continuation = "";
67
+ const seen = /* @__PURE__ */ new Set();
68
+ do {
69
+ const page = await request(() => transport.get(pathFor(kind, target.namespace), {
70
+ limit: 200,
71
+ ...continuation ? { continue: continuation } : {}
72
+ }, signal), signal);
73
+ items.push(...page.items ?? []);
74
+ continuation = page.metadata?.continue ?? "";
75
+ if (continuation && seen.has(continuation)) throw new Error("Repeated resource page");
76
+ seen.add(continuation);
77
+ if (items.length >= 1e4 && continuation) {
78
+ notes.push("Resource discovery reached its page budget");
79
+ break;
80
+ }
81
+ } while (continuation);
82
+ return items;
83
+ }
84
+ let owners = /* @__PURE__ */ new Set([target.uid]);
85
+ const owned = (item) => item.metadata?.ownerReferences?.some((owner) => owners.has(owner.uid) && owner.controller === true);
86
+ if (target.kind === "Deployment" || target.kind === "CronJob") {
87
+ const children = await list(target.kind === "Deployment" ? "ReplicaSet" : "Job");
88
+ owners = new Set(children.filter(owned).flatMap((item) => item.metadata?.uid ? [item.metadata.uid] : []));
89
+ }
90
+ const pods = target.kind === "Pod" ? [root] : (await list("Pod")).filter(owned);
91
+ const sources = [];
92
+ for (const pod of pods) {
93
+ if (!pod.metadata?.uid || !pod.metadata.name || pod.metadata.namespace && pod.metadata.namespace !== target.namespace) continue;
94
+ for (const container of [...pod.spec?.containers ?? [], ...pod.spec?.initContainers ?? []]) {
95
+ if (sources.length >= require_power_logs.POWER_LOGS_LIMITS.sources) {
96
+ notes.push(`Only the first ${require_power_logs.POWER_LOGS_LIMITS.sources} container sources are included`);
97
+ return {
98
+ sources,
99
+ partial: true,
100
+ notes
101
+ };
102
+ }
103
+ sources.push({
104
+ namespace: target.namespace,
105
+ pod: pod.metadata.name,
106
+ podUid: pod.metadata.uid,
107
+ container: container.name
108
+ });
109
+ }
110
+ }
111
+ return {
112
+ sources,
113
+ partial: notes.length > 0,
114
+ notes
115
+ };
116
+ }
117
+ var historicalActive = 0;
118
+ async function historicalSlot(signal) {
119
+ while (historicalActive >= require_power_logs.POWER_LOGS_LIMITS.historyConcurrency) await delay(50, signal);
120
+ check(signal);
121
+ historicalActive++;
122
+ }
123
+ async function consume(source, transport, options, follow) {
124
+ const podPath = `/api/v1/namespaces/${encodeURIComponent(source.namespace)}/pods/${encodeURIComponent(source.pod)}`;
125
+ if ((await request(() => transport.get(podPath, void 0, options.signal), options.signal)).metadata?.uid !== source.podUid) throw new Error("The container source has changed");
126
+ const decoder = new require_power_log_parser.LogLineDecoder();
127
+ let bytes = 0;
128
+ let lineCount = 0;
129
+ const query = {
130
+ container: source.container,
131
+ timestamps: true,
132
+ follow,
133
+ tailLines: Math.max(1, Math.min(Math.max(require_power_logs.POWER_LOGS_LIMITS.historyLines, require_power_logs.POWER_LOGS_LIMITS.captureSourceLines), options.tailLines ?? require_power_logs.POWER_LOGS_LIMITS.historyLines)),
134
+ ...!follow ? { limitBytes: Math.max(1, Math.min(Math.max(require_power_logs.POWER_LOGS_LIMITS.historyBytes, require_power_logs.POWER_LOGS_LIMITS.captureSourceBytes), options.limitBytes ?? require_power_logs.POWER_LOGS_LIMITS.historyBytes)) } : {},
135
+ ...source.previous ? { previous: true } : {},
136
+ ...options.sinceTime ? { sinceTime: options.sinceTime } : options.sinceSeconds ? { sinceSeconds: options.sinceSeconds } : {}
137
+ };
138
+ const path = `/api/v1/namespaces/${encodeURIComponent(source.namespace)}/pods/${encodeURIComponent(source.pod)}/log`;
139
+ let started = false;
140
+ let opened = false;
141
+ try {
142
+ await request(async () => {
143
+ try {
144
+ for await (const chunk of transport.stream(path, query, options.signal, () => {
145
+ if (!opened) {
146
+ opened = true;
147
+ options.onSourceActivity?.(1);
148
+ }
149
+ })) {
150
+ started = true;
151
+ check(options.signal);
152
+ const size = typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.byteLength;
153
+ bytes += size;
154
+ if (!follow && bytes > Number(query.limitBytes)) return;
155
+ await bytesPermit(size, options.signal);
156
+ const records = decoder.push(chunk).map((line) => require_power_log_parser.parseLogLine(line, source));
157
+ lineCount += records.length;
158
+ if (records.length) await options.onRecords(records);
159
+ }
160
+ } catch (error) {
161
+ if (started) throw new Error("Container log stream interrupted");
162
+ throw error;
163
+ }
164
+ const final = decoder.push(/* @__PURE__ */ new Uint8Array(), true).map((line) => require_power_log_parser.parseLogLine(line, source));
165
+ lineCount += final.length;
166
+ if (final.length) await options.onRecords(final);
167
+ }, options.signal);
168
+ } finally {
169
+ if (opened) options.onSourceActivity?.(-1);
170
+ }
171
+ return decoder.truncated || !follow && (bytes >= Number(query.limitBytes) || lineCount >= Number(query.tailLines)) || follow && started;
172
+ }
173
+ async function collectHistoricalLogs(sources, transport, options) {
174
+ const notes = [];
175
+ let next = 0;
176
+ await Promise.all(Array.from({ length: Math.min(require_power_logs.POWER_LOGS_LIMITS.historyConcurrency, sources.length) }, async () => {
177
+ while (next < sources.length) {
178
+ const source = sources[next++];
179
+ await historicalSlot(options.signal);
180
+ try {
181
+ if (await consume(source, transport, options, false)) notes.push("Some source logs reached a collection limit");
182
+ } catch {
183
+ check(options.signal);
184
+ notes.push("A container log source was unavailable");
185
+ } finally {
186
+ historicalActive--;
187
+ }
188
+ }
189
+ }));
190
+ return {
191
+ partial: notes.length > 0,
192
+ notes: [...new Set(notes)]
193
+ };
194
+ }
195
+ function startLiveLogs(sources, transport, options) {
196
+ const controller = new AbortController();
197
+ const stop = () => controller.abort();
198
+ options.signal?.addEventListener("abort", stop, { once: true });
199
+ if (options.signal?.aborted) stop();
200
+ const coverage = {
201
+ active: 0,
202
+ total: sources.length,
203
+ partial: sources.length > require_power_logs.POWER_LOGS_LIMITS.liveConcurrency,
204
+ notes: sources.length > require_power_logs.POWER_LOGS_LIMITS.liveConcurrency ? ["All sources are polled in rotation; live coverage is delayed and bounded tails can omit busy-source logs"] : []
205
+ };
206
+ const notify = () => options.onCoverage?.({
207
+ ...coverage,
208
+ notes: [...coverage.notes]
209
+ });
210
+ const note = (message) => {
211
+ coverage.partial = true;
212
+ if (!coverage.notes.includes(message)) coverage.notes.push(message);
213
+ notify();
214
+ };
215
+ notify();
216
+ const seen = /* @__PURE__ */ new Map();
217
+ const cursors = /* @__PURE__ */ new Map();
218
+ const sourceKey = (source) => `${source.podUid}/${source.container}/${Boolean(source.previous)}`;
219
+ const recordKey = (record) => {
220
+ const projected = {
221
+ timestamp: record.timestamp,
222
+ pod: record.pod,
223
+ podUid: record.podUid,
224
+ container: record.container,
225
+ level: record.level,
226
+ message: record.message,
227
+ fieldsJson: record.fieldsJson,
228
+ previous: record.previous === true
229
+ };
230
+ return (0, node_crypto.createHash)("sha256").update(sourceKey(record)).update(JSON.stringify(projected)).digest("hex");
231
+ };
232
+ const initialCounts = /* @__PURE__ */ new Map();
233
+ for (const record of (options.initialRecords ?? []).slice(-require_power_logs.POWER_LOGS_LIMITS.liveRows)) {
234
+ const digest = recordKey(record), occurrence = (initialCounts.get(digest) ?? 0) + 1;
235
+ initialCounts.set(digest, occurrence);
236
+ seen.set(`${digest}/${occurrence}`, true);
237
+ if (record.timestamp !== null) cursors.set(sourceKey(record), Math.max(cursors.get(sourceKey(record)) ?? 0, record.timestamp));
238
+ }
239
+ async function collect(source, follow) {
240
+ const key = sourceKey(source);
241
+ const counts = /* @__PURE__ */ new Map();
242
+ const cursor = cursors.get(key);
243
+ return consume(source, transport, {
244
+ ...options,
245
+ signal: controller.signal,
246
+ onSourceActivity: (delta) => {
247
+ coverage.active = Math.max(0, coverage.active + delta);
248
+ notify();
249
+ },
250
+ ...cursor !== void 0 ? { sinceTime: new Date(cursor).toISOString() } : {},
251
+ onRecords: async (records) => {
252
+ const fresh = [];
253
+ for (const record of records) {
254
+ const digest = recordKey(record);
255
+ const occurrence = (counts.get(digest) ?? 0) + 1;
256
+ counts.set(digest, occurrence);
257
+ const identity = `${digest}/${occurrence}`;
258
+ if (!seen.has(identity)) {
259
+ fresh.push(record);
260
+ seen.set(identity, true);
261
+ }
262
+ if (record.timestamp !== null) cursors.set(key, Math.max(cursors.get(key) ?? 0, record.timestamp));
263
+ while (seen.size > require_power_logs.POWER_LOGS_LIMITS.liveRows) seen.delete(seen.keys().next().value);
264
+ if (counts.size > require_power_logs.POWER_LOGS_LIMITS.liveRows) counts.delete(counts.keys().next().value);
265
+ }
266
+ if (fresh.length) await options.onRecords(fresh);
267
+ }
268
+ }, follow);
269
+ }
270
+ return {
271
+ stop,
272
+ coverage,
273
+ done: (async () => {
274
+ if (sources.length > require_power_logs.POWER_LOGS_LIMITS.liveConcurrency) while (!controller.signal.aborted) {
275
+ let next = 0;
276
+ await Promise.all(Array.from({ length: require_power_logs.POWER_LOGS_LIMITS.historyConcurrency }, async () => {
277
+ while (next < sources.length && !controller.signal.aborted) {
278
+ const source = sources[next++];
279
+ await historicalSlot(controller.signal);
280
+ try {
281
+ if (await collect(source, false)) note("Some live polling tails reached their byte or line budget");
282
+ } catch {
283
+ if (!controller.signal.aborted) note("A live container log source was unavailable");
284
+ } finally {
285
+ historicalActive--;
286
+ }
287
+ }
288
+ }));
289
+ await delay(5e3, controller.signal);
290
+ }
291
+ else await Promise.all(sources.map(async (source) => {
292
+ while (!controller.signal.aborted) {
293
+ try {
294
+ await collect(source, true);
295
+ if (!controller.signal.aborted) note("A live source disconnected and is reconnecting");
296
+ } catch {
297
+ if (!controller.signal.aborted) note("A live container log source was unavailable and is reconnecting");
298
+ }
299
+ await delay(5e3, controller.signal);
300
+ }
301
+ }));
302
+ })().catch(() => {
303
+ if (!controller.signal.aborted) note("Live collection stopped unexpectedly");
304
+ }).finally(() => {
305
+ options.signal?.removeEventListener("abort", stop);
306
+ coverage.active = 0;
307
+ notify();
308
+ })
309
+ };
310
+ }
311
+ //#endregion
312
+ exports.collectHistoricalLogs = collectHistoricalLogs;
313
+ exports.resolveLogSources = resolveLogSources;
314
+ exports.startLiveLogs = startLiveLogs;
315
+
316
+ //# sourceMappingURL=power-logs-collector.js.map