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

Refactor Nodes view metrics renderer (#3990)

This commit is contained in:
Sebastian Malton 2021-11-30 10:30:54 -05:00 committed by GitHub
parent f0274d08a4
commit 2f14b7a70a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 60 deletions

View File

@ -95,17 +95,17 @@ export interface Node {
status: { status: {
capacity?: { capacity?: {
cpu: string; cpu: string;
["ephemeral-storage"]: string; "ephemeral-storage": string;
["hugepages-1Gi"]: string; "hugepages-1Gi": string;
["hugepages-2Mi"]: string; "hugepages-2Mi": string;
memory: string; memory: string;
pods: string; pods: string;
}; };
allocatable?: { allocatable?: {
cpu: string; cpu: string;
["ephemeral-storage"]: string; "ephemeral-storage": string;
["hugepages-1Gi"]: string; "hugepages-1Gi": string;
["hugepages-2Mi"]: string; "hugepages-2Mi": string;
memory: string; memory: string;
pods: string; pods: string;
}; };

View File

@ -56,6 +56,15 @@ enum columnId {
interface Props extends RouteComponentProps<NodesRouteParams> { interface Props extends RouteComponentProps<NodesRouteParams> {
} }
type MetricsTooltipFormatter = (metrics: [number, number]) => string;
interface UsageArgs {
node: Node;
title: string;
metricNames: [string, string];
formatters: MetricsTooltipFormatter[];
}
@observer @observer
export class Nodes extends React.Component<Props> { export class Nodes extends React.Component<Props> {
@observable.ref metrics: Partial<INodeMetrics> = {}; @observable.ref metrics: Partial<INodeMetrics> = {};
@ -78,18 +87,17 @@ export class Nodes extends React.Component<Props> {
if (isEmpty(this.metrics)) { if (isEmpty(this.metrics)) {
return []; return [];
} }
const nodeName = node.getName(); const nodeName = node.getName();
return metricNames.map(metricName => { return metricNames.map(metricName => {
try { try {
const metric = this.metrics[metricName]; const metric = this.metrics[metricName];
const result = metric.data.result.find(result => { const result = metric.data.result.find(({ metric: { node, instance, kubernetes_node }}) => (
return [ nodeName === node
result.metric.node, || nodeName === instance
result.metric.instance, || nodeName === kubernetes_node
result.metric.kubernetes_node, ));
].includes(nodeName);
});
return result ? parseFloat(result.values.slice(-1)[0][1]) : 0; return result ? parseFloat(result.values.slice(-1)[0][1]) : 0;
} catch (e) { } catch (e) {
@ -98,74 +106,69 @@ export class Nodes extends React.Component<Props> {
}); });
} }
renderCpuUsage(node: Node) { private renderUsage({ node, title, metricNames, formatters }: UsageArgs) {
const metrics = this.getLastMetricValues(node, ["cpuUsage", "cpuCapacity"]); const metrics = this.getLastMetricValues(node, metricNames);
if (!metrics || !metrics[1]) return <LineProgress value={0}/>; if (!metrics || metrics.length < 2) {
const usage = metrics[0]; return <LineProgress value={0}/>;
const cores = metrics[1]; }
const cpuUsagePercent = Math.ceil(usage * 100) / cores;
const cpuUsagePercentLabel: String = cpuUsagePercent % 1 === 0 const [usage, capacity] = metrics;
? cpuUsagePercent.toString()
: cpuUsagePercent.toFixed(2);
return ( return (
<LineProgress <LineProgress
max={cores} max={capacity}
value={usage} value={usage}
tooltip={{ tooltip={{
preferredPositions: TooltipPosition.BOTTOM, preferredPositions: TooltipPosition.BOTTOM,
children: `CPU: ${cpuUsagePercentLabel}\%, cores: ${cores}`, children: `${title}: ${formatters.map(formatter => formatter([usage, capacity])).join(", ")}`,
}} }}
/> />
); );
} }
renderCpuUsage(node: Node) {
return this.renderUsage({
node,
title: "CPU",
metricNames: ["cpuUsage", "cpuCapacity"],
formatters: [
([usage, capacity]) => `${(usage * 100 / capacity).toFixed(2)}%`,
([, cap]) => `cores: ${cap}`,
],
});
}
renderMemoryUsage(node: Node) { renderMemoryUsage(node: Node) {
const metrics = this.getLastMetricValues(node, ["workloadMemoryUsage", "memoryAllocatableCapacity"]); return this.renderUsage({
node,
if (!metrics || !metrics[1]) return <LineProgress value={0}/>; title: "Memory",
const usage = metrics[0]; metricNames: ["workloadMemoryUsage", "memoryAllocatableCapacity"],
const capacity = metrics[1]; formatters: [
([usage, capacity]) => `${(usage * 100 / capacity).toFixed(2)}%`,
return ( ([usage]) => bytesToUnits(usage, 3),
<LineProgress ],
max={capacity} });
value={usage}
tooltip={{
preferredPositions: TooltipPosition.BOTTOM,
children: `Memory: ${Math.ceil(usage * 100 / capacity)}%, ${bytesToUnits(usage, 3)}`,
}}
/>
);
} }
renderDiskUsage(node: Node): any { renderDiskUsage(node: Node) {
const metrics = this.getLastMetricValues(node, ["fsUsage", "fsSize"]); return this.renderUsage({
node,
if (!metrics || !metrics[1]) return <LineProgress value={0}/>; title: "Disk",
const usage = metrics[0]; metricNames: ["fsUsage", "fsSize"],
const capacity = metrics[1]; formatters: [
([usage, capacity]) => `${(usage * 100 / capacity).toFixed(2)}%`,
return ( ([usage]) => bytesToUnits(usage, 3),
<LineProgress ],
max={capacity} });
value={usage}
tooltip={{
preferredPositions: TooltipPosition.BOTTOM,
children: `Disk: ${Math.ceil(usage * 100 / capacity)}%, ${bytesToUnits(usage, 3)}`,
}}
/>
);
} }
renderConditions(node: Node) { renderConditions(node: Node) {
if (!node.status.conditions) { if (!node.status.conditions) {
return null; return null;
} }
const conditions = node.getActiveConditions();
return conditions.map(condition => { return node.getActiveConditions().map(condition => {
const { type } = condition; const { type } = condition;
const tooltipId = `node-${node.getName()}-condition-${type}`; const tooltipId = `node-${node.getName()}-condition-${type}`;
@ -180,7 +183,8 @@ export class Nodes extends React.Component<Props> {
</div>, </div>,
)} )}
</Tooltip> </Tooltip>
</div>); </div>
);
}); });
} }