【发布时间】:2019-09-09 20:55:09
【问题描述】:
我想在环境变量/配置属性值更改时进行观察
我发现 viper 应该支持这种情况但不能
让它工作。
我看到 OnConfigChange 被调用,但是来自 config
更改时不会从配置中获取。配置加载成功
我创建了一个示例来演示该问题。
文件cfg.go
go/src/myproj/configuration/cfg.go
package configuration
import (
"fmt"
"os"
"strings"
"github.com/fsnotify/fsnotify"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
const (
varLogLevel = "log"
varPathToConfig = "config.file"
)
type Configuration struct {
v *viper.Viper
}
func New() *Configuration {
c := Configuration{
v: viper.New(),
}
c.v.SetDefault(varPathToConfig, "./config.yaml")
c.v.SetDefault(varLogLevel, "info")
c.v.AutomaticEnv()
c.v.SetConfigFile(c.GetPathToConfig())
err := c.v.ReadInConfig() // Find and read the config file
logrus.WithField("path", c.GetPathToConfig()).Warn("loading config")
// just use the default value(s) if the config file was not found
if _, ok := err.(*os.PathError); ok {
logrus.Warnf("no config file '%s' not found. Using default values", c.GetPathToConfig())
} else if err != nil { // Handle other errors that occurred while reading the config file
panic(fmt.Errorf("fatal error while reading the config file: %s", err))
}
setLogLevel(c.GetLogLevel())
// monitor the changes in the config file
c.v.WatchConfig()
c.v.OnConfigChange(func(e fsnotify.Event) {
logrus.WithField("file", e.Name).Warn("Config file changed")
setLogLevel(c.GetLogLevel())
})
return &c
}
// GetLogLevel returns the log level
func (c *Configuration) GetLogLevel() string {
s := c.v.GetString(varLogLevel)
return s
}
// GetPathToConfig returns the path to the config file
func (c *Configuration) GetPathToConfig() string {
return c.v.GetString(varPathToConfig)
}
func setLogLevel(logLevel string) {
logrus.WithField("level", logLevel).Warn("setting log level")
level, err := logrus.ParseLevel(logLevel)
if err != nil {
logrus.WithField("level", logLevel).Fatalf("failed to start: %s", err.Error())
}
logrus.SetLevel(level)
}
我创建了一些示例 Web 应用程序服务器来使程序在后台运行 (能够更改配置并查看wheatear 发生了什么变化)
go/src/myproj
package main
import (
"fmt"
"net/http"
"myproj/configuration"
)
func main() {
cfg := configuration.New()
fmt.Println(cfg)
http.HandleFunc("/", HelloServer)
http.ListenAndServe(":8080", nil)
}
func HelloServer(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}
问题是函数GetLogLevel() 带来了旧值而不是从配置中读取值?
这是 config-file 的示例(我把它放在根项目文件夹下的 main.go 文件的同级文件中
这是项目结构
go/src/myproj
- main.go
- configuration #folder
-- cfg.go
- config.yaml
data:
config.yaml: 'log: debug'
当我将其从 info 更改为 debug(或其他选项)时,我看到事件 watch 已引发但
它不获取新值(如调试)。有什么想法吗?
更新
当我像@Tom 建议的那样更改配置文件时,我能够看到日志已更改但级别未更改,它保持在warn
这是日志,我仍然看到警告
WARN[0000] loading config path=./config.yaml
WARN[0000] setting log level fields.level=info
&{0xc00012e300}
WARN[0008] Config file changed file=config.yaml
WARN[0008] setting log level fields.level=error
WARN[0020] Config file changed file=config.yaml
WARN[0020] setting log level fields.level=debug
WARN[0060] Config file changed file=config.yaml
WARN[0060] setting log level fields.level=warn
【问题讨论】:
-
“我想在环境变量值发生变化时做一些观察”——这在程序运行时永远不会发生,除非你的程序自己改变它。
-
@Flimzy - 目前我想检查配置是否已更改(这正在工作,事件已引发)但
new值(已在 conifgfile 中更改)没有反映,有什么想法吗? -
@JennyM
viper_env/configuration来自哪里? -
@TomTrebicky - 应该是
myproj,我已经更新了帖子,谢谢。它引用第一个文件
标签: go