-
Notifications
You must be signed in to change notification settings - Fork 814
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add log-level flag for skopeo #2514
base: main
Are you sure you want to change the base?
Conversation
First time actually pushing a cobra change and making sure a global log level is applied to the containers org, would appreciate fact-checking to make sure I didn't break anything. |
Keep the debug flag for backwards compatibility, but support other log levels. Signed-off-by: Robb Manes <[email protected]>
0556e50
to
8d9ca07
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Yes, having this option makes sense.
skopeo.1.md
needs updating- Non-blocking: Unit tests for the log level parsing (perhaps split from
.before
into a smaller function?), covering (--log-level={valid,invalid}
,--debug
, both set, neither) would be nice.
var defaultUserAgent = "skopeo/" + version.Version | ||
|
||
type globalOptions struct { | ||
debug bool // Enable debug output | ||
logLevel string // Set log level at or above debug (trace, etc) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment is incorrect – --log-level=fatal
would also work.
@@ -79,6 +84,7 @@ func createApp() (*cobra.Command, *globalOptions) { | |||
var dummyVersion bool | |||
rootCommand.Flags().BoolVarP(&dummyVersion, "version", "v", false, "Version for Skopeo") | |||
rootCommand.PersistentFlags().BoolVar(&opts.debug, "debug", false, "enable debug output") | |||
rootCommand.PersistentFlags().StringVar(&opts.logLevel, "log-level", defaultLogLevel, fmt.Sprintf("Log messages above specified level (%s)", strings.Join(logLevels, ", "))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Contrary to Podman’s practice, I think it makes much more sense to not set default option values. With option values defaulted at the CLI level, the code later has difficulty telling apart actual user input from the hard-coded defaults (or from values that come from config files).
@@ -19,10 +19,15 @@ import ( | |||
// and will be populated by the Makefile | |||
var gitCommit = "" | |||
|
|||
// Supported logrus log levels | |||
var logLevels = []string{"trace", "debug", "info", "warn", "warning", "error", "fatal", "panic"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be built from logrus.AllLevels
, not hard-coded in Skopeo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
… second thought, all of logrus
is deprecated. Nowadays the standard-library logging defines fewer levels: https://pkg.go.dev/log/slog#Level .
We probably do want “trace”; but maybe we can avoid committing to fatal
/panic
for now?
@@ -19,10 +19,15 @@ import ( | |||
// and will be populated by the Makefile | |||
var gitCommit = "" | |||
|
|||
// Supported logrus log levels | |||
var logLevels = []string{"trace", "debug", "info", "warn", "warning", "error", "fatal", "panic"} | |||
var defaultLogLevel = "warn" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default of logrus
is actually info
, but, anyway, see elsewhere, this should not need to exist.
var found bool | ||
for _, l := range logLevels { | ||
if l == strings.ToLower(logLevel) { | ||
found = true | ||
break | ||
} | ||
} | ||
|
||
if !found { | ||
logrus.Fatal("Log Level %s is not supported, choose from: %s\n", logLevel, strings.Join(logLevels, ", ")) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is unnecessary, logrus.ParseLevel
already fails if the input is invalid.
|
||
logrus.SetLevel(level) | ||
if logrus.IsLevelEnabled(logrus.InfoLevel) { | ||
logrus.Infof("Filtering at log level %s", logrus.GetLevel()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’d prefer not starting every command output with such a line. (“info” is the default level).
- There’s the UNIX tradition of “in simple cases, on success, print nothing”.
- Some (mistaken?) users fail callers if anything has been printed to
stderr
- Anyway, longer scripts that include calls to Skopeo would probably want to collect full
stderr
output, and having that contain lines like this (with no context and possibly no other output following) seems unclean to me.
With a strict enough parsing, the users should be confident that the output exactly matches their expectations. We don’t have ls dir
confirming “yes, I am reading dir
”.
} | ||
|
||
logrus.SetLevel(level) | ||
if logrus.IsLevelEnabled(logrus.InfoLevel) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Infof
already includes an IsLevelEnabled
check; this is optimizing out only the GetLevel
call, a single atomic load. I think that’s not worth the extra code.
@@ -114,9 +121,34 @@ func createApp() (*cobra.Command, *globalOptions) { | |||
|
|||
// before is run by the cli package for any command, before running the command-specific handler. | |||
func (opts *globalOptions) before(cmd *cobra.Command, args []string) error { | |||
// Set logging level based on debug or logLevel flags |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using both --log-level
and --debug
should fail because the user has probably made a mistake.
One way to do that would be to use NewOptionalStringValue
.
PR containers/image#2713 should really be type
Tracef
rather thanDebugf
, butskopeo
doesn't support any log level except what the--debug
flag offers.More-or-less copy the
--log-level
behavior frompodman
for compatibility and this should allow forTrace
logrus
levels to work.Keep the debug flag for backwards compatibility as well and it make it mutually exclusive with
--debug
.