1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Extracting metrics out of stores

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
Alex Andreev 2021-07-19 13:22:49 +03:00
parent 1d09251a70
commit 3772c82542
15 changed files with 141 additions and 237 deletions

View File

@ -27,13 +27,12 @@ import kebabCase from "lodash/kebabCase";
import { disposeOnUnmount, observer } from "mobx-react";
import { DrawerItem, DrawerItemLabels } from "../drawer";
import { Badge } from "../badge";
import { nodesStore } from "./nodes.store";
import { ResourceMetrics } from "../resource-metrics";
import { podsStore } from "../+workloads-pods/pods.store";
import type { KubeObjectDetailsProps } from "../kube-object";
import type { Node } from "../../api/endpoints";
import { getMetricsByNodeNames, IClusterMetrics, Node } from "../../api/endpoints";
import { NodeCharts } from "./node-charts";
import { reaction } from "mobx";
import { action, observable, reaction } from "mobx";
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
@ -46,17 +45,22 @@ interface Props extends KubeObjectDetailsProps<Node> {
@observer
export class NodeDetails extends React.Component<Props> {
@observable metrics: Partial<IClusterMetrics>;
@disposeOnUnmount
clean = reaction(() => this.props.object.getName(), () => {
nodesStore.nodeMetrics = null;
this.metrics = null;
});
async componentDidMount() {
podsStore.reloadAll();
}
componentWillUnmount() {
nodesStore.nodeMetrics = null;
@action
async loadMetrics() {
const { object: node } = this.props;
this.metrics = await getMetricsByNodeNames([node.getName()]);
}
render() {
@ -68,7 +72,7 @@ export class NodeDetails extends React.Component<Props> {
const conditions = node.getActiveConditions();
const taints = node.getTaints();
const childPods = podsStore.getPodsByNode(node.getName());
const metrics = nodesStore.nodeMetrics;
const { metrics } = this;
const metricTabs = [
"CPU",
"Memory",
@ -81,7 +85,7 @@ export class NodeDetails extends React.Component<Props> {
<div className="NodeDetails">
{!isMetricHidden && podsStore.isLoaded && (
<ResourceMetrics
loader={() => nodesStore.loadMetrics(node.getName())}
loader={this.loadMetrics}
tabs={metricTabs} object={node} params={{ metrics }}
>
<NodeCharts/>

View File

@ -18,22 +18,17 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { sum } from "lodash";
import { action, computed, observable, makeObservable } from "mobx";
import { clusterApi, IClusterMetrics, INodeMetrics, Node, nodesApi } from "../../api/endpoints";
import { autoBind } from "../../utils";
import { KubeObjectStore } from "../../kube-object.store";
import { computed, makeObservable } from "mobx";
import { apiManager } from "../../api/api-manager";
import { Node, nodesApi } from "../../api/endpoints";
import { KubeObjectStore } from "../../kube-object.store";
import { autoBind } from "../../utils";
export class NodesStore extends KubeObjectStore<Node> {
api = nodesApi;
@observable metrics: Partial<INodeMetrics> = {};
@observable nodeMetrics: Partial<IClusterMetrics> = null;
@observable metricsLoading = false;
@observable metricsLoaded = false;
constructor() {
super();
@ -41,23 +36,6 @@ export class NodesStore extends KubeObjectStore<Node> {
autoBind(this);
}
@action
async loadUsageMetrics() {
this.metricsLoading = true;
try {
this.metrics = await nodesApi.getMetrics();
this.metricsLoaded = true;
} finally {
this.metricsLoading = false;
}
}
@action
async loadMetrics(nodeName: string) {
this.nodeMetrics = await clusterApi.getMetrics([nodeName]);
}
@computed get masterNodes() {
return this.items.filter(node => node.getRoleLabels().includes("master"));
}
@ -66,41 +44,9 @@ export class NodesStore extends KubeObjectStore<Node> {
return this.items.filter(node => !node.getRoleLabels().includes("master"));
}
getLastMetricValues(node: Node, metricNames: string[]): number[] {
if (!this.metricsLoaded) {
return [];
}
const nodeName = node.getName();
return metricNames.map(metricName => {
try {
const metric = this.metrics[metricName];
const result = metric.data.result.find(result => {
return [
result.metric.node,
result.metric.instance,
result.metric.kubernetes_node,
].includes(nodeName);
});
return result ? parseFloat(result.values.slice(-1)[0][1]) : 0;
} catch (e) {
return 0;
}
});
}
getWarningsCount(): number {
return sum(this.items.map((node: Node) => node.getWarningConditions().length));
}
reset() {
super.reset();
this.metrics = {};
this.nodeMetrics = null;
this.metricsLoading = false;
this.metricsLoaded = false;
}
}
export const nodesStore = new NodesStore();

View File

@ -28,7 +28,7 @@ import { TabLayout } from "../layout/tab-layout";
import { nodesStore } from "./nodes.store";
import { podsStore } from "../+workloads-pods/pods.store";
import { KubeObjectListLayout } from "../kube-object";
import type { Node } from "../../api/endpoints/nodes.api";
import { getMetricsForAllNodes, INodeMetrics, Node } from "../../api/endpoints/nodes.api";
import { LineProgress } from "../line-progress";
import { bytesToUnits } from "../../utils/convertMemory";
import { Tooltip, TooltipPosition } from "../tooltip";
@ -39,6 +39,8 @@ import { Badge } from "../badge/badge";
import { kubeWatchApi } from "../../api/kube-watch-api";
import { eventStore } from "../+events/event.store";
import type { NodesRouteParams } from "../../../common/routes";
import { observable } from "mobx";
import isEmpty from "lodash/isEmpty";
enum columnId {
name = "name",
@ -58,7 +60,8 @@ interface Props extends RouteComponentProps<NodesRouteParams> {
@observer
export class Nodes extends React.Component<Props> {
private metricsWatcher = interval(30, () => nodesStore.loadUsageMetrics());
@observable metrics: Partial<INodeMetrics> = {};
private metricsWatcher = interval(30, async () => await getMetricsForAllNodes());
componentDidMount() {
this.metricsWatcher.start(true);
@ -73,8 +76,32 @@ export class Nodes extends React.Component<Props> {
this.metricsWatcher.stop();
}
getLastMetricValues(node: Node, metricNames: string[]): number[] {
if (isEmpty(this.metrics)) {
return [];
}
const nodeName = node.getName();
return metricNames.map(metricName => {
try {
const metric = this.metrics[metricName];
const result = metric.data.result.find(result => {
return [
result.metric.node,
result.metric.instance,
result.metric.kubernetes_node,
].includes(nodeName);
});
return result ? parseFloat(result.values.slice(-1)[0][1]) : 0;
} catch (e) {
return 0;
}
});
}
renderCpuUsage(node: Node) {
const metrics = nodesStore.getLastMetricValues(node, ["cpuUsage", "cpuCapacity"]);
const metrics = this.getLastMetricValues(node, ["cpuUsage", "cpuCapacity"]);
if (!metrics || !metrics[1]) return <LineProgress value={0}/>;
const usage = metrics[0];
@ -97,7 +124,7 @@ export class Nodes extends React.Component<Props> {
}
renderMemoryUsage(node: Node) {
const metrics = nodesStore.getLastMetricValues(node, ["workloadMemoryUsage", "memoryAllocatableCapacity"]);
const metrics = this.getLastMetricValues(node, ["workloadMemoryUsage", "memoryAllocatableCapacity"]);
if (!metrics || !metrics[1]) return <LineProgress value={0}/>;
const usage = metrics[0];
@ -116,7 +143,7 @@ export class Nodes extends React.Component<Props> {
}
renderDiskUsage(node: Node): any {
const metrics = nodesStore.getLastMetricValues(node, ["fsUsage", "fsSize"]);
const metrics = this.getLastMetricValues(node, ["fsUsage", "fsSize"]);
if (!metrics || !metrics[1]) return <LineProgress value={0}/>;
const usage = metrics[0];
@ -172,9 +199,9 @@ export class Nodes extends React.Component<Props> {
isSelectable={false}
sortingCallbacks={{
[columnId.name]: (node: Node) => node.getName(),
[columnId.cpu]: (node: Node) => nodesStore.getLastMetricValues(node, ["cpuUsage"]),
[columnId.memory]: (node: Node) => nodesStore.getLastMetricValues(node, ["memoryUsage"]),
[columnId.disk]: (node: Node) => nodesStore.getLastMetricValues(node, ["fsUsage"]),
[columnId.cpu]: (node: Node) => this.getLastMetricValues(node, ["cpuUsage"]),
[columnId.memory]: (node: Node) => this.getLastMetricValues(node, ["memoryUsage"]),
[columnId.disk]: (node: Node) => this.getLastMetricValues(node, ["fsUsage"]),
[columnId.conditions]: (node: Node) => node.getNodeConditionText(),
[columnId.taints]: (node: Node) => node.getTaints().length,
[columnId.roles]: (node: Node) => node.getRoleLabels(),

View File

@ -22,17 +22,16 @@
import "./volume-claim-details.scss";
import React, { Fragment } from "react";
import { reaction } from "mobx";
import { action, observable, reaction } from "mobx";
import { disposeOnUnmount, observer } from "mobx-react";
import { DrawerItem, DrawerTitle } from "../drawer";
import { Badge } from "../badge";
import { podsStore } from "../+workloads-pods/pods.store";
import { Link } from "react-router-dom";
import { volumeClaimStore } from "./volume-claim.store";
import { ResourceMetrics } from "../resource-metrics";
import { VolumeClaimDiskChart } from "./volume-claim-disk-chart";
import { getDetailsUrl, KubeObjectDetailsProps, KubeObjectMeta } from "../kube-object";
import type { PersistentVolumeClaim } from "../../api/endpoints";
import { getMetricsForPvc, IPvcMetrics, PersistentVolumeClaim } from "../../api/endpoints";
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
import { ClusterMetricsResourceType } from "../../../main/cluster";
@ -41,13 +40,18 @@ interface Props extends KubeObjectDetailsProps<PersistentVolumeClaim> {
@observer
export class PersistentVolumeClaimDetails extends React.Component<Props> {
@observable metrics: IPvcMetrics = null;
@disposeOnUnmount
clean = reaction(() => this.props.object, () => {
volumeClaimStore.reset();
this.metrics = null;
});
componentWillUnmount() {
volumeClaimStore.reset();
@action
async loadMetrics() {
const { object: volumeClaim } = this.props;
this.metrics = await getMetricsForPvc(volumeClaim);
}
render() {
@ -57,7 +61,7 @@ export class PersistentVolumeClaimDetails extends React.Component<Props> {
return null;
}
const { storageClassName, accessModes } = volumeClaim.spec;
const { metrics } = volumeClaimStore;
const { metrics } = this;
const pods = volumeClaim.getPods(podsStore.items);
const metricTabs = [
"Disk"
@ -68,7 +72,7 @@ export class PersistentVolumeClaimDetails extends React.Component<Props> {
<div className="PersistentVolumeClaimDetails">
{!isMetricHidden && (
<ResourceMetrics
loader={() => volumeClaimStore.loadMetrics(volumeClaim)}
loader={this.loadMetrics}
tabs={metricTabs} object={volumeClaim} params={{ metrics }}
>
<VolumeClaimDiskChart/>

View File

@ -18,32 +18,12 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { action, observable, makeObservable } from "mobx";
import { KubeObjectStore } from "../../kube-object.store";
import { autoBind } from "../../utils";
import { IPvcMetrics, PersistentVolumeClaim, pvcApi } from "../../api/endpoints";
import { apiManager } from "../../api/api-manager";
import { PersistentVolumeClaim, pvcApi } from "../../api/endpoints";
import { KubeObjectStore } from "../../kube-object.store";
export class VolumeClaimStore extends KubeObjectStore<PersistentVolumeClaim> {
api = pvcApi;
@observable metrics: IPvcMetrics = null;
constructor() {
super();
makeObservable(this);
autoBind(this);
}
@action
async loadMetrics(pvc: PersistentVolumeClaim) {
this.metrics = await pvcApi.getMetrics(pvc.getName(), pvc.getNs());
}
reset() {
this.metrics = null;
}
}
export const volumeClaimStore = new VolumeClaimStore();

View File

@ -31,10 +31,10 @@ import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities"
import { daemonSetStore } from "./daemonsets.store";
import { podsStore } from "../+workloads-pods/pods.store";
import type { KubeObjectDetailsProps } from "../kube-object";
import type { DaemonSet } from "../../api/endpoints";
import { DaemonSet, getMetricsForDaemonSets, IPodMetrics } from "../../api/endpoints";
import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics";
import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
import { reaction } from "mobx";
import { observable, reaction } from "mobx";
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { getActiveClusterEntity } from "../../api/catalog-entity-registry";
@ -45,17 +45,21 @@ interface Props extends KubeObjectDetailsProps<DaemonSet> {
@observer
export class DaemonSetDetails extends React.Component<Props> {
@observable metrics: IPodMetrics = null;
@disposeOnUnmount
clean = reaction(() => this.props.object, () => {
daemonSetStore.reset();
this.metrics = null;
});
componentDidMount() {
podsStore.reloadAll();
}
componentWillUnmount() {
daemonSetStore.reset();
async loadMetrics() {
const { object: daemonSet } = this.props;
this.metrics = await getMetricsForDaemonSets([daemonSet], daemonSet.getNs(), "");
}
render() {
@ -67,15 +71,14 @@ export class DaemonSetDetails extends React.Component<Props> {
const images = daemonSet.getImages();
const nodeSelector = daemonSet.getNodeSelectors();
const childPods = daemonSetStore.getChildPods(daemonSet);
const metrics = daemonSetStore.metrics;
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.DaemonSet);
return (
<div className="DaemonSetDetails">
{!isMetricHidden && podsStore.isLoaded && (
<ResourceMetrics
loader={() => daemonSetStore.loadMetrics(daemonSet)}
tabs={podMetricTabs} object={daemonSet} params={{ metrics }}
loader={this.loadMetrics}
tabs={podMetricTabs} object={daemonSet} params={{ metrics: this.metrics }}
>
<PodCharts/>
</ResourceMetrics>
@ -110,7 +113,7 @@ export class DaemonSetDetails extends React.Component<Props> {
<DrawerItem name="Pod Status" className="pod-status">
<PodDetailsStatuses pods={childPods}/>
</DrawerItem>
<ResourceMetricsText metrics={metrics}/>
<ResourceMetricsText metrics={this.metrics}/>
<PodDetailsList pods={childPods} owner={daemonSet}/>
</div>
);

View File

@ -18,19 +18,17 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { makeObservable } from "mobx";
import { observable, makeObservable } from "mobx";
import { KubeObjectStore } from "../../kube-object.store";
import { autoBind } from "../../utils";
import { DaemonSet, daemonSetApi, IPodMetrics, Pod, podsApi, PodStatus } from "../../api/endpoints";
import { podsStore } from "../+workloads-pods/pods.store";
import { apiManager } from "../../api/api-manager";
import { DaemonSet, daemonSetApi, Pod, PodStatus } from "../../api/endpoints";
import { KubeObjectStore } from "../../kube-object.store";
import { autoBind } from "../../utils";
export class DaemonSetStore extends KubeObjectStore<DaemonSet> {
api = daemonSetApi;
@observable metrics: IPodMetrics = null;
constructor() {
super();
@ -38,12 +36,6 @@ export class DaemonSetStore extends KubeObjectStore<DaemonSet> {
autoBind(this);
}
async loadMetrics(daemonSet: DaemonSet) {
const pods = this.getChildPods(daemonSet);
this.metrics = await podsApi.getMetrics(pods, daemonSet.getNs(), "");
}
getChildPods(daemonSet: DaemonSet): Pod[] {
return podsStore.getPodsByOwnerId(daemonSet.getId());
}
@ -67,10 +59,6 @@ export class DaemonSetStore extends KubeObjectStore<DaemonSet> {
return status;
}
reset() {
this.metrics = null;
}
}
export const daemonSetStore = new DaemonSetStore();

View File

@ -26,7 +26,7 @@ import kebabCase from "lodash/kebabCase";
import { disposeOnUnmount, observer } from "mobx-react";
import { DrawerItem } from "../drawer";
import { Badge } from "../badge";
import type { Deployment } from "../../api/endpoints";
import { Deployment, getMetricsForDeployments, IPodMetrics } from "../../api/endpoints";
import { PodDetailsTolerations } from "../+workloads-pods/pod-details-tolerations";
import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities";
import { podsStore } from "../+workloads-pods/pods.store";
@ -34,7 +34,7 @@ import type { KubeObjectDetailsProps } from "../kube-object";
import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics";
import { deploymentStore } from "./deployments.store";
import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
import { reaction } from "mobx";
import { observable, reaction } from "mobx";
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { replicaSetStore } from "../+workloads-replicasets/replicasets.store";
@ -47,9 +47,11 @@ interface Props extends KubeObjectDetailsProps<Deployment> {
@observer
export class DeploymentDetails extends React.Component<Props> {
@observable metrics: IPodMetrics = null;
@disposeOnUnmount
clean = reaction(() => this.props.object, () => {
deploymentStore.reset();
this.metrics = null;
});
componentDidMount() {
@ -57,8 +59,10 @@ export class DeploymentDetails extends React.Component<Props> {
replicaSetStore.reloadAll();
}
componentWillUnmount() {
deploymentStore.reset();
async loadMetrics() {
const { object: deployment } = this.props;
this.metrics = await getMetricsForDeployments([deployment], deployment.getNs(), "");
}
render() {
@ -70,15 +74,14 @@ export class DeploymentDetails extends React.Component<Props> {
const selectors = deployment.getSelectors();
const childPods = deploymentStore.getChildPods(deployment);
const replicaSets = replicaSetStore.getReplicaSetsByOwner(deployment);
const metrics = deploymentStore.metrics;
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Deployment);
return (
<div className="DeploymentDetails">
{!isMetricHidden && podsStore.isLoaded && (
<ResourceMetrics
loader={() => deploymentStore.loadMetrics(deployment)}
tabs={podMetricTabs} object={deployment} params={{ metrics }}
loader={this.loadMetrics}
tabs={podMetricTabs} object={deployment} params={{ metrics: this.metrics }}
>
<PodCharts/>
</ResourceMetrics>
@ -132,7 +135,7 @@ export class DeploymentDetails extends React.Component<Props> {
</DrawerItem>
<PodDetailsTolerations workload={deployment}/>
<PodDetailsAffinities workload={deployment}/>
<ResourceMetricsText metrics={metrics}/>
<ResourceMetricsText metrics={this.metrics}/>
<DeploymentReplicaSets replicaSets={replicaSets}/>
<PodDetailsList pods={childPods} owner={deployment}/>
</div>

View File

@ -18,17 +18,16 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { makeObservable } from "mobx";
import { observable, makeObservable } from "mobx";
import { Deployment, deploymentApi, IPodMetrics, podsApi, PodStatus } from "../../api/endpoints";
import { KubeObjectStore } from "../../kube-object.store";
import { autoBind } from "../../utils";
import { podsStore } from "../+workloads-pods/pods.store";
import { apiManager } from "../../api/api-manager";
import { Deployment, deploymentApi, PodStatus } from "../../api/endpoints";
import { KubeObjectStore } from "../../kube-object.store";
import { autoBind } from "../../utils";
export class DeploymentStore extends KubeObjectStore<Deployment> {
api = deploymentApi;
@observable metrics: IPodMetrics = null;
constructor() {
super();
@ -43,12 +42,6 @@ export class DeploymentStore extends KubeObjectStore<Deployment> {
], "desc");
}
async loadMetrics(deployment: Deployment) {
const pods = this.getChildPods(deployment);
this.metrics = await podsApi.getMetrics(pods, deployment.getNs(), "");
}
getStatuses(deployments?: Deployment[]) {
const status = { failed: 0, pending: 0, running: 0 };
@ -74,10 +67,6 @@ export class DeploymentStore extends KubeObjectStore<Deployment> {
.getByLabel(deployment.getTemplateLabels())
.filter(pod => pod.getNs() === deployment.getNs());
}
reset() {
this.metrics = null;
}
}
export const deploymentStore = new DeploymentStore();

View File

@ -25,18 +25,17 @@ import React from "react";
import kebabCase from "lodash/kebabCase";
import { disposeOnUnmount, observer } from "mobx-react";
import { Link } from "react-router-dom";
import { autorun, observable, reaction, makeObservable } from "mobx";
import { IPodMetrics, nodesApi, Pod, pvcApi, configMapApi } from "../../api/endpoints";
import { observable, reaction, makeObservable } from "mobx";
import { IPodMetrics, nodesApi, Pod, pvcApi, configMapApi, getMetricsForPods } from "../../api/endpoints";
import { DrawerItem, DrawerTitle } from "../drawer";
import { Badge } from "../badge";
import { boundMethod, cssNames, interval, toJS } from "../../utils";
import { boundMethod, cssNames, toJS } from "../../utils";
import { PodDetailsContainer } from "./pod-details-container";
import { PodDetailsAffinities } from "./pod-details-affinities";
import { PodDetailsTolerations } from "./pod-details-tolerations";
import { Icon } from "../icon";
import { PodDetailsSecrets } from "./pod-details-secrets";
import { ResourceMetrics } from "../resource-metrics";
import { podsStore } from "./pods.store";
import { getDetailsUrl, KubeObjectDetailsProps } from "../kube-object";
import { getItemMetrics } from "../../api/endpoints/metrics.api";
import { PodCharts, podMetricTabs } from "./pod-charts";
@ -49,10 +48,9 @@ interface Props extends KubeObjectDetailsProps<Pod> {
@observer
export class PodDetails extends React.Component<Props> {
@observable metrics: IPodMetrics;
@observable containerMetrics: IPodMetrics;
private watcher = interval(60, () => this.loadMetrics());
constructor(props: Props) {
super(props);
makeObservable(this);
@ -60,26 +58,19 @@ export class PodDetails extends React.Component<Props> {
componentDidMount() {
disposeOnUnmount(this, [
autorun(() => {
this.containerMetrics = null;
this.loadMetrics();
}),
reaction(() => this.props.object, () => {
podsStore.reset();
this.metrics = null;
this.containerMetrics = null;
})
]);
this.watcher.start();
}
componentWillUnmount() {
podsStore.reset();
}
@boundMethod
async loadMetrics() {
const { object: pod } = this.props;
this.containerMetrics = await podsStore.loadContainerMetrics(pod);
this.metrics = await getMetricsForPods([pod], pod.getNs());
this.containerMetrics = await getMetricsForPods([pod], pod.getNs(), "container, namespace");
}
render() {
@ -92,15 +83,14 @@ export class PodDetails extends React.Component<Props> {
const { nodeName } = spec;
const nodeSelector = pod.getNodeSelectors();
const volumes = pod.getVolumes();
const metrics = podsStore.metrics;
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.Pod);
return (
<div className="PodDetails">
{!isMetricHidden && (
<ResourceMetrics
loader={() => podsStore.loadMetrics(pod)}
tabs={podMetricTabs} object={pod} params={{ metrics }}
loader={this.loadMetrics}
tabs={podMetricTabs} object={pod} params={{ metrics: this.metrics }}
>
<PodCharts/>
</ResourceMetrics>

View File

@ -20,17 +20,16 @@
*/
import countBy from "lodash/countBy";
import { action, observable, makeObservable } from "mobx";
import { observable, makeObservable } from "mobx";
import { KubeObjectStore } from "../../kube-object.store";
import { autoBind, cpuUnitsToNumber, unitsToBytes } from "../../utils";
import { IPodMetrics, Pod, PodMetrics, podMetricsApi, podsApi } from "../../api/endpoints";
import { Pod, PodMetrics, podMetricsApi, podsApi } from "../../api/endpoints";
import { apiManager } from "../../api/api-manager";
import type { WorkloadKubeObject } from "../../api/workload-kube-object";
export class PodsStore extends KubeObjectStore<Pod> {
api = podsApi;
@observable metrics: IPodMetrics = null;
@observable kubeMetrics = observable.array<PodMetrics>([]);
constructor() {
@ -40,15 +39,6 @@ export class PodsStore extends KubeObjectStore<Pod> {
autoBind(this);
}
@action
async loadMetrics(pod: Pod) {
this.metrics = await podsApi.getMetrics([pod], pod.getNs());
}
loadContainerMetrics(pod: Pod) {
return podsApi.getMetrics([pod], pod.getNs(), "container, namespace");
}
async loadKubeMetrics(namespace?: string) {
try {
const metrics = await podMetricsApi.list({ namespace });
@ -113,10 +103,6 @@ export class PodsStore extends KubeObjectStore<Pod> {
};
}, empty);
}
reset() {
this.metrics = null;
}
}
export const podsStore = new PodsStore();

View File

@ -21,7 +21,7 @@
import "./replicaset-details.scss";
import React from "react";
import { reaction } from "mobx";
import { observable, reaction } from "mobx";
import { DrawerItem } from "../drawer";
import { Badge } from "../badge";
import { replicaSetStore } from "./replicasets.store";
@ -31,7 +31,7 @@ import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities"
import { disposeOnUnmount, observer } from "mobx-react";
import { podsStore } from "../+workloads-pods/pods.store";
import type { KubeObjectDetailsProps } from "../kube-object";
import type { ReplicaSet } from "../../api/endpoints";
import { getMetricsForReplicaSets, IPodMetrics, ReplicaSet } from "../../api/endpoints";
import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics";
import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
@ -44,24 +44,28 @@ interface Props extends KubeObjectDetailsProps<ReplicaSet> {
@observer
export class ReplicaSetDetails extends React.Component<Props> {
@observable metrics: IPodMetrics = null;
@disposeOnUnmount
clean = reaction(() => this.props.object, () => {
replicaSetStore.reset();
this.metrics = null;
});
async componentDidMount() {
podsStore.reloadAll();
}
componentWillUnmount() {
replicaSetStore.reset();
async loadMetrics() {
const { object: replicaSet } = this.props;
this.metrics = await getMetricsForReplicaSets([replicaSet], replicaSet.getNs(), "");
}
render() {
const { object: replicaSet } = this.props;
if (!replicaSet) return null;
const { metrics } = replicaSetStore;
const { metrics } = this;
const { status } = replicaSet;
const { availableReplicas, replicas } = status;
const selectors = replicaSet.getSelectors();
@ -74,7 +78,7 @@ export class ReplicaSetDetails extends React.Component<Props> {
<div className="ReplicaSetDetails">
{!isMetricHidden && podsStore.isLoaded && (
<ResourceMetrics
loader={() => replicaSetStore.loadMetrics(replicaSet)}
loader={this.loadMetrics}
tabs={podMetricTabs} object={replicaSet} params={{ metrics }}
>
<PodCharts/>

View File

@ -18,18 +18,17 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { makeObservable } from "mobx";
import { observable, makeObservable } from "mobx";
import { autoBind } from "../../utils";
import { KubeObjectStore } from "../../kube-object.store";
import { Deployment, IPodMetrics, podsApi, ReplicaSet, replicaSetApi } from "../../api/endpoints";
import { podsStore } from "../+workloads-pods/pods.store";
import { apiManager } from "../../api/api-manager";
import { Deployment, ReplicaSet, replicaSetApi } from "../../api/endpoints";
import { PodStatus } from "../../api/endpoints/pods.api";
import { KubeObjectStore } from "../../kube-object.store";
import { autoBind } from "../../utils";
export class ReplicaSetStore extends KubeObjectStore<ReplicaSet> {
api = replicaSetApi;
@observable metrics: IPodMetrics = null;
constructor() {
super();
@ -38,12 +37,6 @@ export class ReplicaSetStore extends KubeObjectStore<ReplicaSet> {
autoBind(this);
}
async loadMetrics(replicaSet: ReplicaSet) {
const pods = this.getChildPods(replicaSet);
this.metrics = await podsApi.getMetrics(pods, replicaSet.getNs(), "");
}
getChildPods(replicaSet: ReplicaSet) {
return podsStore.getPodsByOwnerId(replicaSet.getId());
}
@ -73,10 +66,6 @@ export class ReplicaSetStore extends KubeObjectStore<ReplicaSet> {
!!replicaSet.getOwnerRefs().find(owner => owner.uid === deployment.getId())
);
}
reset() {
this.metrics = null;
}
}
export const replicaSetStore = new ReplicaSetStore();

View File

@ -23,7 +23,7 @@ import "./statefulset-details.scss";
import React from "react";
import { disposeOnUnmount, observer } from "mobx-react";
import { reaction } from "mobx";
import { observable, reaction } from "mobx";
import { Badge } from "../badge";
import { DrawerItem } from "../drawer";
import { PodDetailsStatuses } from "../+workloads-pods/pod-details-statuses";
@ -32,7 +32,7 @@ import { PodDetailsAffinities } from "../+workloads-pods/pod-details-affinities"
import { podsStore } from "../+workloads-pods/pods.store";
import { statefulSetStore } from "./statefulset.store";
import type { KubeObjectDetailsProps } from "../kube-object";
import type { StatefulSet } from "../../api/endpoints";
import { getMetricsForStatefulSets, IPodMetrics, StatefulSet } from "../../api/endpoints";
import { ResourceMetrics, ResourceMetricsText } from "../resource-metrics";
import { PodCharts, podMetricTabs } from "../+workloads-pods/pod-charts";
import { PodDetailsList } from "../+workloads-pods/pod-details-list";
@ -45,17 +45,21 @@ interface Props extends KubeObjectDetailsProps<StatefulSet> {
@observer
export class StatefulSetDetails extends React.Component<Props> {
@observable metrics: IPodMetrics = null;
@disposeOnUnmount
clean = reaction(() => this.props.object, () => {
statefulSetStore.reset();
this.metrics = null;
});
componentDidMount() {
podsStore.reloadAll();
}
componentWillUnmount() {
statefulSetStore.reset();
async loadMetrics() {
const { object: statefulSet } = this.props;
this.metrics = await getMetricsForStatefulSets([statefulSet], statefulSet.getNs(), "");
}
render() {
@ -66,15 +70,14 @@ export class StatefulSetDetails extends React.Component<Props> {
const selectors = statefulSet.getSelectors();
const nodeSelector = statefulSet.getNodeSelectors();
const childPods = statefulSetStore.getChildPods(statefulSet);
const metrics = statefulSetStore.metrics;
const isMetricHidden = getActiveClusterEntity()?.isMetricHidden(ClusterMetricsResourceType.StatefulSet);
return (
<div className="StatefulSetDetails">
{!isMetricHidden && podsStore.isLoaded && (
<ResourceMetrics
loader={() => statefulSetStore.loadMetrics(statefulSet)}
tabs={podMetricTabs} object={statefulSet} params={{ metrics }}
loader={() => this.loadMetrics}
tabs={podMetricTabs} object={statefulSet} params={{ metrics: this.metrics }}
>
<PodCharts/>
</ResourceMetrics>
@ -108,7 +111,7 @@ export class StatefulSetDetails extends React.Component<Props> {
<DrawerItem name="Pod Status" className="pod-status">
<PodDetailsStatuses pods={childPods}/>
</DrawerItem>
<ResourceMetricsText metrics={metrics}/>
<ResourceMetricsText metrics={this.metrics}/>
<PodDetailsList pods={childPods} owner={statefulSet}/>
</div>
);

View File

@ -18,17 +18,16 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import { makeObservable } from "mobx";
import { observable, makeObservable } from "mobx";
import { autoBind } from "../../utils";
import { KubeObjectStore } from "../../kube-object.store";
import { IPodMetrics, podsApi, PodStatus, StatefulSet, statefulSetApi } from "../../api/endpoints";
import { podsStore } from "../+workloads-pods/pods.store";
import { apiManager } from "../../api/api-manager";
import { PodStatus, StatefulSet, statefulSetApi } from "../../api/endpoints";
import { KubeObjectStore } from "../../kube-object.store";
import { autoBind } from "../../utils";
export class StatefulSetStore extends KubeObjectStore<StatefulSet> {
api = statefulSetApi;
@observable metrics: IPodMetrics = null;
constructor() {
super();
@ -37,13 +36,6 @@ export class StatefulSetStore extends KubeObjectStore<StatefulSet> {
autoBind(this);
}
async loadMetrics(statefulSet: StatefulSet) {
const pods = this.getChildPods(statefulSet);
this.metrics = await podsApi.getMetrics(pods, statefulSet.getNs(), "");
}
getChildPods(statefulSet: StatefulSet) {
return podsStore.getPodsByOwnerId(statefulSet.getId());
}
@ -67,10 +59,6 @@ export class StatefulSetStore extends KubeObjectStore<StatefulSet> {
return status;
}
reset() {
this.metrics = null;
}
}
export const statefulSetStore = new StatefulSetStore();