logs: support standard flag.FlagSet

This is useful for binaries that don't use pflag and cannot migrate to it
because they have to support the traditional single-dash command line
parsing. pflag is a drop-in replacement at the source code level, but the
behavior of flag parsing in the resulting binary is different.
This commit is contained in:
Patrick Ohly 2022-12-28 22:28:05 +01:00
parent f21c603417
commit d627b1686c
2 changed files with 62 additions and 0 deletions

View File

@ -220,6 +220,41 @@ func apply(c *LoggingConfiguration, options *LoggingOptions, featureGate feature
// AddFlags adds command line flags for the configuration.
func AddFlags(c *LoggingConfiguration, fs *pflag.FlagSet) {
addFlags(c, fs)
}
// AddGoFlags is a variant of AddFlags for a standard FlagSet.
func AddGoFlags(c *LoggingConfiguration, fs *flag.FlagSet) {
addFlags(c, goFlagSet{FlagSet: fs})
}
// flagSet is the interface implemented by pflag.FlagSet, with
// just those methods defined which are needed by addFlags.
type flagSet interface {
BoolVar(p *bool, name string, value bool, usage string)
DurationVar(p *time.Duration, name string, value time.Duration, usage string)
StringVar(p *string, name string, value string, usage string)
Var(value pflag.Value, name string, usage string)
VarP(value pflag.Value, name, shorthand, usage string)
}
// goFlagSet implements flagSet for a stdlib flag.FlagSet.
type goFlagSet struct {
*flag.FlagSet
}
func (fs goFlagSet) Var(value pflag.Value, name string, usage string) {
fs.FlagSet.Var(value, name, usage)
}
func (fs goFlagSet) VarP(value pflag.Value, name, shorthand, usage string) {
// Ignore shorthand, it's not needed and not supported.
fs.FlagSet.Var(value, name, usage)
}
// addFlags can be used with both flag.FlagSet and pflag.FlagSet. The internal
// interface definition avoids duplicating this code.
func addFlags(c *LoggingConfiguration, fs flagSet) {
formats := logRegistry.list()
fs.StringVar(&c.Format, "logging-format", c.Format, fmt.Sprintf("Sets the log format. Permitted formats: %s.", formats))
// No new log formats should be added after generation is of flag options

View File

@ -152,6 +152,33 @@ $`, buffer.String())
$`, buffer.String())
})
t.Run("AddGoFlags", func(t *testing.T) {
newOptions := NewLoggingConfiguration()
var fs flag.FlagSet
var buffer bytes.Buffer
AddGoFlags(newOptions, &fs)
fs.SetOutput(&buffer)
fs.PrintDefaults()
// In contrast to copying through VisitAll, the type of some options is now
// known:
// -log-flush-frequency duration
// Maximum number of seconds between log flushes (default 5s)
// -logging-format string
// Sets the log format. Permitted formats: "text". (default "text")
// -v value
// number for the log level verbosity
// -vmodule value
// comma-separated list of pattern=N settings for file-filtered logging (only works for text log format)
assert.Regexp(t, `^.*-log-flush-frequency.*duration.*
.*default 5s.*
.*-logging-format.*string.*
.*default.*text.*
.*-v.*
.*
.*-vmodule.*
.*
$`, buffer.String())
})
}
func TestContextualLogging(t *testing.T) {