فهرست منبع

format metrics tabs (#4167)

d-g-town 2 سال پیش
والد
کامیت
d081d4739e

+ 25 - 17
dashboard/src/main/home/app-dashboard/expanded-app/metrics/types.ts

@@ -1,20 +1,28 @@
-import { NormalizedMetricsData, NormalizedNginxStatusMetricsData } from "main/home/cluster-dashboard/expanded-chart/metrics/types";
+import {
+  type NormalizedMetricsData,
+  type NormalizedNginxStatusMetricsData,
+} from "main/home/cluster-dashboard/expanded-chart/metrics/types";
 
-export type MetricType = 'cpu' | 'memory' | 'network' | 'nginx:status' | 'nginx:errors' | 'hpa_replicas';
-export interface Metric {
-    type: MetricType;
-    label: string;
-}
-export interface AggregatedMetric extends Metric {
-    data: NormalizedMetricsData[];
-    aggregatedData: Record<string, NormalizedMetricsData[]>;
-    hpaData: NormalizedMetricsData[];
-}
-export interface NginxStatusMetric extends Metric {
-    areaData: NormalizedNginxStatusMetricsData[];
-}
+export type MetricType =
+  | "cpu"
+  | "memory"
+  | "network"
+  | "nginx:status"
+  | "nginx:errors"
+  | "hpa_replicas";
+export type Metric = {
+  type: MetricType;
+  label: string;
+};
+export type AggregatedMetric = {
+  data: NormalizedMetricsData[];
+  aggregatedData: Record<string, NormalizedMetricsData[]>;
+  hpaData: NormalizedMetricsData[];
+} & Metric;
+export type NginxStatusMetric = {
+  areaData: NormalizedNginxStatusMetricsData[];
+} & Metric;
 
 export const isNginxMetric = (metric: Metric): metric is NginxStatusMetric => {
-    return metric.type === 'nginx:status';
-}
-
+  return metric.type === "nginx:status";
+};

+ 230 - 222
dashboard/src/main/home/app-dashboard/expanded-app/metrics/utils.ts

@@ -1,113 +1,116 @@
-import * as stats from "simple-statistics";
 import _ from "lodash";
+import * as stats from "simple-statistics";
 
 import {
-    GenericMetricResponse,
-    MetricsCPUDataResponse,
-    MetricsMemoryDataResponse,
-    MetricsNetworkDataResponse,
-    MetricsNGINXErrorsDataResponse,
-    MetricsNGINXStatusDataResponse,
-    AvailableMetrics,
-    MetricsHpaReplicasDataResponse,
-    MetricsNGINXLatencyDataResponse,
-    NormalizedMetricsData,
-    NormalizedNginxStatusMetricsData,
+  type AvailableMetrics,
+  type GenericMetricResponse,
+  type MetricsCPUDataResponse,
+  type MetricsHpaReplicasDataResponse,
+  type MetricsMemoryDataResponse,
+  type MetricsNetworkDataResponse,
+  type MetricsNGINXErrorsDataResponse,
+  type MetricsNGINXLatencyDataResponse,
+  type MetricsNGINXStatusDataResponse,
+  type NormalizedMetricsData,
+  type NormalizedNginxStatusMetricsData,
 } from "main/home/cluster-dashboard/expanded-chart/metrics/types";
 
 // these match log colors
 export const StatusCodeDataColors: Record<string, string> = {
-    "1xx": "#4B4F7C", // gray
-    "2xx": "#FFFFFF", // white
-    "3xx": "#54B835", // green
-    "4xx": "#BBBB3C", // yellow
-    "5xx": "#9C20A5", // purple
+  "1xx": "#4B4F7C", // gray
+  "2xx": "#FFFFFF", // white
+  "3xx": "#54B835", // green
+  "4xx": "#BBBB3C", // yellow
+  "5xx": "#9C20A5", // purple
 };
 
 export const ColorTheme = {
-    background: "#3b697800",
-    background2: "#20405100",
-    accentColor: "#949eff",
-    accentColorDark: "#949eff",
-}
+  background: "#3b697800",
+  background2: "#20405100",
+  accentColor: "#949eff",
+  accentColorDark: "#949eff",
+};
 
 type RGB = {
-    r: number;
-    g: number;
-    b: number;
+  r: number;
+  g: number;
+  b: number;
 };
 
 function componentToHex(c: number) {
-    c = Math.round(c);
-    var hex = c.toString(16);
-    return hex.length == 1 ? "0" + hex : hex;
+  c = Math.round(c);
+  const hex = c.toString(16);
+  return hex.length == 1 ? "0" + hex : hex;
 }
 
 function hexToRgb(hex: string): RGB | null {
-    const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
-    return result
-        ? {
-            r: parseInt(result[1], 16),
-            g: parseInt(result[2], 16),
-            b: parseInt(result[3], 16),
-        }
-        : null;
+  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+  return result
+    ? {
+        r: parseInt(result[1], 16),
+        g: parseInt(result[2], 16),
+        b: parseInt(result[3], 16),
+      }
+    : null;
 }
 
 function rgbToHex(rgb: RGB) {
-    return (
-        "#" + componentToHex(rgb.r) + componentToHex(rgb.g) + componentToHex(rgb.b)
-    );
+  return (
+    "#" + componentToHex(rgb.r) + componentToHex(rgb.g) + componentToHex(rgb.b)
+  );
 }
 
 export function pickColor(
-    color1: string,
-    color2: string,
-    index: number,
-    total: number
+  color1: string,
+  color2: string,
+  index: number,
+  total: number
 ) {
-    if (total == 1) {
-        return color1;
-    }
+  if (total == 1) {
+    return color1;
+  }
 
-    const w1 = index / (total - 1);
-    const w2 = 1 - w1;
+  const w1 = index / (total - 1);
+  const w2 = 1 - w1;
 
-    const rgb1 = hexToRgb(color1);
-    const rgb2 = hexToRgb(color2);
+  const rgb1 = hexToRgb(color1);
+  const rgb2 = hexToRgb(color2);
 
-    if (rgb1 == null || rgb2 == null) {
-        return "#000000";
-    }
+  if (rgb1 == null || rgb2 == null) {
+    return "#000000";
+  }
 
-    const rgb: RGB = {
-        r: Math.round(rgb1.r * w1 + rgb2.r * w2),
-        g: Math.round(rgb1.g * w1 + rgb2.g * w2),
-        b: Math.round(rgb1.b * w1 + rgb2.b * w2),
-    };
+  const rgb: RGB = {
+    r: Math.round(rgb1.r * w1 + rgb2.r * w2),
+    g: Math.round(rgb1.g * w1 + rgb2.g * w2),
+    b: Math.round(rgb1.b * w1 + rgb2.b * w2),
+  };
 
-    return rgbToHex(rgb);
+  return rgbToHex(rgb);
 }
 
-export const getServiceNameFromControllerName = (controllerName: string, porterAppName: string): string => {
-    const prefix = `${porterAppName}-`;
+export const getServiceNameFromControllerName = (
+  controllerName: string,
+  porterAppName: string
+): string => {
+  const prefix = `${porterAppName}-`;
 
-    if (!controllerName.startsWith(prefix)) {
-        return "";
-    }
+  if (!controllerName.startsWith(prefix)) {
+    return "";
+  }
 
-    controllerName = controllerName.substring(prefix.length);
+  controllerName = controllerName.substring(prefix.length);
 
-    const suffixes = ["-web", "-wkr", "-job"];
-    let index = -1;
+  const suffixes = ["-web", "-wkr", "-job"];
+  let index = -1;
 
-    for (const suffix of suffixes) {
-        const newIndex = controllerName.lastIndexOf(suffix);
-        index = Math.max(index, newIndex);
-    }
+  for (const suffix of suffixes) {
+    const newIndex = controllerName.lastIndexOf(suffix);
+    index = Math.max(index, newIndex);
+  }
 
-    return index !== -1 ? controllerName.substring(0, index) : controllerName;
-}
+  return index !== -1 ? controllerName.substring(0, index) : controllerName;
+};
 
 /**
  * Normalize values from the API to be readable by the AreaChart component.
@@ -115,170 +118,175 @@ export const getServiceNameFromControllerName = (controllerName: string, porterA
  * and improve readability
  */
 export class MetricNormalizer {
-    metric_results: GenericMetricResponse["results"];
-    kind: AvailableMetrics;
-
-    constructor(data: GenericMetricResponse[], kind: AvailableMetrics) {
-        if (!Array.isArray(data) || !data[0]?.results) {
-            throw new Error("Failed parsing response" + JSON.stringify(data));
-        }
-        this.metric_results = data[0].results;
-        this.kind = kind;
-    }
-
-    getParsedData(): NormalizedMetricsData[] {
-        if (this.kind.includes("cpu")) {
-            return this.parseCPUMetrics(this.metric_results);
-        }
-        if (this.kind.includes("memory")) {
-            return this.parseMemoryMetrics(this.metric_results);
-        }
-        if (this.kind.includes("network")) {
-            return this.parseNetworkMetrics(this.metric_results);
-        }
-        if (this.kind.includes("nginx:errors")) {
-            return this.parseNGINXErrorsMetrics(this.metric_results);
-        }
-        if (
-            this.kind.includes("nginx:latency") ||
-            this.kind.includes("nginx:latency-histogram")
-        ) {
-            return this.parseNGINXLatencyMetrics(this.metric_results);
-        }
-        if (this.kind.includes("hpa_replicas")) {
-            return this.parseHpaReplicaMetrics(this.metric_results);
-        }
-        return [];
-    }
-
-    getNginxStatusData(): NormalizedNginxStatusMetricsData[] {
-        if (this.kind.includes("nginx:status")) {
-            return this.parseNGINXStatusMetrics(this.metric_results);
-        }
+  metric_results: GenericMetricResponse["results"];
+  kind: AvailableMetrics;
 
-        return []
+  constructor(data: GenericMetricResponse[], kind: AvailableMetrics) {
+    if (!Array.isArray(data) || !data[0]?.results) {
+      throw new Error("Failed parsing response" + JSON.stringify(data));
     }
+    this.metric_results = data[0].results;
+    this.kind = kind;
+  }
 
-    getAggregatedData(): [NormalizedMetricsData[], Record<string, NormalizedMetricsData[]>] {
-        const groupedByDate = _.groupBy(this.getParsedData(), "date");
-
-        const avg = Object.keys(groupedByDate).map((date) => {
-            const values = groupedByDate[date].map((d) => d.value);
-            return {
-                date: Number(date),
-                value: stats.mean(values),
-            };
-        });
-
-        const min = Object.keys(groupedByDate).map((date) => {
-            const values = groupedByDate[date].map((d) => d.value);
-            return {
-                date: Number(date),
-                value: stats.min(values),
-            };
-        });
-
-        const max = Object.keys(groupedByDate).map((date) => {
-            const values = groupedByDate[date].map((d) => d.value);
-            return {
-                date: Number(date),
-                value: stats.max(values),
-            };
-        });
-
-        return [avg, {
-            min,
-            max,
-        }];
+  getParsedData(): NormalizedMetricsData[] {
+    if (this.kind.includes("cpu")) {
+      return this.parseCPUMetrics(this.metric_results);
     }
-
-    private parseCPUMetrics(arr: MetricsCPUDataResponse["results"]) {
-        return arr.map((d) => {
-            return {
-                date: d.date,
-                value: parseFloat(d.cpu),
-            };
-        });
+    if (this.kind.includes("memory")) {
+      return this.parseMemoryMetrics(this.metric_results);
     }
-
-    private parseMemoryMetrics(arr: MetricsMemoryDataResponse["results"]) {
-        return arr.map((d) => {
-            return {
-                date: d.date,
-                value: parseFloat(d.memory) / (1024 * 1024), // put units in Mi
-            };
-        });
+    if (this.kind.includes("network")) {
+      return this.parseNetworkMetrics(this.metric_results);
     }
-
-    private parseNetworkMetrics(arr: MetricsNetworkDataResponse["results"]) {
-        return arr.map((d) => {
-            return {
-                date: d.date,
-                value: parseFloat(d.bytes) / 1024, // put units in Ki
-            };
-        });
+    if (this.kind.includes("nginx:errors")) {
+      return this.parseNGINXErrorsMetrics(this.metric_results);
     }
-
-    private parseNGINXErrorsMetrics(
-        arr: MetricsNGINXErrorsDataResponse["results"]
+    if (
+      this.kind.includes("nginx:latency") ||
+      this.kind.includes("nginx:latency-histogram")
     ) {
-        return arr.map((d) => {
-            return {
-                date: d.date,
-                value: parseFloat(d.error_pct),
-            };
-        });
+      return this.parseNGINXLatencyMetrics(this.metric_results);
     }
-
-    private parseNGINXStatusMetrics(
-        arr: MetricsNGINXStatusDataResponse["results"]
-    ) {
-        return arr.map((d) => {
-            return {
-                date: d.date,
-                "1xx": parseInt(d["1xx"]),
-                "2xx": parseInt(d["2xx"]),
-                "3xx": parseInt(d["3xx"]),
-                "4xx": parseInt(d["4xx"]),
-                "5xx": parseInt(d["5xx"]),
-            };
-        });
+    if (this.kind.includes("hpa_replicas")) {
+      return this.parseHpaReplicaMetrics(this.metric_results);
     }
+    return [];
+  }
 
-    private parseNGINXLatencyMetrics(
-        arr: MetricsNGINXLatencyDataResponse["results"]
-    ) {
-        return arr.map((d) => {
-            return {
-                date: d.date,
-                value: d.latency != "NaN" ? parseFloat(d.latency) : 0,
-            };
-        });
+  getNginxStatusData(): NormalizedNginxStatusMetricsData[] {
+    if (this.kind.includes("nginx:status")) {
+      return this.parseNGINXStatusMetrics(this.metric_results);
     }
 
-    private parseHpaReplicaMetrics(
-        arr: MetricsHpaReplicasDataResponse["results"]
-    ) {
-        return arr.map((d) => {
-            return {
-                date: d.date,
-                value: parseInt(d.replicas),
-            };
-        });
-    }
+    return [];
+  }
+
+  getAggregatedData(): [
+    NormalizedMetricsData[],
+    Record<string, NormalizedMetricsData[]>,
+  ] {
+    const groupedByDate = _.groupBy(this.getParsedData(), "date");
+
+    const avg = Object.keys(groupedByDate).map((date) => {
+      const values = groupedByDate[date].map((d) => d.value);
+      return {
+        date: Number(date),
+        value: stats.mean(values),
+      };
+    });
+
+    const min = Object.keys(groupedByDate).map((date) => {
+      const values = groupedByDate[date].map((d) => d.value);
+      return {
+        date: Number(date),
+        value: stats.min(values),
+      };
+    });
+
+    const max = Object.keys(groupedByDate).map((date) => {
+      const values = groupedByDate[date].map((d) => d.value);
+      return {
+        date: Number(date),
+        value: stats.max(values),
+      };
+    });
+
+    return [
+      avg,
+      {
+        min,
+        max,
+      },
+    ];
+  }
+
+  private parseCPUMetrics(arr: MetricsCPUDataResponse["results"]) {
+    return arr.map((d) => {
+      return {
+        date: d.date,
+        value: parseFloat(d.cpu),
+      };
+    });
+  }
+
+  private parseMemoryMetrics(arr: MetricsMemoryDataResponse["results"]) {
+    return arr.map((d) => {
+      return {
+        date: d.date,
+        value: parseFloat(d.memory) / (1024 * 1024), // put units in Mi
+      };
+    });
+  }
+
+  private parseNetworkMetrics(arr: MetricsNetworkDataResponse["results"]) {
+    return arr.map((d) => {
+      return {
+        date: d.date,
+        value: parseFloat(d.bytes) / 1024, // put units in Ki
+      };
+    });
+  }
+
+  private parseNGINXErrorsMetrics(
+    arr: MetricsNGINXErrorsDataResponse["results"]
+  ) {
+    return arr.map((d) => {
+      return {
+        date: d.date,
+        value: parseFloat(d.error_pct),
+      };
+    });
+  }
+
+  private parseNGINXStatusMetrics(
+    arr: MetricsNGINXStatusDataResponse["results"]
+  ) {
+    return arr.map((d) => {
+      return {
+        date: d.date,
+        "1xx": parseInt(d["1xx"]),
+        "2xx": parseInt(d["2xx"]),
+        "3xx": parseInt(d["3xx"]),
+        "4xx": parseInt(d["4xx"]),
+        "5xx": parseInt(d["5xx"]),
+      };
+    });
+  }
+
+  private parseNGINXLatencyMetrics(
+    arr: MetricsNGINXLatencyDataResponse["results"]
+  ) {
+    return arr.map((d) => {
+      return {
+        date: d.date,
+        value: d.latency != "NaN" ? parseFloat(d.latency) : 0,
+      };
+    });
+  }
+
+  private parseHpaReplicaMetrics(
+    arr: MetricsHpaReplicasDataResponse["results"]
+  ) {
+    return arr.map((d) => {
+      return {
+        date: d.date,
+        value: parseInt(d.replicas),
+      };
+    });
+  }
 }
 
-export const resolutions: { [range: string]: string } = {
-    "1H": "1s",
-    "6H": "15s",
-    "1D": "15s",
-    "1M": "5h",
+export const resolutions: Record<string, string> = {
+  "1H": "1s",
+  "6H": "15s",
+  "1D": "15s",
+  "1M": "5h",
 };
 
-export const secondsBeforeNow: { [range: string]: number } = {
-    "1H": 60 * 60,
-    "6H": 60 * 60 * 6,
-    "1D": 60 * 60 * 24,
-    "1M": 60 * 60 * 24 * 30,
+export const secondsBeforeNow: Record<string, number> = {
+  "1H": 60 * 60,
+  "6H": 60 * 60 * 6,
+  "1D": 60 * 60 * 24,
+  "1M": 60 * 60 * 24 * 30,
 };
-

+ 14 - 13
dashboard/src/main/home/cluster-dashboard/expanded-chart/metrics/MetricNormalizer.ts

@@ -1,17 +1,18 @@
-import * as stats from "simple-statistics";
 import _ from "lodash";
+import * as stats from "simple-statistics";
+
 import {
-  GenericMetricResponse,
-  MetricsCPUDataResponse,
-  MetricsMemoryDataResponse,
-  MetricsNetworkDataResponse,
-  MetricsNGINXErrorsDataResponse,
-  MetricsNGINXStatusDataResponse,
-  AvailableMetrics,
-  MetricsHpaReplicasDataResponse,
-  MetricsNGINXLatencyDataResponse,
-  NormalizedMetricsData,
-  NormalizedNginxStatusMetricsData,
+  type AvailableMetrics,
+  type GenericMetricResponse,
+  type MetricsCPUDataResponse,
+  type MetricsHpaReplicasDataResponse,
+  type MetricsMemoryDataResponse,
+  type MetricsNetworkDataResponse,
+  type MetricsNGINXErrorsDataResponse,
+  type MetricsNGINXLatencyDataResponse,
+  type MetricsNGINXStatusDataResponse,
+  type NormalizedMetricsData,
+  type NormalizedNginxStatusMetricsData,
 } from "./types";
 
 /**
@@ -61,7 +62,7 @@ export class MetricNormalizer {
       return this.parseNGINXStatusMetrics(this.metric_results);
     }
 
-    return []
+    return [];
   }
 
   getAggregatedData(): Record<string, NormalizedMetricsData[]> {