From d9d2b615d294131e15af98e13539194ea729af92 Mon Sep 17 00:00:00 2001
From: Simon Larsen
Date: Mon, 11 Nov 2024 17:24:05 +0000
Subject: [PATCH] Refactor code for consistency by standardizing property names
and improving formatting across various components
---
Common/Server/API/BaseAnalyticsAPI.ts | 11 +-
.../Services/AnalyticsDatabaseService.ts | 16 +-
.../AnalyticsDatabase/StatementGenerator.ts | 9 +-
Common/Types/Metrics/MetricsQuery.ts | 7 +-
.../Charts/ChartGroup/ChartGroup.tsx | 2 +-
.../ChartLibrary/LineChart/LineChart.tsx | 4 +-
.../UI/Components/Charts/Line/LineChart.tsx | 4 +-
.../src/Components/Metrics/MetricQuery.tsx | 2 +-
.../Components/Metrics/MetricQueryConfig.tsx | 2 +-
.../src/Components/Metrics/MetricView.tsx | 63 +++----
.../src/Components/Monitor/MonitorMetrics.tsx | 161 ++++++++++++++++--
11 files changed, 211 insertions(+), 70 deletions(-)
diff --git a/Common/Server/API/BaseAnalyticsAPI.ts b/Common/Server/API/BaseAnalyticsAPI.ts
index 2f7e81d66a..eba73a4a74 100644
--- a/Common/Server/API/BaseAnalyticsAPI.ts
+++ b/Common/Server/API/BaseAnalyticsAPI.ts
@@ -291,15 +291,14 @@ export default class BaseAnalyticsAPI<
) as any;
}
- let groupBy: GroupBy | null = req.body["groupBy"] || null;
+ let groupBy: GroupBy | null =
+ req.body["groupBy"] || null;
- if(groupBy && Object.keys(groupBy).length > 0) {
- groupBy = JSONFunctions.deserialize(
- groupBy as JSONObject,
- ) as any;
+ if (groupBy && Object.keys(groupBy).length > 0) {
+ groupBy = JSONFunctions.deserialize(groupBy as JSONObject) as any;
}
- if(groupBy && Object.keys(groupBy).length === 0) {
+ if (groupBy && Object.keys(groupBy).length === 0) {
groupBy = null;
}
diff --git a/Common/Server/Services/AnalyticsDatabaseService.ts b/Common/Server/Services/AnalyticsDatabaseService.ts
index 19065bef9f..9f0e38d872 100644
--- a/Common/Server/Services/AnalyticsDatabaseService.ts
+++ b/Common/Server/Services/AnalyticsDatabaseService.ts
@@ -57,14 +57,14 @@ import ModelEventType from "../../Types/Realtime/ModelEventType";
export default class AnalyticsDatabaseService<
TBaseModel extends AnalyticsBaseModel,
> extends BaseService {
- public modelType!: { new(): TBaseModel };
+ public modelType!: { new (): TBaseModel };
public database!: ClickhouseDatabase;
public model!: TBaseModel;
public databaseClient!: ClickhouseClient;
public statementGenerator!: StatementGenerator;
public constructor(data: {
- modelType: { new(): TBaseModel };
+ modelType: { new (): TBaseModel };
database?: ClickhouseDatabase | undefined;
}) {
super();
@@ -240,8 +240,6 @@ export default class AnalyticsDatabaseService<
columns: Array;
} = this.toAggregateStatement(aggregateBy);
- debugger;
-
const dbResult: ExecResult = await this.execute(
findStatement.statement,
);
@@ -261,22 +259,24 @@ export default class AnalyticsDatabaseService<
// convert date column from string to date.
- const groupByColumnName: keyof TBaseModel | undefined = aggregateBy.groupBy && Object.keys(aggregateBy.groupBy).length > 0 ? Object.keys(aggregateBy.groupBy)[0] as keyof TBaseModel : undefined;
+ const groupByColumnName: keyof TBaseModel | undefined =
+ aggregateBy.groupBy && Object.keys(aggregateBy.groupBy).length > 0
+ ? (Object.keys(aggregateBy.groupBy)[0] as keyof TBaseModel)
+ : undefined;
for (const item of items) {
if (
!(item as JSONObject)[
- aggregateBy.aggregationTimestampColumnName as string
+ aggregateBy.aggregationTimestampColumnName as string
]
) {
continue;
}
-
const aggregatedModel: AggregatedModel = {
timestamp: OneUptimeDate.fromString(
(item as JSONObject)[
- aggregateBy.aggregationTimestampColumnName as string
+ aggregateBy.aggregationTimestampColumnName as string
] as string,
),
value: (item as JSONObject)[
diff --git a/Common/Server/Utils/AnalyticsDatabase/StatementGenerator.ts b/Common/Server/Utils/AnalyticsDatabase/StatementGenerator.ts
index 1fb2ae8c9b..15fb12b6d8 100644
--- a/Common/Server/Utils/AnalyticsDatabase/StatementGenerator.ts
+++ b/Common/Server/Utils/AnalyticsDatabase/StatementGenerator.ts
@@ -548,17 +548,18 @@ export default class StatementGenerator {
`${aggregationMethod}(${aggregateBy.aggregateColumnName.toString()}) as ${aggregateBy.aggregateColumnName.toString()}, date_trunc('${aggregationInterval.toLowerCase()}', toStartOfInterval(${aggregateBy.aggregationTimestampColumnName.toString()}, INTERVAL 1 ${aggregationInterval.toLowerCase()})) as ${aggregateBy.aggregationTimestampColumnName.toString()}`,
);
-
const columns: Array = [
aggregateBy.aggregateColumnName.toString(),
aggregateBy.aggregationTimestampColumnName.toString(),
];
- if(aggregateBy.groupBy && Object.keys(aggregateBy.groupBy).length > 0) {
- const groupByStatement: Statement = this.toGroupByStatement(aggregateBy.groupBy);
+ if (aggregateBy.groupBy && Object.keys(aggregateBy.groupBy).length > 0) {
+ const groupByStatement: Statement = this.toGroupByStatement(
+ aggregateBy.groupBy,
+ );
selectStatement.append(SQL`, `).append(groupByStatement);
- // add to columns.
+ // add to columns.
for (const key in aggregateBy.groupBy) {
columns.push(key);
}
diff --git a/Common/Types/Metrics/MetricsQuery.ts b/Common/Types/Metrics/MetricsQuery.ts
index 1a4d4c0ff7..b9a0f86575 100644
--- a/Common/Types/Metrics/MetricsQuery.ts
+++ b/Common/Types/Metrics/MetricsQuery.ts
@@ -7,12 +7,11 @@ export default interface MetricsQuery {
aggegationType: MetricsAggregationType;
aggregateBy: Dictionary;
-
- // This is used for example for probes.
- // To display US probe and EU probe in chart for example.
+ // This is used for example for probes.
+ // To display US probe and EU probe in chart for example.
// In this case groupByAttribute is "probeId"
// and attributeValueToLegendMap is { "xx-xx-xx-xx": "US Probe", "yy-yyy-yyy-yy-yy": "EU Probe" }
-
+
groupByAttribute?: string | undefined;
attributeValueToLegendMap?: Dictionary;
}
diff --git a/Common/UI/Components/Charts/ChartGroup/ChartGroup.tsx b/Common/UI/Components/Charts/ChartGroup/ChartGroup.tsx
index 1f7dcd6369..60defa14cf 100644
--- a/Common/UI/Components/Charts/ChartGroup/ChartGroup.tsx
+++ b/Common/UI/Components/Charts/ChartGroup/ChartGroup.tsx
@@ -47,7 +47,7 @@ const ChartGroup: FunctionComponent = (
{chart.description}
)}
-
+
);
default:
diff --git a/Common/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx b/Common/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx
index 434d481a32..8fe14d7918 100644
--- a/Common/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx
+++ b/Common/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx
@@ -571,7 +571,7 @@ interface LineChartProps extends React.HTMLAttributes {
legendPosition?: "left" | "center" | "right";
tooltipCallback?: (tooltipCallbackContent: TooltipProps) => void;
customTooltip?: React.ComponentType;
- syncId?: string | undefined;
+ syncid?: string | undefined;
}
const LineChart: React.ForwardRefExoticComponent<
@@ -692,7 +692,7 @@ const LineChart: React.ForwardRefExoticComponent<
{
diff --git a/Common/UI/Components/Charts/Line/LineChart.tsx b/Common/UI/Components/Charts/Line/LineChart.tsx
index ac0d5f4e91..f301e39ade 100644
--- a/Common/UI/Components/Charts/Line/LineChart.tsx
+++ b/Common/UI/Components/Charts/Line/LineChart.tsx
@@ -16,7 +16,7 @@ export interface ComponentProps {
}
export interface LineInternalProps extends ComponentProps {
- syncId: string;
+ syncid: string;
}
const LineChartElement: FunctionComponent = (
@@ -64,7 +64,7 @@ const LineChartElement: FunctionComponent = (
showTooltip={true}
connectNulls={true}
curve={props.curve}
- syncId={props.sync ? props.syncId : undefined}
+ syncid={props.sync ? props.syncid : undefined}
yAxisWidth={60}
/>
);
diff --git a/Dashboard/src/Components/Metrics/MetricQuery.tsx b/Dashboard/src/Components/Metrics/MetricQuery.tsx
index d4f7704eeb..3024b9af6a 100644
--- a/Dashboard/src/Components/Metrics/MetricQuery.tsx
+++ b/Dashboard/src/Components/Metrics/MetricQuery.tsx
@@ -12,7 +12,7 @@ import Metric from "Common/Models/AnalyticsModels/Metric";
export interface MetricQueryData {
filterData: FilterData;
- groupBy?: GroupBy | undefined;
+ groupBy?: GroupBy | undefined;
}
export interface ComponentProps {
diff --git a/Dashboard/src/Components/Metrics/MetricQueryConfig.tsx b/Dashboard/src/Components/Metrics/MetricQueryConfig.tsx
index ecdf1e6cc5..ec1290f161 100644
--- a/Dashboard/src/Components/Metrics/MetricQueryConfig.tsx
+++ b/Dashboard/src/Components/Metrics/MetricQueryConfig.tsx
@@ -10,7 +10,7 @@ import Button, {
import MetricNameAndUnit from "./Types/MetricNameAndUnit";
import AggregatedModel from "Common/Types/BaseDatabase/AggregatedModel";
-export interface ChartSeries {
+export interface ChartSeries {
title: string;
}
diff --git a/Dashboard/src/Components/Metrics/MetricView.tsx b/Dashboard/src/Components/Metrics/MetricView.tsx
index fa6c84e128..362e4636c6 100644
--- a/Dashboard/src/Components/Metrics/MetricView.tsx
+++ b/Dashboard/src/Components/Metrics/MetricView.tsx
@@ -5,7 +5,10 @@ import React, {
useEffect,
useState,
} from "react";
-import MetricQueryConfig, { ChartSeries, MetricQueryConfigData } from "./MetricQueryConfig";
+import MetricQueryConfig, {
+ ChartSeries,
+ MetricQueryConfigData,
+} from "./MetricQueryConfig";
import MetricGraphConfig, {
MetricFormulaConfigData,
} from "./MetricFormulaConfig";
@@ -199,12 +202,9 @@ const MetricView: FunctionComponent = (
xAxisAggregationType = XAxisAggregateType.Average;
}
- let chartSeries: Array = [
-
- ];
+ const chartSeries: Array = [];
if (queryConfig.getSeries) {
-
for (const item of metricResults[index]!.data) {
const series: ChartSeries = queryConfig.getSeries(item);
const seriesName: string = series.title;
@@ -213,27 +213,30 @@ const MetricView: FunctionComponent = (
// if it does not exist then create a new series and add the data to it
- const existingSeries: SeriesPoint | undefined = chartSeries.find((s: SeriesPoint) => {
- return s.seriesName === seriesName;
- });
+ const existingSeries: SeriesPoint | undefined = chartSeries.find(
+ (s: SeriesPoint) => {
+ return s.seriesName === seriesName;
+ },
+ );
if (existingSeries) {
existingSeries.data.push({
x: OneUptimeDate.fromString(item.timestamp),
- y: item.value
+ y: item.value,
});
} else {
const newSeries: SeriesPoint = {
seriesName: seriesName,
- data: [{
- x: OneUptimeDate.fromString(item.timestamp),
- y: item.value
- }]
+ data: [
+ {
+ x: OneUptimeDate.fromString(item.timestamp),
+ y: item.value,
+ },
+ ],
};
chartSeries.push(newSeries);
}
-
}
} else {
chartSeries.push({
@@ -241,14 +244,12 @@ const MetricView: FunctionComponent = (
queryConfig.metricAliasData.title ||
queryConfig.metricQueryData.filterData.metricName?.toString() ||
"",
- data: metricResults[index]!.data.map(
- (result: AggregatedModel) => {
- return {
- x: OneUptimeDate.fromString(result.timestamp),
- y: result.value,
- };
- },
- ),
+ data: metricResults[index]!.data.map((result: AggregatedModel) => {
+ return {
+ x: OneUptimeDate.fromString(result.timestamp),
+ y: result.value,
+ };
+ }),
});
}
@@ -365,14 +366,14 @@ const MetricView: FunctionComponent = (
const metricAttributesResponse:
| HTTPResponse
| HTTPErrorResponse = await API.post(
- URL.fromString(APP_API_URL.toString()).addRoute(
- "/telemetry/metrics/get-attributes",
- ),
- {},
- {
- ...ModelAPI.getCommonHeaders(),
- },
- );
+ URL.fromString(APP_API_URL.toString()).addRoute(
+ "/telemetry/metrics/get-attributes",
+ ),
+ {},
+ {
+ ...ModelAPI.getCommonHeaders(),
+ },
+ );
if (metricAttributesResponse instanceof HTTPErrorResponse) {
throw metricAttributesResponse;
@@ -421,7 +422,7 @@ const MetricView: FunctionComponent = (
OneUptimeDate.getCurrentDate(),
limit: LIMIT_PER_PROJECT,
skip: 0,
- groupBy: queryConfig.metricQueryData.groupBy
+ groupBy: queryConfig.metricQueryData.groupBy,
},
});
diff --git a/Dashboard/src/Components/Monitor/MonitorMetrics.tsx b/Dashboard/src/Components/Monitor/MonitorMetrics.tsx
index 20e4ef9663..ee513090f1 100644
--- a/Dashboard/src/Components/Monitor/MonitorMetrics.tsx
+++ b/Dashboard/src/Components/Monitor/MonitorMetrics.tsx
@@ -9,16 +9,26 @@ import MonitorMetricTypeUtil from "Common/Utils/Monitor/MonitorMetricType";
import OneUptimeDate from "Common/Types/Date";
import InBetween from "Common/Types/BaseDatabase/InBetween";
import MetricView from "../Metrics/MetricView";
-import { MetricQueryConfigData } from "../Metrics/MetricQueryConfig";
+import {
+ ChartSeries,
+ MetricQueryConfigData,
+} from "../Metrics/MetricQueryConfig";
import DashboardNavigation from "../../Utils/Navigation";
import MonitorMetricType from "Common/Types/Monitor/MonitorMetricType";
-import MonitorType from "Common/Types/Monitor/MonitorType";
+import MonitorType, {
+ MonitorTypeHelper,
+} from "Common/Types/Monitor/MonitorType";
import API from "Common/UI/Utils/API/API";
import Monitor from "Common/Models/DatabaseModels/Monitor";
import ModelAPI from "Common/UI/Utils/ModelAPI/ModelAPI";
import PageLoader from "Common/UI/Components/Loader/PageLoader";
import ErrorMessage from "Common/UI/Components/ErrorMessage/ErrorMessage";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
+import ProbeUtil from "../../Utils/Probe";
+import Probe from "Common/Models/DatabaseModels/Probe";
+import AggregateModel from "Common/Types/BaseDatabase/AggregatedModel";
+import { JSONObject } from "Common/Types/JSON";
+import JSONFunctions from "Common/Types/JSONFunctions";
export interface ComponentProps {
monitorId: ObjectID;
@@ -35,6 +45,8 @@ const MonitorMetricsElement: FunctionComponent = (
const [error, setError] = useState("");
+ const [probes, setProbes] = useState>([]);
+
const fetchMonitor: PromiseVoidFunction = async (): Promise => {
setIsLoading(true);
@@ -47,7 +59,16 @@ const MonitorMetricsElement: FunctionComponent = (
},
});
- setMonitorType(item?.monitorType || MonitorType.Manual);
+ const monitorType: MonitorType = item?.monitorType || MonitorType.Manual;
+
+ setMonitorType(monitorType);
+
+ const isProbeableMonitor: boolean =
+ MonitorTypeHelper.isProbableMonitor(monitorType);
+
+ if (isProbeableMonitor) {
+ setProbes(await ProbeUtil.getAllProbes());
+ }
} catch (err) {
setError(API.getFriendlyMessage(err));
}
@@ -89,6 +110,10 @@ const MonitorMetricsElement: FunctionComponent = (
(): Array => {
const queries: Array = [];
+ if (!monitorType) {
+ return [];
+ }
+
for (const monitorMetricType of monitorMetricTypesByMonitor) {
queries.push({
metricAliasData: {
@@ -113,18 +138,134 @@ const MonitorMetricsElement: FunctionComponent = (
MonitorMetricTypeUtil.getAggregationTypeByMonitorMetricType(
monitorMetricType,
),
-
},
groupBy: {
- attributes: true
- }
-
+ attributes: true,
+ },
},
- getSeries: (data) => {
+ getSeries: (data: AggregateModel): ChartSeries => {
+ const isProbeableMonitor: boolean =
+ MonitorTypeHelper.isProbableMonitor(monitorType);
+
+ if (!data) {
+ return {
+ title:
+ MonitorMetricTypeUtil.getTitleByMonitorMetricType(
+ monitorMetricType,
+ ),
+ };
+ }
+
+ if (isProbeableMonitor) {
+ let attributes: JSONObject = data["attributes"] as JSONObject;
+
+ if (!attributes) {
+ return {
+ title:
+ MonitorMetricTypeUtil.getTitleByMonitorMetricType(
+ monitorMetricType,
+ ),
+ };
+ }
+
+ // if attributes is typeof string then parse it to JSON
+
+ if (typeof attributes === "string") {
+ try {
+ attributes = JSONFunctions.parseJSONObject(attributes);
+ } catch (err) {
+ return {
+ title:
+ MonitorMetricTypeUtil.getTitleByMonitorMetricType(
+ monitorMetricType,
+ ),
+ };
+ }
+ }
+
+ const probeId: ObjectID = new ObjectID(
+ ((attributes as JSONObject)["probeId"] as string)?.toString(),
+ );
+
+ if (!probeId) {
+ return {
+ title:
+ MonitorMetricTypeUtil.getTitleByMonitorMetricType(
+ monitorMetricType,
+ ),
+ };
+ }
+
+ const probe: Probe | undefined = probes.find((probe: Probe) => {
+ return probe.id?.toString() === probeId.toString();
+ });
+
+ if (probe) {
+ return {
+ title:
+ probe.name?.toString() ||
+ MonitorMetricTypeUtil.getTitleByMonitorMetricType(
+ monitorMetricType,
+ ),
+ };
+ }
+
+ return {
+ title:
+ MonitorMetricTypeUtil.getTitleByMonitorMetricType(
+ monitorMetricType,
+ ),
+ };
+ }
+
+ if (monitorType === MonitorType.Server) {
+ let attributes: JSONObject = data["attributes"] as JSONObject;
+
+ if (!attributes) {
+ return {
+ title:
+ MonitorMetricTypeUtil.getTitleByMonitorMetricType(
+ monitorMetricType,
+ ),
+ };
+ }
+
+ // if attributes is typeof string then parse it to JSON
+
+ if (typeof attributes === "string") {
+ try {
+ attributes = JSONFunctions.parseJSONObject(attributes);
+ } catch (err) {
+ return {
+ title:
+ MonitorMetricTypeUtil.getTitleByMonitorMetricType(
+ monitorMetricType,
+ ),
+ };
+ }
+ }
+
+ if (attributes["diskPath"]) {
+ return {
+ title: attributes["diskPath"].toString(),
+ };
+ }
+
+ return {
+ title:
+ MonitorMetricTypeUtil.getTitleByMonitorMetricType(
+ monitorMetricType,
+ ),
+ };
+ }
+
return {
- title: data.attributes.monitorId,
+ title:
+ MonitorMetricTypeUtil.getTitleByMonitorMetricType(
+ monitorMetricType,
+ ),
};
- }
+ },
});
}