wood chen 50e6abaa2f refactor(monitoring): enhance TopReferers handling and JSON serialization
- Improved LogRequest function to correctly increment counts for referers, ensuring accurate tracking of direct and indirect accesses.
- Added MarshalJSON method to SystemMetrics for proper serialization of TopReferers, facilitating better JSON representation of metrics.
- Updated comments for clarity and maintainability, enhancing code readability.
2024-12-01 01:46:57 +08:00

108 lines
2.5 KiB
Go

package monitoring
import (
"encoding/json"
"runtime"
"strings"
"sync"
"time"
)
type SystemMetrics struct {
// 基础指标
Uptime time.Duration `json:"uptime"`
StartTime time.Time `json:"start_time"`
// 系统指标
NumCPU int `json:"num_cpu"`
NumGoroutine int `json:"num_goroutine"`
AverageLatency float64 `json:"average_latency"`
MemoryStats struct {
HeapAlloc uint64 `json:"heap_alloc"`
HeapSys uint64 `json:"heap_sys"`
} `json:"memory_stats"`
// 热门引用来源
TopReferers sync.Map `json:"-"` // 内部使用 sync.Map
}
type RequestLog struct {
Time int64 `json:"time"`
Path string `json:"path"`
Method string `json:"method"`
StatusCode int `json:"status_code"`
Latency float64 `json:"latency"`
IP string `json:"ip"`
Referer string `json:"referer"`
}
var (
metrics SystemMetrics
startTime = time.Now()
)
func init() {
// 定期清理引用来源
go func() {
ticker := time.NewTicker(5 * time.Minute)
for range ticker.C {
metrics.TopReferers = sync.Map{} // 直接重置
}
}()
}
func LogRequest(log RequestLog) {
// 更新引用来源
if log.Referer != "direct" {
if val, ok := metrics.TopReferers.Load(log.Referer); ok {
metrics.TopReferers.Store(log.Referer, val.(int64)+1)
} else {
metrics.TopReferers.Store(log.Referer, int64(1))
}
} else {
if val, ok := metrics.TopReferers.Load("直接访问"); ok {
metrics.TopReferers.Store("直接访问", val.(int64)+1)
} else {
metrics.TopReferers.Store("直接访问", int64(1))
}
}
// 更新平均延迟 (只关心 API 请求)
if strings.HasPrefix(log.Path, "/pic/") || strings.HasPrefix(log.Path, "/video/") {
metrics.AverageLatency = (metrics.AverageLatency + log.Latency) / 2
}
}
func CollectMetrics() *SystemMetrics {
var m runtime.MemStats
runtime.ReadMemStats(&m)
metrics.Uptime = time.Since(startTime)
metrics.StartTime = startTime
metrics.NumCPU = runtime.NumCPU()
metrics.NumGoroutine = runtime.NumGoroutine()
metrics.MemoryStats.HeapAlloc = m.HeapAlloc
metrics.MemoryStats.HeapSys = m.HeapSys
return &metrics
}
// 添加 MarshalJSON 方法来正确序列化 TopReferers
func (m *SystemMetrics) MarshalJSON() ([]byte, error) {
type Alias SystemMetrics
referers := make(map[string]int64)
m.TopReferers.Range(func(key, value interface{}) bool {
referers[key.(string)] = value.(int64)
return true
})
return json.Marshal(&struct {
*Alias
TopReferers map[string]int64 `json:"top_referers"`
}{
Alias: (*Alias)(m),
TopReferers: referers,
})
}