mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 13:00:52 +08:00
refactor(watcher): Extract config change logging to new function
This commit is contained in:
@@ -538,71 +538,16 @@ func (w *Watcher) reloadConfig() bool {
|
|||||||
log.Debugf("log level updated - debug mode changed from %t to %t", oldConfig.Debug, newConfig.Debug)
|
log.Debugf("log level updated - debug mode changed from %t to %t", oldConfig.Debug, newConfig.Debug)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log configuration changes in debug mode
|
// Log configuration changes in debug mode, only when there are material diffs
|
||||||
if oldConfig != nil {
|
if oldConfig != nil {
|
||||||
log.Debugf("config changes detected:")
|
details := buildConfigChangeDetails(oldConfig, newConfig)
|
||||||
if oldConfig.Port != newConfig.Port {
|
if len(details) > 0 {
|
||||||
log.Debugf(" port: %d -> %d", oldConfig.Port, newConfig.Port)
|
log.Debugf("config changes detected:")
|
||||||
}
|
for _, d := range details {
|
||||||
if oldConfig.AuthDir != newConfig.AuthDir {
|
log.Debugf(" %s", d)
|
||||||
log.Debugf(" auth-dir: %s -> %s", oldConfig.AuthDir, newConfig.AuthDir)
|
|
||||||
}
|
|
||||||
if oldConfig.Debug != newConfig.Debug {
|
|
||||||
log.Debugf(" debug: %t -> %t", oldConfig.Debug, newConfig.Debug)
|
|
||||||
}
|
|
||||||
if oldConfig.ProxyURL != newConfig.ProxyURL {
|
|
||||||
log.Debugf(" proxy-url: %s -> %s", oldConfig.ProxyURL, newConfig.ProxyURL)
|
|
||||||
}
|
|
||||||
if oldConfig.RequestLog != newConfig.RequestLog {
|
|
||||||
log.Debugf(" request-log: %t -> %t", oldConfig.RequestLog, newConfig.RequestLog)
|
|
||||||
}
|
|
||||||
if oldConfig.RequestRetry != newConfig.RequestRetry {
|
|
||||||
log.Debugf(" request-retry: %d -> %d", oldConfig.RequestRetry, newConfig.RequestRetry)
|
|
||||||
}
|
|
||||||
if len(oldConfig.APIKeys) != len(newConfig.APIKeys) {
|
|
||||||
log.Debugf(" api-keys count: %d -> %d", len(oldConfig.APIKeys), len(newConfig.APIKeys))
|
|
||||||
}
|
|
||||||
if len(oldConfig.GlAPIKey) != len(newConfig.GlAPIKey) {
|
|
||||||
log.Debugf(" generative-language-api-key count: %d -> %d", len(oldConfig.GlAPIKey), len(newConfig.GlAPIKey))
|
|
||||||
}
|
|
||||||
if len(oldConfig.ClaudeKey) != len(newConfig.ClaudeKey) {
|
|
||||||
log.Debugf(" claude-api-key count: %d -> %d", len(oldConfig.ClaudeKey), len(newConfig.ClaudeKey))
|
|
||||||
}
|
|
||||||
if len(oldConfig.CodexKey) != len(newConfig.CodexKey) {
|
|
||||||
log.Debugf(" codex-api-key count: %d -> %d", len(oldConfig.CodexKey), len(newConfig.CodexKey))
|
|
||||||
}
|
|
||||||
if oldConfig.RemoteManagement.AllowRemote != newConfig.RemoteManagement.AllowRemote {
|
|
||||||
log.Debugf(" remote-management.allow-remote: %t -> %t", oldConfig.RemoteManagement.AllowRemote, newConfig.RemoteManagement.AllowRemote)
|
|
||||||
}
|
|
||||||
if oldConfig.RemoteManagement.SecretKey != newConfig.RemoteManagement.SecretKey {
|
|
||||||
switch {
|
|
||||||
case oldConfig.RemoteManagement.SecretKey == "" && newConfig.RemoteManagement.SecretKey != "":
|
|
||||||
log.Debug(" remote-management.secret-key: created")
|
|
||||||
case oldConfig.RemoteManagement.SecretKey != "" && newConfig.RemoteManagement.SecretKey == "":
|
|
||||||
log.Debug(" remote-management.secret-key: deleted")
|
|
||||||
default:
|
|
||||||
log.Debug(" remote-management.secret-key: updated")
|
|
||||||
}
|
|
||||||
if newConfig.RemoteManagement.SecretKey == "" {
|
|
||||||
log.Info("management routes will be disabled after secret key removal")
|
|
||||||
} else {
|
|
||||||
log.Info("management routes will be enabled after secret key update")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if oldConfig.RemoteManagement.DisableControlPanel != newConfig.RemoteManagement.DisableControlPanel {
|
|
||||||
log.Debugf(" remote-management.disable-control-panel: %t -> %t", oldConfig.RemoteManagement.DisableControlPanel, newConfig.RemoteManagement.DisableControlPanel)
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
if changes := diffOpenAICompatibility(oldConfig.OpenAICompatibility, newConfig.OpenAICompatibility); len(changes) > 0 {
|
|
||||||
log.Debugf(" openai-compatibility:")
|
|
||||||
for _, change := range changes {
|
|
||||||
log.Debugf(" %s", change)
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log.Debugf("no material config field changes detected")
|
||||||
}
|
}
|
||||||
if oldConfig.QuotaExceeded.SwitchProject != newConfig.QuotaExceeded.SwitchProject {
|
if oldConfig.QuotaExceeded.SwitchProject != newConfig.QuotaExceeded.SwitchProject {
|
||||||
log.Debugf(" quota-exceeded.switch-project: %t -> %t", oldConfig.QuotaExceeded.SwitchProject, newConfig.QuotaExceeded.SwitchProject)
|
log.Debugf(" quota-exceeded.switch-project: %t -> %t", oldConfig.QuotaExceeded.SwitchProject, newConfig.QuotaExceeded.SwitchProject)
|
||||||
@@ -1213,3 +1158,138 @@ func openAICompatKey(entry config.OpenAICompatibility, index int) (string, strin
|
|||||||
}
|
}
|
||||||
return fmt.Sprintf("index:%d", index), fmt.Sprintf("entry-%d", index+1)
|
return fmt.Sprintf("index:%d", index), fmt.Sprintf("entry-%d", index+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// buildConfigChangeDetails computes a redacted, human-readable list of config changes.
|
||||||
|
// It avoids printing secrets (like API keys) and focuses on structural or non-sensitive fields.
|
||||||
|
func buildConfigChangeDetails(oldCfg, newCfg *config.Config) []string {
|
||||||
|
changes := make([]string, 0, 16)
|
||||||
|
if oldCfg == nil || newCfg == nil {
|
||||||
|
return changes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple scalars
|
||||||
|
if oldCfg.Port != newCfg.Port {
|
||||||
|
changes = append(changes, fmt.Sprintf("port: %d -> %d", oldCfg.Port, newCfg.Port))
|
||||||
|
}
|
||||||
|
if oldCfg.AuthDir != newCfg.AuthDir {
|
||||||
|
changes = append(changes, fmt.Sprintf("auth-dir: %s -> %s", oldCfg.AuthDir, newCfg.AuthDir))
|
||||||
|
}
|
||||||
|
if oldCfg.Debug != newCfg.Debug {
|
||||||
|
changes = append(changes, fmt.Sprintf("debug: %t -> %t", oldCfg.Debug, newCfg.Debug))
|
||||||
|
}
|
||||||
|
if oldCfg.LoggingToFile != newCfg.LoggingToFile {
|
||||||
|
changes = append(changes, fmt.Sprintf("logging-to-file: %t -> %t", oldCfg.LoggingToFile, newCfg.LoggingToFile))
|
||||||
|
}
|
||||||
|
if oldCfg.UsageStatisticsEnabled != newCfg.UsageStatisticsEnabled {
|
||||||
|
changes = append(changes, fmt.Sprintf("usage-statistics-enabled: %t -> %t", oldCfg.UsageStatisticsEnabled, newCfg.UsageStatisticsEnabled))
|
||||||
|
}
|
||||||
|
if oldCfg.RequestLog != newCfg.RequestLog {
|
||||||
|
changes = append(changes, fmt.Sprintf("request-log: %t -> %t", oldCfg.RequestLog, newCfg.RequestLog))
|
||||||
|
}
|
||||||
|
if oldCfg.RequestRetry != newCfg.RequestRetry {
|
||||||
|
changes = append(changes, fmt.Sprintf("request-retry: %d -> %d", oldCfg.RequestRetry, newCfg.RequestRetry))
|
||||||
|
}
|
||||||
|
if oldCfg.ProxyURL != newCfg.ProxyURL {
|
||||||
|
changes = append(changes, fmt.Sprintf("proxy-url: %s -> %s", oldCfg.ProxyURL, newCfg.ProxyURL))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quota-exceeded behavior
|
||||||
|
if oldCfg.QuotaExceeded.SwitchProject != newCfg.QuotaExceeded.SwitchProject {
|
||||||
|
changes = append(changes, fmt.Sprintf("quota-exceeded.switch-project: %t -> %t", oldCfg.QuotaExceeded.SwitchProject, newCfg.QuotaExceeded.SwitchProject))
|
||||||
|
}
|
||||||
|
if oldCfg.QuotaExceeded.SwitchPreviewModel != newCfg.QuotaExceeded.SwitchPreviewModel {
|
||||||
|
changes = append(changes, fmt.Sprintf("quota-exceeded.switch-preview-model: %t -> %t", oldCfg.QuotaExceeded.SwitchPreviewModel, newCfg.QuotaExceeded.SwitchPreviewModel))
|
||||||
|
}
|
||||||
|
|
||||||
|
// API keys (redacted) and counts
|
||||||
|
if len(oldCfg.APIKeys) != len(newCfg.APIKeys) {
|
||||||
|
changes = append(changes, fmt.Sprintf("api-keys count: %d -> %d", len(oldCfg.APIKeys), len(newCfg.APIKeys)))
|
||||||
|
} else if !reflect.DeepEqual(trimStrings(oldCfg.APIKeys), trimStrings(newCfg.APIKeys)) {
|
||||||
|
changes = append(changes, "api-keys: values updated (count unchanged, redacted)")
|
||||||
|
}
|
||||||
|
if len(oldCfg.GlAPIKey) != len(newCfg.GlAPIKey) {
|
||||||
|
changes = append(changes, fmt.Sprintf("generative-language-api-key count: %d -> %d", len(oldCfg.GlAPIKey), len(newCfg.GlAPIKey)))
|
||||||
|
} else if !reflect.DeepEqual(trimStrings(oldCfg.GlAPIKey), trimStrings(newCfg.GlAPIKey)) {
|
||||||
|
changes = append(changes, "generative-language-api-key: values updated (count unchanged, redacted)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claude keys (do not print key material)
|
||||||
|
if len(oldCfg.ClaudeKey) != len(newCfg.ClaudeKey) {
|
||||||
|
changes = append(changes, fmt.Sprintf("claude-api-key count: %d -> %d", len(oldCfg.ClaudeKey), len(newCfg.ClaudeKey)))
|
||||||
|
} else {
|
||||||
|
for i := range oldCfg.ClaudeKey {
|
||||||
|
if i >= len(newCfg.ClaudeKey) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
o := oldCfg.ClaudeKey[i]
|
||||||
|
n := newCfg.ClaudeKey[i]
|
||||||
|
if strings.TrimSpace(o.BaseURL) != strings.TrimSpace(n.BaseURL) {
|
||||||
|
changes = append(changes, fmt.Sprintf("claude[%d].base-url: %s -> %s", i, strings.TrimSpace(o.BaseURL), strings.TrimSpace(n.BaseURL)))
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(o.ProxyURL) != strings.TrimSpace(n.ProxyURL) {
|
||||||
|
changes = append(changes, fmt.Sprintf("claude[%d].proxy-url: %s -> %s", i, strings.TrimSpace(o.ProxyURL), strings.TrimSpace(n.ProxyURL)))
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(o.APIKey) != strings.TrimSpace(n.APIKey) {
|
||||||
|
changes = append(changes, fmt.Sprintf("claude[%d].api-key: updated", i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Codex keys (do not print key material)
|
||||||
|
if len(oldCfg.CodexKey) != len(newCfg.CodexKey) {
|
||||||
|
changes = append(changes, fmt.Sprintf("codex-api-key count: %d -> %d", len(oldCfg.CodexKey), len(newCfg.CodexKey)))
|
||||||
|
} else {
|
||||||
|
for i := range oldCfg.CodexKey {
|
||||||
|
if i >= len(newCfg.CodexKey) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
o := oldCfg.CodexKey[i]
|
||||||
|
n := newCfg.CodexKey[i]
|
||||||
|
if strings.TrimSpace(o.BaseURL) != strings.TrimSpace(n.BaseURL) {
|
||||||
|
changes = append(changes, fmt.Sprintf("codex[%d].base-url: %s -> %s", i, strings.TrimSpace(o.BaseURL), strings.TrimSpace(n.BaseURL)))
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(o.ProxyURL) != strings.TrimSpace(n.ProxyURL) {
|
||||||
|
changes = append(changes, fmt.Sprintf("codex[%d].proxy-url: %s -> %s", i, strings.TrimSpace(o.ProxyURL), strings.TrimSpace(n.ProxyURL)))
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(o.APIKey) != strings.TrimSpace(n.APIKey) {
|
||||||
|
changes = append(changes, fmt.Sprintf("codex[%d].api-key: updated", i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remote management (never print the key)
|
||||||
|
if oldCfg.RemoteManagement.AllowRemote != newCfg.RemoteManagement.AllowRemote {
|
||||||
|
changes = append(changes, fmt.Sprintf("remote-management.allow-remote: %t -> %t", oldCfg.RemoteManagement.AllowRemote, newCfg.RemoteManagement.AllowRemote))
|
||||||
|
}
|
||||||
|
if oldCfg.RemoteManagement.DisableControlPanel != newCfg.RemoteManagement.DisableControlPanel {
|
||||||
|
changes = append(changes, fmt.Sprintf("remote-management.disable-control-panel: %t -> %t", oldCfg.RemoteManagement.DisableControlPanel, newCfg.RemoteManagement.DisableControlPanel))
|
||||||
|
}
|
||||||
|
if oldCfg.RemoteManagement.SecretKey != newCfg.RemoteManagement.SecretKey {
|
||||||
|
switch {
|
||||||
|
case oldCfg.RemoteManagement.SecretKey == "" && newCfg.RemoteManagement.SecretKey != "":
|
||||||
|
changes = append(changes, "remote-management.secret-key: created")
|
||||||
|
case oldCfg.RemoteManagement.SecretKey != "" && newCfg.RemoteManagement.SecretKey == "":
|
||||||
|
changes = append(changes, "remote-management.secret-key: deleted")
|
||||||
|
default:
|
||||||
|
changes = append(changes, "remote-management.secret-key: updated")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenAI compatibility providers (summarized)
|
||||||
|
if compat := diffOpenAICompatibility(oldCfg.OpenAICompatibility, newCfg.OpenAICompatibility); len(compat) > 0 {
|
||||||
|
changes = append(changes, "openai-compatibility:")
|
||||||
|
for _, c := range compat {
|
||||||
|
changes = append(changes, " "+c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes
|
||||||
|
}
|
||||||
|
|
||||||
|
func trimStrings(in []string) []string {
|
||||||
|
out := make([]string, len(in))
|
||||||
|
for i := range in {
|
||||||
|
out[i] = strings.TrimSpace(in[i])
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user