Merge pull request #3325 from bluewave-labs/feat/pagespeed-date-range

feat: pagespeed date range
This commit is contained in:
Alexander Holliday
2026-02-21 13:09:58 -08:00
committed by GitHub
8 changed files with 95 additions and 18 deletions
@@ -12,7 +12,7 @@ import {
import { HistogramPageSpeedScoresTooltip } from "@/Components/monitors";
import { useTheme } from "@mui/material/styles";
import type { CheckSnapshot } from "@/Types/Check";
import type { PageSpeedGroupedCheck } from "@/Types/Check";
import type { Palette } from "@mui/material/styles";
type PaletteColorKey = Extract<
keyof Palette,
@@ -52,7 +52,7 @@ export const HistogramPageSpeedDetails = ({
checks,
range,
}: {
checks: CheckSnapshot[];
checks: PageSpeedGroupedCheck[];
range: string;
}) => {
const theme = useTheme();
@@ -73,7 +73,7 @@ export const HistogramPageSpeedDetails = ({
>
<AreaChart data={checks}>
<XAxis
dataKey={"createdAt"}
dataKey={"bucketDate"}
tick={(props) => (
<XTick
{...props}
+24 -4
View File
@@ -1,4 +1,5 @@
import { BasePage } from "@/Components/design-elements";
import { HeaderTimeRange } from "@/Components/common";
import type { PageSpeedDetailsResponse } from "@/Types/Monitor";
import Stack from "@mui/material/Stack";
import {
@@ -13,23 +14,36 @@ import { useIsAdmin } from "@/Hooks/useIsAdmin";
import { useGet } from "@/Hooks/UseApi";
import { useParams } from "react-router-dom";
import { useTheme } from "@mui/material";
import { useState, useMemo } from "react";
const PageSpeedDetails = () => {
const { monitorId } = useParams();
const isAdmin = useIsAdmin();
const theme = useTheme();
const [dateRange, setDateRange] = useState<string>("day");
const monitorDetailsUrl = useMemo(() => {
if (!monitorId) {
return null;
}
const params = new URLSearchParams();
params.append("dateRange", dateRange);
return `/monitors/pagespeed/details/${monitorId}?${params.toString()}`;
}, [monitorId, dateRange]);
const {
data: monitorData,
isLoading,
error,
refetch,
} = useGet<PageSpeedDetailsResponse>(
monitorId ? `/monitors/pagespeed/details/${monitorId}?dateRange=day` : null,
monitorDetailsUrl,
{},
{ keepPreviousData: true, refreshInterval: 30000 }
);
const monitor = monitorData?.monitor;
const monitor = monitorData?.monitorData?.monitor;
const groupedChecks = monitorData?.monitorData?.groupedChecks || [];
const monitorStats = monitorData?.monitorStats || null;
return (
@@ -47,9 +61,15 @@ const PageSpeedDetails = () => {
monitor={monitor}
monitorStats={monitorStats}
/>
<HeaderTimeRange
isLoading={isLoading}
hasDateRange={true}
dateRange={dateRange}
setDateRange={setDateRange}
/>
<HistogramPageSpeedDetails
checks={monitor?.recentChecks || []}
range="day"
checks={groupedChecks}
range={dateRange}
/>
<Stack
direction={{ xs: "column", md: "row" }}
+9
View File
@@ -151,6 +151,15 @@ export interface GroupedCheck {
totalChecks: number;
}
export interface PageSpeedGroupedCheck {
bucketDate: string;
performance: number;
accessibility: number;
bestPractices: number;
seo: number;
totalChecks: number;
}
export interface LatestCheck {
status: boolean;
responseTime: number;
+5 -1
View File
@@ -1,4 +1,5 @@
import type { GroupedCheck, CheckSnapshot } from "@/Types/Check";
import type { PageSpeedGroupedCheck } from "@/Types/Check";
export const MonitorTypes = [
"http",
@@ -112,7 +113,10 @@ export interface MonitorDetailsResponse {
}
export interface PageSpeedDetailsResponse {
monitor: MonitorWithChecks;
monitorData: {
monitor: Monitor;
groupedChecks: PageSpeedGroupedCheck[];
};
monitorStats: MonitorStats | null;
}
@@ -378,7 +378,7 @@ class MongoChecksRepository implements IChecksRepository {
return this.findHardwareDateRangeChecks(monitorObjectId, startDate, endDate, dateString);
}
if (options?.type === "pagespeed") {
return this.findPageSpeedDateRangeChecks(monitorObjectId, startDate, endDate);
return this.findPageSpeedDateRangeChecks(monitorObjectId, startDate, endDate, dateString);
}
return this.findUptimeDateRangeChecks(options?.type ?? "http", monitorObjectId, startDate, endDate, dateString);
};
@@ -572,16 +572,50 @@ class MongoChecksRepository implements IChecksRepository {
};
};
private findPageSpeedDateRangeChecks = async (monitorObjectId: mongoose.Types.ObjectId, startDate: Date, endDate: Date) => {
private findPageSpeedDateRangeChecks = async (monitorObjectId: mongoose.Types.ObjectId, startDate: Date, endDate: Date, dateString: string) => {
const matchStage = {
"metadata.monitorId": monitorObjectId,
createdAt: { $gte: startDate, $lte: endDate },
};
const checks = await CheckModel.find(matchStage).sort({ createdAt: -1 }).limit(25).lean();
const [result] = await CheckModel.aggregate([
{ $match: matchStage },
{ $sort: { createdAt: 1 } },
{
$facet: {
groupedChecks: [
{
$group: {
_id: {
$dateToString: { format: dateString, date: "$createdAt" },
},
avgPerformance: { $avg: "$performance" },
avgAccessibility: { $avg: "$accessibility" },
avgBestPractices: { $avg: "$bestPractices" },
avgSeo: { $avg: "$seo" },
totalChecks: { $sum: 1 },
},
},
{ $sort: { _id: 1 } },
{
$project: {
bucketDate: "$_id",
performance: "$avgPerformance",
accessibility: "$avgAccessibility",
bestPractices: "$avgBestPractices",
seo: "$avgSeo",
totalChecks: 1,
_id: 0,
},
},
],
},
},
]);
return {
monitorType: "pagespeed" as const,
checks: this.mapDocuments(checks),
groupedChecks: result?.groupedChecks ?? [],
};
};
@@ -308,9 +308,9 @@ export class MonitorService implements IMonitorService {
const monitorStats = await this.monitorStatsRepository.findByMonitorId(monitor.id);
return {
monitor: {
...monitor,
checks: checksData.checks,
monitorData: {
monitor,
groupedChecks: checksData.groupedChecks,
},
monitorStats,
};
+10 -1
View File
@@ -124,7 +124,7 @@ export interface ChecksQueryResult {
export interface PageSpeedChecksResult {
monitorType: "pagespeed";
checks: Check[];
groupedChecks: PageSpeedGroupedCheck[];
}
export interface HardwareChecksResult {
@@ -170,6 +170,15 @@ export interface GroupedCheck {
totalChecks: number;
}
export interface PageSpeedGroupedCheck {
bucketDate: string;
performance: number;
accessibility: number;
bestPractices: number;
seo: number;
totalChecks: number;
}
export interface UptimeChecksResult {
monitorType: Exclude<MonitorType, "hardware" | "pagespeed">;
groupedChecks: GroupedCheck[];
+3 -2
View File
@@ -125,8 +125,9 @@ export interface HardwareDetailsResult {
}
export interface PageSpeedDetailsResult {
monitor: Monitor & {
checks: import("./check.js").Check[];
monitorData: {
monitor: Monitor;
groupedChecks: import("./check.js").PageSpeedGroupedCheck[];
};
monitorStats: import("./monitorStats.js").MonitorStats | null;
}