refactor(discovery): use ping for discovery and fill MAC via SSH

This commit is contained in:
12600k-rog-d4
2026-08-12 21:45:51 +08:00
parent 906bb54aaa
commit 175c5e8c6c
21 changed files with 542 additions and 310 deletions

View File

@@ -0,0 +1,131 @@
package stress
import (
"encoding/json"
"fmt"
"os"
"strings"
)
// chartData 给 JS 用的数据
type chartData struct {
Labels []string `json:"labels"`
CPU []float64 `json:"cpu"`
Temp []float64 `json:"temp"`
Title string `json:"title"`
}
// WriteChartHTML 根据采样数据生成折线图 HTML 文件,返回文件路径
func WriteChartHTML(ip string, result Result, reportDir string) (string, error) {
if len(result.Samples) == 0 {
return "", nil
}
cd := chartData{
Title: fmt.Sprintf("%s - %s 压测曲线 (%s)", ip, result.Type, result.Duration),
}
for _, s := range result.Samples {
cd.Labels = append(cd.Labels, s.Time)
cd.CPU = append(cd.CPU, s.CPU)
cd.Temp = append(cd.Temp, s.Temp)
}
dataJSON, err := json.Marshal(cd)
if err != nil {
return "", err
}
html := strings.Replace(chartHTMLTemplate, "__DATA__", string(dataJSON), 1)
os.MkdirAll(reportDir, 0755)
filename := fmt.Sprintf("%s/chart-%s-%s.html", reportDir, result.Type, SanitizeFilename(ip))
if err := os.WriteFile(filename, []byte(html), 0644); err != nil {
return "", err
}
return filename, nil
}
// SanitizeFilename 清理 IP 中的特殊字符,用于文件名
func SanitizeFilename(ip string) string {
return strings.ReplaceAll(ip, ":", "_")
}
const chartHTMLTemplate = `<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>压测曲线</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4"></script>
<style>
body { font-family: -apple-system, sans-serif; margin: 40px; background: #f5f5f5; }
.container { max-width: 960px; margin: 0 auto; background: #fff; padding: 30px; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.08); }
h2 { margin: 0 0 20px; color: #333; }
canvas { max-height: 400px; }
.legend { display: flex; gap: 24px; margin-top: 16px; font-size: 13px; color: #666; }
.legend span { display: flex; align-items: center; gap: 6px; }
.legend .dot { width: 12px; height: 12px; border-radius: 50%; display: inline-block; }
</style>
</head>
<body>
<div class="container">
<h2 id="title"></h2>
<canvas id="chart"></canvas>
<div class="legend">
<span><span class="dot" style="background:#f97316"></span> CPU 使用率 (%)</span>
<span><span class="dot" style="background:#ef4444"></span> 温度 (°C)</span>
</div>
</div>
<script>
const data = __DATA__;
document.getElementById('title').textContent = data.title;
new Chart(document.getElementById('chart'), {
type: 'line',
data: {
labels: data.labels,
datasets: [
{
label: 'CPU 使用率 (%)',
data: data.cpu,
borderColor: '#f97316',
backgroundColor: 'rgba(249,115,22,0.08)',
fill: true,
tension: 0.3,
yAxisID: 'y'
},
{
label: '温度 (°C)',
data: data.temp,
borderColor: '#ef4444',
backgroundColor: 'rgba(239,68,68,0.05)',
fill: true,
tension: 0.3,
yAxisID: 'y1'
}
]
},
options: {
responsive: true,
interaction: { intersect: false, mode: 'index' },
plugins: { legend: { display: false } },
scales: {
y: {
type: 'linear',
position: 'left',
min: 0,
max: 100,
title: { display: true, text: 'CPU (%)' },
grid: { color: '#f0f0f0' }
},
y1: {
type: 'linear',
position: 'right',
title: { display: true, text: '温度 (°C)' },
grid: { drawOnChartArea: false }
}
}
}
});
</script>
</body>
</html>`