From df877206d65943cec5b77eb41b4fb2fdbeb9f5eb Mon Sep 17 00:00:00 2001 From: lukebp Date: Mon, 29 Nov 2021 13:53:44 -0600 Subject: [PATCH] pictl: Add timer flag. This commit adds a --timer flag to pictl that prints command execution time statistics when used. This can be helpful when performance testing. It also cleans up the functions related to converting between unix timestamps and human readable strings. --- politeiawww/cmd/pictl/cmdcommentvote.go | 2 +- politeiawww/cmd/pictl/cmdproposaledit.go | 8 ++-- politeiawww/cmd/pictl/cmdproposalnew.go | 4 +- .../cmd/pictl/cmdproposalsetbillingstatus.go | 2 +- politeiawww/cmd/pictl/cmdrfptest.go | 4 +- politeiawww/cmd/pictl/cmdseedproposals.go | 4 +- politeiawww/cmd/pictl/cmdvoteauthorize.go | 2 +- politeiawww/cmd/pictl/comment.go | 4 +- politeiawww/cmd/pictl/pictl.go | 19 ++++++++- politeiawww/cmd/pictl/proposal.go | 10 ++--- politeiawww/cmd/pictl/ticketvote.go | 2 +- politeiawww/cmd/pictl/time.go | 41 ++++++++++--------- politeiawww/cmd/shared/config.go | 5 ++- 13 files changed, 62 insertions(+), 45 deletions(-) diff --git a/politeiawww/cmd/pictl/cmdcommentvote.go b/politeiawww/cmd/pictl/cmdcommentvote.go index bdb217d1b..e782735c9 100644 --- a/politeiawww/cmd/pictl/cmdcommentvote.go +++ b/politeiawww/cmd/pictl/cmdcommentvote.go @@ -103,7 +103,7 @@ func (c *cmdCommentVote) Execute(args []string) error { // Print receipt printf("Downvotes: %v\n", int64(cvr.Downvotes)*-1) printf("Upvotes : %v\n", cvr.Upvotes) - printf("Timestamp: %v\n", timestampFromUnix(cvr.Timestamp)) + printf("Timestamp: %v\n", dateAndTimeFromUnix(cvr.Timestamp)) printf("Receipt : %v\n", cvr.Receipt) return nil diff --git a/politeiawww/cmd/pictl/cmdproposaledit.go b/politeiawww/cmd/pictl/cmdproposaledit.go index 4926d9d0f..95f439dfb 100644 --- a/politeiawww/cmd/pictl/cmdproposaledit.go +++ b/politeiawww/cmd/pictl/cmdproposaledit.go @@ -163,8 +163,8 @@ func proposalEdit(c *cmdProposalEdit) (*rcv1.Record, error) { } c.Name = pm.Name c.Amount = pm.Amount - c.StartDate = timestampFromUnix(pm.StartDate) - c.EndDate = timestampFromUnix(pm.EndDate) + c.StartDate = dateAndTimeFromUnix(pm.StartDate) + c.EndDate = dateAndTimeFromUnix(pm.EndDate) c.Domain = pm.Domain // Set random metadata values in case no specific value is provided. case c.Random: @@ -206,13 +206,13 @@ func proposalEdit(c *cmdProposalEdit) (*rcv1.Record, error) { } if c.StartDate != "" { // Parse start & end dates string timestamps. - pm.StartDate, err = unixFromTimestamp(c.StartDate) + pm.StartDate, err = unixFromDate(c.StartDate) if err != nil { return nil, err } } if c.EndDate != "" { - pm.EndDate, err = unixFromTimestamp(c.EndDate) + pm.EndDate, err = unixFromDate(c.EndDate) if err != nil { return nil, err } diff --git a/politeiawww/cmd/pictl/cmdproposalnew.go b/politeiawww/cmd/pictl/cmdproposalnew.go index 142b16276..ab64948fd 100644 --- a/politeiawww/cmd/pictl/cmdproposalnew.go +++ b/politeiawww/cmd/pictl/cmdproposalnew.go @@ -173,13 +173,13 @@ func proposalNew(c *cmdProposalNew) (*rcv1.Record, error) { } // Parse start & end dates string timestamps. if c.StartDate != "" { - pm.StartDate, err = unixFromTimestamp(c.StartDate) + pm.StartDate, err = unixFromDate(c.StartDate) if err != nil { return nil, err } } if c.EndDate != "" { - pm.EndDate, err = unixFromTimestamp(c.EndDate) + pm.EndDate, err = unixFromDate(c.EndDate) if err != nil { return nil, err } diff --git a/politeiawww/cmd/pictl/cmdproposalsetbillingstatus.go b/politeiawww/cmd/pictl/cmdproposalsetbillingstatus.go index 634b2df3b..d4fbffb5b 100644 --- a/politeiawww/cmd/pictl/cmdproposalsetbillingstatus.go +++ b/politeiawww/cmd/pictl/cmdproposalsetbillingstatus.go @@ -73,7 +73,7 @@ func (c *cmdProposalSetBillingStatus) Execute(args []string) error { // Print receipt printf("Token : %v\n", sbs.Token) printf("Status : %v\n", piv1.BillingStatuses[sbs.Status]) - printf("Timestamp: %v\n", timestampFromUnix(sbsr.Timestamp)) + printf("Timestamp: %v\n", dateAndTimeFromUnix(sbsr.Timestamp)) printf("Receipt : %v\n", sbsr.Receipt) return nil } diff --git a/politeiawww/cmd/pictl/cmdrfptest.go b/politeiawww/cmd/pictl/cmdrfptest.go index 2b3719b89..75554dbd2 100644 --- a/politeiawww/cmd/pictl/cmdrfptest.go +++ b/politeiawww/cmd/pictl/cmdrfptest.go @@ -99,7 +99,7 @@ func (c *cmdRFPTest) Execute(args []string) error { } // Log start time - fmt.Printf("Start time: %v\n", timestampFromUnix(time.Now().Unix())) + fmt.Printf("Start time: %v\n", dateAndTimeFromUnix(time.Now().Unix())) // Verify admin login credentials admin := user{ @@ -378,7 +378,7 @@ func (c *cmdRFPTest) Execute(args []string) error { } } - ts := timestampFromUnix(time.Now().Unix()) + ts := dateAndTimeFromUnix(time.Now().Unix()) fmt.Printf("Done!\n") fmt.Printf("Stop time: %v\n", ts) diff --git a/politeiawww/cmd/pictl/cmdseedproposals.go b/politeiawww/cmd/pictl/cmdseedproposals.go index ff8d30b14..4227243e5 100644 --- a/politeiawww/cmd/pictl/cmdseedproposals.go +++ b/politeiawww/cmd/pictl/cmdseedproposals.go @@ -116,7 +116,7 @@ func (c *cmdSeedProposals) Execute(args []string) error { } // Log start time - fmt.Printf("Start time: %v\n", timestampFromUnix(time.Now().Unix())) + fmt.Printf("Start time: %v\n", dateAndTimeFromUnix(time.Now().Unix())) // Setup users users := make([]user, 0, userCount) @@ -433,7 +433,7 @@ func (c *cmdSeedProposals) Execute(args []string) error { } fmt.Printf("\n") - ts := timestampFromUnix(time.Now().Unix()) + ts := dateAndTimeFromUnix(time.Now().Unix()) fmt.Printf("Done!\n") fmt.Printf("Stop time : %v\n", ts) fmt.Printf("Users : %v\n", userCount) diff --git a/politeiawww/cmd/pictl/cmdvoteauthorize.go b/politeiawww/cmd/pictl/cmdvoteauthorize.go index d1dfd25b4..5d30f98bc 100644 --- a/politeiawww/cmd/pictl/cmdvoteauthorize.go +++ b/politeiawww/cmd/pictl/cmdvoteauthorize.go @@ -115,7 +115,7 @@ func (c *cmdVoteAuthorize) Execute(args []string) error { // Print receipt printf("Token : %v\n", a.Token) printf("Action : %v\n", a.Action) - printf("Timestamp: %v\n", timestampFromUnix(ar.Timestamp)) + printf("Timestamp: %v\n", dateAndTimeFromUnix(ar.Timestamp)) printf("Receipt : %v\n", ar.Receipt) return nil diff --git a/politeiawww/cmd/pictl/comment.go b/politeiawww/cmd/pictl/comment.go index a207e1fa3..99f3e2f6d 100644 --- a/politeiawww/cmd/pictl/comment.go +++ b/politeiawww/cmd/pictl/comment.go @@ -18,7 +18,7 @@ func printComment(c cmv1.Comment) { printf(" Score : %v %v\n", downvotes, c.Upvotes) printf(" Username : %v\n", c.Username) printf(" Parent ID : %v\n", c.ParentID) - printf(" Timestamp : %v\n", timestampFromUnix(c.Timestamp)) + printf(" Timestamp : %v\n", dateAndTimeFromUnix(c.Timestamp)) // If the comment is an author update print extra data info if c.ExtraDataHint != "" { @@ -71,6 +71,6 @@ func printCommentVotes(votes []cmv1.CommentVote) { for _, v := range votes { printf(" %-22v comment %v vote %v\n", - timestampFromUnix(v.Timestamp), v.CommentID, v.Vote) + dateAndTimeFromUnix(v.Timestamp), v.CommentID, v.Vote) } } diff --git a/politeiawww/cmd/pictl/pictl.go b/politeiawww/cmd/pictl/pictl.go index 893589d1e..331ebbeae 100644 --- a/politeiawww/cmd/pictl/pictl.go +++ b/politeiawww/cmd/pictl/pictl.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "os" + "time" flags "github.com/jessevdk/go-flags" @@ -121,13 +122,15 @@ type pictl struct { } const helpMsg = `Application Options: + -V, --version Display version information and exit --appdata= Path to application home directory --host= politeiawww host - -j, --json Print raw JSON output - --version Display version information and exit + --httscert politeiawww https cert file path --skipverify Skip verifying the server's certificate chain and host name + -j, --json Print raw JSON output -v, --verbose Print verbose output --silent Suppress all output + --timer Print command execution time stats Help commands help Print detailed help message for a command @@ -247,6 +250,9 @@ func _main() error { return fmt.Errorf("parse help flag: %v", err) } + // Setup timer stats + startTime := time.Now() + // Parse CLI args and execute command parser = flags.NewParser(&pictl{Config: *cfg}, flags.Default) _, err = parser.Parse() @@ -257,6 +263,15 @@ func _main() error { os.Exit(1) } + // Print timer stats + if cfg.Timer { + stopTime := time.Now() + printf("---Timer Stats---\n") + printf(" Start : %v\n", dateAndTimeFromUnix(startTime.Unix())) + printf(" Stop : %v\n", dateAndTimeFromUnix(stopTime.Unix())) + printf(" Elapsed: %v\n", stopTime.Sub(startTime)) + } + return nil } diff --git a/politeiawww/cmd/pictl/proposal.go b/politeiawww/cmd/pictl/proposal.go index 9a6c961d8..b1a1a3351 100644 --- a/politeiawww/cmd/pictl/proposal.go +++ b/politeiawww/cmd/pictl/proposal.go @@ -79,8 +79,8 @@ func printProposalFiles(files []rcv1.File) error { printf(" Name : %v\n", pm.Name) printf(" Domain : %v\n", pm.Domain) printf(" Amount : %v\n", dollars(int64(pm.Amount))) - printf(" Start Date: %v\n", timestampFromUnix(pm.StartDate)) - printf(" End Date : %v\n", timestampFromUnix(pm.EndDate)) + printf(" Start Date: %v\n", dateAndTimeFromUnix(pm.StartDate)) + printf(" End Date : %v\n", dateAndTimeFromUnix(pm.EndDate)) case isRFP: printf(" Name : %v\n", pm.Name) printf(" Domain: %v\n", pm.Domain) @@ -94,7 +94,7 @@ func printProposalFiles(files []rcv1.File) error { printf(" LinkTo: %v\n", vm.LinkTo) } if vm.LinkBy != 0 { - printf(" LinkBy: %v\n", timestampFromUnix(vm.LinkBy)) + printf(" LinkBy: %v\n", dateAndTimeFromUnix(vm.LinkBy)) } } @@ -106,7 +106,7 @@ func printProposal(r rcv1.Record) error { printf("Version : %v\n", r.Version) printf("State : %v\n", rcv1.RecordStates[r.State]) printf("Status : %v\n", rcv1.RecordStatuses[r.Status]) - printf("Timestamp: %v\n", timestampFromUnix(r.Timestamp)) + printf("Timestamp: %v\n", dateAndTimeFromUnix(r.Timestamp)) printf("Username : %v\n", r.Username) printf("Merkle : %v\n", r.CensorshipRecord.Merkle) printf("Receipt : %v\n", r.CensorshipRecord.Signature) @@ -135,7 +135,7 @@ func printBillingStatusChange(bsc piv1.BillingStatusChange) { printf(" PublicKey: %v\n", bsc.PublicKey) printf(" Signature: %v\n", bsc.Signature) printf(" Receipt : %v\n", bsc.Receipt) - printf(" Timestamp: %v\n", timestampFromUnix(bsc.Timestamp)) + printf(" Timestamp: %v\n", dateAndTimeFromUnix(bsc.Timestamp)) } // indexFileRandom returns a proposal index file filled with random data. diff --git a/politeiawww/cmd/pictl/ticketvote.go b/politeiawww/cmd/pictl/ticketvote.go index 6c5a6949b..1a6933c5f 100644 --- a/politeiawww/cmd/pictl/ticketvote.go +++ b/politeiawww/cmd/pictl/ticketvote.go @@ -27,7 +27,7 @@ const ( func printAuthDetails(a tkv1.AuthDetails) { printf("Token : %v\n", a.Token) printf("Action : %v\n", a.Action) - printf("Timestamp: %v\n", timestampFromUnix(a.Timestamp)) + printf("Timestamp: %v\n", dateAndTimeFromUnix(a.Timestamp)) printf("Receipt : %v\n", a.Receipt) } diff --git a/politeiawww/cmd/pictl/time.go b/politeiawww/cmd/pictl/time.go index 39702022e..de40293a2 100644 --- a/politeiawww/cmd/pictl/time.go +++ b/politeiawww/cmd/pictl/time.go @@ -9,44 +9,45 @@ import ( ) const ( - // timeFormat contains the reference time format that is used - // throughout this CLI tool. This format is how timestamps are - // printed when we want to print the human readable version. + // dateAndTimeFormat contains the reference time format that is used + // to print a human readable date and time. // - // Mon Jan 2 15:04:05 2006 - timeFormat = "01/02/2006 3:04pm" + // Reference date: "Mon Jan 2 15:04:05 2006" + dateAndTimeFormat = "2 Jan 2006 3:04:05pm" + + // userInputDateFormat contains the reference time format that is used to + // parse user input dates. + // + // Reference date: "Mon Jan 2 15:04:05 2006" + userInputDateFormat = "01/02/2006" // locationName is the name of the time zone location that is used // in the human readable timestamps. locationName = "Local" - - // userTimeFormat contains the reference time format that is expected - // from the user when a date value is provided. - // - // Jan 2 2006 - userTimeFormat = "01/02/2006" ) -// timestampFromUnix converts a unix timestamp into a human readable timestamp -// string formatted according to the timeFormat global variable. -func timestampFromUnix(unixTime int64) string { +// dateAndTimeFromUnix converts a unix timestamp into a human readable +// timestamp string formatted according to the dateAndTime global variable. +func dateAndTimeFromUnix(unixTime int64) string { t := time.Unix(unixTime, 0) - return t.Format(timeFormat) + return t.Format(dateAndTimeFormat) } +// dateFromUnix coverts a unix timestamp into a human readable timestamp string +// formatted according to the userInputDateFormat global variable. func dateFromUnix(unixTime int64) string { t := time.Unix(unixTime, 0) - return t.Format(userTimeFormat) + return t.Format(userInputDateFormat) } -// unixFromTimestamp converts a human readable timestamp string formatted -// according to the timeFormat global variable into a unix timestamp. -func unixFromTimestamp(timestamp string) (int64, error) { +// unixFromDate converts a human readable timestamp string formatted according +// to the userInputDateFormat global variable into a unix timestamp. +func unixFromDate(timestamp string) (int64, error) { location, err := time.LoadLocation(locationName) if err != nil { return 0, err } - t, err := time.ParseInLocation(userTimeFormat, timestamp, location) + t, err := time.ParseInLocation(userInputDateFormat, timestamp, location) if err != nil { return 0, err } diff --git a/politeiawww/cmd/shared/config.go b/politeiawww/cmd/shared/config.go index f8d32c5f8..5ddd7fa2a 100644 --- a/politeiawww/cmd/shared/config.go +++ b/politeiawww/cmd/shared/config.go @@ -46,14 +46,15 @@ var ( // Config represents the CLI configuration settings. type Config struct { + ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"` HomeDir string `long:"appdata" description:"Path to application home directory"` Host string `long:"host" description:"politeiawww host"` HTTPSCert string `long:"httpscert" description:"politeiawww https cert"` - RawJSON bool `short:"j" long:"json" description:"Print raw JSON output"` - ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"` SkipVerify bool `long:"skipverify" description:"Skip verifying the server's certifcate chain and host name"` + RawJSON bool `short:"j" long:"json" description:"Print raw JSON output"` Verbose bool `short:"v" long:"verbose" description:"Print verbose output"` Silent bool `long:"silent" description:"Suppress all output"` + Timer bool `long:"timer" description:"Print command execution time stats"` ClientCert string `long:"clientcert" description:"Path to TLS certificate for client authentication"` ClientKey string `long:"clientkey" description:"Path to TLS client authentication key"`