fix uptime graph

This commit is contained in:
Simon Larsen 2023-11-01 10:34:38 +00:00
parent 28f4a1f473
commit d6788c138b
No known key found for this signature in database
GPG Key ID: AB45983AA9C81CDE
4 changed files with 148 additions and 22 deletions

View File

@ -359,6 +359,12 @@ export default class OneUptimeDate {
return moment(date).isAfter(startDate);
}
public static isEqualBySeconds(date: Date, startDate: Date): boolean {
date = this.fromString(date);
startDate = this.fromString(startDate);
return moment(date).isSame(startDate, 'seconds');
}
public static hasExpired(expirationDate: Date): boolean {
expirationDate = this.fromString(expirationDate);
return !moment(this.getCurrentDate()).isBefore(expirationDate);

View File

@ -46,9 +46,7 @@ export class Service extends DatabaseService<MonitorGroup> {
limit: LIMIT_PER_PROJECT,
skip: 0,
select: {
monitor: {
currentMonitorStatusId: true,
},
monitorId: true,
},
props: {
isRoot: true,
@ -68,8 +66,8 @@ export class Service extends DatabaseService<MonitorGroup> {
createdAt: QueryHelper.inBetween(startDate, endDate),
},
select: {
monitorId: true,
createdAt: true,
monitorId: true,
monitorStatus: {
name: true,
color: true,

View File

@ -12,6 +12,11 @@ import OneUptimeDate from 'Common/Types/Date';
import DayUptimeGraph, { Event } from '../Graphs/DayUptimeGraph';
import { Green } from 'Common/Types/BrandColors';
import ErrorMessage from '../ErrorMessage/ErrorMessage';
import ObjectID from 'Common/Types/ObjectID';
export interface MonitorEvent extends Event {
monitorId: ObjectID;
}
export interface ComponentProps {
startDate: Date;
@ -28,27 +33,144 @@ const MonitorUptimeGraph: FunctionComponent<ComponentProps> = (
): ReactElement => {
const [events, setEvents] = useState<Array<Event>>([]);
useEffect(() => {
const eventList: Array<Event> = [];
// convert data to events.
for (let i: number = 0; i < props.items.length; i++) {
if (!props.items[i]) {
break;
/**
* This function, `getMonitorEventsForId`, takes a `monitorId` as an argument and returns an array of `MonitorEvent` objects.
* @param {ObjectID} monitorId - The ID of the monitor for which events are to be fetched.
* @returns {Array<MonitorEvent>} - An array of `MonitorEvent` objects.
*/
const getMonitorEventsForId: (monitorId: ObjectID) => Array<MonitorEvent> = (monitorId: ObjectID): Array<MonitorEvent> => {
// Initialize an empty array to store the monitor events.
const eventList: Array<MonitorEvent> = [];
const monitorEvents = props.items.filter((item) => item.monitorId?.toString() === monitorId.toString());
// Loop through the items in the props object.
for (let i: number = 0; i < monitorEvents.length; i++) {
// If the current item is null or undefined, skip to the next iteration.
if (!monitorEvents[i]) {
continue;
}
// Set the start date of the event to the creation date of the current item. If it doesn't exist, use the current date.
const startDate: Date = monitorEvents[i]!.createdAt || OneUptimeDate.getCurrentDate();
// Initialize the end date as the current date.
let endDate: Date = OneUptimeDate.getCurrentDate();
// If there is a next item and it has a creation date, use that as the end date.
if (monitorEvents[i + 1] && monitorEvents[i + 1]!.createdAt) {
endDate = monitorEvents[i + 1]!.createdAt!;
}
// Push a new MonitorEvent object to the eventList array with properties from the current item and calculated dates.
eventList.push({
startDate:
props.items[i]!.createdAt || OneUptimeDate.getCurrentDate(),
endDate:
props.items[i + 1] && props.items[i + 1]!.createdAt
? (props.items[i + 1]?.createdAt as Date)
: OneUptimeDate.getCurrentDate(),
label: props.items[i]?.monitorStatus?.name || 'Operational',
priority: props.items[i]?.monitorStatus?.priority || 0,
color: props.items[i]?.monitorStatus?.color || Green,
startDate: startDate,
endDate: endDate,
label: monitorEvents[i]?.monitorStatus?.name || 'Operational',
priority: monitorEvents[i]?.monitorStatus?.priority || 0,
color: monitorEvents[i]?.monitorStatus?.color || Green,
monitorId: monitorEvents[i]?.monitorId!,
});
}
// Return the populated eventList array.
return eventList;
}
const getMonitorEvents: () => Array<MonitorEvent> = (): Array<MonitorEvent> => {
// get all distinct monitor ids.
const monitorIds: Array<ObjectID> = [];
for (let i: number = 0; i < props.items.length; i++) {
if (!props.items[i]) {
continue;
}
const monitorId: string | undefined = props.items[i]!.monitorId?.toString();
if (!monitorId) {
continue;
}
if (!monitorIds.find((item) => item.toString() === monitorId)) {
monitorIds.push(new ObjectID(monitorId));
}
}
const eventList: Array<MonitorEvent> = [];
// convert data to events.
for (const monitorId of monitorIds) {
const monitorEvents: Array<MonitorEvent> = getMonitorEventsForId(monitorId);
eventList.push(...monitorEvents);
}
// sort event list by start date.
eventList.sort((a: MonitorEvent, b: MonitorEvent) => {
if (OneUptimeDate.isAfter(a.startDate, b.startDate)) {
return 1;
}
if (OneUptimeDate.isAfter(b.startDate, a.startDate)) {
return -1;
}
return 0;
});
return [...eventList];
}
useEffect(() => {
let monitorEventList: Array<Event> = getMonitorEvents();
let eventList: Array<Event> = [];
for(const monitorEvent of monitorEventList) {
// if this event starts after the last event, then add it to the list directly.
if(eventList.length === 0 || OneUptimeDate.isAfter(monitorEvent.startDate, eventList[eventList.length - 1]!.endDate) || OneUptimeDate.isEqualBySeconds(monitorEvent.startDate, eventList[eventList.length - 1]!.endDate)) {
eventList.push(monitorEvent);
continue;
}
// if this event starts before the last event, then we need to check if it ends before the last event. If it does, then we can skip this event if the monitrEvent is of lower priority than the last event. If it is of higher priority, then we need to add it to the list and remove the last event from the list.
if(OneUptimeDate.isBefore(monitorEvent.startDate, eventList[eventList.length - 1]!.endDate)) {
if(monitorEvent.priority > eventList[eventList.length - 1]!.priority) {
// end the last event at the start of this event.
const tempLastEvent: Event = {...eventList[eventList.length - 1]} as any;
eventList[eventList.length - 1]!.endDate = monitorEvent.startDate;
eventList.push(monitorEvent);
// if the monitorEvent endDate is before the end of the last event, then we need to add the end of the last event to the list.
if(OneUptimeDate.isBefore(monitorEvent.endDate, tempLastEvent.endDate)) {
eventList.push({
startDate: monitorEvent.endDate,
endDate: tempLastEvent.endDate,
label: tempLastEvent.label,
priority: tempLastEvent.priority,
color: tempLastEvent.color,
});
}
}
continue;
}
}
setEvents(eventList);
}, [props.items]);

View File

@ -58,7 +58,7 @@ const MonitorGroupView: FunctionComponent<PageComponentProps> = (
DASHBOARD_API_URL.toString()
)
.addRoute(new MonitorGroup().getCrudApiPath()!)
.addRoute('/current-status/')
.addRoute('/timeline/')
.addRoute(`/${modelId.toString()}`),
}
);
@ -116,7 +116,7 @@ const MonitorGroupView: FunctionComponent<PageComponentProps> = (
},
]}
cardProps={{
title: 'Monitor Group Hello',
title: 'Monitor Group Details',
description:
'Here are more details for this monitor group.',
}}
@ -230,7 +230,7 @@ const MonitorGroupView: FunctionComponent<PageComponentProps> = (
<Card
title="Uptime Graph"
description="Here the 90 day uptime history of this monitor."
description="Here the 90 day uptime history of this monitor group."
>
<MonitorUptimeGraph
error={error}