diff --git a/pkg/display/display.go b/pkg/display/display.go index 8f3414394..0a7ecdbf4 100644 --- a/pkg/display/display.go +++ b/pkg/display/display.go @@ -8,6 +8,7 @@ import ( "fmt" "os" "strings" + "time" "unicode/utf8" "github.com/jedib0t/go-pretty/v6/table" @@ -341,3 +342,20 @@ func iterateResults(result *queryresult.Result, displayResult displayResultsFunc // we will not get here return nil } + +// DisplayErrorTiming shows the time taken for the query to fail +func DisplayErrorTiming(t time.Time) { + elapsed := time.Since(t) + var sb strings.Builder + // large numbers should be formatted with commas + p := message.NewPrinter(language.English) + + milliseconds := float64(elapsed.Microseconds()) / 1000 + seconds := elapsed.Seconds() + if seconds < 0.5 { + sb.WriteString(p.Sprintf("\nTime: %dms.", int64(milliseconds))) + } else { + sb.WriteString(p.Sprintf("\nTime: %.1fs.", seconds)) + } + fmt.Println(sb.String()) +} diff --git a/pkg/interactive/interactive_client.go b/pkg/interactive/interactive_client.go index 610889fad..7833cf047 100644 --- a/pkg/interactive/interactive_client.go +++ b/pkg/interactive/interactive_client.go @@ -9,6 +9,7 @@ import ( "sort" "strings" "sync" + "time" "github.com/alecthomas/chroma/formatters" "github.com/alecthomas/chroma/lexers" @@ -19,6 +20,7 @@ import ( "github.com/turbot/steampipe/pkg/cmdconfig" "github.com/turbot/steampipe/pkg/constants" "github.com/turbot/steampipe/pkg/db/db_common" + "github.com/turbot/steampipe/pkg/display" "github.com/turbot/steampipe/pkg/query" "github.com/turbot/steampipe/pkg/query/metaquery" "github.com/turbot/steampipe/pkg/query/queryhistory" @@ -338,9 +340,14 @@ func (c *InteractiveClient) executor(ctx context.Context, line string) { } else { // otherwise execute query + t := time.Now() result, err := c.client().Execute(queryContext, query) if err != nil { utils.ShowError(ctx, utils.HandleCancelError(err)) + // if timing flag is enabled, show the time taken for the query to fail + if cmdconfig.Viper().GetBool(constants.ArgTiming) { + display.DisplayErrorTiming(t) + } } else { c.resultsStreamer.StreamResult(result) } diff --git a/pkg/query/queryexecute/execute.go b/pkg/query/queryexecute/execute.go index 50bc067a3..368dd73a7 100644 --- a/pkg/query/queryexecute/execute.go +++ b/pkg/query/queryexecute/execute.go @@ -3,8 +3,10 @@ package queryexecute import ( "context" "fmt" + "time" "github.com/spf13/viper" + "github.com/turbot/steampipe/pkg/cmdconfig" "github.com/turbot/steampipe/pkg/constants" "github.com/turbot/steampipe/pkg/contexthelpers" "github.com/turbot/steampipe/pkg/db/db_common" @@ -62,10 +64,15 @@ func executeQueries(ctx context.Context, queries []string, client db_common.Clie // run all queries failures := 0 + t := time.Now() for i, q := range queries { if err := executeQuery(ctx, q, client); err != nil { failures++ utils.ShowWarning(fmt.Sprintf("executeQueries: query %d of %d failed: %v", i+1, len(queries), err)) + // if timing flag is enabled, show the time taken for the query to fail + if cmdconfig.Viper().GetBool(constants.ArgTiming) { + display.DisplayErrorTiming(t) + } } // TODO move into display layer // Only show the blank line between queries, not after the last one