From 651ed6ea86ac228183ee826f6afc540883accfdc Mon Sep 17 00:00:00 2001 From: HuKeping Date: Sat, 14 May 2016 17:43:15 +0800 Subject: [PATCH] [PATCH 4/8] Feature: hot increment/decrement logging level for notary server This patch will allow people to: - use SIGUSR1 to increment the logging level - use SIGUSR2 to decrement the logging level And it will allow the logging level to be turned up or down as much as desired by sending the appropriate signal multiple times. Signed-off-by: Hu Keping --- cmd/notary-server/config.go | 38 +++++++++++++++++++++++++++++++++++++ cmd/notary-server/main.go | 7 +++++++ utils/configuration.go | 28 +++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/cmd/notary-server/config.go b/cmd/notary-server/config.go index 0177be6a36..2845ec5204 100644 --- a/cmd/notary-server/config.go +++ b/cmd/notary-server/config.go @@ -6,6 +6,9 @@ import ( "path" "strconv" "strings" + "os" + "os/signal" + "syscall" "time" "github.com/Sirupsen/logrus" @@ -225,6 +228,7 @@ func parseServerConfig(configFilePath string, hRegister healthRegister) (context } ctx := context.Background() + ctx = context.WithValue(ctx, "config", config) // default is error level lvl, err := utils.ParseLogLevel(config, logrus.ErrorLevel) @@ -278,3 +282,37 @@ func parseServerConfig(configFilePath string, hRegister healthRegister) (context ConsistentCacheControlConfig: consistentCache, }, nil } + +func setupConfigReloadTrap(oldConfig *viper.Viper, configFile string, envPrefix string) { + c := make(chan os.Signal, 1) + signal.Notify(c, notary.NotarySupportedSignals...) + go func() { + for { + reloadConfig(<-c, configFile, oldConfig, envPrefix) + } + }() +} + +// reloadConfig was designed to do all the dirty work that needed to reload +// the config for notary-server and make the entrance-ReloadConfiguration() +// for hot configuration reload do some generic things. +func reloadConfig(sig os.Signal, configFile string, oldConfig *viper.Viper, envPrefix string) { + reload := func(config *viper.Viper) { + switch sig { + case syscall.SIGUSR1: + if err := utils.AdjustLogLevel(true); err != nil { + fmt.Println("Increase log level failed, will use the old one, error: ", err) + return + } + case syscall.SIGUSR2: + if err := utils.AdjustLogLevel(false); err != nil { + fmt.Println("Decrease log level failed, will use the old one, error: ", err) + return + } + } + + fmt.Println("Successfully setting log level to ", logrus.GetLevel()) + } + + utils.ReloadConfiguration(oldConfig, configFile, envPrefix, reload) +} diff --git a/cmd/notary-server/main.go b/cmd/notary-server/main.go index 62042e4df9..6f7cc22ae9 100644 --- a/cmd/notary-server/main.go +++ b/cmd/notary-server/main.go @@ -12,6 +12,7 @@ import ( "github.com/docker/distribution/health" "github.com/docker/notary/server" "github.com/docker/notary/version" + "github.com/spf13/viper" ) // DebugAddress is the debug server address to listen on @@ -57,6 +58,12 @@ func main() { logrus.Fatal(err.Error()) } + config, ok := ctx.Value("config").(*viper.Viper) + if !ok { + logrus.Fatalf("parse config failed") + } + setupConfigReloadTrap(config, configFile, envPrefix) + if doBootstrap { err = bootstrap(ctx) } else { diff --git a/utils/configuration.go b/utils/configuration.go index f94b73a270..a59d536439 100644 --- a/utils/configuration.go +++ b/utils/configuration.go @@ -244,3 +244,31 @@ func AdjustLogLevel(increment bool) error { logrus.SetLevel(lvl) return nil } + +// ReloadConfiguration reads and parse the configuration in the host and do some verification. +func ReloadConfiguration(oldConfig *viper.Viper, configFile string, envPrefix string, reload func(*viper.Viper)) error { + logrus.Infof("Got signal to reload configuration, reloading from: %s", configFile) + + // parse a viper as the new Config + newConfig := viper.New() + SetupViper(newConfig, envPrefix) + if err := ParseViper(newConfig, configFile); err != nil { + return err + } + + // To check if there was anything wrong + if err := validateConfiguration(oldConfig, newConfig); err != nil { + return err + } + + reload(newConfig) + return nil +} + +// Reserved for future use, we can use it to validate some specific configs when necessary. +// For example: +// - to check if there are conflicts. +// - to do some sanity check maybe. +func validateConfiguration(oldConfig, newConfig *viper.Viper) error { + return nil +}