mirror of
https://github.com/woodchen-ink/proxy-go.git
synced 2025-07-18 16:41:54 +08:00
feat(metrics): 添加引用来源统计持久化支持
- 在 MetricsStorage 结构体中新增 refererStatsFile 字段 - 在 SaveMetrics 方法中添加引用来源统计保存逻辑 - 在 LoadMetrics 方法中实现引用来源统计的加载和恢复 - 前端页面调整路径显示,增加长路径的截断处理 - 优化引用来源统计的数据处理和类型转换
This commit is contained in:
parent
d2e5020d22
commit
2a41458bb8
@ -14,16 +14,17 @@ import (
|
|||||||
|
|
||||||
// MetricsStorage 指标存储结构
|
// MetricsStorage 指标存储结构
|
||||||
type MetricsStorage struct {
|
type MetricsStorage struct {
|
||||||
collector *Collector
|
collector *Collector
|
||||||
saveInterval time.Duration
|
saveInterval time.Duration
|
||||||
dataDir string
|
dataDir string
|
||||||
stopChan chan struct{}
|
stopChan chan struct{}
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
lastSaveTime time.Time
|
lastSaveTime time.Time
|
||||||
mutex sync.RWMutex
|
mutex sync.RWMutex
|
||||||
metricsFile string
|
metricsFile string
|
||||||
pathStatsFile string
|
pathStatsFile string
|
||||||
statusCodeFile string
|
statusCodeFile string
|
||||||
|
refererStatsFile string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMetricsStorage 创建新的指标存储
|
// NewMetricsStorage 创建新的指标存储
|
||||||
@ -33,13 +34,14 @@ func NewMetricsStorage(collector *Collector, dataDir string, saveInterval time.D
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &MetricsStorage{
|
return &MetricsStorage{
|
||||||
collector: collector,
|
collector: collector,
|
||||||
saveInterval: saveInterval,
|
saveInterval: saveInterval,
|
||||||
dataDir: dataDir,
|
dataDir: dataDir,
|
||||||
stopChan: make(chan struct{}),
|
stopChan: make(chan struct{}),
|
||||||
metricsFile: filepath.Join(dataDir, "metrics.json"),
|
metricsFile: filepath.Join(dataDir, "metrics.json"),
|
||||||
pathStatsFile: filepath.Join(dataDir, "path_stats.json"),
|
pathStatsFile: filepath.Join(dataDir, "path_stats.json"),
|
||||||
statusCodeFile: filepath.Join(dataDir, "status_codes.json"),
|
statusCodeFile: filepath.Join(dataDir, "status_codes.json"),
|
||||||
|
refererStatsFile: filepath.Join(dataDir, "referer_stats.json"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,6 +131,11 @@ func (ms *MetricsStorage) SaveMetrics() error {
|
|||||||
return fmt.Errorf("保存状态码统计失败: %v", err)
|
return fmt.Errorf("保存状态码统计失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 保存引用来源统计
|
||||||
|
if err := saveJSONToFile(ms.refererStatsFile, stats["top_referers"]); err != nil {
|
||||||
|
return fmt.Errorf("保存引用来源统计失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
ms.mutex.Lock()
|
ms.mutex.Lock()
|
||||||
ms.lastSaveTime = time.Now()
|
ms.lastSaveTime = time.Now()
|
||||||
ms.mutex.Unlock()
|
ms.mutex.Unlock()
|
||||||
@ -165,6 +172,17 @@ func (ms *MetricsStorage) LoadMetrics() error {
|
|||||||
return fmt.Errorf("加载状态码统计失败: %v", err)
|
return fmt.Errorf("加载状态码统计失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加载引用来源统计(如果文件存在)
|
||||||
|
var refererStats []map[string]interface{}
|
||||||
|
if fileExists(ms.refererStatsFile) {
|
||||||
|
if err := loadJSONFromFile(ms.refererStatsFile, &refererStats); err != nil {
|
||||||
|
log.Printf("[MetricsStorage] 加载引用来源统计失败: %v", err)
|
||||||
|
// 不中断加载过程
|
||||||
|
} else {
|
||||||
|
log.Printf("[MetricsStorage] 成功加载引用来源统计: %d 条记录", len(refererStats))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 将加载的数据应用到收集器
|
// 将加载的数据应用到收集器
|
||||||
// 1. 应用总字节数
|
// 1. 应用总字节数
|
||||||
if totalBytes, ok := basicMetrics["total_bytes"].(float64); ok {
|
if totalBytes, ok := basicMetrics["total_bytes"].(float64); ok {
|
||||||
@ -214,6 +232,35 @@ func (ms *MetricsStorage) LoadMetrics() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4. 应用引用来源统计
|
||||||
|
if len(refererStats) > 0 {
|
||||||
|
for _, refererStat := range refererStats {
|
||||||
|
referer, ok := refererStat["path"].(string)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
requestCount, _ := refererStat["request_count"].(float64)
|
||||||
|
errorCount, _ := refererStat["error_count"].(float64)
|
||||||
|
bytesTransferred, _ := refererStat["bytes_transferred"].(float64)
|
||||||
|
|
||||||
|
// 创建或更新引用来源统计
|
||||||
|
var refererMetrics *models.PathMetrics
|
||||||
|
if existingMetrics, ok := ms.collector.refererStats.Load(referer); ok {
|
||||||
|
refererMetrics = existingMetrics.(*models.PathMetrics)
|
||||||
|
} else {
|
||||||
|
refererMetrics = &models.PathMetrics{Path: referer}
|
||||||
|
ms.collector.refererStats.Store(referer, refererMetrics)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置统计值
|
||||||
|
refererMetrics.RequestCount.Store(int64(requestCount))
|
||||||
|
refererMetrics.ErrorCount.Store(int64(errorCount))
|
||||||
|
refererMetrics.BytesTransferred.Store(int64(bytesTransferred))
|
||||||
|
}
|
||||||
|
log.Printf("[MetricsStorage] 应用了 %d 条引用来源统计记录", len(refererStats))
|
||||||
|
}
|
||||||
|
|
||||||
// 4. 应用延迟分布桶(如果有)
|
// 4. 应用延迟分布桶(如果有)
|
||||||
if latencyStats, ok := basicMetrics["latency_stats"].(map[string]interface{}); ok {
|
if latencyStats, ok := basicMetrics["latency_stats"].(map[string]interface{}); ok {
|
||||||
if distribution, ok := latencyStats["distribution"].(map[string]interface{}); ok {
|
if distribution, ok := latencyStats["distribution"].(map[string]interface{}); ok {
|
||||||
|
@ -274,6 +274,7 @@ export default function DashboardPage() {
|
|||||||
let displayRange = range;
|
let displayRange = range;
|
||||||
if (range === "lt10ms") displayRange = "<10ms";
|
if (range === "lt10ms") displayRange = "<10ms";
|
||||||
if (range === "gt1s") displayRange = ">1s";
|
if (range === "gt1s") displayRange = ">1s";
|
||||||
|
if (range === "200-1000ms") displayRange = "0.2-1s";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={range} className="p-3 rounded-lg border bg-card text-card-foreground shadow-sm">
|
<div key={range} className="p-3 rounded-lg border bg-card text-card-foreground shadow-sm">
|
||||||
@ -404,7 +405,7 @@ export default function DashboardPage() {
|
|||||||
<tbody>
|
<tbody>
|
||||||
{metrics.top_referers.map((referer, index) => (
|
{metrics.top_referers.map((referer, index) => (
|
||||||
<tr key={index} className="border-b">
|
<tr key={index} className="border-b">
|
||||||
<td className="p-2">
|
<td className="p-2 max-w-xs truncate">
|
||||||
<span className="text-blue-600">
|
<span className="text-blue-600">
|
||||||
{referer.path}
|
{referer.path}
|
||||||
</span>
|
</span>
|
||||||
@ -441,7 +442,7 @@ export default function DashboardPage() {
|
|||||||
<tbody>
|
<tbody>
|
||||||
{(metrics.top_paths || []).map((path, index) => (
|
{(metrics.top_paths || []).map((path, index) => (
|
||||||
<tr key={index} className="border-b">
|
<tr key={index} className="border-b">
|
||||||
<td className="p-2">
|
<td className="p-2 max-w-xs truncate">
|
||||||
<a
|
<a
|
||||||
href={path.path}
|
href={path.path}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user