mirror of
https://github.com/containrrr/watchtower.git
synced 2025-12-16 15:10:12 +01:00
switch to log-format flag
This commit is contained in:
parent
be98119552
commit
6b0c37f3d3
4 changed files with 109 additions and 59 deletions
52
cmd/root.go
52
cmd/root.go
|
|
@ -1,6 +1,7 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"math"
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -28,18 +29,17 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
client container.Client
|
client container.Client
|
||||||
scheduleSpec string
|
scheduleSpec string
|
||||||
cleanup bool
|
cleanup bool
|
||||||
noRestart bool
|
noRestart bool
|
||||||
monitorOnly bool
|
monitorOnly bool
|
||||||
enableLabel bool
|
enableLabel bool
|
||||||
enableJsonFormatter bool
|
notifier t.Notifier
|
||||||
notifier t.Notifier
|
timeout time.Duration
|
||||||
timeout time.Duration
|
lifecycleHooks bool
|
||||||
lifecycleHooks bool
|
rollingRestart bool
|
||||||
rollingRestart bool
|
scope string
|
||||||
scope string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var rootCmd = NewRootCommand()
|
var rootCmd = NewRootCommand()
|
||||||
|
|
@ -77,31 +77,11 @@ func Execute() {
|
||||||
// PreRun is a lifecycle hook that runs before the command is executed.
|
// PreRun is a lifecycle hook that runs before the command is executed.
|
||||||
func PreRun(cmd *cobra.Command, _ []string) {
|
func PreRun(cmd *cobra.Command, _ []string) {
|
||||||
f := cmd.PersistentFlags()
|
f := cmd.PersistentFlags()
|
||||||
|
if err := flags.SetupLogging(f); err != nil {
|
||||||
|
log.Fatalf("Failed to initialize logging: %s", err.Error())
|
||||||
|
}
|
||||||
flags.ProcessFlagAliases(f)
|
flags.ProcessFlagAliases(f)
|
||||||
|
|
||||||
if enabled, _ := f.GetBool("no-color"); enabled {
|
|
||||||
log.SetFormatter(&log.TextFormatter{
|
|
||||||
DisableColors: true,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// enable logrus built-in support for https://bixense.com/clicolors/
|
|
||||||
log.SetFormatter(&log.TextFormatter{
|
|
||||||
EnvironmentOverrideColors: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
rawLogLevel, _ := f.GetString(`log-level`)
|
|
||||||
if logLevel, err := log.ParseLevel(rawLogLevel); err != nil {
|
|
||||||
log.Fatalf("Invalid log level: %s", err.Error())
|
|
||||||
} else {
|
|
||||||
log.SetLevel(logLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
enableJsonFormatter, _ = f.GetBool("json-logging")
|
|
||||||
if enableJsonFormatter {
|
|
||||||
log.SetFormatter(&log.JSONFormatter{})
|
|
||||||
}
|
|
||||||
|
|
||||||
scheduleSpec, _ = f.GetString("schedule")
|
scheduleSpec, _ = f.GetString("schedule")
|
||||||
|
|
||||||
flags.GetSecretsFromFiles(cmd)
|
flags.GetSecretsFromFiles(cmd)
|
||||||
|
|
@ -205,7 +185,7 @@ func Run(c *cobra.Command, names []string) {
|
||||||
httpAPI.RegisterHandler(metricsHandler.Path, metricsHandler.Handle)
|
httpAPI.RegisterHandler(metricsHandler.Path, metricsHandler.Handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := httpAPI.Start(enableUpdateAPI && !unblockHTTPAPI); err != nil && err != http.ErrServerClosed {
|
if err := httpAPI.Start(enableUpdateAPI && !unblockHTTPAPI); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
log.Error("failed to start API", err)
|
log.Error("failed to start API", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,15 +107,15 @@ Environment Variable: WATCHTOWER_LOG_LEVEL
|
||||||
Default: info
|
Default: info
|
||||||
```
|
```
|
||||||
|
|
||||||
## JSON Logging
|
## Logging format
|
||||||
|
|
||||||
Enables the JSON log formatter for logging, changing the log output to JSON format. By default, the log output follows the standard text-based format.
|
Sets what logging format to use for console output.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Argument: --json-logging
|
Argument: --log-format, -l
|
||||||
Environment Variable: WATCHTOWER_JSON_LOGGING
|
Environment Variable: WATCHTOWER_LOG_FORMAT
|
||||||
Type: Boolean
|
Possible values: Auto, LogFmt, Pretty or JSON
|
||||||
Default: false
|
Default: Auto
|
||||||
```
|
```
|
||||||
|
|
||||||
## ANSI colors
|
## ANSI colors
|
||||||
|
|
@ -374,4 +374,4 @@ requests and may rate limit pull requests (mainly docker.io).
|
||||||
Environment Variable: WATCHTOWER_WARN_ON_HEAD_FAILURE
|
Environment Variable: WATCHTOWER_WARN_ON_HEAD_FAILURE
|
||||||
Possible values: always, auto, never
|
Possible values: always, auto, never
|
||||||
Default: auto
|
Default: auto
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -86,11 +86,11 @@ func RegisterSystemFlags(rootCmd *cobra.Command) {
|
||||||
viper.GetBool("WATCHTOWER_LABEL_ENABLE"),
|
viper.GetBool("WATCHTOWER_LABEL_ENABLE"),
|
||||||
"Watch containers where the com.centurylinklabs.watchtower.enable label is true")
|
"Watch containers where the com.centurylinklabs.watchtower.enable label is true")
|
||||||
|
|
||||||
flags.BoolP(
|
flags.StringP(
|
||||||
"json-logging",
|
"log-format",
|
||||||
"j",
|
"l",
|
||||||
viper.GetBool("WATCHTOWER_JSON_LOGGING"),
|
viper.GetString("WATCHTOWER_LOG_FORMAT"),
|
||||||
"Enables the JSON log formatter for logging")
|
"Sets what logging format to use for console output. Possible values: Auto, LogFmt, Pretty, JSON")
|
||||||
|
|
||||||
flags.BoolP(
|
flags.BoolP(
|
||||||
"debug",
|
"debug",
|
||||||
|
|
@ -385,6 +385,7 @@ func SetDefaults() {
|
||||||
viper.SetDefault("WATCHTOWER_NOTIFICATION_EMAIL_SUBJECTTAG", "")
|
viper.SetDefault("WATCHTOWER_NOTIFICATION_EMAIL_SUBJECTTAG", "")
|
||||||
viper.SetDefault("WATCHTOWER_NOTIFICATION_SLACK_IDENTIFIER", "watchtower")
|
viper.SetDefault("WATCHTOWER_NOTIFICATION_SLACK_IDENTIFIER", "watchtower")
|
||||||
viper.SetDefault("WATCHTOWER_LOG_LEVEL", "info")
|
viper.SetDefault("WATCHTOWER_LOG_LEVEL", "info")
|
||||||
|
viper.SetDefault("WATCHTOWER_LOG_FORMAT", "auto")
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnvConfig translates the command-line options into environment variables
|
// EnvConfig translates the command-line options into environment variables
|
||||||
|
|
@ -583,6 +584,46 @@ func ProcessFlagAliases(flags *pflag.FlagSet) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetupLogging reads only the flags that is needed to set up logging and applies them to the global logger
|
||||||
|
func SetupLogging(f *pflag.FlagSet) error {
|
||||||
|
logFormat, _ := f.GetString(`log-format`)
|
||||||
|
noColor, _ := f.GetBool("no-color")
|
||||||
|
|
||||||
|
switch strings.ToLower(logFormat) {
|
||||||
|
case "auto":
|
||||||
|
// This will either use the "pretty" or "logfmt" format, based on whether the standard out is connected to a TTY
|
||||||
|
log.SetFormatter(&log.TextFormatter{
|
||||||
|
DisableColors: noColor,
|
||||||
|
// enable logrus built-in support for https://bixense.com/clicolors/
|
||||||
|
EnvironmentOverrideColors: true,
|
||||||
|
})
|
||||||
|
case "json":
|
||||||
|
log.SetFormatter(&log.JSONFormatter{})
|
||||||
|
case "logfmt":
|
||||||
|
log.SetFormatter(&log.TextFormatter{
|
||||||
|
DisableColors: true,
|
||||||
|
FullTimestamp: true,
|
||||||
|
})
|
||||||
|
case "pretty":
|
||||||
|
log.SetFormatter(&log.TextFormatter{
|
||||||
|
// "Pretty" format combined with `--no-color` will only change the timestamp to the time since start
|
||||||
|
ForceColors: !noColor,
|
||||||
|
FullTimestamp: false,
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid log format: %s", logFormat)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawLogLevel, _ := f.GetString(`log-level`)
|
||||||
|
if logLevel, err := log.ParseLevel(rawLogLevel); err != nil {
|
||||||
|
return fmt.Errorf("invalid log level: %e", err)
|
||||||
|
} else {
|
||||||
|
log.SetLevel(logLevel)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func flagIsEnabled(flags *pflag.FlagSet, name string) bool {
|
func flagIsEnabled(flags *pflag.FlagSet, name string) bool {
|
||||||
value, err := flags.GetBool(name)
|
value, err := flags.GetBool(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -183,26 +183,55 @@ func TestProcessFlagAliasesLogLevelFromEnvironment(t *testing.T) {
|
||||||
assert.Equal(t, `debug`, logLevel)
|
assert.Equal(t, `debug`, logLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestJSONLoggingFlag(t *testing.T) {
|
func TestLogFormatFlag(t *testing.T) {
|
||||||
cmd := new(cobra.Command)
|
cmd := new(cobra.Command)
|
||||||
|
|
||||||
SetDefaults()
|
SetDefaults()
|
||||||
RegisterDockerFlags(cmd)
|
RegisterDockerFlags(cmd)
|
||||||
RegisterSystemFlags(cmd)
|
RegisterSystemFlags(cmd)
|
||||||
|
|
||||||
// Ensure the default value is false
|
// Ensure the default value is Auto
|
||||||
enableJsonFormatter, err := cmd.PersistentFlags().GetBool("json-logging")
|
require.NoError(t, cmd.ParseFlags([]string{}))
|
||||||
require.NoError(t, err)
|
require.NoError(t, SetupLogging(cmd.Flags()))
|
||||||
|
assert.IsType(t, &logrus.TextFormatter{}, logrus.StandardLogger().Formatter)
|
||||||
|
|
||||||
assert.Equal(t, false, enableJsonFormatter)
|
// Test JSON format
|
||||||
|
require.NoError(t, cmd.ParseFlags([]string{`--log-format`, `JSON`}))
|
||||||
|
require.NoError(t, SetupLogging(cmd.Flags()))
|
||||||
|
assert.IsType(t, &logrus.JSONFormatter{}, logrus.StandardLogger().Formatter)
|
||||||
|
|
||||||
// Test with the argument
|
// Test Pretty format
|
||||||
require.NoError(t, cmd.ParseFlags([]string{`--json-logging`}))
|
require.NoError(t, cmd.ParseFlags([]string{`--log-format`, `pretty`}))
|
||||||
flags := cmd.Flags()
|
require.NoError(t, SetupLogging(cmd.Flags()))
|
||||||
enableJsonFormatter, _ = flags.GetBool("json-logging")
|
assert.IsType(t, &logrus.TextFormatter{}, logrus.StandardLogger().Formatter)
|
||||||
require.NoError(t, err)
|
textFormatter, ok := (logrus.StandardLogger().Formatter).(*logrus.TextFormatter)
|
||||||
assert.Equal(t, true, enableJsonFormatter)
|
assert.True(t, ok)
|
||||||
|
assert.True(t, textFormatter.ForceColors)
|
||||||
|
assert.False(t, textFormatter.FullTimestamp)
|
||||||
|
|
||||||
|
// Test LogFmt format
|
||||||
|
require.NoError(t, cmd.ParseFlags([]string{`--log-format`, `logfmt`}))
|
||||||
|
require.NoError(t, SetupLogging(cmd.Flags()))
|
||||||
|
textFormatter, ok = (logrus.StandardLogger().Formatter).(*logrus.TextFormatter)
|
||||||
|
assert.True(t, ok)
|
||||||
|
assert.True(t, textFormatter.DisableColors)
|
||||||
|
assert.True(t, textFormatter.FullTimestamp)
|
||||||
|
|
||||||
|
// Test invalid format
|
||||||
|
require.NoError(t, cmd.ParseFlags([]string{`--log-format`, `cowsay`}))
|
||||||
|
require.Error(t, SetupLogging(cmd.Flags()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLogLevelFlag(t *testing.T) {
|
||||||
|
cmd := new(cobra.Command)
|
||||||
|
|
||||||
|
SetDefaults()
|
||||||
|
RegisterDockerFlags(cmd)
|
||||||
|
RegisterSystemFlags(cmd)
|
||||||
|
|
||||||
|
// Test invalid format
|
||||||
|
require.NoError(t, cmd.ParseFlags([]string{`--log-level`, `gossip`}))
|
||||||
|
require.Error(t, SetupLogging(cmd.Flags()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestProcessFlagAliasesSchedAndInterval(t *testing.T) {
|
func TestProcessFlagAliasesSchedAndInterval(t *testing.T) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue