import React from 'react' import { Refresh } from '../components/icons' import { JsonTree } from '../components/json-tree' import { Section } from '../components/layout' import { Badge, Button, Empty } from '../components/ui' import type { IamIDevtoolsEngine, IamIDevtoolsMetrics } from '../lib/types' function Stat({ label, value, hint }: { label: string; value: string | number; hint?: string }) { return (
{label} {value} {hint && {hint}}
) } export function IamMetricsPanel({ engine, metrics, pollMs = 1000, }: { engine: IamIDevtoolsEngine metrics?: IamIDevtoolsMetrics pollMs?: number }) { const [stats, setStats] = React.useState(() => engine.stats()) const [snap, setSnap] = React.useState(() => metrics?.snapshot() ?? null) React.useEffect(() => { const id = setInterval(() => { setStats(engine.stats()) if (metrics) setSnap(metrics.snapshot()) }, pollMs) return () => clearInterval(id) }, [engine, metrics, pollMs]) const allowRate = snap && snap.total > 0 ? Math.round((snap.allow / snap.total) * 100) : 0 return (
Telemetry poll {pollMs}ms
{!metrics ? ( ) : !snap ? ( ) : (
)}
{Object.entries(stats).map(([name, s]) => { const total = s.hits + s.misses const hit = total > 0 ? Math.round((s.hits / total) * 100) : 0 return (
{name} 80 ? 'allow' : hit > 50 ? 'info' : 'warn'}>{hit}%
size {s.size} {s.hits} hits / {s.misses} miss
) })}
) }