Merge pull request #2835 from QuantumNous/feat/performance-monitoring

feat(performance): implement system performance monitoring
This commit is contained in:
Calcium-Ion
2026-02-04 21:34:44 +08:00
committed by GitHub
12 changed files with 450 additions and 32 deletions

View File

@@ -0,0 +1,33 @@
package common
import "sync/atomic"
// PerformanceMonitorConfig 性能监控配置
type PerformanceMonitorConfig struct {
Enabled bool
CPUThreshold int
MemoryThreshold int
DiskThreshold int
}
var performanceMonitorConfig atomic.Value
func init() {
// 初始化默认配置
performanceMonitorConfig.Store(PerformanceMonitorConfig{
Enabled: true,
CPUThreshold: 90,
MemoryThreshold: 90,
DiskThreshold: 90,
})
}
// GetPerformanceMonitorConfig 获取性能监控配置
func GetPerformanceMonitorConfig() PerformanceMonitorConfig {
return performanceMonitorConfig.Load().(PerformanceMonitorConfig)
}
// SetPerformanceMonitorConfig 设置性能监控配置
func SetPerformanceMonitorConfig(config PerformanceMonitorConfig) {
performanceMonitorConfig.Store(config)
}

81
common/system_monitor.go Normal file
View File

@@ -0,0 +1,81 @@
package common
import (
"sync/atomic"
"time"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/mem"
)
// DiskSpaceInfo 磁盘空间信息
type DiskSpaceInfo struct {
// 总空间(字节)
Total uint64 `json:"total"`
// 可用空间(字节)
Free uint64 `json:"free"`
// 已用空间(字节)
Used uint64 `json:"used"`
// 使用百分比
UsedPercent float64 `json:"used_percent"`
}
// SystemStatus 系统状态信息
type SystemStatus struct {
CPUUsage float64
MemoryUsage float64
DiskUsage float64
}
var latestSystemStatus atomic.Value
func init() {
latestSystemStatus.Store(SystemStatus{})
}
// StartSystemMonitor 启动系统监控
func StartSystemMonitor() {
go func() {
for {
config := GetPerformanceMonitorConfig()
if !config.Enabled {
time.Sleep(30 * time.Second)
continue
}
updateSystemStatus()
time.Sleep(5 * time.Second)
}
}()
}
func updateSystemStatus() {
var status SystemStatus
// CPU
// 注意cpu.Percent(0, false) 返回自上次调用以来的 CPU 使用率
// 如果是第一次调用,可能会返回错误或不准确的值,但在循环中会逐渐正常
percents, err := cpu.Percent(0, false)
if err == nil && len(percents) > 0 {
status.CPUUsage = percents[0]
}
// Memory
memInfo, err := mem.VirtualMemory()
if err == nil {
status.MemoryUsage = memInfo.UsedPercent
}
// Disk
diskInfo := GetDiskSpaceInfo()
if diskInfo.Total > 0 {
status.DiskUsage = diskInfo.UsedPercent
}
latestSystemStatus.Store(status)
}
// GetSystemStatus 获取当前系统状态
func GetSystemStatus() SystemStatus {
return latestSystemStatus.Load().(SystemStatus)
}

View File

@@ -1,17 +1,16 @@
//go:build !windows
package controller
package common
import (
"os"
"github.com/QuantumNous/new-api/common"
"golang.org/x/sys/unix"
)
// getDiskSpaceInfo 获取缓存目录所在磁盘的空间信息 (Unix/Linux/macOS)
func getDiskSpaceInfo() DiskSpaceInfo {
cachePath := common.GetDiskCachePath()
// GetDiskSpaceInfo 获取缓存目录所在磁盘的空间信息 (Unix/Linux/macOS)
func GetDiskSpaceInfo() DiskSpaceInfo {
cachePath := GetDiskCachePath()
if cachePath == "" {
cachePath = os.TempDir()
}

View File

@@ -1,18 +1,16 @@
//go:build windows
package controller
package common
import (
"os"
"syscall"
"unsafe"
"github.com/QuantumNous/new-api/common"
)
// getDiskSpaceInfo 获取缓存目录所在磁盘的空间信息 (Windows)
func getDiskSpaceInfo() DiskSpaceInfo {
cachePath := common.GetDiskCachePath()
// GetDiskSpaceInfo 获取缓存目录所在磁盘的空间信息 (Windows)
func GetDiskSpaceInfo() DiskSpaceInfo {
cachePath := GetDiskCachePath()
if cachePath == "" {
cachePath = os.TempDir()
}

View File

@@ -19,7 +19,7 @@ type PerformanceStats struct {
// 磁盘缓存目录信息
DiskCacheInfo DiskCacheInfo `json:"disk_cache_info"`
// 磁盘空间信息
DiskSpaceInfo DiskSpaceInfo `json:"disk_space_info"`
DiskSpaceInfo common.DiskSpaceInfo `json:"disk_space_info"`
// 配置信息
Config PerformanceConfig `json:"config"`
}
@@ -50,18 +50,6 @@ type DiskCacheInfo struct {
TotalSize int64 `json:"total_size"`
}
// DiskSpaceInfo 磁盘空间信息
type DiskSpaceInfo struct {
// 总空间(字节)
Total uint64 `json:"total"`
// 可用空间(字节)
Free uint64 `json:"free"`
// 已用空间(字节)
Used uint64 `json:"used"`
// 使用百分比
UsedPercent float64 `json:"used_percent"`
}
// PerformanceConfig 性能配置
type PerformanceConfig struct {
// 是否启用磁盘缓存
@@ -74,6 +62,15 @@ type PerformanceConfig struct {
DiskCachePath string `json:"disk_cache_path"`
// 是否在容器中运行
IsRunningInContainer bool `json:"is_running_in_container"`
// MonitorEnabled 是否启用性能监控
MonitorEnabled bool `json:"monitor_enabled"`
// MonitorCPUThreshold CPU 使用率阈值(%
MonitorCPUThreshold int `json:"monitor_cpu_threshold"`
// MonitorMemoryThreshold 内存使用率阈值(%
MonitorMemoryThreshold int `json:"monitor_memory_threshold"`
// MonitorDiskThreshold 磁盘使用率阈值(%
MonitorDiskThreshold int `json:"monitor_disk_threshold"`
}
// GetPerformanceStats 获取性能统计信息
@@ -91,16 +88,30 @@ func GetPerformanceStats(c *gin.Context) {
// 获取配置信息
diskConfig := common.GetDiskCacheConfig()
monitorConfig := common.GetPerformanceMonitorConfig()
config := PerformanceConfig{
DiskCacheEnabled: diskConfig.Enabled,
DiskCacheThresholdMB: diskConfig.ThresholdMB,
DiskCacheMaxSizeMB: diskConfig.MaxSizeMB,
DiskCachePath: diskConfig.Path,
IsRunningInContainer: common.IsRunningInContainer(),
DiskCacheEnabled: diskConfig.Enabled,
DiskCacheThresholdMB: diskConfig.ThresholdMB,
DiskCacheMaxSizeMB: diskConfig.MaxSizeMB,
DiskCachePath: diskConfig.Path,
IsRunningInContainer: common.IsRunningInContainer(),
MonitorEnabled: monitorConfig.Enabled,
MonitorCPUThreshold: monitorConfig.CPUThreshold,
MonitorMemoryThreshold: monitorConfig.MemoryThreshold,
MonitorDiskThreshold: monitorConfig.DiskThreshold,
}
// 获取磁盘空间信息
diskSpaceInfo := getDiskSpaceInfo()
// 使用缓存的系统状态,避免频繁调用系统 API
systemStatus := common.GetSystemStatus()
diskSpaceInfo := common.DiskSpaceInfo{
UsedPercent: systemStatus.DiskUsage,
}
// 如果需要详细信息,可以按需获取,或者扩展 SystemStatus
// 这里为了保持接口兼容性,我们仍然调用 GetDiskSpaceInfo但注意这可能会有性能开销
// 考虑到 GetPerformanceStats 是管理接口,频率较低,直接调用是可以接受的
// 但为了一致性,我们也可以考虑从 SystemStatus 中获取部分信息
diskSpaceInfo = common.GetDiskSpaceInfo()
stats := PerformanceStats{
CacheStats: cacheStats,

View File

@@ -274,5 +274,9 @@ func InitResources() error {
if err != nil {
return err
}
// 启动系统监控
common.StartSystemMonitor()
return nil
}

65
middleware/performance.go Normal file
View File

@@ -0,0 +1,65 @@
package middleware
import (
"errors"
"net/http"
"strings"
"github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/types"
"github.com/gin-gonic/gin"
)
// SystemPerformanceCheck 检查系统性能中间件
func SystemPerformanceCheck() gin.HandlerFunc {
return func(c *gin.Context) {
// 仅检查 Relay 接口 (/v1, /v1beta 等)
// 这里简单判断路径前缀,可以根据实际路由调整
path := c.Request.URL.Path
if strings.HasPrefix(path, "/v1/messages") {
if err := checkSystemPerformance(); err != nil {
c.JSON(err.StatusCode, gin.H{
"error": err.ToClaudeError(),
})
c.Abort()
return
}
} else {
if err := checkSystemPerformance(); err != nil {
c.JSON(err.StatusCode, gin.H{
"error": err.ToOpenAIError(),
})
c.Abort()
return
}
}
c.Next()
}
}
// checkSystemPerformance 检查系统性能是否超过阈值
func checkSystemPerformance() *types.NewAPIError {
config := common.GetPerformanceMonitorConfig()
if !config.Enabled {
return nil
}
status := common.GetSystemStatus()
// 检查 CPU
if config.CPUThreshold > 0 && int(status.CPUUsage) > config.CPUThreshold {
return types.NewErrorWithStatusCode(errors.New("system cpu overloaded"), "system_cpu_overloaded", http.StatusServiceUnavailable)
}
// 检查内存
if config.MemoryThreshold > 0 && int(status.MemoryUsage) > config.MemoryThreshold {
return types.NewErrorWithStatusCode(errors.New("system memory overloaded"), "system_memory_overloaded", http.StatusServiceUnavailable)
}
// 检查磁盘
if config.DiskThreshold > 0 && int(status.DiskUsage) > config.DiskThreshold {
return types.NewErrorWithStatusCode(errors.New("system disk overloaded"), "system_disk_overloaded", http.StatusServiceUnavailable)
}
return nil
}

View File

@@ -57,11 +57,13 @@ func SetRelayRouter(router *gin.Engine) {
}
playgroundRouter := router.Group("/pg")
playgroundRouter.Use(middleware.SystemPerformanceCheck())
playgroundRouter.Use(middleware.UserAuth(), middleware.Distribute())
{
playgroundRouter.POST("/chat/completions", controller.Playground)
}
relayV1Router := router.Group("/v1")
relayV1Router.Use(middleware.SystemPerformanceCheck())
relayV1Router.Use(middleware.TokenAuth())
relayV1Router.Use(middleware.ModelRequestRateLimit())
{
@@ -159,13 +161,16 @@ func SetRelayRouter(router *gin.Engine) {
}
relayMjRouter := router.Group("/mj")
relayMjRouter.Use(middleware.SystemPerformanceCheck())
registerMjRouterGroup(relayMjRouter)
relayMjModeRouter := router.Group("/:mode/mj")
relayMjModeRouter.Use(middleware.SystemPerformanceCheck())
registerMjRouterGroup(relayMjModeRouter)
//relayMjRouter.Use()
relaySunoRouter := router.Group("/suno")
relaySunoRouter.Use(middleware.SystemPerformanceCheck())
relaySunoRouter.Use(middleware.TokenAuth(), middleware.Distribute())
{
relaySunoRouter.POST("/submit/:action", controller.RelayTask)
@@ -174,6 +179,7 @@ func SetRelayRouter(router *gin.Engine) {
}
relayGeminiRouter := router.Group("/v1beta")
relayGeminiRouter.Use(middleware.SystemPerformanceCheck())
relayGeminiRouter.Use(middleware.TokenAuth())
relayGeminiRouter.Use(middleware.ModelRequestRateLimit())
relayGeminiRouter.Use(middleware.Distribute())

View File

@@ -15,6 +15,15 @@ type PerformanceSetting struct {
DiskCacheMaxSizeMB int `json:"disk_cache_max_size_mb"`
// DiskCachePath 磁盘缓存目录
DiskCachePath string `json:"disk_cache_path"`
// MonitorEnabled 是否启用性能监控
MonitorEnabled bool `json:"monitor_enabled"`
// MonitorCPUThreshold CPU 使用率阈值(%
MonitorCPUThreshold int `json:"monitor_cpu_threshold"`
// MonitorMemoryThreshold 内存使用率阈值(%
MonitorMemoryThreshold int `json:"monitor_memory_threshold"`
// MonitorDiskThreshold 磁盘使用率阈值(%
MonitorDiskThreshold int `json:"monitor_disk_threshold"`
}
// 默认配置
@@ -23,6 +32,11 @@ var performanceSetting = PerformanceSetting{
DiskCacheThresholdMB: 10, // 超过 10MB 使用磁盘缓存
DiskCacheMaxSizeMB: 1024, // 最大 1GB 磁盘缓存
DiskCachePath: "", // 空表示使用系统临时目录
MonitorEnabled: true,
MonitorCPUThreshold: 90,
MonitorMemoryThreshold: 90,
MonitorDiskThreshold: 90,
}
func init() {
@@ -40,6 +54,13 @@ func syncToCommon() {
MaxSizeMB: performanceSetting.DiskCacheMaxSizeMB,
Path: performanceSetting.DiskCachePath,
})
common.SetPerformanceMonitorConfig(common.PerformanceMonitorConfig{
Enabled: performanceSetting.MonitorEnabled,
CPUThreshold: performanceSetting.MonitorCPUThreshold,
MemoryThreshold: performanceSetting.MonitorMemoryThreshold,
DiskThreshold: performanceSetting.MonitorDiskThreshold,
})
}
// GetPerformanceSetting 获取性能设置

View File

@@ -2316,6 +2316,45 @@
"输入验证码完成设置": "Enter verification code to complete setup",
"输出": "Output",
"输出 {{completion}} tokens / 1M tokens * {{symbol}}{{compPrice}}) * {{ratioType}} {{ratio}}": "Output {{completion}} tokens / 1M tokens * {{symbol}}{{compPrice}} * {{ratioType}} {{ratio}}",
"磁盘缓存设置(磁盘换内存)": "Disk Cache Settings (Disk Swap Memory)",
"启用磁盘缓存后,大请求体将临时存储到磁盘而非内存,可显著降低内存占用,适用于处理包含大量图片/文件的请求。建议在 SSD 环境下使用。": "When enabled, large request bodies are temporarily stored on disk instead of memory, significantly reducing memory usage. Suitable for requests with large images/files. SSD recommended.",
"启用磁盘缓存": "Enable Disk Cache",
"将大请求体临时存储到磁盘": "Store large request bodies temporarily on disk",
"磁盘缓存阈值 (MB)": "Disk Cache Threshold (MB)",
"请求体超过此大小时使用磁盘缓存": "Use disk cache when request body exceeds this size",
"磁盘缓存最大总量 (MB)": "Max Disk Cache Size (MB)",
"可用空间: {{free}} / 总空间: {{total}}": "Free: {{free}} / Total: {{total}}",
"磁盘缓存占用的最大空间": "Maximum space occupied by disk cache",
"留空使用系统临时目录": "Leave empty to use system temp directory",
"例如 /var/cache/new-api": "e.g. /var/cache/new-api",
"性能监控": "Performance Monitor",
"刷新统计": "Refresh Stats",
"重置统计": "Reset Stats",
"执行 GC": "Run GC",
"请求体磁盘缓存": "Request Body Disk Cache",
"活跃文件": "Active Files",
"磁盘命中": "Disk Hits",
"请求体内存缓存": "Request Body Memory Cache",
"当前缓存大小": "Current Cache Size",
"活跃缓存数": "Active Cache Count",
"内存命中": "Memory Hits",
"缓存目录磁盘空间": "Cache Directory Disk Space",
"磁盘可用空间小于缓存最大总量设置": "Disk free space is less than max cache size setting",
"已分配内存": "Allocated Memory",
"总分配内存": "Total Allocated Memory",
"系统内存": "System Memory",
"GC 次数": "GC Count",
"Goroutine 数": "Goroutine Count",
"目录文件数": "Directory File Count",
"目录总大小": "Directory Total Size",
"磁盘缓存已清理": "Disk cache cleared",
"清理失败": "Cleanup failed",
"统计已重置": "Statistics reset",
"重置失败": "Reset failed",
"GC 已执行": "GC executed",
"GC 执行失败": "GC execution failed",
"缓存目录": "Cache Directory",
"可用": "Available",
"输出价格": "Output Price",
"输出价格:{{symbol}}{{price}} * {{completionRatio}} = {{symbol}}{{total}} / 1M tokens (补全倍率: {{completionRatio}})": "Output price: {{symbol}}{{price}} * {{completionRatio}} = {{symbol}}{{total}} / 1M tokens (Completion ratio: {{completionRatio}})",
"输出倍率 {{completionRatio}}": "Output ratio {{completionRatio}}",
@@ -2687,6 +2726,46 @@
"套餐名称": "Plan Name",
"应付金额": "Amount Due",
"支付": "Pay",
"管理员未开启在线支付功能,请联系管理员配置。": "Online payment is not enabled by the admin. Please contact the administrator."
"管理员未开启在线支付功能,请联系管理员配置。": "Online payment is not enabled by the admin. Please contact the administrator.",
"磁盘缓存设置(磁盘换内存)": "Disk Cache Settings (Disk Swap Memory)",
"启用磁盘缓存后,大请求体将临时存储到磁盘而非内存,可显著降低内存占用,适用于处理包含大量图片/文件的请求。建议在 SSD 环境下使用。": "When enabled, large request bodies are temporarily stored on disk instead of memory, significantly reducing memory usage. Suitable for requests with large images/files. SSD recommended.",
"启用磁盘缓存": "Enable Disk Cache",
"将大请求体临时存储到磁盘": "Store large request bodies temporarily on disk",
"磁盘缓存阈值 (MB)": "Disk Cache Threshold (MB)",
"请求体超过此大小时使用磁盘缓存": "Use disk cache when request body exceeds this size",
"磁盘缓存最大总量 (MB)": "Max Disk Cache Size (MB)",
"可用空间: {{free}} / 总空间: {{total}}": "Free: {{free}} / Total: {{total}}",
"磁盘缓存占用的最大空间": "Maximum space occupied by disk cache",
"留空使用系统临时目录": "Leave empty to use system temp directory",
"例如 /var/cache/new-api": "e.g. /var/cache/new-api",
"性能监控": "Performance Monitor",
"刷新统计": "Refresh Stats",
"重置统计": "Reset Stats",
"执行 GC": "Run GC",
"请求体磁盘缓存": "Request Body Disk Cache",
"活跃文件": "Active Files",
"磁盘命中": "Disk Hits",
"请求体内存缓存": "Request Body Memory Cache",
"当前缓存大小": "Current Cache Size",
"活跃缓存数": "Active Cache Count",
"内存命中": "Memory Hits",
"缓存目录磁盘空间": "Cache Directory Disk Space",
"磁盘可用空间小于缓存最大总量设置": "Disk free space is less than max cache size setting",
"已分配内存": "Allocated Memory",
"总分配内存": "Total Allocated Memory",
"系统内存": "System Memory",
"GC 次数": "GC Count",
"Goroutine 数": "Goroutine Count",
"目录文件数": "Directory File Count",
"目录总大小": "Directory Total Size",
"磁盘缓存已清理": "Disk cache cleared",
"清理失败": "Cleanup failed",
"统计已重置": "Statistics reset",
"重置失败": "Reset failed",
"GC 已执行": "GC executed",
"GC execution failed": "GC execution failed",
"Cache Directory": "Cache Directory",
"Available": "Available",
"输出价格": "Output Price"
}
}

View File

@@ -1823,6 +1823,17 @@
"系统文档和帮助信息": "系统文档和帮助信息",
"系统消息": "系统消息",
"系统管理功能": "系统管理功能",
"系统性能监控": "系统性能监控",
"启用性能监控后,当系统资源使用率超过设定阈值时,将拒绝新的 Relay 请求 (/v1, /v1beta 等),以保护系统稳定性。": "启用性能监控后,当系统资源使用率超过设定阈值时,将拒绝新的 Relay 请求 (/v1, /v1beta 等),以保护系统稳定性。",
"启用性能监控": "启用性能监控",
"超过阈值时拒绝新请求": "超过阈值时拒绝新请求",
"CPU 阈值 (%)": "CPU 阈值 (%)",
"CPU 使用率超过此值时拒绝请求": "CPU 使用率超过此值时拒绝请求",
"内存 阈值 (%)": "内存 阈值 (%)",
"内存使用率超过此值时拒绝请求": "内存使用率超过此值时拒绝请求",
"磁盘 阈值 (%)": "磁盘 阈值 (%)",
"磁盘使用率超过此值时拒绝请求": "磁盘使用率超过此值时拒绝请求",
"保存性能设置": "保存性能设置",
"系统设置": "系统设置",
"系统访问令牌": "系统访问令牌",
"约": "约",
@@ -2305,6 +2316,45 @@
"输入验证码完成设置": "输入验证码完成设置",
"输出": "输出",
"输出 {{completion}} tokens / 1M tokens * {{symbol}}{{compPrice}}) * {{ratioType}} {{ratio}}": "输出 {{completion}} tokens / 1M tokens * {{symbol}}{{compPrice}}) * {{ratioType}} {{ratio}}",
"磁盘缓存设置(磁盘换内存)": "磁盘缓存设置(磁盘换内存)",
"启用磁盘缓存后,大请求体将临时存储到磁盘而非内存,可显著降低内存占用,适用于处理包含大量图片/文件的请求。建议在 SSD 环境下使用。": "启用磁盘缓存后,大请求体将临时存储到磁盘而非内存,可显著降低内存占用,适用于处理包含大量图片/文件的请求。建议在 SSD 环境下使用。",
"启用磁盘缓存": "启用磁盘缓存",
"将大请求体临时存储到磁盘": "将大请求体临时存储到磁盘",
"磁盘缓存阈值 (MB)": "磁盘缓存阈值 (MB)",
"请求体超过此大小时使用磁盘缓存": "请求体超过此大小时使用磁盘缓存",
"磁盘缓存最大总量 (MB)": "磁盘缓存最大总量 (MB)",
"可用空间: {{free}} / 总空间: {{total}}": "可用空间: {{free}} / 总空间: {{total}}",
"磁盘缓存占用的最大空间": "磁盘缓存占用的最大空间",
"留空使用系统临时目录": "留空使用系统临时目录",
"例如 /var/cache/new-api": "例如 /var/cache/new-api",
"性能监控": "性能监控",
"刷新统计": "刷新统计",
"重置统计": "重置统计",
"执行 GC": "执行 GC",
"请求体磁盘缓存": "请求体磁盘缓存",
"活跃文件": "活跃文件",
"磁盘命中": "磁盘命中",
"请求体内存缓存": "请求体内存缓存",
"当前缓存大小": "当前缓存大小",
"活跃缓存数": "活跃缓存数",
"内存命中": "内存命中",
"缓存目录磁盘空间": "缓存目录磁盘空间",
"磁盘可用空间小于缓存最大总量设置": "磁盘可用空间小于缓存最大总量设置",
"已分配内存": "已分配内存",
"总分配内存": "总分配内存",
"系统内存": "系统内存",
"GC 次数": "GC 次数",
"Goroutine 数": "Goroutine 数",
"目录文件数": "目录文件数",
"目录总大小": "目录总大小",
"磁盘缓存已清理": "磁盘缓存已清理",
"清理失败": "清理失败",
"统计已重置": "统计已重置",
"重置失败": "重置失败",
"GC 已执行": "GC 已执行",
"GC 执行失败": "GC 执行失败",
"缓存目录": "缓存目录",
"可用": "可用",
"输出价格": "输出价格",
"输出价格:{{symbol}}{{price}} * {{completionRatio}} = {{symbol}}{{total}} / 1M tokens (补全倍率: {{completionRatio}})": "输出价格:{{symbol}}{{price}} * {{completionRatio}} = {{symbol}}{{total}} / 1M tokens (补全倍率: {{completionRatio}})",
"输出倍率 {{completionRatio}}": "输出倍率 {{completionRatio}}",

View File

@@ -65,6 +65,10 @@ export default function SettingsPerformance(props) {
'performance_setting.disk_cache_threshold_mb': 10,
'performance_setting.disk_cache_max_size_mb': 1024,
'performance_setting.disk_cache_path': '',
'performance_setting.monitor_enabled': false,
'performance_setting.monitor_cpu_threshold': 90,
'performance_setting.monitor_memory_threshold': 90,
'performance_setting.monitor_disk_threshold': 90,
});
const refForm = useRef();
const [inputsRow, setInputsRow] = useState(inputs);
@@ -274,6 +278,70 @@ export default function SettingsPerformance(props) {
</Col>
)}
</Row>
</Form.Section>
<Form.Section text={t('系统性能监控')}>
<Banner
type='info'
description={t(
'启用性能监控后,当系统资源使用率超过设定阈值时,将拒绝新的 Relay 请求 (/v1, /v1beta 等),以保护系统稳定性。',
)}
style={{ marginBottom: 16 }}
/>
<Row gutter={16}>
<Col xs={24} sm={12} md={6} lg={6} xl={6}>
<Form.Switch
field={'performance_setting.monitor_enabled'}
label={t('启用性能监控')}
extraText={t('超过阈值时拒绝新请求')}
size='default'
checkedText=''
uncheckedText=''
onChange={handleFieldChange(
'performance_setting.monitor_enabled',
)}
/>
</Col>
<Col xs={24} sm={12} md={6} lg={6} xl={6}>
<Form.InputNumber
field={'performance_setting.monitor_cpu_threshold'}
label={t('CPU 阈值 (%)')}
extraText={t('CPU 使用率超过此值时拒绝请求')}
min={0}
max={100}
onChange={handleFieldChange(
'performance_setting.monitor_cpu_threshold',
)}
disabled={!inputs['performance_setting.monitor_enabled']}
/>
</Col>
<Col xs={24} sm={12} md={6} lg={6} xl={6}>
<Form.InputNumber
field={'performance_setting.monitor_memory_threshold'}
label={t('内存 阈值 (%)')}
extraText={t('内存使用率超过此值时拒绝请求')}
min={0}
max={100}
onChange={handleFieldChange(
'performance_setting.monitor_memory_threshold',
)}
disabled={!inputs['performance_setting.monitor_enabled']}
/>
</Col>
<Col xs={24} sm={12} md={6} lg={6} xl={6}>
<Form.InputNumber
field={'performance_setting.monitor_disk_threshold'}
label={t('磁盘 阈值 (%)')}
extraText={t('磁盘使用率超过此值时拒绝请求')}
min={0}
max={100}
onChange={handleFieldChange(
'performance_setting.monitor_disk_threshold',
)}
disabled={!inputs['performance_setting.monitor_enabled']}
/>
</Col>
</Row>
<Row>
<Button size='default' onClick={onSubmit}>
{t('保存性能设置')}
@@ -490,7 +558,10 @@ export default function SettingsPerformance(props) {
key: t('Goroutine 数'),
value: stats.memory_stats.num_goroutine,
},
{ key: t('缓存目录'), value: stats.disk_cache_info.path },
{
key: t('缓存目录'),
value: stats.disk_cache_info.path,
},
{
key: t('目录文件数'),
value: stats.disk_cache_info.file_count,