From da867ac4643275bde339f3ee1bc52fb8df100f41 Mon Sep 17 00:00:00 2001 From: AdheipSingh Date: Sun, 10 Nov 2024 07:53:09 +0530 Subject: [PATCH] make veriferis, add wait sync groups --- go.mod | 6 +-- go.sum | 3 ++ main.go | 96 ++++++++++++++++++++++++-------------- pkg/analytics/analytics.go | 47 ++++++++++--------- 4 files changed, 94 insertions(+), 58 deletions(-) diff --git a/go.mod b/go.mod index c622463..8f39a8e 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,8 @@ require ( github.com/charmbracelet/bubbletea v0.26.6 github.com/charmbracelet/lipgloss v0.12.1 github.com/dustin/go-humanize v1.0.1 - github.com/google/uuid v1.6.0 + github.com/oklog/ulid/v2 v2.1.0 + github.com/spf13/pflag v1.0.5 golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 golang.org/x/term v0.21.0 google.golang.org/grpc v1.64.1 @@ -27,7 +28,6 @@ require ( github.com/klauspost/compress v1.15.15 // indirect github.com/klauspost/cpuid/v2 v2.2.3 // indirect github.com/pierrec/lz4/v4 v4.1.17 // indirect - github.com/spf13/pflag v1.0.5 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/zeebo/xxh3 v1.0.2 // indirect golang.org/x/mod v0.18.0 // indirect @@ -41,7 +41,7 @@ require ( require ( github.com/atotto/clipboard v0.1.4 // indirect github.com/evertras/bubble-table v0.15.2 - github.com/muesli/termenv v0.15.2 + github.com/muesli/termenv v0.15.2 // indirect github.com/pelletier/go-toml/v2 v2.0.9 github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f // indirect ) diff --git a/go.sum b/go.sum index e9b2573..ea491fe 100644 --- a/go.sum +++ b/go.sum @@ -61,6 +61,9 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= +github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= +github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= +github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc= diff --git a/main.go b/main.go index ce62d85..ba1c1e3 100644 --- a/main.go +++ b/main.go @@ -20,14 +20,17 @@ import ( "errors" "fmt" "os" - "pb/cmd" + pb "pb/cmd" "pb/pkg/analytics" "pb/pkg/config" + "sync" "github.com/spf13/cobra" ) +var wg sync.WaitGroup + // populated at build time var ( Version string @@ -52,7 +55,7 @@ var cli = &cobra.Command{ Use: "pb", Short: "\nParseable command line interface", Long: "\npb is the command line interface for Parseable", - PersistentPreRunE: analytics.CheckAndCreateUUID, + PersistentPreRunE: analytics.CheckAndCreateULID, RunE: func(command *cobra.Command, _ []string) error { if p, _ := command.Flags().GetBool(versionFlag); p { pb.PrintVersion(Version, Commit) @@ -61,7 +64,11 @@ var cli = &cobra.Command{ return errors.New("no command or flag supplied") }, PersistentPostRun: func(cmd *cobra.Command, args []string) { - analytics.PostRunAnalytics(cmd, args) + wg.Add(1) + go func() { + defer wg.Done() + analytics.PostRunAnalytics(cmd, args) + }() }, } @@ -71,7 +78,11 @@ var profile = &cobra.Command{ Long: "\nuse profile command to configure different Parseable instances. Each profile takes a URL and credentials.", PersistentPreRunE: combinedPreRun, PersistentPostRun: func(cmd *cobra.Command, args []string) { - analytics.PostRunAnalytics(cmd, args) + wg.Add(1) + go func() { + defer wg.Done() + analytics.PostRunAnalytics(cmd, args) + }() }, } @@ -81,7 +92,11 @@ var user = &cobra.Command{ Long: "\nuser command is used to manage users.", PersistentPreRunE: combinedPreRun, PersistentPostRun: func(cmd *cobra.Command, args []string) { - analytics.PostRunAnalytics(cmd, args) + wg.Add(1) + go func() { + defer wg.Done() + analytics.PostRunAnalytics(cmd, args) + }() }, } @@ -91,7 +106,11 @@ var role = &cobra.Command{ Long: "\nrole command is used to manage roles.", PersistentPreRunE: combinedPreRun, PersistentPostRun: func(cmd *cobra.Command, args []string) { - analytics.PostRunAnalytics(cmd, args) + wg.Add(1) + go func() { + defer wg.Done() + analytics.PostRunAnalytics(cmd, args) + }() }, } @@ -101,7 +120,11 @@ var stream = &cobra.Command{ Long: "\nstream command is used to manage streams.", PersistentPreRunE: combinedPreRun, PersistentPostRun: func(cmd *cobra.Command, args []string) { - analytics.PostRunAnalytics(cmd, args) + wg.Add(1) + go func() { + defer wg.Done() + analytics.PostRunAnalytics(cmd, args) + }() }, } @@ -111,48 +134,52 @@ var query = &cobra.Command{ Long: "\nRun SQL query on a log stream. Default output format is json. Use -i flag to open interactive table view.", PersistentPreRunE: combinedPreRun, PersistentPostRun: func(cmd *cobra.Command, args []string) { - analytics.PostRunAnalytics(cmd, args) + wg.Add(1) + go func() { + defer wg.Done() + analytics.PostRunAnalytics(cmd, args) + }() }, } func main() { - profile.AddCommand(cmd.AddProfileCmd) - profile.AddCommand(cmd.RemoveProfileCmd) - profile.AddCommand(cmd.ListProfileCmd) - profile.AddCommand(cmd.DefaultProfileCmd) + profile.AddCommand(pb.AddProfileCmd) + profile.AddCommand(pb.RemoveProfileCmd) + profile.AddCommand(pb.ListProfileCmd) + profile.AddCommand(pb.DefaultProfileCmd) - user.AddCommand(cmd.AddUserCmd) - user.AddCommand(cmd.RemoveUserCmd) - user.AddCommand(cmd.ListUserCmd) - user.AddCommand(cmd.SetUserRoleCmd) + user.AddCommand(pb.AddUserCmd) + user.AddCommand(pb.RemoveUserCmd) + user.AddCommand(pb.ListUserCmd) + user.AddCommand(pb.SetUserRoleCmd) - role.AddCommand(cmd.AddRoleCmd) - role.AddCommand(cmd.RemoveRoleCmd) - role.AddCommand(cmd.ListRoleCmd) + role.AddCommand(pb.AddRoleCmd) + role.AddCommand(pb.RemoveRoleCmd) + role.AddCommand(pb.ListRoleCmd) - stream.AddCommand(cmd.AddStreamCmd) - stream.AddCommand(cmd.RemoveStreamCmd) - stream.AddCommand(cmd.ListStreamCmd) - stream.AddCommand(cmd.StatStreamCmd) + stream.AddCommand(pb.AddStreamCmd) + stream.AddCommand(pb.RemoveStreamCmd) + stream.AddCommand(pb.ListStreamCmd) + stream.AddCommand(pb.StatStreamCmd) - query.AddCommand(cmd.QueryCmd) - query.AddCommand(cmd.SavedQueryList) + query.AddCommand(pb.QueryCmd) + query.AddCommand(pb.SavedQueryList) cli.AddCommand(profile) cli.AddCommand(query) cli.AddCommand(stream) cli.AddCommand(user) cli.AddCommand(role) - cli.AddCommand(cmd.TailCmd) + cli.AddCommand(pb.TailCmd) - cli.AddCommand(cmd.AutocompleteCmd) + cli.AddCommand(pb.AutocompleteCmd) // Set as command - cmd.VersionCmd.Run = func(_ *cobra.Command, _ []string) { - cmd.PrintVersion(Version, Commit) + pb.VersionCmd.Run = func(_ *cobra.Command, _ []string) { + pb.PrintVersion(Version, Commit) } - cli.AddCommand(cmd.VersionCmd) + cli.AddCommand(pb.VersionCmd) // set as flag cli.Flags().BoolP(versionFlag, versionFlagShort, false, "Print version") @@ -196,17 +223,18 @@ func main() { if err != nil { os.Exit(1) } + wg.Wait() } -// Wrapper to combine existing pre-run logic and UUID check +// Wrapper to combine existing pre-run logic and ULID check func combinedPreRun(cmd *cobra.Command, args []string) error { err := pb.PreRunDefaultProfile(cmd, args) if err != nil { - return fmt.Errorf("error initialising default profile: %w", err) + return fmt.Errorf("error initializing default profile: %w", err) } - if err := analytics.CheckAndCreateUUID(cmd, args); err != nil { - return fmt.Errorf("error while creating UUID: %v", err) + if err := analytics.CheckAndCreateULID(cmd, args); err != nil { + return fmt.Errorf("error while creating ulid: %v", err) } return nil diff --git a/pkg/analytics/analytics.go b/pkg/analytics/analytics.go index 5211d8d..62f16f6 100644 --- a/pkg/analytics/analytics.go +++ b/pkg/analytics/analytics.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "math/rand" "net/http" "os" "os/exec" @@ -17,7 +18,7 @@ import ( "pb/pkg/config" internalHTTP "pb/pkg/http" - "github.com/google/uuid" + "github.com/oklog/ulid/v2" "github.com/spf13/cobra" "github.com/spf13/pflag" "gopkg.in/yaml.v2" @@ -25,7 +26,7 @@ import ( type Event struct { CLIVersion string `json:"cli_version"` - UUID string `json:"uuid"` + ULID string `json:"ulid"` CommitHash string `json:"commit_hash"` OSName string `json:"os_name"` OSVersion string `json:"os_version"` @@ -76,11 +77,11 @@ type Command struct { // Config struct for parsing YAML type Config struct { - UUID string `yaml:"uuid"` + ULID string `yaml:"ulid"` } -// CheckAndCreateUUID checks for a UUID in the config file and creates it if absent. -func CheckAndCreateUUID(_ *cobra.Command, _ []string) error { +// CheckAndCreateULID checks for a ULID in the config file and creates it if absent. +func CheckAndCreateULID(_ *cobra.Command, _ []string) error { homeDir, err := os.UserHomeDir() if err != nil { fmt.Printf("could not find home directory: %v\n", err) @@ -109,21 +110,25 @@ func CheckAndCreateUUID(_ *cobra.Command, _ []string) error { } } - // Check if UUID is missing - if config.UUID == "" { - config.UUID = uuid.New().String() // Generate a new UUID + // Check if ULID is missing + if config.ULID == "" { + // Generate a new ULID + entropy := ulid.Monotonic(rand.New(rand.NewSource(time.Now().UnixNano())), 0) + ulidInstance := ulid.MustNew(ulid.Timestamp(time.Now()), entropy) + config.ULID = ulidInstance.String() + newData, err := yaml.Marshal(&config) if err != nil { fmt.Printf("could not marshal config data: %v\n", err) return err } - // Write updated config with UUID back to the file + // Write updated config with ULID back to the file if err := os.WriteFile(configPath, newData, 0644); err != nil { fmt.Printf("could not write to config file: %v\n", err) return err } - fmt.Printf("Generated and saved new UUID: %s\n", config.UUID) + fmt.Printf("Generated and saved new ULID: %s\n", config.ULID) } return nil @@ -152,9 +157,9 @@ func PostRunAnalytics(cmd *cobra.Command, args []string) { // sendEvent is a placeholder function to simulate sending an event after command execution. func sendEvent(commandName string, arguments []string, errors *string, executionTimestamp string, flags map[string]string) error { - uuid, err := ReadUUID() + ulid, err := ReadUULD() if err != nil { - return fmt.Errorf("could not load UUID: %v", err) + return fmt.Errorf("could not load ULID: %v", err) } profile, err := GetProfile() @@ -179,7 +184,7 @@ func sendEvent(commandName string, arguments []string, errors *string, execution // Populate the Event struct with OS details and timestamp event := Event{ CLIVersion: about.Commit, - UUID: uuid, + ULID: ulid, CommitHash: about.Commit, Profile: profile, OSName: GetOSName(), @@ -199,7 +204,7 @@ func sendEvent(commandName string, arguments []string, errors *string, execution } // Define the target URL for the HTTP request - url := "https://ingestor.demo.parseable.com/api/v1/logstream/analytics-test" + url := "https://ingestor.demo.parseable.com/api/v1/logstream/analytics-test-new" // Create the HTTP POST request req, err := http.NewRequest("POST", url, bytes.NewBuffer(eventJSON)) @@ -221,7 +226,7 @@ func sendEvent(commandName string, arguments []string, errors *string, execution return fmt.Errorf("received non-2xx response: %v", resp.Status) } - fmt.Println("Event sent successfully:", string(eventJSON)) + //fmt.Println("Event sent successfully:", string(eventJSON)) return nil } @@ -309,7 +314,7 @@ func getWindowsVersion() string { return strings.TrimSpace(string(out)) } -func ReadUUID() (string, error) { +func ReadUULD() (string, error) { homeDir, err := os.UserHomeDir() if err != nil { return "", fmt.Errorf("could not find home directory: %v", err) @@ -319,7 +324,7 @@ func ReadUUID() (string, error) { // Check if config path exists if _, err := os.Stat(configPath); os.IsNotExist(err) { - return "", fmt.Errorf("config file does not exist, please run CheckAndCreateUUID first") + return "", fmt.Errorf("config file does not exist, please run CheckAndCreateULID first") } // Read the config file @@ -329,16 +334,16 @@ func ReadUUID() (string, error) { return "", fmt.Errorf("could not read config file: %v", err) } - // Unmarshal the content to get the UUID + // Unmarshal the content to get the ULID if err := yaml.Unmarshal(data, &config); err != nil { return "", fmt.Errorf("could not parse config file: %v", err) } - if config.UUID == "" { - return "", fmt.Errorf("UUID is missing in config file") + if config.ULID == "" { + return "", fmt.Errorf("ULID is missing in config file") } - return config.UUID, nil + return config.ULID, nil } func FetchAbout(client *internalHTTP.HTTPClient) (about About, err error) {