143 lines
6.3 KiB
JavaScript
143 lines
6.3 KiB
JavaScript
import React from 'react';
|
|
import TitleCard from '../components/TitleCard';
|
|
import { useModelList } from '../services/modelRegistryApi';
|
|
import { useSystemHealth } from '../services/healthApi';
|
|
import { useInferenceSummary } from '../services/auditApi';
|
|
|
|
import { FaPlay, FaDatabase, FaClock, FaCheckCircle, FaTimesCircle, FaPercent, FaSyncAlt } from 'react-icons/fa';
|
|
import { Link } from 'react-router-dom';
|
|
|
|
// ----------------------------------------------------
|
|
// Helper Component: สรุปตัวเลขสถิติ (Stats)
|
|
// ----------------------------------------------------
|
|
const StatCard = ({ icon, title, value, unit, colorClass, linkPath, isLoading }) => {
|
|
|
|
// แสดง loading spinner ถ้ากำลังโหลดข้อมูล
|
|
const displayValue = isLoading ? (
|
|
<span className="loading loading-spinner loading-md text-primary"></span>
|
|
) : (
|
|
value
|
|
);
|
|
|
|
return (
|
|
<div className="stats shadow-lg bg-base-100 hover:bg-base-200 transition duration-150">
|
|
<div className="stat">
|
|
<div className={`stat-figure text-secondary ${colorClass}`}>
|
|
{icon}
|
|
</div>
|
|
<div className="stat-title text-base-content/70">{title}</div>
|
|
<div className="stat-value text-base-content">{displayValue} <span className="text-sm font-normal">{unit}</span></div>
|
|
{linkPath && (
|
|
<div className="stat-desc mt-2">
|
|
<Link to={linkPath} className="link link-hover text-primary hover:underline">
|
|
ดูรายละเอียด
|
|
</Link>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
function Dashboard() {
|
|
// Hooks สำหรับดึงข้อมูลสถานะ
|
|
const { data: models, isLoading: modelsLoading } = useModelList();
|
|
const { data: health, isLoading: healthLoading, isFetching: healthFetching } = useSystemHealth();
|
|
const { data: summary, isLoading: summaryLoading } = useInferenceSummary();
|
|
|
|
// --- Logic คำนวณ ---
|
|
const activeModelCount = models?.filter(m => m.status === 'ACTIVE').length || 0;
|
|
const totalModelCount = models?.length || 0;
|
|
|
|
// Health Status
|
|
const healthStatus = health?.status || (healthLoading ? 'CHECKING' : 'UNKNOWN');
|
|
const isHealthy = healthStatus === 'Healthy';
|
|
const healthIcon = isHealthy ? <FaCheckCircle /> : <FaTimesCircle />;
|
|
const healthColor = isHealthy ? 'text-success' : 'text-error';
|
|
|
|
// Inference Stats (จาก useInferenceSummary)
|
|
const totalRuns = summary?.total_runs || 0;
|
|
const successRate = summary?.success_rate || 0;
|
|
const avgLatencyMs = summary?.avg_latency_ms || 0;
|
|
|
|
|
|
return (
|
|
<div className="space-y-8">
|
|
<h1 className="text-3xl font-bold text-base-content">แดชบอร์ด/ภาพรวม</h1>
|
|
|
|
{/* 1. ส่วนแสดงสถิติสำคัญ (KPI Cards) */}
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
|
|
|
{/* Card 1: Model Active Count */}
|
|
<StatCard
|
|
icon={<FaDatabase />}
|
|
title="Model พร้อมรัน (ACTIVE)"
|
|
value={activeModelCount}
|
|
unit={`จาก ${totalModelCount}`}
|
|
colorClass="text-success"
|
|
linkPath="/dashboard/model-registry"
|
|
isLoading={modelsLoading}
|
|
/>
|
|
|
|
{/* Card 2: Total Inference Runs (Audit Log) */}
|
|
<StatCard
|
|
icon={<FaPlay />}
|
|
title="งานรันทั้งหมด (24 ชม.)"
|
|
value={totalRuns}
|
|
unit="ครั้ง"
|
|
colorClass="text-info"
|
|
isLoading={summaryLoading}
|
|
// Note: ต้องมีเมนู Pipeline Logs หรือ Audit Log List
|
|
/>
|
|
|
|
{/* Card 3: Success Rate (Audit Log) */}
|
|
<StatCard
|
|
icon={<FaPercent />}
|
|
title="Success Rate (24 ชม.)"
|
|
value={successRate}
|
|
unit="%"
|
|
colorClass={successRate > 90 ? "text-success" : "text-warning"}
|
|
isLoading={summaryLoading}
|
|
/>
|
|
|
|
{/* Card 4: Avg Latency (Audit Log) */}
|
|
<StatCard
|
|
icon={<FaClock />}
|
|
title="Latency เฉลี่ย (AI)"
|
|
value={avgLatencyMs}
|
|
unit="ms"
|
|
colorClass={avgLatencyMs > 5000 ? "text-error" : "text-warning"}
|
|
isLoading={summaryLoading}
|
|
/>
|
|
</div>
|
|
|
|
{/* 2. ส่วนแสดงสถานะ Infrastructure (Health) */}
|
|
<TitleCard title="สถานะ Infrastructure & Health" topMargin="mt-0"
|
|
TopSideButtons={healthFetching ? <FaSyncAlt className="animate-spin text-primary" title="Refreshing..." /> : null}
|
|
>
|
|
<StatCard
|
|
icon={healthIcon}
|
|
title="สถานะรวมของระบบ"
|
|
value={healthStatus}
|
|
unit={healthLoading ? "(กำลังตรวจสอบ...)" : ""}
|
|
colorClass={healthColor}
|
|
linkPath="/dashboard/health"
|
|
isLoading={healthLoading}
|
|
/>
|
|
|
|
<p className="text-xs text-base-content/60 mt-4">
|
|
ตรวจสอบสถานะของ DB, Redis, MinIO, และ AI Model Endpoints ได้ที่เมนูสถานะระบบ
|
|
</p>
|
|
</TitleCard>
|
|
|
|
{/* 3. ส่วนแสดง Log ล่าสุด (Audit Log) */}
|
|
<TitleCard title="Recent MLOps Events (Audit Log)">
|
|
<pre className="text-sm bg-base-200 p-3 rounded max-h-40 overflow-auto">
|
|
{summaryLoading ? "กำลังโหลด Log ล่าสุด..." : JSON.stringify(summary?.last_logs || [], null, 2)}
|
|
</pre>
|
|
</TitleCard>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default Dashboard; |