fix: choose buckets
This commit is contained in:
+18
-15
@@ -7,13 +7,6 @@ import sql from "./db";
|
||||
export type Window = "24h" | "7d" | "30d" | "90d";
|
||||
export type BucketType = "hourly" | "daily";
|
||||
|
||||
const WINDOW_TO_BUCKET: Record<Window, { bucket: BucketType; count: number }> = {
|
||||
"24h": { bucket: "hourly", count: 24 },
|
||||
"7d": { bucket: "daily", count: 7 },
|
||||
"30d": { bucket: "daily", count: 30 },
|
||||
"90d": { bucket: "daily", count: 90 }, // 90 daily bars; 90 rows per monitor, cached.
|
||||
};
|
||||
|
||||
export interface StatusPageRow {
|
||||
id: string;
|
||||
account_id: string;
|
||||
@@ -28,6 +21,8 @@ export interface StatusPageRow {
|
||||
show_cert_expiry: boolean;
|
||||
default_window: Window;
|
||||
display_mode: "compact" | "expanded";
|
||||
bar_frequency: BucketType;
|
||||
bar_count: number;
|
||||
custom_css: string | null;
|
||||
footer_text: string | null;
|
||||
og_image_url: string | null;
|
||||
@@ -153,7 +148,13 @@ export async function loadGroups(pageId: string): Promise<GroupRow[]> {
|
||||
`;
|
||||
}
|
||||
|
||||
export async function loadMonitors(pageId: string, window: Window, pageDisplayMode: "compact" | "expanded" = "expanded"): Promise<MonitorRow[]> {
|
||||
export async function loadMonitors(
|
||||
pageId: string,
|
||||
window: Window,
|
||||
pageDisplayMode: "compact" | "expanded" = "expanded",
|
||||
barFrequency: BucketType = "daily",
|
||||
barCount: number = 90,
|
||||
): Promise<MonitorRow[]> {
|
||||
// Step 1: page → monitors with display overrides + group + position.
|
||||
const monitorRows = await sql<any[]>`
|
||||
SELECT
|
||||
@@ -188,11 +189,13 @@ export async function loadMonitors(pageId: string, window: Window, pageDisplayMo
|
||||
});
|
||||
}
|
||||
|
||||
// Step 3: uptime rollup buckets covering the requested window. We keep
|
||||
// region in the result so JS can pick the fastest region per monitor and
|
||||
// emit per-bucket latency from just that region (status pages are
|
||||
// customer-facing, we show our best foot forward).
|
||||
const { bucket, count } = WINDOW_TO_BUCKET[window];
|
||||
// Step 3: uptime rollup buckets covering the requested window. The bar
|
||||
// frequency + count are admin-controlled per page (independent of the
|
||||
// multi-window uptime cells). We keep region in the result so JS can pick
|
||||
// the fastest region per monitor and emit per-bucket latency from just
|
||||
// that region (status pages are customer-facing — show the best line).
|
||||
const bucket: BucketType = barFrequency;
|
||||
const count = Math.max(1, Math.min(180, barCount));
|
||||
const truncUnit = bucket === "hourly" ? "hour" : "day";
|
||||
const intervalLiteral = `${count} ${truncUnit}s`;
|
||||
let rollupRows = await sql<any[]>`
|
||||
@@ -432,7 +435,7 @@ export async function loadMonitorDetail(slug: string, monitorId: string, window?
|
||||
const win = (window ?? page.default_window) as Window;
|
||||
// Reuse the bulk loader with a single-monitor list — keeps the bucket/state
|
||||
// logic in one place. Cheap because we're querying for one ID.
|
||||
const monitors = await loadMonitors(page.id, win, page.display_mode);
|
||||
const monitors = await loadMonitors(page.id, win, page.display_mode, page.bar_frequency, page.bar_count);
|
||||
const m = monitors.find((x) => x.id === monitorId);
|
||||
if (!m) return null;
|
||||
|
||||
@@ -493,7 +496,7 @@ export async function loadPagePayload(slug: string, window?: Window): Promise<Pa
|
||||
const win = (window ?? page.default_window) as Window;
|
||||
const [groups, monitors, incidents] = await Promise.all([
|
||||
loadGroups(page.id),
|
||||
loadMonitors(page.id, win, page.display_mode),
|
||||
loadMonitors(page.id, win, page.display_mode, page.bar_frequency, page.bar_count),
|
||||
loadIncidents(page.id),
|
||||
]);
|
||||
const { password_hash, ...publicPage } = page;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// class on click. Reads its config from window.PINGQL_PAGE.
|
||||
(function () {
|
||||
var cfg = window.PINGQL_PAGE || {};
|
||||
var defaultWindow = cfg.default_window || "24h";
|
||||
var barFrequency = cfg.bar_frequency || "daily";
|
||||
|
||||
// ── Click to expand/collapse ──────────────────────────────────────────
|
||||
var rows = document.querySelectorAll(".monitor .monitor-row");
|
||||
@@ -23,13 +23,13 @@
|
||||
var tooltip = document.getElementById("bar-tooltip");
|
||||
if (!tooltip) return;
|
||||
|
||||
var bucketSpanMs = (defaultWindow === "24h") ? 3600 * 1000 : 86400 * 1000;
|
||||
var bucketSpanMs = (barFrequency === "hourly") ? 3600 * 1000 : 86400 * 1000;
|
||||
function fmtBucketRange(startIso) {
|
||||
var start = new Date(startIso);
|
||||
var end = new Date(start.getTime() + bucketSpanMs);
|
||||
var dateOpts = { month: "short", day: "numeric" };
|
||||
var timeOpts = { hour: "2-digit", minute: "2-digit" };
|
||||
if (defaultWindow === "24h") {
|
||||
if (barFrequency === "hourly") {
|
||||
return start.toLocaleDateString(undefined, dateOpts) + ", " +
|
||||
start.toLocaleTimeString(undefined, timeOpts) + " — " +
|
||||
end.toLocaleTimeString(undefined, timeOpts);
|
||||
|
||||
@@ -257,10 +257,9 @@
|
||||
// page-level isCompact is kept only as a hint for whether to emit the
|
||||
// expand JS at all.
|
||||
const anyCompact = monitors.some(m => m.display_mode === 'compact');
|
||||
const windowLabel = page.default_window === '24h' ? 'Last 24 hours'
|
||||
: page.default_window === '7d' ? 'Last 7 days'
|
||||
: page.default_window === '30d' ? 'Last 30 days'
|
||||
: 'Last 90 days';
|
||||
const windowLabel = page.bar_frequency === 'hourly'
|
||||
? ('Last ' + page.bar_count + ' hour' + (page.bar_count === 1 ? '' : 's'))
|
||||
: ('Last ' + page.bar_count + ' day' + (page.bar_count === 1 ? '' : 's'));
|
||||
function fmtTimestamp(iso) {
|
||||
const d = new Date(iso);
|
||||
return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' });
|
||||
@@ -366,7 +365,7 @@
|
||||
</main>
|
||||
|
||||
<div id="bar-tooltip" role="tooltip"></div>
|
||||
<script>window.PINGQL_PAGE = <%~ JSON.stringify({ slug: page.slug, default_window: page.default_window, show_response_time: !!page.show_response_time }) %>;</script>
|
||||
<script>window.PINGQL_PAGE = <%~ JSON.stringify({ slug: page.slug, default_window: page.default_window, bar_frequency: page.bar_frequency, show_response_time: !!page.show_response_time }) %>;</script>
|
||||
<script src="/_static/expand.js?v=<%= it.expandJsHash %>" defer></script>
|
||||
|
||||
<% if (page.auto_refresh_s > 0) { %>
|
||||
|
||||
Reference in New Issue
Block a user