feat(server): implement management endpoints and redis sync

Enable full resource management via API and support data plane
synchronization.

- Add CRUD handlers for Providers, Models, and Keys using DTOs
- Implement LogWriter service for asynchronous, batched audit logging
- Update SyncService to snapshot full configuration state to Redis
- Register new API routes and initialize background services
- Add configuration options for logging performance tuning
This commit is contained in:
zenfun
2025-12-02 14:26:16 +08:00
parent 2c3a6af7bf
commit 64d71953a6
10 changed files with 479 additions and 40 deletions

22
internal/model/log.go Normal file
View File

@@ -0,0 +1,22 @@
package model
import "gorm.io/gorm"
// LogRecord stores lightweight metadata for auditing. Avoids full payload unless audit is triggered.
type LogRecord struct {
gorm.Model
Group string `json:"group"`
KeyID uint `json:"key_id"`
ModelName string `json:"model"`
StatusCode int `json:"status_code"`
LatencyMs int64 `json:"latency_ms"`
TokensIn int64 `json:"tokens_in"`
TokensOut int64 `json:"tokens_out"`
ErrorMessage string `json:"error_message"`
ClientIP string `json:"client_ip"`
RequestSize int64 `json:"request_size"`
ResponseSize int64 `json:"response_size"`
AuditReason string `json:"audit_reason"`
RequestBody string `json:"request_body"` // optional, only when audit triggered
ResponseBody string `json:"response_body"` // optional, only when audit triggered
}

View File

@@ -6,32 +6,37 @@ import (
type User struct {
gorm.Model
Username string `gorm:"uniqueIndex;not null"`
Quota int64 `gorm:"default:0"`
Role string `gorm:"default:'user'"` // admin, user
Username string `gorm:"uniqueIndex;not null" json:"username"`
Quota int64 `gorm:"default:0" json:"quota"`
Role string `gorm:"default:'user'" json:"role"` // admin, user
}
type Provider struct {
gorm.Model
Name string `gorm:"not null"`
Type string `gorm:"not null"` // openai, anthropic, etc.
BaseURL string
APIKey string
Name string `gorm:"not null" json:"name"`
Type string `gorm:"not null" json:"type"` // openai, anthropic, etc.
BaseURL string `json:"base_url"`
APIKey string `json:"api_key"`
}
type Key struct {
gorm.Model
ProviderID *uint
Provider *Provider
KeySecret string `gorm:"not null"`
Balance float64
Status string `gorm:"default:'active'"` // active, suspended
Weight int `gorm:"default:10"`
ProviderID *uint `json:"provider_id"`
Provider *Provider `json:"-"`
KeySecret string `gorm:"not null" json:"key_secret"`
Balance float64 `json:"balance"`
Status string `gorm:"default:'active'" json:"status"` // active, suspended
Weight int `gorm:"default:10" json:"weight"`
}
type Model struct {
gorm.Model
Name string `gorm:"uniqueIndex;not null"`
ContextWindow int
CostPerToken float64
Name string `gorm:"uniqueIndex;not null" json:"name"`
ContextWindow int `json:"context_window"`
CostPerToken float64 `json:"cost_per_token"`
SupportsVision bool `json:"supports_vision"`
SupportsFunctions bool `json:"supports_functions"`
SupportsToolChoice bool `json:"supports_tool_choice"`
SupportsFIM bool `json:"supports_fim"`
MaxOutputTokens int `json:"max_output_tokens"`
}