feat: 监控告警体系统一重构 + 自动化任务调度引擎 + 监控大屏拆分
告警中心 - 新增统一告警(alert_unified)、监控告警规则(monitor_alert_rule)、指标目录(alert_metric_catalog) - 通知策略与消息分发(alert_notify_policy/dispatch/message)、静默规则 - 告警引擎按阈值/SNMP 拆分(alert_engine_monitor/snmp) 监控采集 - SNMP 常量/模板与历史指标(snmp templates/constants、snmp_metrics_history、snmp_collect) - 中间件监控 Redis 采集与种子(middleware_monitor_redis/seed) - 站点探测 pkg(siteprobe) + 站点视图(site_view) 自动化任务 - cron 调度器(cronscheduler)、脚本运行器(scriptrunner)、系统任务(systask)及运行记录(cron_job_run、system_task) 审计与凭证 - 审计设置(audit_setting) + 历史清理(auditcleaner) 前端 - 监控页面(host/middleware/site/snmp)拆分为子模块并大屏化 - 告警中心多 Tab(规则/指标目录/通知策略/静默)、任务管理组件重构、Agent CLI Markdown 渲染 - 移除旧脚本卡片/详情/日志组件,统一为 ScriptTable/ScriptCodeEditor/TerminalOutput Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
092d0e4b9e
commit
471353e3d7
190 files changed
+16640
-3484
No files matched your search
@@ -4,20 +4,21 @@ import { useTranslation } from 'react-i18next';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { Clock, Server, ArrowRight } from 'lucide-react';
|
||||
import { dashboardStatsApi, serverApi, kubernetesApi } from '@/api';
|
||||
import { dashboardStatsApi, kubernetesApi } from '@/api';
|
||||
import { StatStrip } from '@/components/ui/stat-strip';
|
||||
import { CostOverviewCard, TopResourceUsageCard, ResourceUsageCard } from './DashboardCharts';
|
||||
import {
|
||||
AlertMessagesCard,
|
||||
CertificateExpiryCard,
|
||||
ReleaseHistoryCard,
|
||||
ServerStatusCard,
|
||||
OpsOverviewCard,
|
||||
KubernetesClusterCard,
|
||||
} from './DashboardRecent';
|
||||
import type {
|
||||
DashboardRelease,
|
||||
DashboardServer,
|
||||
DashboardCluster,
|
||||
DashboardAutomationStats,
|
||||
DashboardOpsStats,
|
||||
} from './DashboardRecent';
|
||||
import { SkeletonDashboard } from '@/components/layout/SkeletonCard';
|
||||
import { PageShell } from '@/components/layout/PageShell';
|
||||
@@ -41,7 +42,6 @@ export function Dashboard() {
|
||||
const [initialLoading, setInitialLoading] = useState(true);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const [stats, setStats] = useState<JsonData>(null);
|
||||
const [servers, setServers] = useState<DashboardServer[]>([]);
|
||||
const [clusters, setClusters] = useState<DashboardCluster[]>([]);
|
||||
const [alerts, setAlerts] = useState<AlertEventRecord[]>([]);
|
||||
const [releases, setReleases] = useState<DashboardRelease[]>([]);
|
||||
@@ -51,15 +51,11 @@ export function Dashboard() {
|
||||
const refreshData = useCallback(async () => {
|
||||
setRefreshing(true);
|
||||
try {
|
||||
const [statsRes, serversRes, clustersRes, alertsRes, releasesRes, metricsRes] = await Promise.all([
|
||||
const [statsRes, clustersRes, alertsRes, releasesRes, metricsRes] = await Promise.all([
|
||||
dashboardStatsApi.getStats().catch((e) => {
|
||||
console.error('Failed to fetch dashboard stats:', e);
|
||||
return null;
|
||||
}),
|
||||
serverApi.getServers({ page: 1, page_size: 100 }).catch((e) => {
|
||||
console.error('Failed to fetch servers:', e);
|
||||
return null;
|
||||
}),
|
||||
kubernetesApi.getClusters().catch((e) => {
|
||||
console.error('Failed to fetch k8s clusters:', e);
|
||||
return null;
|
||||
@@ -79,7 +75,6 @@ export function Dashboard() {
|
||||
]);
|
||||
|
||||
setStats(statsRes);
|
||||
setServers(serversRes?.list ?? []);
|
||||
setClusters(clustersRes?.list ?? []);
|
||||
setAlerts(Array.isArray(alertsRes) ? alertsRes : []);
|
||||
setReleases(Array.isArray(releasesRes) ? releasesRes : []);
|
||||
@@ -95,8 +90,8 @@ export function Dashboard() {
|
||||
|
||||
useEffect(() => {
|
||||
refreshData();
|
||||
// 每 5 秒自动刷新
|
||||
const interval = setInterval(refreshData, 5000);
|
||||
// 每 30 秒自动刷新(集群列表含实时统计,不宜过频)// Logan.Li
|
||||
const interval = setInterval(refreshData, 30_000);
|
||||
return () => clearInterval(interval);
|
||||
}, [refreshData]);
|
||||
|
||||
@@ -108,6 +103,9 @@ export function Dashboard() {
|
||||
const k8sStats = stats?.kubernetes_stats;
|
||||
const alertStats = stats?.alert_stats;
|
||||
const costStats = stats?.cost_stats;
|
||||
const automationStats = stats?.automation_stats as DashboardAutomationStats | undefined;
|
||||
const opsStats = stats?.ops_stats as DashboardOpsStats | undefined;
|
||||
|
||||
|
||||
return (
|
||||
<PageShell
|
||||
@@ -136,18 +134,19 @@ export function Dashboard() {
|
||||
<StatStrip
|
||||
items={[
|
||||
{ label: t('dashboard.stat.servers'), value: serverStats?.total ?? 0, color: 'blue' },
|
||||
{ label: t('dashboard.stat.kubernetes'), value: k8sStats?.total ?? 0, color: 'purple' },
|
||||
{ label: t('dashboard.stat.running'), value: serverStats?.running ?? 0, color: 'emerald' },
|
||||
{ label: t('dashboard.stat.k8sClusters'), value: k8sStats?.total ?? 0, color: 'purple' },
|
||||
{ label: t('dashboard.stat.healthyClusters'), value: k8sStats?.healthy ?? 0, color: 'cyan' },
|
||||
{ label: t('dashboard.stat.cronJobs'), value: automationStats?.cron_job_count ?? 0, color: 'cyan' },
|
||||
{ label: t('dashboard.stat.siteProbes'), value: opsStats?.site_task_count ?? 0, color: 'green' },
|
||||
{ label: t('dashboard.stat.alerts'), value: alertStats?.firing ?? 0, color: alertStats?.firing > 0 ? 'red' : 'muted' },
|
||||
{ label: t('dashboard.stat.critical'), value: alertStats?.critical ?? 0, color: 'red' },
|
||||
{ label: t('dashboard.stat.monthlyCost'), value: `¥${Number(costStats?.month_cost ?? 0).toLocaleString()}`, color: 'amber' },
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
contentClassName="space-y-6"
|
||||
>
|
||||
<div>
|
||||
{/* 资源使用率趋势 — 第一行 */}
|
||||
<div className="animate-fade-in-delay-1">
|
||||
<ResourceUsageCard
|
||||
avgCpu={Number(serverStats?.avg_cpu ?? 0)}
|
||||
avgMemory={Number(serverStats?.avg_memory ?? 0)}
|
||||
@@ -161,23 +160,29 @@ export function Dashboard() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Cost & Top Resource Usage */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 animate-fade-in-delay-3">
|
||||
<CostOverviewCard costStats={costStats} />
|
||||
{/* 运维概览 → K8s 集群 → Top5 资源使用 */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 animate-fade-in-delay-2">
|
||||
<OpsOverviewCard
|
||||
automation={automationStats}
|
||||
ops={opsStats}
|
||||
serverCount={serverStats?.total}
|
||||
hostMonitorCount={serverStats?.running}
|
||||
firingAlerts={alertStats?.firing}
|
||||
/>
|
||||
<KubernetesClusterCard clusters={clusters} />
|
||||
<TopResourceUsageCard topUsage={stats?.top_resource_usage} />
|
||||
</div>
|
||||
|
||||
{/* Alert Messages & Certificate Expiry */}
|
||||
{/* 费用概览 & 发布历史 */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 animate-fade-in-delay-3">
|
||||
<AlertMessagesCard alerts={alerts} />
|
||||
<CertificateExpiryCard expCerts={expCerts} />
|
||||
<CostOverviewCard costStats={costStats} />
|
||||
<ReleaseHistoryCard releases={releases} />
|
||||
</div>
|
||||
|
||||
{/* Bottom Row */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 animate-fade-in-delay-4">
|
||||
<ReleaseHistoryCard releases={releases} />
|
||||
<ServerStatusCard servers={servers} />
|
||||
<KubernetesClusterCard clusters={clusters} />
|
||||
{/* 告警消息 & 证书到期提醒 — 置底 */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 animate-fade-in-delay-4">
|
||||
<AlertMessagesCard alerts={alerts} />
|
||||
<CertificateExpiryCard expCerts={expCerts} />
|
||||
</div>
|
||||
</PageShell>
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user