From 871d097b30ac2adc581f650c74e7e6faee1a4f60 Mon Sep 17 00:00:00 2001 From: Marco Jantke Date: Wed, 11 Oct 2017 10:38:03 +0200 Subject: [PATCH] Fix traefik logs to behave like configured --- cmd/traefik/traefik.go | 128 ++++++++++++++-------------- configuration/configuration.go | 12 ++- configuration/configuration_test.go | 46 +++++++++- provider/web/web.go | 2 +- server/server.go | 2 +- 5 files changed, 121 insertions(+), 69 deletions(-) diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index 1ce892af5..3b3e704f4 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -45,19 +45,7 @@ Complete documentation is available at https://traefik.io`, Config: traefikConfiguration, DefaultPointersConfig: traefikPointersConfiguration, Run: func() error { - globalConfiguration := traefikConfiguration.GlobalConfiguration - if globalConfiguration.File != nil && len(globalConfiguration.File.Filename) == 0 { - // no filename, setting to global config file - if len(traefikConfiguration.ConfigFile) != 0 { - globalConfiguration.File.Filename = traefikConfiguration.ConfigFile - } else { - log.Errorln("Error using file configuration backend, no filename defined") - } - } - if len(traefikConfiguration.ConfigFile) != 0 { - log.Infof("Using TOML configuration file %s", traefikConfiguration.ConfigFile) - } - run(&globalConfiguration) + run(&traefikConfiguration.GlobalConfiguration, traefikConfiguration.ConfigFile) return nil }, } @@ -222,58 +210,16 @@ Complete documentation is available at https://traefik.io`, os.Exit(0) } -func run(globalConfiguration *configuration.GlobalConfiguration) { - fmtlog.SetFlags(fmtlog.Lshortfile | fmtlog.LstdFlags) +func run(globalConfiguration *configuration.GlobalConfiguration, configFile string) { + configureLogging(globalConfiguration) + + if len(configFile) > 0 { + log.Infof("Using TOML configuration file %s", configFile) + } http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment - globalConfiguration.SetEffectiveConfiguration() - - // logging - level, err := logrus.ParseLevel(strings.ToLower(globalConfiguration.LogLevel)) - if err != nil { - log.Error("Error getting level", err) - } - log.SetLevel(level) - - logFile := globalConfiguration.TraefikLogsFile - if len(logFile) > 0 { - log.Warn("top-level traefiklogsfile has been deprecated -- please use traefiklog.filepath") - } - if globalConfiguration.TraefikLog != nil && len(globalConfiguration.TraefikLog.FilePath) > 0 { - logFile = globalConfiguration.TraefikLog.FilePath - } - - var formatter logrus.Formatter - if globalConfiguration.TraefikLog != nil && globalConfiguration.TraefikLog.Format == "json" { - formatter = &logrus.JSONFormatter{} - } else { - disableColors := false - if len(logFile) > 0 { - disableColors = true - } - formatter = &logrus.TextFormatter{DisableColors: disableColors, FullTimestamp: true, DisableSorting: true} - } - log.SetFormatter(formatter) - - if len(logFile) > 0 { - dir := filepath.Dir(logFile) - - err := os.MkdirAll(dir, 0755) - if err != nil { - log.Errorf("Failed to create log path %s: %s", dir, err) - } - - err = log.OpenFile(logFile) - defer func() { - if err := log.CloseFile(); err != nil { - log.Error("Error closing log", err) - } - }() - if err != nil { - log.Error("Error opening file", err) - } - } + globalConfiguration.SetEffectiveConfiguration(configFile) jsonConf, _ := json.Marshal(globalConfiguration) log.Infof("Traefik version %s built on %s", version.Version, version.BuildDate) @@ -308,6 +254,64 @@ func run(globalConfiguration *configuration.GlobalConfiguration) { } svr.Wait() log.Info("Shutting down") + logrus.Exit(0) +} + +func configureLogging(globalConfiguration *configuration.GlobalConfiguration) { + // configure default log flags + fmtlog.SetFlags(fmtlog.Lshortfile | fmtlog.LstdFlags) + + if globalConfiguration.Debug { + globalConfiguration.LogLevel = "DEBUG" + } + + // configure log level + level, err := logrus.ParseLevel(strings.ToLower(globalConfiguration.LogLevel)) + if err != nil { + log.Error("Error getting level", err) + } + log.SetLevel(level) + + // configure log output file + logFile := globalConfiguration.TraefikLogsFile + if len(logFile) > 0 { + log.Warn("top-level traefiklogsfile has been deprecated -- please use traefiklog.filepath") + } + if globalConfiguration.TraefikLog != nil && len(globalConfiguration.TraefikLog.FilePath) > 0 { + logFile = globalConfiguration.TraefikLog.FilePath + } + + // configure log format + var formatter logrus.Formatter + if globalConfiguration.TraefikLog != nil && globalConfiguration.TraefikLog.Format == "json" { + formatter = &logrus.JSONFormatter{} + } else { + disableColors := false + if len(logFile) > 0 { + disableColors = true + } + formatter = &logrus.TextFormatter{DisableColors: disableColors, FullTimestamp: true, DisableSorting: true} + } + log.SetFormatter(formatter) + + if len(logFile) > 0 { + dir := filepath.Dir(logFile) + + err := os.MkdirAll(dir, 0755) + if err != nil { + log.Errorf("Failed to create log path %s: %s", dir, err) + } + + err = log.OpenFile(logFile) + logrus.RegisterExitHandler(func() { + if err := log.CloseFile(); err != nil { + log.Error("Error closing log", err) + } + }) + if err != nil { + log.Error("Error opening file", err) + } + } } // CreateKvSource creates KvSource diff --git a/configuration/configuration.go b/configuration/configuration.go index 108a195d1..7ac80dd3c 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -89,7 +89,7 @@ type GlobalConfiguration struct { // SetEffectiveConfiguration adds missing configuration parameters derived from // existing ones. It also takes care of maintaining backwards compatibility. -func (gc *GlobalConfiguration) SetEffectiveConfiguration() { +func (gc *GlobalConfiguration) SetEffectiveConfiguration(configFile string) { if len(gc.EntryPoints) == 0 { gc.EntryPoints = map[string]*EntryPoint{"http": {Address: ":80"}} gc.DefaultEntryPoints = []string{"http"} @@ -128,8 +128,14 @@ func (gc *GlobalConfiguration) SetEffectiveConfiguration() { } } - if gc.Debug { - gc.LogLevel = "DEBUG" + // Try to fallback to traefik config file in case the file provider is enabled + // but has no file name configured. + if gc.File != nil && len(gc.File.Filename) == 0 { + if len(configFile) > 0 { + gc.File.Filename = configFile + } else { + log.Errorln("Error using file configuration backend, no filename defined") + } } } diff --git a/configuration/configuration_test.go b/configuration/configuration_test.go index b6fc259ab..7f949b6e6 100644 --- a/configuration/configuration_test.go +++ b/configuration/configuration_test.go @@ -6,10 +6,14 @@ import ( "time" "github.com/containous/flaeg" + "github.com/containous/traefik/provider" + "github.com/containous/traefik/provider/file" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) +const defaultConfigFile = "traefik.toml" + func Test_parseEntryPointsConfiguration(t *testing.T) { testCases := []struct { name string @@ -196,7 +200,7 @@ func TestEntryPoints_Set(t *testing.T) { } } -func TestSetEffecticeConfiguration(t *testing.T) { +func TestSetEffectiveConfigurationGraceTimeout(t *testing.T) { tests := []struct { desc string legacyGraceTimeout time.Duration @@ -235,11 +239,49 @@ func TestSetEffecticeConfiguration(t *testing.T) { } } - gc.SetEffectiveConfiguration() + gc.SetEffectiveConfiguration(defaultConfigFile) + gotGraceTimeout := time.Duration(gc.LifeCycle.GraceTimeOut) if gotGraceTimeout != test.wantGraceTimeout { t.Fatalf("got effective grace timeout %d, want %d", gotGraceTimeout, test.wantGraceTimeout) } + + }) + } +} + +func TestSetEffectiveConfigurationFileProviderFilename(t *testing.T) { + tests := []struct { + desc string + fileProvider *file.Provider + wantFileProviderFilename string + }{ + { + desc: "no filename for file provider given", + fileProvider: &file.Provider{}, + wantFileProviderFilename: defaultConfigFile, + }, + { + desc: "filename for file provider given", + fileProvider: &file.Provider{BaseProvider: provider.BaseProvider{Filename: "other.toml"}}, + wantFileProviderFilename: "other.toml", + }, + } + + for _, test := range tests { + test := test + t.Run(test.desc, func(t *testing.T) { + t.Parallel() + gc := &GlobalConfiguration{ + File: test.fileProvider, + } + + gc.SetEffectiveConfiguration(defaultConfigFile) + + gotFileProviderFilename := gc.File.Filename + if gotFileProviderFilename != test.wantFileProviderFilename { + t.Fatalf("got file provider file name %q, want %q", gotFileProviderFilename, test.wantFileProviderFilename) + } }) } } diff --git a/provider/web/web.go b/provider/web/web.go index dcbf42ecf..da2f74935 100644 --- a/provider/web/web.go +++ b/provider/web/web.go @@ -157,7 +157,7 @@ func (provider *Provider) Provide(configurationChan chan<- types.ConfigMessage, err = http.ListenAndServe(provider.Address, negroniInstance) } - if err != nil { + if err != http.ErrServerClosed { log.Fatal("Error creating server: ", err) } }) diff --git a/server/server.go b/server/server.go index b4f6ec187..b65c200e1 100644 --- a/server/server.go +++ b/server/server.go @@ -627,7 +627,7 @@ func (server *Server) startServer(serverEntryPoint *serverEntryPoint, globalConf } else { err = serverEntryPoint.httpServer.Serve(serverEntryPoint.listener) } - if err != nil { + if err != http.ErrServerClosed { log.Error("Error creating server: ", err) } }