106 lines
3.5 KiB
TypeScript
Executable file
106 lines
3.5 KiB
TypeScript
Executable file
/** @jsxImportSource react */
|
|
|
|
import { useState } from 'react'
|
|
import type { FC } from 'react'
|
|
|
|
import {
|
|
usePerformanceMetrics,
|
|
useEndpointMetrics,
|
|
} from '../hooks/useAdminQuery'
|
|
|
|
export const PerformancePage: FC = () => {
|
|
const { data: metrics, isLoading, isError } = usePerformanceMetrics()
|
|
const { data: endpoints } = useEndpointMetrics()
|
|
const [_timeRange, setTimeRange] = useState('1 Hour')
|
|
|
|
if (isLoading) {
|
|
return <div>Loading performance data...</div>
|
|
}
|
|
|
|
if (isError) {
|
|
return <div>Failed to load performance data</div>
|
|
}
|
|
|
|
const elevatedErrorRate = (metrics?.errorRate ?? 0) > 1
|
|
const slowResponse = (metrics?.avgResponseTime ?? 0) > 500
|
|
|
|
return (
|
|
<div className="performance-page">
|
|
<h1 data-testid="page-title">Performance Analytics</h1>
|
|
|
|
{/* Performance Alerts */}
|
|
{elevatedErrorRate && <div className="alert">Elevated Error Rate Alert</div>}
|
|
{slowResponse && <div className="alert">Slow Response Times Detected</div>}
|
|
|
|
{/* KPI Cards */}
|
|
<div className="kpi-cards">
|
|
<div className="kpi-card">
|
|
<div className="kpi-label">Avg Response Time</div>
|
|
<div className="kpi-value">{metrics?.avgResponseTime}ms</div>
|
|
</div>
|
|
<div className="kpi-card">
|
|
<div className="kpi-label">P50 Response Time</div>
|
|
<div className="kpi-value">{metrics?.p50ResponseTime}ms</div>
|
|
</div>
|
|
<div className="kpi-card">
|
|
<div className="kpi-label">P95 Response Time</div>
|
|
<div className="kpi-value">{metrics?.p95ResponseTime}ms</div>
|
|
</div>
|
|
<div className="kpi-card">
|
|
<div className="kpi-label">P99 Response Time</div>
|
|
<div className="kpi-value">{metrics?.p99ResponseTime}ms</div>
|
|
</div>
|
|
<div className="kpi-card">
|
|
<div className="kpi-label">Requests per Second</div>
|
|
<div className="kpi-value">{metrics?.requestsPerSecond}</div>
|
|
</div>
|
|
<div className="kpi-card">
|
|
<div className="kpi-label">Error Rate</div>
|
|
<div className="kpi-value">{metrics?.errorRate}%</div>
|
|
</div>
|
|
<div className="kpi-card">
|
|
<div className="kpi-label">Uptime</div>
|
|
<div className="kpi-value">{metrics?.uptime}%</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Time Range Selector */}
|
|
<div className="time-range">
|
|
<button onClick={() => setTimeRange('1 Hour')}>1 Hour</button>
|
|
<button onClick={() => setTimeRange('6 Hours')}>6 Hours</button>
|
|
<button onClick={() => setTimeRange('24 Hours')}>24 Hours</button>
|
|
</div>
|
|
|
|
{/* Performance Trend */}
|
|
<div className="performance-trend">
|
|
<h2>Performance Trend</h2>
|
|
<div className="chart">Chart placeholder</div>
|
|
</div>
|
|
|
|
{/* Endpoint Performance */}
|
|
<div className="endpoint-performance">
|
|
<h2>Endpoint Performance</h2>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Endpoint</th>
|
|
<th>Avg Response Time</th>
|
|
<th>Request Count</th>
|
|
<th>Error Rate</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{endpoints?.map((endpoint, idx) => (
|
|
<tr key={idx}>
|
|
<td>{endpoint.endpoint}</td>
|
|
<td>{endpoint.avgResponseTime}ms</td>
|
|
<td>{endpoint.requestCount.toLocaleString()}</td>
|
|
<td>{endpoint.errorRate}%</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|