config.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package config
  2. import (
  3. "fmt"
  4. "github.com/coroot/coroot-node-agent/utils"
  5. "strings"
  6. "sync"
  7. klog "github.com/sirupsen/logrus"
  8. "github.com/spf13/viper"
  9. "github.com/coroot/coroot-node-agent/flags"
  10. )
  11. var (
  12. configOnce sync.Once
  13. configInstance *viper.Viper // 运行时配置(用于读取)
  14. configMutex sync.RWMutex
  15. cmdLineFlagsSet map[string]bool // 记录通过命令行参数设置的配置项
  16. cmdLineFlagsSetOnce sync.Once
  17. )
  18. // InitConfig 初始化 Viper 配置
  19. func InitConfig(configPath string) error {
  20. var err error
  21. configOnce.Do(func() {
  22. v := viper.New()
  23. // 设置配置文件路径
  24. if configPath != "" {
  25. v.SetConfigFile(configPath)
  26. } else {
  27. v.SetConfigFile(utils.GetDefaultConfigPath())
  28. }
  29. // 设置环境变量前缀和键替换规则
  30. v.SetEnvPrefix("EUSPACE")
  31. // 设置环境变量键替换规则:将点号替换为下划线
  32. v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
  33. v.AutomaticEnv()
  34. // 读取配置文件
  35. // 注意:配置文件读取失败(不存在、格式错误、权限问题等)都不是致命错误
  36. // 程序会继续启动,使用默认值、命令行参数和环境变量
  37. if err = v.ReadInConfig(); err != nil {
  38. // 所有配置文件读取错误都视为非致命错误,只记录警告
  39. if _, ok := err.(viper.ConfigFileNotFoundError); ok {
  40. klog.Warnf("⚠️ [CONFIG] Config file not found, using defaults: %v", err)
  41. } else {
  42. klog.Warnf("⚠️ [CONFIG] Error reading config file (will use defaults): %v", err)
  43. }
  44. err = nil // 不返回错误,允许程序继续启动
  45. } else {
  46. actualConfigFile := v.ConfigFileUsed()
  47. klog.Infof("✓ [CONFIG] Using config file: %s", actualConfigFile)
  48. // 启动配置文件轮询监听
  49. startConfigFileWatcher(actualConfigFile, v)
  50. }
  51. // 监控 common.ini 文件(如果 RunInOmniagent 为 true)
  52. // 注意:RunInOmniagent 是启动时确定的标志,不支持热更新
  53. // 只有在启动时 RunInOmniagent 为 true 时,才会启动此监控
  54. if *flags.RunInOmniagent && *flags.CommonIni != "" {
  55. watchCommonIni(*flags.CommonIni)
  56. }
  57. configInstance = v
  58. // 初始化 Config 管理器
  59. cfg := Get()
  60. cfg.Init(v)
  61. // 应用初始配置(首次加载,可以覆盖默认值)
  62. // 注意:现在通过 Config 管理器统一处理,applyConfig 主要用于向后兼容
  63. applyConfig(v, false)
  64. })
  65. return err
  66. }
  67. // GetConfig 获取配置实例
  68. func GetConfig() *viper.Viper {
  69. if configInstance == nil {
  70. // 如果未初始化,使用默认配置
  71. InitConfig("")
  72. }
  73. return configInstance
  74. }
  75. // ReloadConfig 手动重新加载配置
  76. func ReloadConfig() error {
  77. configMutex.Lock()
  78. defer configMutex.Unlock()
  79. if configInstance == nil {
  80. return fmt.Errorf("config not initialized")
  81. }
  82. if err := configInstance.ReadInConfig(); err != nil {
  83. return fmt.Errorf("error reading config file: %w", err)
  84. }
  85. applyConfig(configInstance, false)
  86. return nil
  87. }
  88. // GetConfigValue 获取配置值(支持热加载)
  89. func GetConfigValue(key string) interface{} {
  90. configMutex.RLock()
  91. defer configMutex.RUnlock()
  92. if configInstance == nil {
  93. return nil
  94. }
  95. return configInstance.Get(key)
  96. }