| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- package config
- import (
- "fmt"
- "os"
- "path/filepath"
- "github.com/pelletier/go-toml/v2"
- "go.uber.org/zap/zapcore"
- )
- // AppConfig 应用配置结构
- type AppConfig struct {
- Server ServerConfig `toml:"server"`
- Log LogConfig `toml:"log"`
- Audit AuditConfig `toml:"audit"`
- Storage StorageConfig `toml:"storage"`
- }
- // ServerConfig 服务器配置
- type ServerConfig struct {
- Ip string `toml:"ip"`
- Port int `toml:"port"`
- }
- // LogConfig 日志配置
- type LogConfig struct {
- Level string `toml:"level"` // 日志级别: debug, info, warn, error, fatal
- Development bool `toml:"development"` // 开发模式
- Encoding string `toml:"encoding"` // 编码格式: json, console
- OutputPaths []string `toml:"output_paths"` // 输出路径
- LogDir string `toml:"log_dir"` // 日志目录
- }
- // AuditConfig 审计配置
- type AuditConfig struct {
- Enabled bool `toml:"enabled"` // 是否启用审计
- DatabasePath string `toml:"database_path"` // 数据库路径
- RetentionDays int `toml:"retention_days"` // 保留天数
- BufferSize int `toml:"buffer_size"` // 缓冲区大小
- }
- // StorageConfig 存储配置
- type StorageConfig struct {
- // 存储类型: "file" 或 "db"
- Type string `toml:"type"`
- // 文件存储配置
- ConfigPath string `toml:"config_path"` // 配置文件路径 (用于文件存储)
- SQLBaseDir string `toml:"sql_base_dir"` // 脚本(Script)基础目录 (用于文件存储)
- // 数据库存储配置
- DatabasePath string `toml:"database_path"` // 数据库文件路径 (用于数据库存储)
- // 通用配置
- DataFile string `toml:"data_file"` // 数据文件路径 (向后兼容)
- }
- // LoadConfig 加载配置文件
- func LoadConfig(path string) (*AppConfig, error) {
- // 检查文件是否存在
- if _, err := os.Stat(path); os.IsNotExist(err) {
- // 如果配置文件不存在,创建默认配置
- if err := CreateDefaultConfig(path); err != nil {
- return nil, fmt.Errorf("创建默认配置文件失败: %w", err)
- }
- }
- // 使用 os.ReadFile (Go 1.16+)
- data, err := os.ReadFile(path)
- if err != nil {
- return nil, err
- }
- var cfg AppConfig
- if err := toml.Unmarshal(data, &cfg); err != nil {
- return nil, err
- }
- return &cfg, nil
- }
- // CreateDefaultConfig 创建默认配置文件
- func CreateDefaultConfig(configPath string) error {
- // 创建默认配置
- defaultConfig := &AppConfig{
- Server: ServerConfig{
- Ip: "127.0.0.1",
- Port: 8080,
- },
- Log: LogConfig{
- Level: "info",
- Development: false,
- Encoding: "json",
- OutputPaths: []string{"stdout", "app.log"},
- LogDir: "./DBconfig/logs",
- },
- Audit: AuditConfig{
- Enabled: true,
- DatabasePath: "./DBconfig/audit.db",
- RetentionDays: 90,
- BufferSize: 1000,
- },
- Storage: StorageConfig{
- Type: "db",
- ConfigPath: "./DBconfig/data.toml",
- SQLBaseDir: "./DBconfig/sqlfiles",
- DatabasePath: "./DBconfig/storage.db",
- DataFile: "./DBconfig/data.toml",
- },
- }
- // 确保配置目录存在
- configDir := filepath.Dir(configPath)
- if err := os.MkdirAll(configDir, 0755); err != nil {
- return fmt.Errorf("创建配置目录失败: %w", err)
- }
- // 创建必要的目录
- if err := defaultConfig.CreateDirectories(); err != nil {
- return fmt.Errorf("创建必要目录失败: %w", err)
- }
- // 将配置序列化为TOML格式
- data, err := toml.Marshal(defaultConfig)
- if err != nil {
- return fmt.Errorf("序列化配置失败: %w", err)
- }
- // 写入配置文件
- if err := os.WriteFile(configPath, data, 0644); err != nil {
- return fmt.Errorf("写入配置文件失败: %w", err)
- }
- return nil
- }
- // LoadConfigFromFile 从文件句柄加载配置
- func LoadConfigFromFile(file *os.File) (*AppConfig, error) {
- var cfg AppConfig
- if err := toml.NewDecoder(file).Decode(&cfg); err != nil {
- return nil, err
- }
- return &cfg, nil
- }
- // SetDefaults 设置默认值
- func (cfg *AppConfig) SetDefaults() {
- // 服务器默认值
- if cfg.Server.Port == 0 {
- cfg.Server.Port = 8080
- }
- // 日志默认值
- if cfg.Log.Level == "" {
- cfg.Log.Level = "info"
- }
- if cfg.Log.Encoding == "" {
- cfg.Log.Encoding = "json"
- }
- if len(cfg.Log.OutputPaths) == 0 {
- cfg.Log.OutputPaths = []string{"stdout"}
- }
- if cfg.Log.LogDir == "" {
- cfg.Log.LogDir = "./DBconfig/logs"
- }
- // 审计默认值
- if cfg.Audit.DatabasePath == "" {
- cfg.Audit.DatabasePath = "./DBconfig/audit.db"
- }
- if cfg.Audit.RetentionDays == 0 {
- cfg.Audit.RetentionDays = 90
- }
- if cfg.Audit.BufferSize == 0 {
- cfg.Audit.BufferSize = 1000
- }
- // 注意:Audit.Enabled 默认为 false,需要明确启用
- // 存储默认值
- if cfg.Storage.Type == "" {
- cfg.Storage.Type = "db" // 默认使用数据库存储
- }
- if cfg.Storage.ConfigPath == "" {
- cfg.Storage.ConfigPath = "./DBconfig/data.toml"
- }
- if cfg.Storage.SQLBaseDir == "" {
- cfg.Storage.SQLBaseDir = "./DBconfig/sqlfiles"
- }
- if cfg.Storage.DatabasePath == "" {
- cfg.Storage.DatabasePath = "./DBconfig/storage.db"
- }
- if cfg.Storage.DataFile == "" {
- cfg.Storage.DataFile = "./DBconfig/data.toml" // 向后兼容
- }
- }
- // GetLogLevel 将字符串日志级别转换为 zapcore.Level
- func (lc *LogConfig) GetLogLevel() zapcore.Level {
- switch lc.Level {
- case "debug":
- return zapcore.DebugLevel
- case "info":
- return zapcore.InfoLevel
- case "warn", "warning":
- return zapcore.WarnLevel
- case "error":
- return zapcore.ErrorLevel
- case "fatal":
- return zapcore.FatalLevel
- default:
- return zapcore.InfoLevel
- }
- }
- // GetOutputPaths 获取完整的输出路径列表
- func (lc *LogConfig) GetOutputPaths() []string {
- paths := make([]string, 0, len(lc.OutputPaths))
- for _, path := range lc.OutputPaths {
- if path == "stdout" {
- paths = append(paths, "stdout")
- } else if path == "stderr" {
- paths = append(paths, "stderr")
- } else {
- // 如果是相对路径,转换为绝对路径
- if !filepath.IsAbs(path) {
- absPath := filepath.Join(lc.LogDir, path)
- paths = append(paths, absPath)
- } else {
- paths = append(paths, path)
- }
- }
- }
- return paths
- }
- // Validate 验证配置的有效性
- func (cfg *AppConfig) Validate() error {
- // 验证服务器配置
- if cfg.Server.Port <= 0 || cfg.Server.Port > 65535 {
- return fmt.Errorf("invalid server port: %d", cfg.Server.Port)
- }
- // 验证日志配置
- validLevels := map[string]bool{
- "debug": true, "info": true, "warn": true, "warning": true,
- "error": true, "fatal": true,
- }
- if !validLevels[cfg.Log.Level] {
- return fmt.Errorf("invalid log level: %s", cfg.Log.Level)
- }
- validEncodings := map[string]bool{
- "json": true, "console": true,
- }
- if !validEncodings[cfg.Log.Encoding] {
- return fmt.Errorf("invalid log encoding: %s", cfg.Log.Encoding)
- }
- // 验证审计配置
- if cfg.Audit.RetentionDays < 0 {
- return fmt.Errorf("invalid audit retention days: %d", cfg.Audit.RetentionDays)
- }
- if cfg.Audit.BufferSize < 0 {
- return fmt.Errorf("invalid audit buffer size: %d", cfg.Audit.BufferSize)
- }
- // 验证存储配置
- validStorageTypes := map[string]bool{
- "file": true, "db": true,
- }
- if !validStorageTypes[cfg.Storage.Type] {
- return fmt.Errorf("invalid storage type: %s", cfg.Storage.Type)
- }
- return nil
- }
- // CreateDirectories 创建必要的目录
- func (cfg *AppConfig) CreateDirectories() error {
- dirs := []string{
- cfg.Log.LogDir,
- filepath.Dir(cfg.Audit.DatabasePath),
- cfg.Storage.SQLBaseDir,
- filepath.Dir(cfg.Storage.DataFile),
- }
- // 根据存储类型添加额外的目录
- if cfg.Storage.Type == "db" {
- dirs = append(dirs, filepath.Dir(cfg.Storage.DatabasePath))
- }
- for _, dir := range dirs {
- if dir == "" {
- continue
- }
- if err := os.MkdirAll(dir, 0755); err != nil {
- return fmt.Errorf("failed to create directory %s: %w", dir, err)
- }
- }
- return nil
- }
- // GetStorageManager 根据配置创建存储管理器
- func (sc *StorageConfig) GetStorageManager() (interface{}, error) {
- switch sc.Type {
- case "file":
- // 这里需要导入storage包,但为了避免循环依赖,我们返回配置信息
- return map[string]string{
- "type": "file",
- "config_path": sc.ConfigPath,
- "sql_base_dir": sc.SQLBaseDir,
- }, nil
- case "db":
- return map[string]string{
- "type": "db",
- "database_path": sc.DatabasePath,
- }, nil
- default:
- return nil, fmt.Errorf("unsupported storage type: %s", sc.Type)
- }
- }
- // IsFileStorage 是否使用文件存储
- func (sc *StorageConfig) IsFileStorage() bool {
- return sc.Type == "file"
- }
- // IsDBStorage 是否使用数据库存储
- func (sc *StorageConfig) IsDBStorage() bool {
- return sc.Type == "db"
- }
|