performance.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. package controller
  2. import (
  3. "net/http"
  4. "os"
  5. "runtime"
  6. "time"
  7. "github.com/QuantumNous/new-api/common"
  8. "github.com/gin-gonic/gin"
  9. )
  10. // PerformanceStats 性能统计信息
  11. type PerformanceStats struct {
  12. // 缓存统计
  13. CacheStats common.DiskCacheStats `json:"cache_stats"`
  14. // 系统内存统计
  15. MemoryStats MemoryStats `json:"memory_stats"`
  16. // 磁盘缓存目录信息
  17. DiskCacheInfo DiskCacheInfo `json:"disk_cache_info"`
  18. // 磁盘空间信息
  19. DiskSpaceInfo common.DiskSpaceInfo `json:"disk_space_info"`
  20. // 配置信息
  21. Config PerformanceConfig `json:"config"`
  22. }
  23. // MemoryStats 内存统计
  24. type MemoryStats struct {
  25. // 已分配内存(字节)
  26. Alloc uint64 `json:"alloc"`
  27. // 总分配内存(字节)
  28. TotalAlloc uint64 `json:"total_alloc"`
  29. // 系统内存(字节)
  30. Sys uint64 `json:"sys"`
  31. // GC 次数
  32. NumGC uint32 `json:"num_gc"`
  33. // Goroutine 数量
  34. NumGoroutine int `json:"num_goroutine"`
  35. }
  36. // DiskCacheInfo 磁盘缓存目录信息
  37. type DiskCacheInfo struct {
  38. // 缓存目录路径
  39. Path string `json:"path"`
  40. // 目录是否存在
  41. Exists bool `json:"exists"`
  42. // 文件数量
  43. FileCount int `json:"file_count"`
  44. // 总大小(字节)
  45. TotalSize int64 `json:"total_size"`
  46. }
  47. // PerformanceConfig 性能配置
  48. type PerformanceConfig struct {
  49. // 是否启用磁盘缓存
  50. DiskCacheEnabled bool `json:"disk_cache_enabled"`
  51. // 磁盘缓存阈值(MB)
  52. DiskCacheThresholdMB int `json:"disk_cache_threshold_mb"`
  53. // 磁盘缓存最大大小(MB)
  54. DiskCacheMaxSizeMB int `json:"disk_cache_max_size_mb"`
  55. // 磁盘缓存路径
  56. DiskCachePath string `json:"disk_cache_path"`
  57. // 是否在容器中运行
  58. IsRunningInContainer bool `json:"is_running_in_container"`
  59. // MonitorEnabled 是否启用性能监控
  60. MonitorEnabled bool `json:"monitor_enabled"`
  61. // MonitorCPUThreshold CPU 使用率阈值(%)
  62. MonitorCPUThreshold int `json:"monitor_cpu_threshold"`
  63. // MonitorMemoryThreshold 内存使用率阈值(%)
  64. MonitorMemoryThreshold int `json:"monitor_memory_threshold"`
  65. // MonitorDiskThreshold 磁盘使用率阈值(%)
  66. MonitorDiskThreshold int `json:"monitor_disk_threshold"`
  67. }
  68. // GetPerformanceStats 获取性能统计信息
  69. func GetPerformanceStats(c *gin.Context) {
  70. // 不再每次获取统计都全量扫描磁盘,依赖原子计数器保证性能
  71. // 仅在系统启动或显式清理时同步
  72. cacheStats := common.GetDiskCacheStats()
  73. // 获取内存统计
  74. var memStats runtime.MemStats
  75. runtime.ReadMemStats(&memStats)
  76. // 获取磁盘缓存目录信息
  77. diskCacheInfo := getDiskCacheInfo()
  78. // 获取配置信息
  79. diskConfig := common.GetDiskCacheConfig()
  80. monitorConfig := common.GetPerformanceMonitorConfig()
  81. config := PerformanceConfig{
  82. DiskCacheEnabled: diskConfig.Enabled,
  83. DiskCacheThresholdMB: diskConfig.ThresholdMB,
  84. DiskCacheMaxSizeMB: diskConfig.MaxSizeMB,
  85. DiskCachePath: diskConfig.Path,
  86. IsRunningInContainer: common.IsRunningInContainer(),
  87. MonitorEnabled: monitorConfig.Enabled,
  88. MonitorCPUThreshold: monitorConfig.CPUThreshold,
  89. MonitorMemoryThreshold: monitorConfig.MemoryThreshold,
  90. MonitorDiskThreshold: monitorConfig.DiskThreshold,
  91. }
  92. // 获取磁盘空间信息
  93. // 使用缓存的系统状态,避免频繁调用系统 API
  94. systemStatus := common.GetSystemStatus()
  95. diskSpaceInfo := common.DiskSpaceInfo{
  96. UsedPercent: systemStatus.DiskUsage,
  97. }
  98. // 如果需要详细信息,可以按需获取,或者扩展 SystemStatus
  99. // 这里为了保持接口兼容性,我们仍然调用 GetDiskSpaceInfo,但注意这可能会有性能开销
  100. // 考虑到 GetPerformanceStats 是管理接口,频率较低,直接调用是可以接受的
  101. // 但为了一致性,我们也可以考虑从 SystemStatus 中获取部分信息
  102. diskSpaceInfo = common.GetDiskSpaceInfo()
  103. stats := PerformanceStats{
  104. CacheStats: cacheStats,
  105. MemoryStats: MemoryStats{
  106. Alloc: memStats.Alloc,
  107. TotalAlloc: memStats.TotalAlloc,
  108. Sys: memStats.Sys,
  109. NumGC: memStats.NumGC,
  110. NumGoroutine: runtime.NumGoroutine(),
  111. },
  112. DiskCacheInfo: diskCacheInfo,
  113. DiskSpaceInfo: diskSpaceInfo,
  114. Config: config,
  115. }
  116. c.JSON(http.StatusOK, gin.H{
  117. "success": true,
  118. "data": stats,
  119. })
  120. }
  121. // ClearDiskCache 清理不活跃的磁盘缓存
  122. func ClearDiskCache(c *gin.Context) {
  123. // 清理超过 10 分钟未使用的缓存文件
  124. // 10 分钟是一个安全的阈值,确保正在进行的请求不会被误删
  125. err := common.CleanupOldDiskCacheFiles(10 * time.Minute)
  126. if err != nil {
  127. common.ApiError(c, err)
  128. return
  129. }
  130. c.JSON(http.StatusOK, gin.H{
  131. "success": true,
  132. "message": "不活跃的磁盘缓存已清理",
  133. })
  134. }
  135. // ResetPerformanceStats 重置性能统计
  136. func ResetPerformanceStats(c *gin.Context) {
  137. common.ResetDiskCacheStats()
  138. c.JSON(http.StatusOK, gin.H{
  139. "success": true,
  140. "message": "统计信息已重置",
  141. })
  142. }
  143. // ForceGC 强制执行 GC
  144. func ForceGC(c *gin.Context) {
  145. runtime.GC()
  146. c.JSON(http.StatusOK, gin.H{
  147. "success": true,
  148. "message": "GC 已执行",
  149. })
  150. }
  151. // getDiskCacheInfo 获取磁盘缓存目录信息
  152. func getDiskCacheInfo() DiskCacheInfo {
  153. // 使用统一的缓存目录
  154. dir := common.GetDiskCacheDir()
  155. info := DiskCacheInfo{
  156. Path: dir,
  157. Exists: false,
  158. }
  159. entries, err := os.ReadDir(dir)
  160. if err != nil {
  161. return info
  162. }
  163. info.Exists = true
  164. info.FileCount = 0
  165. info.TotalSize = 0
  166. for _, entry := range entries {
  167. if entry.IsDir() {
  168. continue
  169. }
  170. info.FileCount++
  171. if fileInfo, err := entry.Info(); err == nil {
  172. info.TotalSize += fileInfo.Size()
  173. }
  174. }
  175. return info
  176. }