From 357b416b1cbd812c6b6ff6102d9d9e9798af592a Mon Sep 17 00:00:00 2001 From: Nir Soffer Date: Mon, 2 Sep 2024 23:37:12 +0300 Subject: [PATCH] Add json log format Add an option to to format logs in json format. This can be useful for programs running limactl that want to consume some content from the logs in the program own logs. Example: % _output/bin/limactl -h ... Flags: --debug debug mode -h, --help help for limactl --log-format string Set the logging format [text, json] (default "text") --log-level string Set the logging level [trace, debug, info, warn, error] ... % _output/bin/limactl start --log-format json --plain --vm-type vz --tty=false {"level":"info","msg":"Terminal is not available, proceeding without opening an editor","time":"2024-09-02T05:12:28+03:00"} {"level":"info","msg":"Starting the instance \"default\" with VM driver \"vz\"","time":"2024-09-02T05:12:28+03:00"} ... Related changes included: - Show progress only when using text format. When we have json format for the progress we can enable it. - Fix terminal check for windows, was using os.Stdout when we log to os.Stderr. Discussed in https://github.com/lima-vm/lima/discussions/2576 Fixes #2583 Signed-off-by: Nir Soffer --- cmd/limactl/main.go | 25 +++++++++++++++++++------ pkg/progressbar/progressbar.go | 18 +++++++++++++----- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/cmd/limactl/main.go b/cmd/limactl/main.go index 5c0d3334d5f..515945391e7 100644 --- a/cmd/limactl/main.go +++ b/cmd/limactl/main.go @@ -60,6 +60,7 @@ func newApp() *cobra.Command { DisableAutoGenTag: true, } rootCmd.PersistentFlags().String("log-level", "", "Set the logging level [trace, debug, info, warn, error]") + rootCmd.PersistentFlags().String("log-format", "text", "Set the logging format [text, json]") rootCmd.PersistentFlags().Bool("debug", false, "debug mode") // TODO: "survey" does not support using cygwin terminal on windows yet rootCmd.PersistentFlags().Bool("tty", isatty.IsTerminal(os.Stdout.Fd()), "Enable TUI interactions such as opening an editor. Defaults to true when stdout is a terminal. Set to false for automation.") @@ -72,6 +73,24 @@ func newApp() *cobra.Command { } logrus.SetLevel(lvl) } + + logFormat, _ := cmd.Flags().GetString("log-format") + switch logFormat { + case "json": + formatter := new(logrus.JSONFormatter) + logrus.StandardLogger().SetFormatter(formatter) + case "text": + // logrus use text format by default. + if runtime.GOOS == "windows" && isatty.IsCygwinTerminal(os.Stderr.Fd()) { + formatter := new(logrus.TextFormatter) + // the default setting does not recognize cygwin on windows + formatter.ForceColors = true + logrus.StandardLogger().SetFormatter(formatter) + } + default: + return fmt.Errorf("unsupported log-format: %q", logFormat) + } + debug, _ := cmd.Flags().GetBool("debug") if debug { logrus.SetLevel(logrus.DebugLevel) @@ -83,12 +102,6 @@ func newApp() *cobra.Command { return errors.New("limactl is running under rosetta, please reinstall lima with native arch") } - if runtime.GOOS == "windows" && isatty.IsCygwinTerminal(os.Stdout.Fd()) { - formatter := new(logrus.TextFormatter) - // the default setting does not recognize cygwin on windows - formatter.ForceColors = true - logrus.StandardLogger().SetFormatter(formatter) - } if os.Geteuid() == 0 && cmd.Name() != "generate-doc" { return errors.New("must not run as the root user") } diff --git a/pkg/progressbar/progressbar.go b/pkg/progressbar/progressbar.go index 2b6181d42b8..79b22ae76d0 100644 --- a/pkg/progressbar/progressbar.go +++ b/pkg/progressbar/progressbar.go @@ -6,6 +6,7 @@ import ( "github.com/cheggaaa/pb/v3" "github.com/mattn/go-isatty" + "github.com/sirupsen/logrus" ) func New(size int64) (*pb.ProgressBar, error) { @@ -13,11 +14,7 @@ func New(size int64) (*pb.ProgressBar, error) { bar.Set(pb.Bytes, true) - // Both logrous and pb use stderr by default. - logFd := os.Stderr.Fd() - - // Show progress only when logging to terminal. - if isatty.IsTerminal(logFd) || isatty.IsCygwinTerminal(logFd) { + if showProgress() { bar.SetTemplateString(`{{counters . }} {{bar . | green }} {{percent .}} {{speed . "%s/s"}}`) bar.SetRefreshRate(200 * time.Millisecond) } else { @@ -31,3 +28,14 @@ func New(size int64) (*pb.ProgressBar, error) { return bar, nil } + +func showProgress() bool { + // Progress supports only text format fow now. + if _, ok := logrus.StandardLogger().Formatter.(*logrus.TextFormatter); !ok { + return false + } + + // Both logrous and pb use stderr by default. + logFd := os.Stderr.Fd() + return isatty.IsTerminal(logFd) || isatty.IsCygwinTerminal(logFd) +}