【问题标题】:How to change value in config file doesnt provide the value如何更改配置文件中的值不提供值
【发布时间】: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


【解决方案1】:

据我所知,您的代码没有任何问题,因为fsnotify 确实触发了。所以罪魁祸首必须在解析中。在 onConfigChange 回调之外对 setLogLevel(c.GetLogLevel()) 的第一次调用会返回不正确的值。将 yaml 文件的内容更改为只是

log: 'level'

一切都应该按预期工作。

logrus 包支持以下级别(截至撰写本文时):PanicFatalErrorWarnInfoDebugTrace。对应的方法有:logrus.Panic()logrus.Fatal()logrus.Warn()logrus.Info()logrus.Debug()logrus.Trace()

例如,如果当前级别设置为Warn,则调用logrus.Warn("boo!") 应输出boo!。但是,调用 logrus.Info("boo!") 不会显示任何内容。

【讨论】:

  • 对不起,我错过了你的意思:),日志级别将如何更改?我希望当我将值从config.yaml: 'log: debug' 更改为config.yaml: 'log: error' 时,它会将日志输出从debug 更改为error,我怎样才能通过您的建议来实现?
  • 我说的是 config.yaml 文件本身及其内容。而不是整整两行data:\nconfig.yaml: 'log: debug',只写我发布的log: 'level',其中级别是你想要的:infodebugwarn 等。
  • 谢谢! Tom 1+,请查看我的更新,我仍然看到 warn 的所有内容,并且没有根据日志级别进行更改,任何想法都在手表内部更新日志级别
  • 那是因为setLogLevel 函数中的这一行:logrus.WithField("level", logLevel).Warn("setting log level")。您在warn 级别打印该行。将您的配置选项更改为级别error,所有这些消息都会消失。在内部,logrus 的 print 测试请求的日志级别 logrus.WithField().Warn() 是否小于或等于 logrus.SetLevel() 设置的级别,如果是则打印。
  • 嗨,请看看你是否也可以在这里提供帮助,这是类似的问题,但现在在 K8S 上:) stackoverflow.com/questions/57936885/…,谢谢!
猜你喜欢
  • 2015-01-23
  • 2018-03-15
  • 1970-01-01
  • 2011-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-22
相关资源
最近更新 更多