rename: checks → pings throughout (DB, API, UI, Rust)
This commit is contained in:
parent
b4f95fa375
commit
eb2d173cb0
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::query::{self, Response};
|
use crate::query::{self, Response};
|
||||||
use crate::types::{CheckResult, Monitor};
|
use crate::types::{PingResult, Monitor};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
@ -42,7 +42,7 @@ pub async fn fetch_and_run(
|
||||||
Ok(n)
|
Ok(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run_check(client: &reqwest::Client, monitor: &Monitor) -> CheckResult {
|
async fn run_check(client: &reqwest::Client, monitor: &Monitor) -> PingResult {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
|
||||||
// Check cert expiry for HTTPS URLs
|
// Check cert expiry for HTTPS URLs
|
||||||
|
|
@ -56,7 +56,7 @@ async fn run_check(client: &reqwest::Client, monitor: &Monitor) -> CheckResult {
|
||||||
let latency_ms = start.elapsed().as_millis() as u64;
|
let latency_ms = start.elapsed().as_millis() as u64;
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Err(e) => CheckResult {
|
Err(e) => PingResult {
|
||||||
monitor_id: monitor.id.clone(),
|
monitor_id: monitor.id.clone(),
|
||||||
status_code: None,
|
status_code: None,
|
||||||
latency_ms: Some(latency_ms),
|
latency_ms: Some(latency_ms),
|
||||||
|
|
@ -102,7 +102,7 @@ async fn run_check(client: &reqwest::Client, monitor: &Monitor) -> CheckResult {
|
||||||
|
|
||||||
debug!("{} → {status} {latency_ms}ms up={up}", monitor.url);
|
debug!("{} → {status} {latency_ms}ms up={up}", monitor.url);
|
||||||
|
|
||||||
CheckResult {
|
PingResult {
|
||||||
monitor_id: monitor.id.clone(),
|
monitor_id: monitor.id.clone(),
|
||||||
status_code: Some(status),
|
status_code: Some(status),
|
||||||
latency_ms: Some(latency_ms),
|
latency_ms: Some(latency_ms),
|
||||||
|
|
@ -165,7 +165,7 @@ async fn post_result(
|
||||||
client: &reqwest::Client,
|
client: &reqwest::Client,
|
||||||
coordinator_url: &str,
|
coordinator_url: &str,
|
||||||
token: &str,
|
token: &str,
|
||||||
result: CheckResult,
|
result: PingResult,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
client
|
client
|
||||||
.post(format!("{coordinator_url}/internal/ingest"))
|
.post(format!("{coordinator_url}/internal/ingest"))
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ pub struct Monitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub struct CheckResult {
|
pub struct PingResult {
|
||||||
pub monitor_id: String,
|
pub monitor_id: String,
|
||||||
pub status_code: Option<u16>,
|
pub status_code: Option<u16>,
|
||||||
pub latency_ms: Option<u64>,
|
pub latency_ms: Option<u64>,
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@
|
||||||
<div id="stat-uptime" class="text-lg font-semibold text-gray-200"></div>
|
<div id="stat-uptime" class="text-lg font-semibold text-gray-200"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-gray-900 border border-gray-800 rounded-xl p-4">
|
<div class="bg-gray-900 border border-gray-800 rounded-xl p-4">
|
||||||
<div class="text-xs text-gray-500 mb-1">Last Check</div>
|
<div class="text-xs text-gray-500 mb-1">Last Ping</div>
|
||||||
<div id="stat-last" class="text-lg font-semibold text-gray-200"></div>
|
<div id="stat-last" class="text-lg font-semibold text-gray-200"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -73,10 +73,10 @@
|
||||||
<div id="status-bar" class="flex gap-0.5 h-8 rounded overflow-hidden"></div>
|
<div id="status-bar" class="flex gap-0.5 h-8 rounded overflow-hidden"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Recent checks table -->
|
<!-- Recent pings table -->
|
||||||
<div class="bg-gray-900 border border-gray-800 rounded-xl mb-8 overflow-hidden">
|
<div class="bg-gray-900 border border-gray-800 rounded-xl mb-8 overflow-hidden">
|
||||||
<div class="px-4 py-3 border-b border-gray-800">
|
<div class="px-4 py-3 border-b border-gray-800">
|
||||||
<h3 class="text-sm text-gray-400">Recent Checks</h3>
|
<h3 class="text-sm text-gray-400">Recent Pings</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="w-full text-sm">
|
<table class="w-full text-sm">
|
||||||
|
|
@ -89,7 +89,7 @@
|
||||||
<th class="text-left px-4 py-2 font-medium">Error</th>
|
<th class="text-left px-4 py-2 font-medium">Error</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="checks-table" class="divide-y divide-gray-800/50"></tbody>
|
<tbody id="pings-table" class="divide-y divide-gray-800/50"></tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -148,12 +148,12 @@
|
||||||
document.getElementById('content').classList.remove('hidden');
|
document.getElementById('content').classList.remove('hidden');
|
||||||
|
|
||||||
const results = data.results || [];
|
const results = data.results || [];
|
||||||
const lastCheck = results[0];
|
const lastPing = results[0];
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
document.getElementById('monitor-name').textContent = data.name;
|
document.getElementById('monitor-name').textContent = data.name;
|
||||||
document.getElementById('monitor-url').textContent = data.url;
|
document.getElementById('monitor-url').textContent = data.url;
|
||||||
document.getElementById('status-dot').innerHTML = statusBadge(lastCheck?.up);
|
document.getElementById('status-dot').innerHTML = statusBadge(lastPing?.up);
|
||||||
|
|
||||||
// Toggle button
|
// Toggle button
|
||||||
const toggleBtn = document.getElementById('toggle-btn');
|
const toggleBtn = document.getElementById('toggle-btn');
|
||||||
|
|
@ -166,41 +166,41 @@
|
||||||
|
|
||||||
// Delete button
|
// Delete button
|
||||||
document.getElementById('delete-btn').onclick = async () => {
|
document.getElementById('delete-btn').onclick = async () => {
|
||||||
if (!confirm('Delete this monitor and all its check history?')) return;
|
if (!confirm('Delete this monitor and all its ping history?')) return;
|
||||||
await api(`/monitors/${monitorId}`, { method: 'DELETE' });
|
await api(`/monitors/${monitorId}`, { method: 'DELETE' });
|
||||||
window.location.href = '/dashboard/home';
|
window.location.href = '/dashboard/home';
|
||||||
};
|
};
|
||||||
|
|
||||||
// Stats
|
// Stats
|
||||||
const upChecks = results.filter(r => r.up);
|
const upPings = results.filter(r => r.up);
|
||||||
const latencies = results.filter(r => r.latency_ms != null).map(r => r.latency_ms);
|
const latencies = results.filter(r => r.latency_ms != null).map(r => r.latency_ms);
|
||||||
const avgLatency = latencies.length ? Math.round(latencies.reduce((a, b) => a + b, 0) / latencies.length) : null;
|
const avgLatency = latencies.length ? Math.round(latencies.reduce((a, b) => a + b, 0) / latencies.length) : null;
|
||||||
const uptime = results.length ? Math.round((upChecks.length / results.length) * 100) : null;
|
const uptime = results.length ? Math.round((upPings.length / results.length) * 100) : null;
|
||||||
|
|
||||||
document.getElementById('stat-status').innerHTML = lastCheck
|
document.getElementById('stat-status').innerHTML = lastPing
|
||||||
? (lastCheck.up ? '<span class="text-green-400">Up</span>' : '<span class="text-red-400">Down</span>')
|
? (lastPing.up ? '<span class="text-green-400">Up</span>' : '<span class="text-red-400">Down</span>')
|
||||||
: '<span class="text-gray-500">—</span>';
|
: '<span class="text-gray-500">—</span>';
|
||||||
document.getElementById('stat-latency').textContent = avgLatency != null ? `${avgLatency}ms` : '—';
|
document.getElementById('stat-latency').textContent = avgLatency != null ? `${avgLatency}ms` : '—';
|
||||||
document.getElementById('stat-uptime').textContent = uptime != null ? `${uptime}%` : '—';
|
document.getElementById('stat-uptime').textContent = uptime != null ? `${uptime}%` : '—';
|
||||||
document.getElementById('stat-last').textContent = lastCheck ? timeAgo(lastCheck.checked_at) : '—';
|
document.getElementById('stat-last').textContent = lastPing ? timeAgo(lastPing.pinged_at) : '—';
|
||||||
|
|
||||||
// Latency chart
|
// Latency chart
|
||||||
renderLatencyChart(results.slice().reverse());
|
renderLatencyChart(results.slice().reverse());
|
||||||
|
|
||||||
// Status bar
|
// Status bar
|
||||||
const statusBar = document.getElementById('status-bar');
|
const statusBar = document.getElementById('status-bar');
|
||||||
const barChecks = results.slice(0, 60).reverse();
|
const barPings = results.slice(0, 60).reverse();
|
||||||
statusBar.innerHTML = barChecks.map(c =>
|
statusBar.innerHTML = barPings.map(c =>
|
||||||
`<div class="flex-1 ${c.up ? 'bg-green-500/70' : 'bg-red-500/70'}" title="${new Date(c.checked_at).toLocaleString()} — ${c.up ? 'Up' : 'Down'} ${c.latency_ms ? c.latency_ms + 'ms' : ''}"></div>`
|
`<div class="flex-1 ${c.up ? 'bg-green-500/70' : 'bg-red-500/70'}" title="${new Date(c.pinged_at).toLocaleString()} — ${c.up ? 'Up' : 'Down'} ${c.latency_ms ? c.latency_ms + 'ms' : ''}"></div>`
|
||||||
).join('') || '<div class="flex-1 bg-gray-800 text-center text-xs text-gray-600 leading-8">No data</div>';
|
).join('') || '<div class="flex-1 bg-gray-800 text-center text-xs text-gray-600 leading-8">No data</div>';
|
||||||
|
|
||||||
// Checks table
|
// Pings table
|
||||||
document.getElementById('checks-table').innerHTML = results.slice(0, 30).map(c => `
|
document.getElementById('pings-table').innerHTML = results.slice(0, 30).map(c => `
|
||||||
<tr class="hover:bg-gray-800/50">
|
<tr class="hover:bg-gray-800/50">
|
||||||
<td class="px-4 py-2">${c.up ? '<span class="text-green-400">Up</span>' : '<span class="text-red-400">Down</span>'}</td>
|
<td class="px-4 py-2">${c.up ? '<span class="text-green-400">Up</span>' : '<span class="text-red-400">Down</span>'}</td>
|
||||||
<td class="px-4 py-2 text-gray-300">${c.status_code ?? '—'}</td>
|
<td class="px-4 py-2 text-gray-300">${c.status_code ?? '—'}</td>
|
||||||
<td class="px-4 py-2 text-gray-300">${c.latency_ms != null ? c.latency_ms + 'ms' : '—'}</td>
|
<td class="px-4 py-2 text-gray-300">${c.latency_ms != null ? c.latency_ms + 'ms' : '—'}</td>
|
||||||
<td class="px-4 py-2 text-gray-500">${timeAgo(c.checked_at)}</td>
|
<td class="px-4 py-2 text-gray-500">${timeAgo(c.pinged_at)}</td>
|
||||||
<td class="px-4 py-2 text-red-400/70 text-xs truncate max-w-[200px]">${c.error ? escapeHtml(c.error) : ''}</td>
|
<td class="px-4 py-2 text-red-400/70 text-xs truncate max-w-[200px]">${c.error ? escapeHtml(c.error) : ''}</td>
|
||||||
</tr>
|
</tr>
|
||||||
`).join('');
|
`).join('');
|
||||||
|
|
@ -216,9 +216,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderLatencyChart(checks) {
|
function renderLatencyChart(pings) {
|
||||||
const container = document.getElementById('latency-chart');
|
const container = document.getElementById('latency-chart');
|
||||||
const data = checks.filter(c => c.latency_ms != null);
|
const data = pings.filter(c => c.latency_ms != null);
|
||||||
if (data.length < 2) {
|
if (data.length < 2) {
|
||||||
container.innerHTML = '<div class="h-full flex items-center justify-center text-gray-600 text-sm">Not enough data</div>';
|
container.innerHTML = '<div class="h-full flex items-center justify-center text-gray-600 text-sm">Not enough data</div>';
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -54,32 +54,32 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch last check for each monitor
|
// Fetch last ping for each monitor
|
||||||
const monitorsWithChecks = await Promise.all(
|
const monitorsWithPings = await Promise.all(
|
||||||
monitors.map(async (m) => {
|
monitors.map(async (m) => {
|
||||||
try {
|
try {
|
||||||
const checks = await api(`/monitors/${m.id}/history?limit=20`);
|
const pings = await api(`/monitors/${m.id}/pings?limit=20`);
|
||||||
return { ...m, checks };
|
return { ...m, pings };
|
||||||
} catch {
|
} catch {
|
||||||
return { ...m, checks: [] };
|
return { ...m, pings: [] };
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const upCount = monitorsWithChecks.filter(m => m.checks[0]?.up === true).length;
|
const upCount = monitorsWithPings.filter(m => m.pings[0]?.up === true).length;
|
||||||
const downCount = monitorsWithChecks.filter(m => m.checks[0]?.up === false).length;
|
const downCount = monitorsWithPings.filter(m => m.pings[0]?.up === false).length;
|
||||||
summary.innerHTML = `<span class="text-green-400">${upCount} up</span> · <span class="${downCount > 0 ? 'text-red-400' : 'text-gray-500'}">${downCount} down</span> · ${monitors.length} total`;
|
summary.innerHTML = `<span class="text-green-400">${upCount} up</span> · <span class="${downCount > 0 ? 'text-red-400' : 'text-gray-500'}">${downCount} down</span> · ${monitors.length} total`;
|
||||||
|
|
||||||
list.innerHTML = monitorsWithChecks.map(m => {
|
list.innerHTML = monitorsWithPings.map(m => {
|
||||||
const lastCheck = m.checks[0];
|
const lastPing = m.pings[0];
|
||||||
const latencies = m.checks.filter(c => c.latency_ms != null).map(c => c.latency_ms).reverse();
|
const latencies = m.pings.filter(c => c.latency_ms != null).map(c => c.latency_ms).reverse();
|
||||||
const avgLatency = latencies.length ? Math.round(latencies.reduce((a, b) => a + b, 0) / latencies.length) : null;
|
const avgLatency = latencies.length ? Math.round(latencies.reduce((a, b) => a + b, 0) / latencies.length) : null;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<a href="/dashboard/monitors/${m.id}" class="block bg-gray-900 hover:bg-gray-800/80 border border-gray-800 rounded-xl p-4 transition-colors group">
|
<a href="/dashboard/monitors/${m.id}" class="block bg-gray-900 hover:bg-gray-800/80 border border-gray-800 rounded-xl p-4 transition-colors group">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div class="flex items-center gap-3 min-w-0">
|
<div class="flex items-center gap-3 min-w-0">
|
||||||
${statusBadge(lastCheck?.up)}
|
${statusBadge(lastPing?.up)}
|
||||||
<div class="min-w-0">
|
<div class="min-w-0">
|
||||||
<div class="font-medium text-gray-100 group-hover:text-white truncate">${escapeHtml(m.name)}</div>
|
<div class="font-medium text-gray-100 group-hover:text-white truncate">${escapeHtml(m.name)}</div>
|
||||||
<div class="text-xs text-gray-500 truncate">${escapeHtml(m.url)}</div>
|
<div class="text-xs text-gray-500 truncate">${escapeHtml(m.url)}</div>
|
||||||
|
|
@ -89,7 +89,7 @@
|
||||||
<div class="hidden sm:block">${sparkline(latencies)}</div>
|
<div class="hidden sm:block">${sparkline(latencies)}</div>
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<div class="text-sm text-gray-300">${avgLatency != null ? avgLatency + 'ms' : '—'}</div>
|
<div class="text-sm text-gray-300">${avgLatency != null ? avgLatency + 'ms' : '—'}</div>
|
||||||
<div class="text-xs text-gray-500">${lastCheck ? timeAgo(lastCheck.checked_at) : 'no checks'}</div>
|
<div class="text-xs text-gray-500">${lastPing ? timeAgo(lastPing.pinged_at) : 'no pings'}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs px-2 py-1 rounded ${m.enabled ? 'bg-gray-800 text-gray-400' : 'bg-yellow-900/30 text-yellow-500'}">${m.enabled ? m.interval_s + 's' : 'paused'}</div>
|
<div class="text-xs px-2 py-1 rounded ${m.enabled ? 'bg-gray-800 text-gray-400' : 'bg-yellow-900/30 text-yellow-500'}">${m.enabled ? m.interval_s + 's' : 'paused'}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
<label class="block text-xs text-gray-500 uppercase tracking-wider mb-2">Account Key</label>
|
<label class="block text-xs text-gray-500 uppercase tracking-wider mb-2">Account Key</label>
|
||||||
<input id="key-input" type="text" placeholder="XXXX-XXXX-XXXX-XXXX"
|
<input id="key-input" type="text" placeholder="XXXX-XXXX-XXXX-XXXX"
|
||||||
class="w-full bg-gray-800 border border-gray-700 rounded-lg px-4 py-3 text-gray-100 placeholder-gray-600 focus:outline-none focus:border-blue-500 key-display text-center text-lg"
|
class="w-full bg-gray-800 border border-gray-700 rounded-lg px-4 py-3 text-gray-100 placeholder-gray-600 focus:outline-none focus:border-blue-500 key-display text-center text-lg"
|
||||||
maxlength="19" autocomplete="off" spellcheck="false">
|
maxlength="19" autocomplete="off" spellping="false">
|
||||||
<button id="login-btn"
|
<button id="login-btn"
|
||||||
class="w-full mt-3 bg-blue-600 hover:bg-blue-500 text-white font-medium py-3 rounded-lg transition-colors">
|
class="w-full mt-3 bg-blue-600 hover:bg-blue-500 text-white font-medium py-3 rounded-lg transition-colors">
|
||||||
Sign In
|
Sign In
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-sm text-gray-400 mb-1.5">Check Interval</label>
|
<label class="block text-sm text-gray-400 mb-1.5">Ping Interval</label>
|
||||||
<select id="interval"
|
<select id="interval"
|
||||||
class="w-full bg-gray-900 border border-gray-800 rounded-lg px-4 py-2.5 text-gray-100 focus:outline-none focus:border-blue-500">
|
class="w-full bg-gray-900 border border-gray-800 rounded-lg px-4 py-2.5 text-gray-100 focus:outline-none focus:border-blue-500">
|
||||||
<option value="10">10 seconds</option>
|
<option value="10">10 seconds</option>
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ export async function migrate() {
|
||||||
`;
|
`;
|
||||||
|
|
||||||
await sql`
|
await sql`
|
||||||
CREATE TABLE IF NOT EXISTS check_results (
|
CREATE TABLE IF NOT EXISTS pings (
|
||||||
id BIGSERIAL PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
monitor_id TEXT NOT NULL REFERENCES monitors(id) ON DELETE CASCADE,
|
monitor_id TEXT NOT NULL REFERENCES monitors(id) ON DELETE CASCADE,
|
||||||
checked_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
checked_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
|
@ -40,7 +40,7 @@ export async function migrate() {
|
||||||
)
|
)
|
||||||
`;
|
`;
|
||||||
|
|
||||||
await sql`CREATE INDEX IF NOT EXISTS idx_results_monitor ON check_results(monitor_id, checked_at DESC)`;
|
await sql`CREATE INDEX IF NOT EXISTS idx_pings_monitor ON pings(monitor_id, checked_at DESC)`;
|
||||||
|
|
||||||
console.log("DB ready");
|
console.log("DB ready");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ export const internal = new Elysia({ prefix: "/internal", detail: { hide: true }
|
||||||
SELECT m.id, m.url, m.interval_s, m.query
|
SELECT m.id, m.url, m.interval_s, m.query
|
||||||
FROM monitors m
|
FROM monitors m
|
||||||
LEFT JOIN LATERAL (
|
LEFT JOIN LATERAL (
|
||||||
SELECT checked_at FROM check_results
|
SELECT checked_at FROM pings
|
||||||
WHERE monitor_id = m.id
|
WHERE monitor_id = m.id
|
||||||
ORDER BY checked_at DESC LIMIT 1
|
ORDER BY checked_at DESC LIMIT 1
|
||||||
) last ON true
|
) last ON true
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ export const monitors = new Elysia({ prefix: "/monitors" })
|
||||||
if (!monitor) return error(404, { error: "Not found" });
|
if (!monitor) return error(404, { error: "Not found" });
|
||||||
|
|
||||||
const results = await sql`
|
const results = await sql`
|
||||||
SELECT * FROM check_results WHERE monitor_id = ${params.id}
|
SELECT * FROM pings WHERE monitor_id = ${params.id}
|
||||||
ORDER BY checked_at DESC LIMIT 100
|
ORDER BY checked_at DESC LIMIT 100
|
||||||
`;
|
`;
|
||||||
return { ...monitor, results };
|
return { ...monitor, results };
|
||||||
|
|
@ -77,15 +77,15 @@ export const monitors = new Elysia({ prefix: "/monitors" })
|
||||||
}, { detail: { summary: "Toggle monitor on/off", tags: ["monitors"] } })
|
}, { detail: { summary: "Toggle monitor on/off", tags: ["monitors"] } })
|
||||||
|
|
||||||
// Check history
|
// Check history
|
||||||
.get("/:id/history", async ({ accountId, params, query, error }) => {
|
.get("/:id/pings", async ({ accountId, params, query, error }) => {
|
||||||
const [monitor] = await sql`
|
const [monitor] = await sql`
|
||||||
SELECT id FROM monitors WHERE id = ${params.id} AND account_id = ${accountId}
|
SELECT id FROM monitors WHERE id = ${params.id} AND account_id = ${accountId}
|
||||||
`;
|
`;
|
||||||
if (!monitor) return error(404, { error: "Not found" });
|
if (!monitor) return error(404, { error: "Not found" });
|
||||||
const limit = Math.min(Number(query.limit ?? 100), 1000);
|
const limit = Math.min(Number(query.limit ?? 100), 1000);
|
||||||
return sql`
|
return sql`
|
||||||
SELECT * FROM check_results
|
SELECT * FROM pings
|
||||||
WHERE monitor_id = ${params.id}
|
WHERE monitor_id = ${params.id}
|
||||||
ORDER BY checked_at DESC LIMIT ${limit}
|
ORDER BY checked_at DESC LIMIT ${limit}
|
||||||
`;
|
`;
|
||||||
}, { detail: { summary: "Get check history", tags: ["monitors"] } });
|
}, { detail: { summary: "Get ping history", tags: ["monitors"] } });
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ export const ingest = new Elysia()
|
||||||
if (body.cert_expiry_days != null) meta.cert_expiry_days = body.cert_expiry_days;
|
if (body.cert_expiry_days != null) meta.cert_expiry_days = body.cert_expiry_days;
|
||||||
|
|
||||||
await sql`
|
await sql`
|
||||||
INSERT INTO check_results (monitor_id, status_code, latency_ms, up, error, meta)
|
INSERT INTO pings (monitor_id, status_code, latency_ms, up, error, meta)
|
||||||
VALUES (
|
VALUES (
|
||||||
${body.monitor_id},
|
${body.monitor_id},
|
||||||
${body.status_code ?? null},
|
${body.status_code ?? null},
|
||||||
Loading…
Reference in New Issue