From 74179374df8cc5ef9db858a676700bba6c5b4463 Mon Sep 17 00:00:00 2001 From: dushixiang Date: Sun, 14 Dec 2025 21:15:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 1 + go.sum | 2 ++ pkg/agent/service/agent.go | 22 ++++++++++--------- web/src/components/PublicHeader.tsx | 4 ++-- .../components/monitor/ResponseTimeChart.tsx | 2 +- web/src/components/server/charts/CpuChart.tsx | 2 +- .../components/server/charts/DiskIOChart.tsx | 6 ++--- web/src/components/server/charts/GpuChart.tsx | 6 ++--- .../components/server/charts/MemoryChart.tsx | 2 +- .../components/server/charts/NetworkChart.tsx | 6 ++--- .../server/charts/NetworkConnectionChart.tsx | 4 ++-- .../server/charts/TemperatureChart.tsx | 6 ++--- web/src/pages/Public/MonitorList.tsx | 4 ++-- 13 files changed, 36 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index ce29f53..92942ba 100644 --- a/go.mod +++ b/go.mod @@ -72,6 +72,7 @@ require ( github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/sagikazarmark/locafero v0.12.0 // indirect + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spf13/cast v1.10.0 // indirect github.com/spf13/pflag v1.0.10 // indirect github.com/spf13/viper v1.21.0 // indirect diff --git a/go.sum b/go.sum index a6e703e..0dd1304 100644 --- a/go.sum +++ b/go.sum @@ -149,6 +149,8 @@ github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88ee github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI= github.com/shirou/gopsutil/v4 v4.25.11 h1:X53gB7muL9Gnwwo2evPSE+SfOrltMoR6V3xJAXZILTY= github.com/shirou/gopsutil/v4 v4.25.11/go.mod h1:EivAfP5x2EhLp2ovdpKSozecVXn1TmuG7SMzs/Wh4PU= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= diff --git a/pkg/agent/service/agent.go b/pkg/agent/service/agent.go index 4cfa179..317b7a9 100644 --- a/pkg/agent/service/agent.go +++ b/pkg/agent/service/agent.go @@ -21,6 +21,7 @@ import ( "github.com/dushixiang/pika/pkg/version" "github.com/gorilla/websocket" "github.com/jpillora/backoff" + "github.com/sourcegraph/conc" ) // 定义特殊错误类型 @@ -193,35 +194,36 @@ func (a *Agent) runOnce(ctx context.Context, onConnected func()) error { done := make(chan struct{}) errChan := make(chan error, 3) + var wg conc.WaitGroup // 启动读取循环(处理服务端的 Ping/Pong 等控制消息) - go func() { + wg.Go(func() { if err := a.readLoop(rawConn, done); err != nil { errChan <- fmt.Errorf("读取失败: %w", err) } - }() + }) // 启动心跳和数据发送 - go func() { + wg.Go(func() { if err := a.heartbeatLoop(ctx, conn, done); err != nil { errChan <- fmt.Errorf("心跳失败: %w", err) } - }() + }) - go func() { + wg.Go(func() { if err := a.metricsLoop(ctx, conn, collectorManager, done); err != nil { errChan <- fmt.Errorf("数据采集失败: %w", err) } - }() + }) // 启动防篡改事件监控 - go func() { + wg.Go(func() { a.tamperEventLoop(ctx, conn, done) - }() + }) // 启动防篡改属性告警监控 - go func() { + wg.Go(func() { a.tamperAlertLoop(ctx, conn, done) - }() + }) // 等待错误或上下文取消 select { diff --git a/web/src/components/PublicHeader.tsx b/web/src/components/PublicHeader.tsx index f7ad674..68aa441 100644 --- a/web/src/components/PublicHeader.tsx +++ b/web/src/components/PublicHeader.tsx @@ -63,10 +63,10 @@ const PublicHeader = () => {

- {window.SystemConfig?.SystemNameZh} + {window.SystemConfig?.SystemNameEn}

- {window.SystemConfig?.SystemNameEn} + {window.SystemConfig?.SystemNameZh}

diff --git a/web/src/components/monitor/ResponseTimeChart.tsx b/web/src/components/monitor/ResponseTimeChart.tsx index 9f92f0f..c15e69d 100644 --- a/web/src/components/monitor/ResponseTimeChart.tsx +++ b/web/src/components/monitor/ResponseTimeChart.tsx @@ -116,7 +116,7 @@ export const ResponseTimeChart = ({monitorId, monitorStats}: ResponseTimeChartPr if (!historyData?.series) return []; // 过滤出响应时间指标的 series - const responseTimeSeries = historyData.series.filter(s => s.name === 'response_time'); + const responseTimeSeries = historyData.series?.filter(s => s.name === 'response_time'); // 根据选择的探针过滤(使用 agent_name,如果没有则fallback到 agent_id) const filteredSeries = selectedAgent === 'all' diff --git a/web/src/components/server/charts/CpuChart.tsx b/web/src/components/server/charts/CpuChart.tsx index 01ff0e9..fc20cdb 100644 --- a/web/src/components/server/charts/CpuChart.tsx +++ b/web/src/components/server/charts/CpuChart.tsx @@ -23,7 +23,7 @@ export const CpuChart = ({agentId, timeRange}: CpuChartProps) => { // 数据转换 const chartData = useMemo(() => { - const cpuSeries = metricsResponse?.data.series.find(s => s.name === 'usage'); + const cpuSeries = metricsResponse?.data.series?.find(s => s.name === 'usage'); if (!cpuSeries) return []; return cpuSeries.data.map((point) => ({ diff --git a/web/src/components/server/charts/DiskIOChart.tsx b/web/src/components/server/charts/DiskIOChart.tsx index e27e8f9..4932eda 100644 --- a/web/src/components/server/charts/DiskIOChart.tsx +++ b/web/src/components/server/charts/DiskIOChart.tsx @@ -23,10 +23,10 @@ export const DiskIOChart = ({agentId, timeRange}: DiskIOChartProps) => { // 数据转换 const chartData = useMemo(() => { - if (!metricsResponse?.data.series || metricsResponse.data.series.length === 0) return []; + if (!metricsResponse?.data.series || metricsResponse.data.series?.length === 0) return []; - const readSeries = metricsResponse.data.series.find(s => s.name === 'read'); - const writeSeries = metricsResponse.data.series.find(s => s.name === 'write'); + const readSeries = metricsResponse.data.series?.find(s => s.name === 'read'); + const writeSeries = metricsResponse.data.series?.find(s => s.name === 'write'); if (!readSeries || !writeSeries) return []; diff --git a/web/src/components/server/charts/GpuChart.tsx b/web/src/components/server/charts/GpuChart.tsx index 4b8aba2..bf2bff7 100644 --- a/web/src/components/server/charts/GpuChart.tsx +++ b/web/src/components/server/charts/GpuChart.tsx @@ -24,13 +24,13 @@ export const GpuChart = ({agentId, timeRange}: GpuChartProps) => { // 数据转换 const chartData = useMemo(() => { - if (!metricsResponse?.data.series || metricsResponse.data.series.length === 0) return []; + if (!metricsResponse?.data.series || metricsResponse.data.series?.length === 0) return []; // 按时间戳聚合利用率和温度系列 const timeMap = new Map(); - const utilizationSeries = metricsResponse.data.series.find(s => s.name === 'utilization'); - const temperatureSeries = metricsResponse.data.series.find(s => s.name === 'temperature'); + const utilizationSeries = metricsResponse.data.series?.find(s => s.name === 'utilization'); + const temperatureSeries = metricsResponse.data.series?.find(s => s.name === 'temperature'); // 添加利用率数据 utilizationSeries?.data.forEach(point => { diff --git a/web/src/components/server/charts/MemoryChart.tsx b/web/src/components/server/charts/MemoryChart.tsx index 2c5159a..ca644b8 100644 --- a/web/src/components/server/charts/MemoryChart.tsx +++ b/web/src/components/server/charts/MemoryChart.tsx @@ -23,7 +23,7 @@ export const MemoryChart = ({agentId, timeRange}: MemoryChartProps) => { // 数据转换 const chartData = useMemo(() => { - const memorySeries = metricsResponse?.data.series.find(s => s.name === 'usage'); + const memorySeries = metricsResponse?.data.series?.find(s => s.name === 'usage'); if (!memorySeries) return []; return memorySeries.data.map((point) => ({ diff --git a/web/src/components/server/charts/NetworkChart.tsx b/web/src/components/server/charts/NetworkChart.tsx index b3550c8..fafc604 100644 --- a/web/src/components/server/charts/NetworkChart.tsx +++ b/web/src/components/server/charts/NetworkChart.tsx @@ -41,10 +41,10 @@ export const NetworkChart = ({agentId, timeRange}: NetworkChartProps) => { // 数据转换 const chartData = useMemo(() => { - if (!metricsResponse?.data.series || metricsResponse.data.series.length === 0) return []; + if (!metricsResponse?.data.series || metricsResponse.data.series?.length === 0) return []; - const uploadSeries = metricsResponse.data.series.find(s => s.name === 'upload'); - const downloadSeries = metricsResponse.data.series.find(s => s.name === 'download'); + const uploadSeries = metricsResponse.data.series?.find(s => s.name === 'upload'); + const downloadSeries = metricsResponse.data.series?.find(s => s.name === 'download'); if (!uploadSeries || !downloadSeries) return []; diff --git a/web/src/components/server/charts/NetworkConnectionChart.tsx b/web/src/components/server/charts/NetworkConnectionChart.tsx index c56bfad..76f3b0b 100644 --- a/web/src/components/server/charts/NetworkConnectionChart.tsx +++ b/web/src/components/server/charts/NetworkConnectionChart.tsx @@ -23,12 +23,12 @@ export const NetworkConnectionChart = ({agentId, timeRange}: NetworkConnectionCh // 数据转换 const chartData = useMemo(() => { - if (!metricsResponse?.data.series || metricsResponse.data.series.length === 0) return []; + if (!metricsResponse?.data.series || metricsResponse.data.series?.length === 0) return []; // 按时间戳聚合所有连接状态系列 const timeMap = new Map(); - metricsResponse.data.series.forEach(series => { + metricsResponse.data.series?.forEach(series => { const stateName = series.name; // established, time_wait, close_wait, listen series.data.forEach(point => { const time = new Date(point.timestamp).toLocaleTimeString('zh-CN', { diff --git a/web/src/components/server/charts/TemperatureChart.tsx b/web/src/components/server/charts/TemperatureChart.tsx index b08d6f3..8108074 100644 --- a/web/src/components/server/charts/TemperatureChart.tsx +++ b/web/src/components/server/charts/TemperatureChart.tsx @@ -27,12 +27,12 @@ export const TemperatureChart = ({agentId, timeRange}: TemperatureChartProps) => // 数据转换 const chartData = useMemo(() => { - if (!metricsResponse?.data.series || metricsResponse.data.series.length === 0) return []; + if (!metricsResponse?.data.series || metricsResponse.data.series?.length === 0) return []; // 按时间戳聚合所有温度系列 const timeMap = new Map(); - metricsResponse.data.series.forEach(series => { + metricsResponse.data.series?.forEach(series => { const sensorName = series.name; // 使用系列名称作为传感器标识 series.data.forEach(point => { const time = new Date(point.timestamp).toLocaleTimeString('zh-CN', { @@ -54,7 +54,7 @@ export const TemperatureChart = ({agentId, timeRange}: TemperatureChartProps) => // 提取所有唯一的温度类型 const temperatureTypes = useMemo(() => { - return metricsResponse?.data.series.map(s => s.name).sort() || []; + return metricsResponse?.data.series?.map(s => s.name).sort() || []; }, [metricsResponse]); // 根据选中的类型过滤温度数据 diff --git a/web/src/pages/Public/MonitorList.tsx b/web/src/pages/Public/MonitorList.tsx index e7759a2..859fb9b 100644 --- a/web/src/pages/Public/MonitorList.tsx +++ b/web/src/pages/Public/MonitorList.tsx @@ -80,13 +80,13 @@ const MonitorCard = ({monitor, displayMode, onClick}: { // 将 VictoriaMetrics 的时序数据转换为图表数据 const chartData = useMemo(() => { - if (!historyData || !historyData.series || historyData.series.length === 0) { + if (!historyData || !historyData.series || historyData.series?.length === 0) { return []; } const timeMap = new Map(); - historyData.series.forEach(series => { + historyData.series?.forEach(series => { if (series.data && series.data.length > 0) { series.data.forEach(point => { if (!timeMap.has(point.timestamp)) {