diff --git a/cmd/cloud.go b/cmd/cloud.go index 06f3acdf74ab..bbb0d7187700 100644 --- a/cmd/cloud.go +++ b/cmd/cloud.go @@ -89,8 +89,7 @@ This will execute the test on the k6 cloud service. Use "k6 login cloud" to auth return nil }, RunE: func(cmd *cobra.Command, args []string) error { - // TODO: disable in quiet mode? - _, _ = fmt.Fprintf(globalState.stdOut, "\n%s\n\n", getBanner(globalState.flags.noColor || !globalState.stdOut.isTTY)) + printBanner(globalState) logger := globalState.logger progressBar := pb.New( @@ -344,8 +343,14 @@ This will execute the test on the k6 cloud service. Use "k6 login cloud" to auth return errext.WithExitCodeIfNone(errors.New("Test progress error"), exitcodes.CloudFailedToGetProgress) } - valueColor := getColor(globalState.flags.noColor || !globalState.stdOut.isTTY, color.FgCyan) - fprintf(globalState.stdOut, " test status: %s\n", valueColor.Sprint(testProgress.RunStatusText)) + if !globalState.flags.quiet { + valueColor := getColor(globalState.flags.noColor || !globalState.stdOut.isTTY, color.FgCyan) + printToStdout(globalState, fmt.Sprintf( + " test status: %s\n", valueColor.Sprint(testProgress.RunStatusText), + )) + } else { + logger.WithField("run_status", testProgress.RunStatusText).Debug("Test finished") + } if testProgress.ResultStatus == cloudapi.ResultStatusFailed { // TODO: use different exit codes for failed thresholds vs failed test (e.g. aborted by system/limit) diff --git a/cmd/common.go b/cmd/common.go index 8b088a50feaf..43af05b40dbf 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -24,7 +24,6 @@ import ( "archive/tar" "bytes" "fmt" - "io" "github.com/spf13/afero" "github.com/spf13/cobra" @@ -107,11 +106,8 @@ func detectType(data []byte) string { return typeJS } -// fprintf panics when where's an error writing to the supplied io.Writer -func fprintf(w io.Writer, format string, a ...interface{}) (n int) { - n, err := fmt.Fprintf(w, format, a...) - if err != nil { - panic(err.Error()) +func printToStdout(gs *globalState, s string) { + if _, err := fmt.Fprint(gs.stdOut, s); err != nil { + gs.logger.Errorf("could not print '%s' to stdout: %s", s, err.Error()) } - return n } diff --git a/cmd/login_cloud.go b/cmd/login_cloud.go index 775286d5ce35..f7b976763319 100644 --- a/cmd/login_cloud.go +++ b/cmd/login_cloud.go @@ -23,6 +23,7 @@ package cmd import ( "encoding/json" "errors" + "fmt" "syscall" "github.com/fatih/color" @@ -86,7 +87,7 @@ This will set the default token used when just "k6 run -o cloud" is passed.`, switch { case reset.Valid: newCloudConf.Token = null.StringFromPtr(nil) - fprintf(globalState.stdOut, " token reset\n") + printToStdout(globalState, " token reset\n") case show.Bool: case token.Valid: newCloudConf.Token = token @@ -147,7 +148,7 @@ This will set the default token used when just "k6 run -o cloud" is passed.`, if newCloudConf.Token.Valid { valueColor := getColor(globalState.flags.noColor || !globalState.stdOut.isTTY, color.FgCyan) - fprintf(globalState.stdOut, " token: %s\n", valueColor.Sprint(newCloudConf.Token.String)) + printToStdout(globalState, fmt.Sprintf(" token: %s\n", valueColor.Sprint(newCloudConf.Token.String))) } return nil }, diff --git a/cmd/run.go b/cmd/run.go index 2c73130bd315..6404a0c203d0 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -88,8 +88,7 @@ a commandline interface for interacting with it.`, k6 run -o influxdb=http://1.2.3.4:8086/k6`[1:], Args: exactArgsWithMsg(1, "arg should either be \"-\", if reading script from stdin, or a path to a script file"), RunE: func(cmd *cobra.Command, args []string) error { - // TODO: disable in quiet mode? - _, _ = fmt.Fprintf(globalState.stdOut, "\n%s\n\n", getBanner(globalState.flags.noColor || !globalState.stdOut.isTTY)) + printBanner(globalState) logger := globalState.logger logger.Debug("Initializing the runner...") @@ -328,7 +327,9 @@ a commandline interface for interacting with it.`, // do nothing, we were interrupted by Ctrl+C already default: logger.Debug("Linger set; waiting for Ctrl+C...") - fprintf(globalState.stdOut, "Linger set; waiting for Ctrl+C...") + if !globalState.flags.quiet { + printToStdout(globalState, "Linger set; waiting for Ctrl+C...") + } <-lingerCtx.Done() logger.Debug("Ctrl+C received, exiting...") } diff --git a/cmd/ui.go b/cmd/ui.go index 1f63bb221899..dc20f19636a1 100644 --- a/cmd/ui.go +++ b/cmd/ui.go @@ -104,6 +104,18 @@ func getBanner(noColor bool) string { return c.Sprint(consts.Banner()) } +func printBanner(gs *globalState) { + if gs.flags.quiet { + return // do not print banner when --quiet is enabled + } + + banner := getBanner(gs.flags.noColor || !gs.stdOut.isTTY) + _, err := fmt.Fprintf(gs.stdOut, "\n%s\n\n", banner) + if err != nil { + gs.logger.Warnf("could not print k6 banner message to stdout: %s", err.Error()) + } +} + func printBar(gs *globalState, bar *pb.ProgressBar) { if gs.flags.quiet { return @@ -124,7 +136,7 @@ func printBar(gs *globalState, bar *pb.ProgressBar) { } rendered := bar.Render(0, widthDelta) // Only output the left and middle part of the progress bar - fprintf(gs.stdOut, "%s%s", rendered.String(), end) + printToStdout(gs, rendered.String()+end) } func modifyAndPrintBar(gs *globalState, bar *pb.ProgressBar, options ...pb.ProgressBarOption) { @@ -141,8 +153,9 @@ func printExecutionDescription( noColor := gs.flags.noColor || !gs.stdOut.isTTY valueColor := getColor(noColor, color.FgCyan) - fprintf(gs.stdOut, " execution: %s\n", valueColor.Sprint(execution)) - fprintf(gs.stdOut, " script: %s\n", valueColor.Sprint(filename)) + buf := &strings.Builder{} + fmt.Fprintf(buf, " execution: %s\n", valueColor.Sprint(execution)) + fmt.Fprintf(buf, " script: %s\n", valueColor.Sprint(filename)) var outputDescriptions []string switch { @@ -156,8 +169,8 @@ func printExecutionDescription( } } - fprintf(gs.stdOut, " output: %s\n", valueColor.Sprint(strings.Join(outputDescriptions, ", "))) - fprintf(gs.stdOut, "\n") + fmt.Fprintf(buf, " output: %s\n", valueColor.Sprint(strings.Join(outputDescriptions, ", "))) + fmt.Fprintf(buf, "\n") maxDuration, _ := lib.GetEndOffset(execPlan) executorConfigs := conf.Scenarios.GetSortedConfigs() @@ -167,16 +180,22 @@ func printExecutionDescription( scenarioDesc = fmt.Sprintf("%d scenarios", len(executorConfigs)) } - fprintf(gs.stdOut, " scenarios: %s\n", valueColor.Sprintf( + fmt.Fprintf(buf, " scenarios: %s\n", valueColor.Sprintf( "(%.2f%%) %s, %d max VUs, %s max duration (incl. graceful stop):", conf.ExecutionSegment.FloatLength()*100, scenarioDesc, lib.GetMaxPossibleVUs(execPlan), maxDuration.Round(100*time.Millisecond)), ) for _, ec := range executorConfigs { - fprintf(gs.stdOut, " * %s: %s\n", + fmt.Fprintf(buf, " * %s: %s\n", ec.GetName(), ec.GetDescription(et)) } - fprintf(gs.stdOut, "\n") + fmt.Fprintf(buf, "\n") + + if gs.flags.quiet { + gs.logger.Debug(buf.String()) + } else { + printToStdout(gs, buf.String()) + } } //nolint: funlen diff --git a/cmd/version.go b/cmd/version.go index 968a187c016b..f1cf37b97258 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -33,7 +33,7 @@ func getVersionCmd(globalState *globalState) *cobra.Command { Short: "Show application version", Long: `Show the application version and exit.`, Run: func(_ *cobra.Command, _ []string) { - fprintf(globalState.stdOut, "k6 v%s", consts.FullVersion()) + printToStdout(globalState, "k6 v"+consts.FullVersion()) }, } return versionCmd