refactor: Remove unused code in UptimeUtil

This commit is contained in:
Simon Larsen 2024-10-09 11:23:49 +01:00
parent d7f881c468
commit eaf4193cb0
No known key found for this signature in database
GPG Key ID: 96C5DCA24769DBCA
4 changed files with 364 additions and 274 deletions

View File

@ -0,0 +1,309 @@
import { Green } from "../../Types/BrandColors";
import ObjectID from "../../Types/ObjectID";
import MonitorStatus from "../../Models/DatabaseModels/MonitorStatus";
import MonitorStatusTimeline from "../../Models/DatabaseModels/MonitorStatusTimeline";
import StatusPageResource from "../../Models/DatabaseModels/StatusPageResource";
import Dictionary from "../../Types/Dictionary";
import UptimePrecision from "../../Types/StatusPage/UptimePrecision";
import StatusPageGroup from "../../Models/DatabaseModels/StatusPageGroup";
import UptimeUtil from "../Uptime/UptimeUtil";
export default class StatusPageResourceUptimeUtil {
public static getMonitorStatusTimelineForResource(data: {
statusPageResource: StatusPageResource;
monitorStatusTimelines: Array<MonitorStatusTimeline>;
monitorsInGroup: Dictionary<Array<ObjectID>>;
}): Array<MonitorStatusTimeline> {
return [...data.monitorStatusTimelines].filter(
(timeline: MonitorStatusTimeline) => {
// check monitor if first.
if (data.statusPageResource.monitorId) {
return (
timeline.monitorId?.toString() ===
data.statusPageResource.monitorId?.toString()
);
}
if (data.statusPageResource.monitorGroupId) {
const monitorsInThisGroup: Array<ObjectID> | undefined =
data.monitorsInGroup[
data.statusPageResource.monitorGroupId?.toString() || ""
];
if (!monitorsInThisGroup) {
return false;
}
return monitorsInThisGroup.find((monitorId: ObjectID) => {
return monitorId.toString() === timeline.monitorId?.toString();
});
}
return false;
},
);
}
public static getCurrentStatusPageGroupStatus(data: {
statusPageGroup: StatusPageGroup;
monitorStatusTimelines: Array<MonitorStatusTimeline>;
statusPageResources: Array<StatusPageResource>;
monitorStatuses: Array<MonitorStatus>;
monitorGroupCurrentStatuses: Dictionary<ObjectID>;
}): MonitorStatus {
let currentStatus: MonitorStatus = new MonitorStatus();
currentStatus.name = "Operational";
currentStatus.color = Green;
const resourcesInGroup: Array<StatusPageResource> =
this.getResourcesInStatusPageGroup({
statusPageGroup: data.statusPageGroup,
statusPageResources: data.statusPageResources,
});
for (const resource of resourcesInGroup) {
let currentMonitorStatus: MonitorStatus | undefined = undefined;
if (resource.monitor) {
currentMonitorStatus = data.monitorStatuses.find(
(status: MonitorStatus) => {
return (
status._id?.toString() ===
resource.monitor?.currentMonitorStatusId?.toString()
);
},
);
}
if (resource.monitorGroupId) {
currentMonitorStatus = data.monitorStatuses.find(
(status: MonitorStatus) => {
return (
status._id?.toString() ===
data.monitorGroupCurrentStatuses[
resource.monitorGroupId?.toString() || ""
]?.toString()
);
},
);
}
if (!currentMonitorStatus) {
currentMonitorStatus = currentStatus;
}
if (
(currentStatus &&
currentStatus.priority &&
currentMonitorStatus?.priority &&
currentMonitorStatus?.priority > currentStatus.priority) ||
!currentStatus ||
!currentStatus.priority
) {
currentStatus = currentMonitorStatus!;
}
}
return currentStatus;
}
public static calculateUptimePercentOfStatusPageGroup(data: {
statusPageGroup: StatusPageGroup;
monitorStatusTimelines: Array<MonitorStatusTimeline>;
precision: UptimePrecision;
downtimeMonitorStatuses: Array<MonitorStatus>;
statusPageResources: Array<StatusPageResource>;
monitorsInGroup: Dictionary<Array<ObjectID>>;
monitorGroupCurrentStatuses: Dictionary<ObjectID>;
}): number | null {
if (!data.statusPageGroup.showUptimePercent) {
return null;
}
const currentStatus: MonitorStatus | null =
this.getCurrentStatusPageGroupStatus({
statusPageGroup: data.statusPageGroup,
monitorStatusTimelines: data.monitorStatusTimelines,
statusPageResources: data.statusPageResources,
monitorStatuses: data.downtimeMonitorStatuses,
monitorGroupCurrentStatuses: data.monitorGroupCurrentStatuses,
});
const resourcesInGroup: Array<StatusPageResource> =
this.getResourcesInStatusPageGroup({
statusPageGroup: data.statusPageGroup,
statusPageResources: data.statusPageResources,
});
if (resourcesInGroup.length === 0) {
return null; // no resources in group.
}
let allMonitorStatusTimelines: Array<MonitorStatusTimeline> = [];
for (const resource of resourcesInGroup) {
// get monitor status timeline.
const monitorStatusTimelines: Array<MonitorStatusTimeline> =
this.getMonitorStatusTimelineForResource({
statusPageResource: resource,
monitorStatusTimelines: data.monitorStatusTimelines,
monitorsInGroup: data.monitorsInGroup,
});
// add to the monitor status timelines.
allMonitorStatusTimelines = allMonitorStatusTimelines.concat(
monitorStatusTimelines,
);
}
const downtimeMonitorStatuses: Array<MonitorStatus> =
data?.downtimeMonitorStatuses || [];
// if the current status is operational then show uptime Percent.
let precision: UptimePrecision = UptimePrecision.ONE_DECIMAL;
if (data.statusPageGroup.uptimePercentPrecision) {
precision = data.statusPageGroup.uptimePercentPrecision;
}
if (
!downtimeMonitorStatuses.find((downtimeStatus: MonitorStatus) => {
return currentStatus?.id?.toString() === downtimeStatus?.id?.toString();
}) &&
data.statusPageGroup.showUptimePercent
) {
const uptimePercent: number = UptimeUtil.calculateUptimePercentage(
allMonitorStatusTimelines,
precision,
downtimeMonitorStatuses,
);
return uptimePercent;
}
return null;
}
public static getResourcesInStatusPageGroup(data: {
statusPageGroup: StatusPageGroup;
statusPageResources: Array<StatusPageResource>;
}): Array<StatusPageResource> {
return data.statusPageResources.filter((resource: StatusPageResource) => {
return (
resource.statusPageGroupId?.toString() ===
data.statusPageGroup._id?.toString()
);
});
}
public static calculateAvgUptimePercentageOfAllResources(data: {
monitorStatusTimelines: Array<MonitorStatusTimeline>;
precision: UptimePrecision;
downtimeMonitorStatuses: Array<MonitorStatus>;
statusPageResources: Array<StatusPageResource>;
resourceGroups: Array<StatusPageGroup>;
monitorsInGroup: Dictionary<Array<ObjectID>>;
}): number | null {
const showUptimePercentage: boolean = Boolean(
data.statusPageResources.find((item: StatusPageResource) => {
return item.showUptimePercent || item.showStatusHistoryChart;
}),
);
if (!showUptimePercentage) {
return null;
}
const uptimePercentPerResource: Array<number> = [];
for (const resource of data.statusPageResources) {
if (!resource.showUptimePercent && !resource.showStatusHistoryChart) {
continue;
}
let timelinesForThisResource: Array<MonitorStatusTimeline> = [];
if (resource.monitorGroupId) {
timelinesForThisResource = [...data.monitorStatusTimelines].filter(
(timeline: MonitorStatusTimeline) => {
const monitorsInThisGroup: Array<ObjectID> | undefined =
data.monitorsInGroup[resource.monitorGroupId?.toString() || ""];
if (!monitorsInThisGroup) {
return false;
}
return monitorsInThisGroup.find((monitorId: ObjectID) => {
return monitorId.toString() === timeline.monitorId?.toString();
});
},
);
}
if (resource.monitorId || resource.monitor?.id) {
const monitorId: ObjectID | null | undefined =
resource.monitorId || resource.monitor?.id;
if (!monitorId) {
// this should never happen.
continue;
}
timelinesForThisResource = [...data.monitorStatusTimelines].filter(
(timeline: MonitorStatusTimeline) => {
return (
timeline.monitorId?.toString() === resource.monitorId?.toString()
);
},
);
}
const uptimePercent: number = UptimeUtil.calculateUptimePercentage(
timelinesForThisResource,
data.precision,
data.downtimeMonitorStatuses,
);
uptimePercentPerResource.push(uptimePercent);
}
// calculate avg
if (uptimePercentPerResource.length === 0) {
return null;
}
const averageUptimePercentage: number =
uptimePercentPerResource.reduce((a: number, b: number) => {
return a + b;
}) / uptimePercentPerResource.length;
//round this to precision.
if (data.precision === UptimePrecision.NO_DECIMAL) {
const percent: number = Math.round(averageUptimePercentage);
return percent;
}
if (data.precision === UptimePrecision.ONE_DECIMAL) {
const percent: number = Math.round(averageUptimePercentage * 10) / 10;
return percent;
}
if (data.precision === UptimePrecision.TWO_DECIMAL) {
const percent: number = Math.round(averageUptimePercentage * 100) / 100;
return percent;
}
if (data.precision === UptimePrecision.THREE_DECIMAL) {
const percent: number = Math.round(averageUptimePercentage * 1000) / 1000;
return percent;
}
return averageUptimePercentage;
}
}

View File

@ -5,8 +5,6 @@ import OneUptimeDate from "../../Types/Date";
import ObjectID from "../../Types/ObjectID";
import MonitorStatus from "../../Models/DatabaseModels/MonitorStatus";
import MonitorStatusTimeline from "../../Models/DatabaseModels/MonitorStatusTimeline";
import StatusPageResource from "../../Models/DatabaseModels/StatusPageResource";
import Dictionary from "../../Types/Dictionary";
import UptimePrecision from "../../Types/StatusPage/UptimePrecision";
export default class UptimeUtil {
@ -301,113 +299,6 @@ export default class UptimeUtil {
};
}
public static calculateAvgUptimePercentageOfAllResources(data: {
monitorStatusTimelines: Array<MonitorStatusTimeline>;
precision: UptimePrecision;
downtimeMonitorStatuses: Array<MonitorStatus>;
statusPageResources: Array<StatusPageResource>;
monitorsInGroup: Dictionary<Array<ObjectID>>;
}): number | null {
const showUptimePercentage: boolean = Boolean(
data.statusPageResources.find((item: StatusPageResource) => {
return item.showUptimePercent || item.showStatusHistoryChart;
}),
);
if (!showUptimePercentage) {
return null;
}
const uptimePercentPerResource: Array<number> = [];
for (const resource of data.statusPageResources) {
if (!resource.showUptimePercent && !resource.showStatusHistoryChart) {
continue;
}
let timelinesForThisResource: Array<MonitorStatusTimeline> = [];
if (resource.monitorGroupId) {
timelinesForThisResource = [...data.monitorStatusTimelines].filter(
(timeline: MonitorStatusTimeline) => {
const monitorsInThisGroup: Array<ObjectID> | undefined =
data.monitorsInGroup[resource.monitorGroupId?.toString() || ""];
if (!monitorsInThisGroup) {
return false;
}
return monitorsInThisGroup.find((monitorId: ObjectID) => {
return monitorId.toString() === timeline.monitorId?.toString();
});
},
);
}
if (resource.monitorId || resource.monitor?.id) {
const monitorId: ObjectID | null | undefined =
resource.monitorId || resource.monitor?.id;
if (!monitorId) {
// this should never happen.
continue;
}
timelinesForThisResource = [...data.monitorStatusTimelines].filter(
(timeline: MonitorStatusTimeline) => {
return (
timeline.monitorId?.toString() === resource.monitorId?.toString()
);
},
);
}
const uptimePercent: number = this.calculateUptimePercentage(
timelinesForThisResource,
data.precision,
data.downtimeMonitorStatuses,
);
uptimePercentPerResource.push(uptimePercent);
}
// calculate avg
if (uptimePercentPerResource.length === 0) {
return null;
}
const averageUptimePercentage: number =
uptimePercentPerResource.reduce((a: number, b: number) => {
return a + b;
}) / uptimePercentPerResource.length;
//round this to precision.
if (data.precision === UptimePrecision.NO_DECIMAL) {
const percent: number = Math.round(averageUptimePercentage);
return percent;
}
if (data.precision === UptimePrecision.ONE_DECIMAL) {
const percent: number = Math.round(averageUptimePercentage * 10) / 10;
return percent;
}
if (data.precision === UptimePrecision.TWO_DECIMAL) {
const percent: number = Math.round(averageUptimePercentage * 100) / 100;
return percent;
}
if (data.precision === UptimePrecision.THREE_DECIMAL) {
const percent: number = Math.round(averageUptimePercentage * 1000) / 1000;
return percent;
}
return averageUptimePercentage;
}
public static calculateUptimePercentage(
monitorStatusTimelines: Array<MonitorStatusTimeline>,
precision: UptimePrecision,

View File

@ -211,7 +211,7 @@ const DashboardHeader: FunctionComponent<ComponentProps> = (
selectedProject={props.selectedProject}
/>
<div className="flex ml-3">
<div className="flex">
<HeaderAlertGroup>
<HeaderModelAlert<TeamMember>
icon={IconProp.Folder}

View File

@ -53,8 +53,8 @@ import React, {
useEffect,
useState,
} from "react";
import UptimeUtil from "Common/Utils/Uptime/UptimeUtil";
import UptimePrecision from "Common/Types/StatusPage/UptimePrecision";
import StatusPageResourceUptimeUtil from "Common/Utils/StatusPage/ResourceUptime";
const Overview: FunctionComponent<PageComponentProps> = (
props: PageComponentProps,
@ -293,97 +293,42 @@ const Overview: FunctionComponent<PageComponentProps> = (
StatusPageUtil.isPrivateStatusPage(),
]);
type GetMonitorStatusTimelineForResourceFunction = (data: {
resource: StatusPageResource;
}) => Array<MonitorStatusTimeline>;
const getMonitorStatusTimelineForResource: GetMonitorStatusTimelineForResourceFunction =
(data: { resource: StatusPageResource }): Array<MonitorStatusTimeline> => {
return [...monitorStatusTimelines].filter(
(timeline: MonitorStatusTimeline) => {
// check monitor if first.
if (data.resource.monitorId) {
return (
timeline.monitorId?.toString() ===
data.resource.monitorId?.toString()
);
}
if (data.resource.monitorGroupId) {
const monitorsInThisGroup: Array<ObjectID> | undefined =
monitorsInGroup[data.resource.monitorGroupId?.toString() || ""];
if (!monitorsInThisGroup) {
return false;
}
return monitorsInThisGroup.find((monitorId: ObjectID) => {
return monitorId.toString() === timeline.monitorId?.toString();
});
}
return false;
},
);
};
type GetCurrentGroupStatusElementFunction = (data: {
group: StatusPageGroup;
}) => ReactElement;
const getCurrentGroupStatusElement: GetCurrentGroupStatusElementFunction =
(data: { group: StatusPageGroup }): ReactElement => {
const currentStatus: MonitorStatus = getCurrentGroupStatus(data.group);
const resourcesInGroup: Array<StatusPageResource> = getResourcesInGroup(
data.group,
);
if (resourcesInGroup.length === 0) {
return <></>;
}
let allMonitorStatusTimelines: Array<MonitorStatusTimeline> = [];
for (const resource of resourcesInGroup) {
// get monitor status timeline.
const monitorStatusTimelines: Array<MonitorStatusTimeline> =
getMonitorStatusTimelineForResource({
resource: resource,
});
// add to the monitor status timelines.
allMonitorStatusTimelines = allMonitorStatusTimelines.concat(
monitorStatusTimelines,
);
}
const downtimeMonitorStatuses: Array<MonitorStatus> =
statusPage?.downtimeMonitorStatuses || [];
// if the current status is operational then show uptime Percent.
let precision: UptimePrecision = UptimePrecision.ONE_DECIMAL;
if (data.group.uptimePercentPrecision) {
precision = data.group.uptimePercentPrecision;
}
const currentStatus: MonitorStatus =
StatusPageResourceUptimeUtil.getCurrentStatusPageGroupStatus({
statusPageGroup: data.group,
monitorStatusTimelines: monitorStatusTimelines,
statusPageResources: statusPageResources,
monitorStatuses: monitorStatuses,
monitorGroupCurrentStatuses: monitorGroupCurrentStatuses,
});
if (
!downtimeMonitorStatuses.find((downtimeStatus: MonitorStatus) => {
return (
currentStatus?.id?.toString() === downtimeStatus?.id?.toString()
);
}) &&
!(statusPage?.downtimeMonitorStatuses || []).find(
(downtimeStatus: MonitorStatus) => {
return (
currentStatus?.id?.toString() === downtimeStatus?.id?.toString()
);
},
) &&
data.group.showUptimePercent
) {
const uptimePercent: number = UptimeUtil.calculateUptimePercentage(
allMonitorStatusTimelines,
precision,
downtimeMonitorStatuses,
);
const uptimePercent: number | null =
StatusPageResourceUptimeUtil.calculateUptimePercentOfStatusPageGroup({
statusPageGroup: data.group,
monitorStatusTimelines: monitorStatusTimelines,
precision:
data.group.uptimePercentPrecision || UptimePrecision.ONE_DECIMAL,
downtimeMonitorStatuses: statusPage?.downtimeMonitorStatuses || [],
statusPageResources: statusPageResources,
monitorsInGroup: monitorsInGroup,
monitorGroupCurrentStatuses: monitorGroupCurrentStatuses,
});
return (
<div
@ -536,9 +481,13 @@ const Overview: FunctionComponent<PageComponentProps> = (
uptimePrecision={
resource.uptimePercentPrecision || UptimePrecision.ONE_DECIMAL
}
monitorStatusTimeline={getMonitorStatusTimelineForResource({
resource: resource,
})}
monitorStatusTimeline={StatusPageResourceUptimeUtil.getMonitorStatusTimelineForResource(
{
statusPageResource: resource,
monitorStatusTimelines: monitorStatusTimelines,
monitorsInGroup: monitorsInGroup,
},
)}
startDate={startDate}
endDate={endDate}
showHistoryChart={resource.showStatusHistoryChart}
@ -583,9 +532,13 @@ const Overview: FunctionComponent<PageComponentProps> = (
description={resource.displayDescription || ""}
tooltip={resource.displayTooltip || ""}
currentStatus={currentStatus}
monitorStatusTimeline={getMonitorStatusTimelineForResource({
resource: resource,
})}
monitorStatusTimeline={StatusPageResourceUptimeUtil.getMonitorStatusTimelineForResource(
{
statusPageResource: resource,
monitorStatusTimelines: monitorStatusTimelines,
monitorsInGroup: monitorsInGroup,
},
)}
downtimeMonitorStatuses={
statusPage?.downtimeMonitorStatuses || []
}
@ -700,72 +653,6 @@ const Overview: FunctionComponent<PageComponentProps> = (
return groups;
};
type GetResourcesInGroupFunction = (
group: StatusPageGroup,
) => Array<StatusPageResource>;
const getResourcesInGroup: GetResourcesInGroupFunction = (
group: StatusPageGroup,
): Array<StatusPageResource> => {
return statusPageResources.filter((resource: StatusPageResource) => {
return resource.statusPageGroupId?.toString() === group._id?.toString();
});
};
type GetCurrentGroupStatus = (group: StatusPageGroup) => MonitorStatus;
const getCurrentGroupStatus: GetCurrentGroupStatus = (
group: StatusPageGroup,
): MonitorStatus => {
let currentStatus: MonitorStatus = new MonitorStatus();
currentStatus.name = "Operational";
currentStatus.color = Green;
const resourcesInGroup: Array<StatusPageResource> =
getResourcesInGroup(group);
for (const resource of resourcesInGroup) {
let currentMonitorStatus: MonitorStatus | undefined = undefined;
if (resource.monitor) {
currentMonitorStatus = monitorStatuses.find((status: MonitorStatus) => {
return (
status._id?.toString() ===
resource.monitor?.currentMonitorStatusId?.toString()
);
});
}
if (resource.monitorGroupId) {
currentMonitorStatus = monitorStatuses.find((status: MonitorStatus) => {
return (
status._id?.toString() ===
monitorGroupCurrentStatuses[
resource.monitorGroupId?.toString() || ""
]?.toString()
);
});
}
if (!currentMonitorStatus) {
currentMonitorStatus = currentStatus;
}
if (
(currentStatus &&
currentStatus.priority &&
currentMonitorStatus?.priority &&
currentMonitorStatus?.priority > currentStatus.priority) ||
!currentStatus ||
!currentStatus.priority
) {
currentStatus = currentMonitorStatus!;
}
}
return currentStatus;
};
const activeIncidentsInIncidentGroup: Array<IncidentGroup> =
getActiveIncidents();
const activeScheduledMaintenanceEventsInScheduledMaintenanceGroup: Array<ScheduledMaintenanceGroup> =
@ -823,16 +710,19 @@ const Overview: FunctionComponent<PageComponentProps> = (
textOnRight={
currentStatus.isOperationalState &&
statusPage?.showOverallUptimePercentOnStatusPage
? UptimeUtil.calculateAvgUptimePercentageOfAllResources({
monitorStatusTimelines: monitorStatusTimelines,
statusPageResources: statusPageResources,
downtimeMonitorStatuses:
statusPage.downtimeMonitorStatuses || [],
precision:
statusPage.overallUptimePercentPrecision ||
UptimePrecision.TWO_DECIMAL,
monitorsInGroup: monitorsInGroup,
})?.toString() + "% uptime" || "100%"
? StatusPageResourceUptimeUtil.calculateAvgUptimePercentageOfAllResources(
{
monitorStatusTimelines: monitorStatusTimelines,
statusPageResources: statusPageResources,
downtimeMonitorStatuses:
statusPage.downtimeMonitorStatuses || [],
precision:
statusPage.overallUptimePercentPrecision ||
UptimePrecision.TWO_DECIMAL,
resourceGroups: resourceGroups,
monitorsInGroup: monitorsInGroup,
},
)?.toString() + "% uptime" || "100%"
: undefined
}
textClassName="text-white text-lg flex justify-between w-full"