import React, { useEffect, useMemo, useState } from "react"; import { useParams } from "react-router-dom"; import { Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts"; import { apiFetch } from "../api"; import { useAuth } from "../state"; const ranges = { "15m": 15 * 60 * 1000, "1h": 60 * 60 * 1000, "24h": 24 * 60 * 60 * 1000, "7d": 7 * 24 * 60 * 60 * 1000, }; function toQueryRange(range) { const to = new Date(); const from = new Date(to.getTime() - ranges[range]); return { from: from.toISOString(), to: to.toISOString() }; } async function loadMetric(targetId, metric, range, tokens, refresh) { const { from, to } = toQueryRange(range); return apiFetch( `/targets/${targetId}/metrics?metric=${encodeURIComponent(metric)}&from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`, {}, tokens, refresh ); } export function TargetDetailPage() { const { id } = useParams(); const { tokens, refresh } = useAuth(); const [range, setRange] = useState("1h"); const [series, setSeries] = useState({}); const [locks, setLocks] = useState([]); const [activity, setActivity] = useState([]); const [error, setError] = useState(""); const [loading, setLoading] = useState(true); useEffect(() => { let active = true; (async () => { setLoading(true); try { const [connections, xacts, cache, locksTable, activityTable] = await Promise.all([ loadMetric(id, "connections_total", range, tokens, refresh), loadMetric(id, "xacts_total", range, tokens, refresh), loadMetric(id, "cache_hit_ratio", range, tokens, refresh), apiFetch(`/targets/${id}/locks`, {}, tokens, refresh), apiFetch(`/targets/${id}/activity`, {}, tokens, refresh), ]); if (!active) return; setSeries({ connections, xacts, cache }); setLocks(locksTable); setActivity(activityTable); setError(""); } catch (e) { if (active) setError(String(e.message || e)); } finally { if (active) setLoading(false); } })(); return () => { active = false; }; }, [id, range, tokens, refresh]); const chartData = useMemo( () => (series.connections || []).map((point, idx) => ({ ts: new Date(point.ts).toLocaleTimeString(), connections: point.value, xacts: series.xacts?.[idx]?.value || 0, cache: series.cache?.[idx]?.value || 0, })), [series] ); if (loading) return
Lade Target Detail...
; if (error) return
{error}
; return (

Target Detail #{id}

{Object.keys(ranges).map((r) => ( ))}

Connections / TPS approx / Cache hit ratio

Locks

{locks.map((l, i) => ( ))}
Type Mode Granted Relation PID
{l.locktype} {l.mode} {String(l.granted)} {l.relation || "-"} {l.pid}

Activity

{activity.map((a) => ( ))}
PID User State Wait
{a.pid} {a.usename} {a.state} {a.wait_event_type || "-"}
); }