mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 13:00:52 +08:00
feat(config, usage): add usage-statistics-enabled option and dynamic toggling
- Introduced `usage-statistics-enabled` configuration to control in-memory usage aggregation. - Updated API to include handlers for managing `usage-statistics-enabled` and `logging-to-file` options. - Enhanced `watcher` to log changes to both configurations dynamically. - Updated documentation and examples to reflect new configuration options.
This commit is contained in:
@@ -12,6 +12,22 @@ func (h *Handler) GetConfig(c *gin.Context) {
|
||||
func (h *Handler) GetDebug(c *gin.Context) { c.JSON(200, gin.H{"debug": h.cfg.Debug}) }
|
||||
func (h *Handler) PutDebug(c *gin.Context) { h.updateBoolField(c, func(v bool) { h.cfg.Debug = v }) }
|
||||
|
||||
// UsageStatisticsEnabled
|
||||
func (h *Handler) GetUsageStatisticsEnabled(c *gin.Context) {
|
||||
c.JSON(200, gin.H{"usage-statistics-enabled": h.cfg.UsageStatisticsEnabled})
|
||||
}
|
||||
func (h *Handler) PutUsageStatisticsEnabled(c *gin.Context) {
|
||||
h.updateBoolField(c, func(v bool) { h.cfg.UsageStatisticsEnabled = v })
|
||||
}
|
||||
|
||||
// UsageStatisticsEnabled
|
||||
func (h *Handler) GetLoggingToFile(c *gin.Context) {
|
||||
c.JSON(200, gin.H{"logging-to-file": h.cfg.LoggingToFile})
|
||||
}
|
||||
func (h *Handler) PutLoggingToFile(c *gin.Context) {
|
||||
h.updateBoolField(c, func(v bool) { h.cfg.LoggingToFile = v })
|
||||
}
|
||||
|
||||
// Request log
|
||||
func (h *Handler) GetRequestLog(c *gin.Context) { c.JSON(200, gin.H{"request-log": h.cfg.RequestLog}) }
|
||||
func (h *Handler) PutRequestLog(c *gin.Context) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/api/middleware"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/logging"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/usage"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/util"
|
||||
sdkaccess "github.com/router-for-me/CLIProxyAPI/v6/sdk/access"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth"
|
||||
@@ -317,6 +318,14 @@ func (s *Server) setupRoutes() {
|
||||
mgmt.PUT("/debug", s.mgmt.PutDebug)
|
||||
mgmt.PATCH("/debug", s.mgmt.PutDebug)
|
||||
|
||||
mgmt.GET("/logging-to-file", s.mgmt.GetLoggingToFile)
|
||||
mgmt.PUT("/logging-to-file", s.mgmt.PutLoggingToFile)
|
||||
mgmt.PATCH("/logging-to-file", s.mgmt.PutLoggingToFile)
|
||||
|
||||
mgmt.GET("/usage-statistics-enabled", s.mgmt.GetUsageStatisticsEnabled)
|
||||
mgmt.PUT("/usage-statistics-enabled", s.mgmt.PutUsageStatisticsEnabled)
|
||||
mgmt.PATCH("/usage-statistics-enabled", s.mgmt.PutUsageStatisticsEnabled)
|
||||
|
||||
mgmt.GET("/proxy-url", s.mgmt.GetProxyURL)
|
||||
mgmt.PUT("/proxy-url", s.mgmt.PutProxyURL)
|
||||
mgmt.PATCH("/proxy-url", s.mgmt.PutProxyURL)
|
||||
@@ -575,6 +584,13 @@ func (s *Server) UpdateClients(cfg *config.Config) {
|
||||
}
|
||||
}
|
||||
|
||||
if s.cfg == nil || s.cfg.UsageStatisticsEnabled != cfg.UsageStatisticsEnabled {
|
||||
usage.SetStatisticsEnabled(cfg.UsageStatisticsEnabled)
|
||||
if s.cfg != nil {
|
||||
log.Debugf("usage_statistics_enabled updated from %t to %t", s.cfg.UsageStatisticsEnabled, cfg.UsageStatisticsEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
// Update log level dynamically when debug flag changes
|
||||
if s.cfg.Debug != cfg.Debug {
|
||||
util.SetLogLevel(cfg)
|
||||
|
||||
@@ -26,6 +26,9 @@ type Config struct {
|
||||
// LoggingToFile controls whether application logs are written to rotating files or stdout.
|
||||
LoggingToFile bool `yaml:"logging-to-file" json:"logging-to-file"`
|
||||
|
||||
// UsageStatisticsEnabled toggles in-memory usage aggregation; when false, usage data is discarded.
|
||||
UsageStatisticsEnabled bool `yaml:"usage-statistics-enabled" json:"usage-statistics-enabled"`
|
||||
|
||||
// ProxyURL is the URL of an optional proxy server to use for outbound requests.
|
||||
ProxyURL string `yaml:"proxy-url" json:"proxy-url"`
|
||||
|
||||
@@ -206,6 +209,7 @@ func LoadConfig(configFile string) (*Config, error) {
|
||||
var config Config
|
||||
// Set defaults before unmarshal so that absent keys keep defaults.
|
||||
config.LoggingToFile = true
|
||||
config.UsageStatisticsEnabled = true
|
||||
config.GeminiWeb.Context = true
|
||||
if err = yaml.Unmarshal(data, &config); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse config file: %w", err)
|
||||
|
||||
@@ -7,13 +7,17 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
coreusage "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/usage"
|
||||
)
|
||||
|
||||
var statisticsEnabled atomic.Bool
|
||||
|
||||
func init() {
|
||||
statisticsEnabled.Store(true)
|
||||
coreusage.RegisterPlugin(NewLoggerPlugin())
|
||||
}
|
||||
|
||||
@@ -36,12 +40,21 @@ func NewLoggerPlugin() *LoggerPlugin { return &LoggerPlugin{stats: defaultReques
|
||||
// - ctx: The context for the usage record
|
||||
// - record: The usage record to aggregate
|
||||
func (p *LoggerPlugin) HandleUsage(ctx context.Context, record coreusage.Record) {
|
||||
if !statisticsEnabled.Load() {
|
||||
return
|
||||
}
|
||||
if p == nil || p.stats == nil {
|
||||
return
|
||||
}
|
||||
p.stats.Record(ctx, record)
|
||||
}
|
||||
|
||||
// SetStatisticsEnabled toggles whether in-memory statistics are recorded.
|
||||
func SetStatisticsEnabled(enabled bool) { statisticsEnabled.Store(enabled) }
|
||||
|
||||
// StatisticsEnabled reports the current recording state.
|
||||
func StatisticsEnabled() bool { return statisticsEnabled.Load() }
|
||||
|
||||
// RequestStatistics maintains aggregated request metrics in memory.
|
||||
type RequestStatistics struct {
|
||||
mu sync.RWMutex
|
||||
@@ -138,6 +151,9 @@ func (s *RequestStatistics) Record(ctx context.Context, record coreusage.Record)
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
if !statisticsEnabled.Load() {
|
||||
return
|
||||
}
|
||||
timestamp := record.RequestedAt
|
||||
if timestamp.IsZero() {
|
||||
timestamp = time.Now()
|
||||
|
||||
@@ -477,6 +477,12 @@ func (w *Watcher) reloadConfig() bool {
|
||||
if oldConfig.RemoteManagement.AllowRemote != newConfig.RemoteManagement.AllowRemote {
|
||||
log.Debugf(" remote-management.allow-remote: %t -> %t", oldConfig.RemoteManagement.AllowRemote, newConfig.RemoteManagement.AllowRemote)
|
||||
}
|
||||
if oldConfig.LoggingToFile != newConfig.LoggingToFile {
|
||||
log.Debugf(" logging-to-file: %t -> %t", oldConfig.LoggingToFile, newConfig.LoggingToFile)
|
||||
}
|
||||
if oldConfig.UsageStatisticsEnabled != newConfig.UsageStatisticsEnabled {
|
||||
log.Debugf(" usage-statistics-enabled: %t -> %t", oldConfig.UsageStatisticsEnabled, newConfig.UsageStatisticsEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof("config successfully reloaded, triggering client reload")
|
||||
|
||||
Reference in New Issue
Block a user