From fc2d6dec74d1b2f3cb5716f84ee69f28a3fe2524 Mon Sep 17 00:00:00 2001 From: Pantani Date: Tue, 23 Apr 2024 00:55:05 +0200 Subject: [PATCH 01/13] add matomo anlytics --- ignite/internal/analytics/analytics.go | 34 +++--- ignite/pkg/gacli/doc.go | 2 - ignite/pkg/gacli/gacli.go | 7 +- ignite/pkg/matomo/matomo.go | 142 +++++++++++++++++++++++++ 4 files changed, 163 insertions(+), 22 deletions(-) delete mode 100644 ignite/pkg/gacli/doc.go create mode 100644 ignite/pkg/matomo/matomo.go diff --git a/ignite/internal/analytics/analytics.go b/ignite/internal/analytics/analytics.go index 8ad12669b5..5c98002c3d 100644 --- a/ignite/internal/analytics/analytics.go +++ b/ignite/internal/analytics/analytics.go @@ -6,20 +6,19 @@ import ( "path/filepath" "runtime" "strconv" - "strings" "sync" "github.com/manifoldco/promptui" "github.com/spf13/cobra" - "github.com/ignite/cli/v29/ignite/pkg/gacli" "github.com/ignite/cli/v29/ignite/pkg/gitpod" + "github.com/ignite/cli/v29/ignite/pkg/matomo" "github.com/ignite/cli/v29/ignite/pkg/randstr" "github.com/ignite/cli/v29/ignite/version" ) const ( - telemetryEndpoint = "https://telemetry-cli.ignite.com" + telemetryEndpoint = "https://pantani.matomo.cloud/matomo.php" envDoNotTrack = "DO_NOT_TRACK" envCI = "CI" envGitHubActions = "GITHUB_ACTIONS" @@ -27,7 +26,7 @@ const ( igniteAnonIdentity = "anon_identity.json" ) -var gaclient gacli.Client +var matomoClient matomo.Client // anonIdentity represents an analytics identity file. type anonIdentity struct { @@ -38,7 +37,10 @@ type anonIdentity struct { } func init() { - gaclient = gacli.New(telemetryEndpoint) + matomoClient = matomo.New( + telemetryEndpoint, + matomo.WithIDSite(1), + ) } // SendMetric send command metrics to analytics. @@ -53,22 +55,20 @@ func SendMetric(wg *sync.WaitGroup, cmd *cobra.Command) { } path := cmd.CommandPath() - met := gacli.Metric{ - Name: cmd.Name(), - Cmd: path, - Tag: strings.ReplaceAll(path, " ", "+"), - OS: runtime.GOOS, - Arch: runtime.GOARCH, - SessionID: dntInfo.Name, - Version: version.Version, - IsGitPod: gitpod.IsOnGitpod(), - IsCI: getIsCI(), + met := matomo.Metric{ + Name: cmd.Name(), + Cmd: path, + OS: runtime.GOOS, + Arch: runtime.GOARCH, + Version: version.Version, + IsGitPod: gitpod.IsOnGitpod(), + IsCI: getIsCI(), } wg.Add(1) go func() { defer wg.Done() - _ = gaclient.SendMetric(met) + _ = matomoClient.SendMetric(dntInfo.Name, met) }() } @@ -97,7 +97,7 @@ func checkDNT() (anonIdentity, error) { return i, nil } - i.Name = randstr.Runes(10) + i.Name = randstr.Runes(16) i.DoNotTrack = false prompt := promptui.Select{ diff --git a/ignite/pkg/gacli/doc.go b/ignite/pkg/gacli/doc.go deleted file mode 100644 index 9b905a5d3a..0000000000 --- a/ignite/pkg/gacli/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package gacli is a client for Google Analytics to send data points for hint-type=event. -package gacli diff --git a/ignite/pkg/gacli/gacli.go b/ignite/pkg/gacli/gacli.go index a56329dac4..b6fc24f734 100644 --- a/ignite/pkg/gacli/gacli.go +++ b/ignite/pkg/gacli/gacli.go @@ -1,3 +1,4 @@ +// Package gacli is a client for Google Analytics to send data points for hint-type=event. package gacli import ( @@ -79,7 +80,7 @@ func New(endpoint string, opts ...Option) Client { // Send sends metric event to analytics. func (c Client) Send(body Body) error { - // encode body + // encode body. encoded, err := json.Marshal(body) if err != nil { return err @@ -98,7 +99,7 @@ func (c Client) Send(body Body) error { } requestURL.RawQuery = v.Encode() - // Create an HTTP request with the payload + // Create an HTTP request with the payload. resp, err := c.httpClient.Post(requestURL.String(), "application/json", bytes.NewBuffer(encoded)) if err != nil { return errors.Wrapf(err, "error creating HTTP request: %s", requestURL.String()) @@ -107,7 +108,7 @@ func (c Client) Send(body Body) error { if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNoContent { - return errors.Errorf("error to add analytics metric. Status code: %d", resp.StatusCode) + return errors.Errorf("error to add google analytics metric. Status code: %d", resp.StatusCode) } return nil } diff --git a/ignite/pkg/matomo/matomo.go b/ignite/pkg/matomo/matomo.go new file mode 100644 index 0000000000..d58199dbcb --- /dev/null +++ b/ignite/pkg/matomo/matomo.go @@ -0,0 +1,142 @@ +// Package matomo is a client for Matomo to send data points for hint-type=event. +package matomo + +import ( + "encoding/json" + "fmt" + "math/rand" + "net/http" + "net/url" + "strings" + "time" + + "github.com/google/go-querystring/query" + + "github.com/ignite/cli/v29/ignite/pkg/errors" +) + +type ( + // Client is an analytics client. + Client struct { + endpoint string + idSite int // Matomo ID Site. + tokenAuth string // Matomo Token Auth. + httpClient http.Client + } + // Params analytics metrics body. + Params struct { + Rec int `url:"rec"` + IDSite int `url:"idsite"` + TokenAuth string `url:"token_auth"` + ActionName string `url:"action_name"` + UniqueID string `url:"_id"` + UserID string `url:"uid"` + Rand int `url:"rand,omitempty"` + APIVersion int `url:"apiv,omitempty"` + ClientID string `url:"cid,omitempty"` + EventName string `url:"e_n,omitempty"` + EventValue string `url:"e_v,omitempty"` + Hour int `url:"h,omitempty"` + Minute int `url:"m,omitempty"` + Second int `url:"s,omitempty"` + Metric Metric `url:"-"` + } + // Metric represents a custom data. + Metric struct { + Name string `url:"name,omitempty"` + Cmd string `url:"command,omitempty"` + OS string `url:"os,omitempty"` + Arch string `url:"arch,omitempty"` + Version string `url:"version,omitempty"` + IsGitPod bool `url:"is_git_pod,omitempty"` + IsCI bool `url:"is_ci,omitempty"` + } +) + +// Option configures code generation. +type Option func(*Client) + +// WithIDSite adds an id site. +func WithIDSite(idSite int) Option { + return func(c *Client) { + c.idSite = idSite + } +} + +// WithTokenAuth adds an matomo token authentication. +func WithTokenAuth(tokenAuth string) Option { + return func(c *Client) { + c.tokenAuth = tokenAuth + } +} + +// New creates a new Matomo client. +func New(endpoint string, opts ...Option) Client { + c := Client{ + endpoint: endpoint, + httpClient: http.Client{ + Timeout: 1500 * time.Millisecond, + }, + } + // apply analytics options. + for _, o := range opts { + o(&c) + } + return c +} + +// Send sends metric event to analytics. +func (c Client) Send(params Params) error { + requestURL, err := url.Parse(c.endpoint) + if err != nil { + return err + } + + // encode request parameters. + queryParams, err := query.Values(params) + if err != nil { + return err + } + customMetric, err := json.Marshal(params.Metric) + if err != nil { + return errors.Wrapf(err, "can't marshall metric to json: %v", params.Metric) + } + requestURL.RawQuery = fmt.Sprintf("%s&_cvar=%s", queryParams.Encode(), customMetric) + + // Create an HTTP request with the payload. + resp, err := c.httpClient.Get(requestURL.String()) + if err != nil { + return errors.Wrapf(err, "error creating HTTP request: %s", requestURL.String()) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return errors.Errorf("error to add matomo analytics metric. Status code: %d", resp.StatusCode) + } + return nil +} + +// SendMetric build the metrics and send to analytics. +func (c Client) SendMetric(sessionID string, metric Metric) error { + var ( + now = time.Now() + r = rand.New(rand.NewSource(now.Unix())) + ) + return c.Send(Params{ + IDSite: c.idSite, + TokenAuth: c.tokenAuth, + Rec: 1, + APIVersion: 1, + ClientID: sessionID, + UniqueID: sessionID, + UserID: sessionID, + Rand: r.Int(), + Hour: now.Hour(), + Minute: now.Minute(), + Second: now.Second(), + ActionName: metric.Cmd, + EventName: metric.Cmd, + EventValue: strings.ReplaceAll(metric.Cmd, " ", "_"), + Metric: metric, + }) +} From 51b0da961f1b2c7abc47483c03c474a6825372d2 Mon Sep 17 00:00:00 2001 From: Pantani Date: Fri, 17 May 2024 15:03:20 +0200 Subject: [PATCH 02/13] matomo url --- ignite/internal/analytics/analytics.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ignite/internal/analytics/analytics.go b/ignite/internal/analytics/analytics.go index 5c98002c3d..f725858544 100644 --- a/ignite/internal/analytics/analytics.go +++ b/ignite/internal/analytics/analytics.go @@ -18,7 +18,7 @@ import ( ) const ( - telemetryEndpoint = "https://pantani.matomo.cloud/matomo.php" + telemetryEndpoint = "https://matomo-cli.ignite.com" envDoNotTrack = "DO_NOT_TRACK" envCI = "CI" envGitHubActions = "GITHUB_ACTIONS" From 28985e5fe5ca6c731a1b64aa9de9b83a27c7fc90 Mon Sep 17 00:00:00 2001 From: Pantani Date: Wed, 22 May 2024 18:20:29 +0200 Subject: [PATCH 03/13] add changelog --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index c8d3e6b8c4..9b4fdfdc87 100644 --- a/changelog.md +++ b/changelog.md @@ -19,6 +19,7 @@ - [#4133](https://github.com/ignite/cli/pull/4133) Improve buf rate limit - [#4113](https://github.com/ignite/cli/pull/4113) Generate chain config documentation automatically - [#4131](https://github.com/ignite/cli/pull/4131) Support `bytes` as data type in the `scaffold` commands +- [#4095](https://github.com/ignite/cli/pull/4095) Migrate to matomo analytics ### Changes From 149afbf1dbc543ea66c770dda0c9db3c382a7919 Mon Sep 17 00:00:00 2001 From: Pantani Date: Tue, 28 May 2024 01:36:36 +0200 Subject: [PATCH 04/13] matomo analytics refacor --- ignite/cmd/version.go | 9 +- ignite/internal/analytics/analytics.go | 45 +++- .../plugin/testdata/execute_fail/go.mod | 4 +- .../plugin/testdata/execute_ok/go.mod | 4 +- ignite/pkg/matomo/matomo.go | 224 ++++++++++++++---- ignite/version/version.go | 146 ++++++++---- .../plugin/testdata/example-plugin/go.mod | 4 +- 7 files changed, 319 insertions(+), 117 deletions(-) diff --git a/ignite/cmd/version.go b/ignite/cmd/version.go index f7540a6ea1..a4b19bb460 100644 --- a/ignite/cmd/version.go +++ b/ignite/cmd/version.go @@ -11,8 +11,13 @@ func NewVersion() *cobra.Command { c := &cobra.Command{ Use: "version", Short: "Print the current build information", - Run: func(cmd *cobra.Command, _ []string) { - cmd.Println(version.Long(cmd.Context())) + RunE: func(cmd *cobra.Command, _ []string) error { + v, err := version.Long(cmd.Context()) + if err != nil { + return err + } + cmd.Println(v) + return nil }, } return c diff --git a/ignite/internal/analytics/analytics.go b/ignite/internal/analytics/analytics.go index fec087f3cd..e234ad819a 100644 --- a/ignite/internal/analytics/analytics.go +++ b/ignite/internal/analytics/analytics.go @@ -4,8 +4,8 @@ import ( "encoding/json" "os" "path/filepath" - "runtime" "strconv" + "strings" "sync" "github.com/manifoldco/promptui" @@ -39,7 +39,7 @@ type anonIdentity struct { func init() { matomoClient = matomo.New( telemetryEndpoint, - matomo.WithIDSite(1), + matomo.WithIDSite(4), // TODO remove me ) } @@ -54,15 +54,40 @@ func SendMetric(wg *sync.WaitGroup, cmd *cobra.Command) { return } - path := cmd.CommandPath() + versionInfo, err := version.GetInfo(cmd.Context()) + if err != nil { + return + } + + var ( + path = cmd.CommandPath() + scaffoldType = "" + ) + if strings.Contains(path, "ignite scaffold type") { + splitCMD := strings.Split(path, " ") + if len(splitCMD) > 3 { + scaffoldType = splitCMD[3] + } + } + met := matomo.Metric{ - Name: cmd.Name(), - Cmd: path, - OS: runtime.GOOS, - Arch: runtime.GOARCH, - Version: version.Version, - IsGitPod: gitpod.IsOnGitpod(), - IsCI: getIsCI(), + Name: cmd.Name(), + Cmd: path, + ScaffoldType: scaffoldType, + OS: versionInfo.OS, + Arch: versionInfo.Arch, + Version: versionInfo.CLIVersion, + CLIVersion: versionInfo.CLIVersion, + GoVersion: versionInfo.GoVersion, + SDKVersion: versionInfo.SDKVersion, + BuildDate: versionInfo.BuildDate, + SourceHash: versionInfo.SourceHash, + ConfigVersion: versionInfo.ConfigVersion, + Uname: versionInfo.Uname, + CWD: versionInfo.CWD, + BuildFromSource: versionInfo.BuildFromSource, + IsGitPod: gitpod.IsOnGitpod(), + IsCI: getIsCI(), } wg.Add(1) diff --git a/ignite/internal/plugin/testdata/execute_fail/go.mod b/ignite/internal/plugin/testdata/execute_fail/go.mod index 1488336a18..6aa02db449 100644 --- a/ignite/internal/plugin/testdata/execute_fail/go.mod +++ b/ignite/internal/plugin/testdata/execute_fail/go.mod @@ -1,8 +1,8 @@ module execute_fail -go 1.21.1 +go 1.22 -toolchain go1.21.5 +toolchain go1.22.3 require ( github.com/hashicorp/go-plugin v1.6.0 diff --git a/ignite/internal/plugin/testdata/execute_ok/go.mod b/ignite/internal/plugin/testdata/execute_ok/go.mod index 484f6a45cb..6f8e0c2ac3 100644 --- a/ignite/internal/plugin/testdata/execute_ok/go.mod +++ b/ignite/internal/plugin/testdata/execute_ok/go.mod @@ -1,8 +1,8 @@ module execute_ok -go 1.21.1 +go 1.22 -toolchain go1.21.5 +toolchain go1.22.3 require ( github.com/hashicorp/go-plugin v1.6.0 diff --git a/ignite/pkg/matomo/matomo.go b/ignite/pkg/matomo/matomo.go index d58199dbcb..63167c7bfb 100644 --- a/ignite/pkg/matomo/matomo.go +++ b/ignite/pkg/matomo/matomo.go @@ -2,8 +2,8 @@ package matomo import ( - "encoding/json" "fmt" + "io" "math/rand" "net/http" "net/url" @@ -19,37 +19,103 @@ type ( // Client is an analytics client. Client struct { endpoint string - idSite int // Matomo ID Site. + idSite uint // Matomo ID Site. tokenAuth string // Matomo Token Auth. httpClient http.Client } // Params analytics metrics body. Params struct { - Rec int `url:"rec"` - IDSite int `url:"idsite"` - TokenAuth string `url:"token_auth"` - ActionName string `url:"action_name"` - UniqueID string `url:"_id"` - UserID string `url:"uid"` - Rand int `url:"rand,omitempty"` - APIVersion int `url:"apiv,omitempty"` - ClientID string `url:"cid,omitempty"` - EventName string `url:"e_n,omitempty"` - EventValue string `url:"e_v,omitempty"` - Hour int `url:"h,omitempty"` - Minute int `url:"m,omitempty"` - Second int `url:"s,omitempty"` - Metric Metric `url:"-"` + IDSite uint `url:"idsite"` + Rec uint `url:"rec"` + APIVersion uint `url:"apiv,omitempty"` + TokenAuth string `url:"token_auth,omitempty"` + CustomAction uint `url:"ca,omitempty"` + Rand uint64 `url:"rand,omitempty"` + URL string `url:"url,omitempty"` + UTMSource string `url:"utm_source,omitempty"` + UTMMedium string `url:"utm_medium,omitempty"` + UTMCampaign string `url:"utm_campaign,omitempty"` + UTMContent string `url:"utm_content,omitempty"` + UserID string `url:"uid,omitempty"` + UserAgent string `url:"ua,omitempty"` + ActionName string `url:"action_name"` + Hour int `url:"h,omitempty"` + Minute int `url:"m,omitempty"` + Second int `url:"s,omitempty"` + + // Dimension1 development mode boolean. + // 1 = devMode ON | 0 = devMode OFF. + Dimension1 uint `url:"dimension1"` + + // Dimension2 internal boolean. + // 1 = internal ON not supported at present | 0 = internal OFF. + Dimension2 uint `url:"dimension2"` + + // Dimension3 is gitpod (0 or 1). + // 1 = isGitpod ON | 0 = isGitpod OFF. + Dimension3 uint `url:"dimension3"` + + // Dimension4 ignite version + Dimension4 string `url:"dimension4"` + + // Dimension6 ignite config version + Dimension6 string `url:"dimension6"` + + // Dimension7 full cli command + Dimension7 string `url:"dimension7"` + + // Dimension11 scaffold customization type + Dimension11 string `url:"dimension11"` + + // Dimension13 command level 1. + Dimension13 string `url:"dimension13"` + + // Dimension14 command level 2. + Dimension14 string `url:"dimension14"` + + // Dimension15 command level 3. + Dimension15 string `url:"dimension15"` + + // Dimension16 command level 4. + Dimension16 string `url:"dimension16"` + + // Dimension17 cosmos-sdk version. + Dimension17 string `url:"dimension17"` + + // Dimension18 operational system. + Dimension18 string `url:"dimension18"` + + // Dimension19 system architecture. + Dimension19 string `url:"dimension19"` + + // Dimension20 golang version. + Dimension20 string `url:"dimension20"` + + // Dimension21 command level 5. + Dimension21 string `url:"dimension21"` + + // Dimension22 command level 6. + Dimension22 string `url:"dimension22"` } // Metric represents a custom data. Metric struct { - Name string `url:"name,omitempty"` - Cmd string `url:"command,omitempty"` - OS string `url:"os,omitempty"` - Arch string `url:"arch,omitempty"` - Version string `url:"version,omitempty"` - IsGitPod bool `url:"is_git_pod,omitempty"` - IsCI bool `url:"is_ci,omitempty"` + Name string + Cmd string + OS string + Arch string + Version string + CLIVersion string + GoVersion string + SDKVersion string + BuildDate string + SourceHash string + ConfigVersion string + Uname string + CWD string + ScaffoldType string + BuildFromSource bool + IsGitPod bool + IsCI bool } ) @@ -57,13 +123,13 @@ type ( type Option func(*Client) // WithIDSite adds an id site. -func WithIDSite(idSite int) Option { +func WithIDSite(idSite uint) Option { return func(c *Client) { c.idSite = idSite } } -// WithTokenAuth adds an matomo token authentication. +// WithTokenAuth adds a matomo token authentication. func WithTokenAuth(tokenAuth string) Option { return func(c *Client) { c.tokenAuth = tokenAuth @@ -97,11 +163,7 @@ func (c Client) Send(params Params) error { if err != nil { return err } - customMetric, err := json.Marshal(params.Metric) - if err != nil { - return errors.Wrapf(err, "can't marshall metric to json: %v", params.Metric) - } - requestURL.RawQuery = fmt.Sprintf("%s&_cvar=%s", queryParams.Encode(), customMetric) + requestURL.RawQuery = queryParams.Encode() // Create an HTTP request with the payload. resp, err := c.httpClient.Get(requestURL.String()) @@ -110,33 +172,99 @@ func (c Client) Send(params Params) error { } defer resp.Body.Close() + got, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + fmt.Println(string(got)) + if resp.StatusCode != http.StatusOK { return errors.Errorf("error to add matomo analytics metric. Status code: %d", resp.StatusCode) } + return nil } +func splitCMD(cmd string) []string { + slipCmd := strings.Split(cmd, " ") + result := make([]string, 6) + for i := 0; i < len(slipCmd); i++ { + if i > 5 { + break + } + result[i] = slipCmd[i] + } + return result +} + +func (c Client) metricURL(cmd string) string { + return fmt.Sprintf("%s/%s", c.endpoint, strings.ReplaceAll(cmd, " ", "_")) +} + // SendMetric build the metrics and send to analytics. func (c Client) SendMetric(sessionID string, metric Metric) error { var ( - now = time.Now() - r = rand.New(rand.NewSource(now.Unix())) + now = time.Now() + r = rand.New(rand.NewSource(now.Unix())) + utmMedium = "dev" ) + if !metric.BuildFromSource { + utmMedium = "binary" + } + + slipCmd := strings.Split(metric.Cmd, " ") + result := make([]string, 5) + for i := 0; i < len(result); i++ { + if i <= len(result) { + break + } + result[i] = slipCmd[i] + } + + cmd := splitCMD(metric.Cmd) + return c.Send(Params{ - IDSite: c.idSite, - TokenAuth: c.tokenAuth, - Rec: 1, - APIVersion: 1, - ClientID: sessionID, - UniqueID: sessionID, - UserID: sessionID, - Rand: r.Int(), - Hour: now.Hour(), - Minute: now.Minute(), - Second: now.Second(), - ActionName: metric.Cmd, - EventName: metric.Cmd, - EventValue: strings.ReplaceAll(metric.Cmd, " ", "_"), - Metric: metric, + IDSite: c.idSite, + Rec: 1, + APIVersion: 1, + TokenAuth: c.tokenAuth, + CustomAction: 1, + Rand: r.Uint64(), + URL: c.metricURL(metric.Cmd), + UTMSource: c.endpoint, + UTMMedium: utmMedium, + UTMCampaign: metric.SourceHash, + UTMContent: metric.CLIVersion, + UserID: sessionID, + UserAgent: "Go-http-client", + ActionName: metric.Cmd, + Hour: now.Hour(), + Minute: now.Minute(), + Second: now.Second(), + Dimension1: 0, + Dimension2: 0, + Dimension3: formatBool(metric.IsGitPod), + Dimension4: metric.Version, + Dimension6: metric.ConfigVersion, + Dimension7: metric.Cmd, + Dimension11: metric.ScaffoldType, + Dimension13: cmd[0], + Dimension14: cmd[1], + Dimension15: cmd[2], + Dimension16: cmd[3], + Dimension17: metric.SDKVersion, + Dimension18: metric.OS, + Dimension19: metric.Arch, + Dimension20: metric.GoVersion, + Dimension21: cmd[4], + Dimension22: cmd[5], }) } + +// formatBool returns "1" or "0" according to the value of b. +func formatBool(b bool) uint { + if b { + return 1 + } + return 0 +} diff --git a/ignite/version/version.go b/ignite/version/version.go index c88d2c42ce..3b8fb6b715 100644 --- a/ignite/version/version.go +++ b/ignite/version/version.go @@ -8,6 +8,7 @@ import ( "path" "runtime" "runtime/debug" + "strconv" "strings" "text/tabwriter" @@ -35,6 +36,21 @@ Please, follow the migration guide to upgrade your chain to the latest version a // Version is the semantic version of Ignite CLI. var Version = versionDev +type Info struct { + CLIVersion string + GoVersion string + SDKVersion string + BuildDate string + SourceHash string + ConfigVersion string + OS string + Arch string + Uname string + CWD string + IsGitpod bool + BuildFromSource bool +} + // CheckNext checks whether there is a new version of Ignite CLI. func CheckNext(ctx context.Context) (isAvailable bool, version string, err error) { if Version == versionDev || Version == versionNightly { @@ -77,6 +93,11 @@ func getLatestReleaseTag(ctx context.Context) (string, error) { return *latest.TagName, nil } +// fromSource check if the binary was build from source using the CLI version. +func fromSource() bool { + return Version == versionDev +} + // resolveDevVersion creates a string for version printing if the version being used is "development". // the version will be of the form "LATEST-dev" where LATEST is the latest tagged release. func resolveDevVersion(ctx context.Context) string { @@ -108,24 +129,65 @@ func resolveDevVersion(ctx context.Context) string { } // Long generates a detailed version info. -func Long(ctx context.Context) string { +func Long(ctx context.Context) (string, error) { + var ( + w = &tabwriter.Writer{} + b = &bytes.Buffer{} + ) + + info, err := GetInfo(ctx) + if err != nil { + return "", err + } + + write := func(k, v string) { + fmt.Fprintf(w, "%s:\t%s\n", k, v) + } + w.Init(b, 0, 8, 0, '\t', 0) + + write("Ignite CLI version", info.CLIVersion) + write("Ignite CLI build date", info.BuildDate) + write("Ignite CLI source hash", info.SourceHash) + write("Ignite CLI config version", info.ConfigVersion) + write("Cosmos SDK version", info.SDKVersion) + + write("Your OS", info.OS) + write("Your arch", info.Arch) + write("Your go version", info.GoVersion) + write("Your uname -a", info.Uname) + + if info.CWD != "" { + write("Your cwd", info.CWD) + } + + write("Is on Gitpod", strconv.FormatBool(info.IsGitpod)) + + if err := w.Flush(); err != nil { + return "", err + } + + return b.String(), nil +} + +// GetInfo gets the CLI info. +func GetInfo(ctx context.Context) (Info, error) { var ( - w = &tabwriter.Writer{} - b = &bytes.Buffer{} + info Info + modified bool + date = "undefined" head = "undefined" - modified bool sdkVersion = "undefined" ) - if info, ok := debug.ReadBuildInfo(); ok { - for _, dep := range info.Deps { + if buildInfo, ok := debug.ReadBuildInfo(); ok { + for _, dep := range buildInfo.Deps { if cosmosver.CosmosSDKModulePathPattern.MatchString(dep.Path) { sdkVersion = dep.Version break } } - for _, kv := range info.Settings { + for _, kv := range buildInfo.Settings { switch kv.Key { case "vcs.revision": head = kv.Value @@ -141,59 +203,41 @@ func Long(ctx context.Context) string { } } - write := func(k string, v interface{}) { - fmt.Fprintf(w, "%s:\t%v\n", k, v) - } - - w.Init(b, 0, 8, 0, '\t', 0) - - write("Ignite CLI version", resolveDevVersion(ctx)) - write("Ignite CLI build date", date) - write("Ignite CLI source hash", head) - write("Ignite CLI config version", chainconfig.LatestVersion) - write("Cosmos SDK version", sdkVersion) - - write("Your OS", runtime.GOOS) - write("Your arch", runtime.GOARCH) - - cmdOut := &bytes.Buffer{} - - nodeJSCmd := "node" - if xexec.IsCommandAvailable(nodeJSCmd) { - cmdOut.Reset() - - err := exec.Exec(ctx, []string{nodeJSCmd, "-v"}, exec.StepOption(step.Stdout(cmdOut))) - if err == nil { - write("Your Node.js version", strings.TrimSpace(cmdOut.String())) - } - } - - cmdOut.Reset() - err := exec.Exec(ctx, []string{"go", "version"}, exec.StepOption(step.Stdout(cmdOut))) - if err != nil { - panic(err) + goVersionBuf := &bytes.Buffer{} + if err := exec.Exec(ctx, []string{"go", "version"}, exec.StepOption(step.Stdout(goVersionBuf))); err != nil { + return info, err } - write("Your go version", strings.TrimSpace(cmdOut.String())) - unameCmd := "uname" + var ( + unameCmd = "uname" + uname = "" + ) if xexec.IsCommandAvailable(unameCmd) { - cmdOut.Reset() - - err := exec.Exec(ctx, []string{unameCmd, "-a"}, exec.StepOption(step.Stdout(cmdOut))) - if err == nil { - write("Your uname -a", strings.TrimSpace(cmdOut.String())) + unameBuf := &bytes.Buffer{} + unameBuf.Reset() + if err := exec.Exec(ctx, []string{unameCmd, "-a"}, exec.StepOption(step.Stdout(unameBuf))); err != nil { + return info, err } + uname = strings.TrimSpace(unameBuf.String()) } + info.Uname = uname + info.CLIVersion = resolveDevVersion(ctx) + info.BuildDate = date + info.SourceHash = head + info.ConfigVersion = fmt.Sprintf("v%d", chainconfig.LatestVersion) + info.SDKVersion = sdkVersion + info.OS = runtime.GOOS + info.Arch = runtime.GOARCH + info.GoVersion = strings.TrimSpace(goVersionBuf.String()) + info.IsGitpod = gitpod.IsOnGitpod() + info.BuildFromSource = fromSource() + if cwd, err := os.Getwd(); err == nil { - write("Your cwd", cwd) + info.CWD = cwd } - write("Is on Gitpod", gitpod.IsOnGitpod()) - - w.Flush() - - return b.String() + return info, nil } // AssertSupportedCosmosSDKVersion asserts that a Cosmos SDK version is supported by Ignite CLI. diff --git a/integration/plugin/testdata/example-plugin/go.mod b/integration/plugin/testdata/example-plugin/go.mod index fa81cbccaf..c94900f976 100644 --- a/integration/plugin/testdata/example-plugin/go.mod +++ b/integration/plugin/testdata/example-plugin/go.mod @@ -1,8 +1,8 @@ module example-plugin -go 1.21.1 +go 1.22 -toolchain go1.21.4 +toolchain go1.22.3 require ( github.com/hashicorp/go-plugin v1.6.0 From 7b42eceb9de9898f98f52115e21a2da456cf0607 Mon Sep 17 00:00:00 2001 From: Pantani Date: Tue, 28 May 2024 02:45:55 +0200 Subject: [PATCH 05/13] build analytics url --- ignite/internal/analytics/analytics.go | 3 +- ignite/pkg/matomo/matomo.go | 95 ++++++++++++++------------ 2 files changed, 52 insertions(+), 46 deletions(-) diff --git a/ignite/internal/analytics/analytics.go b/ignite/internal/analytics/analytics.go index e234ad819a..faddb5eac0 100644 --- a/ignite/internal/analytics/analytics.go +++ b/ignite/internal/analytics/analytics.go @@ -1,6 +1,7 @@ package analytics import ( + "context" "encoding/json" "os" "path/filepath" @@ -54,7 +55,7 @@ func SendMetric(wg *sync.WaitGroup, cmd *cobra.Command) { return } - versionInfo, err := version.GetInfo(cmd.Context()) + versionInfo, err := version.GetInfo(context.Background()) if err != nil { return } diff --git a/ignite/pkg/matomo/matomo.go b/ignite/pkg/matomo/matomo.go index 63167c7bfb..cbd8b54198 100644 --- a/ignite/pkg/matomo/matomo.go +++ b/ignite/pkg/matomo/matomo.go @@ -21,12 +21,15 @@ type ( endpoint string idSite uint // Matomo ID Site. tokenAuth string // Matomo Token Auth. + source string httpClient http.Client } + // Params analytics metrics body. Params struct { IDSite uint `url:"idsite"` Rec uint `url:"rec"` + ActionName string `url:"action_name"` APIVersion uint `url:"apiv,omitempty"` TokenAuth string `url:"token_auth,omitempty"` CustomAction uint `url:"ca,omitempty"` @@ -38,64 +41,63 @@ type ( UTMContent string `url:"utm_content,omitempty"` UserID string `url:"uid,omitempty"` UserAgent string `url:"ua,omitempty"` - ActionName string `url:"action_name"` Hour int `url:"h,omitempty"` Minute int `url:"m,omitempty"` Second int `url:"s,omitempty"` // Dimension1 development mode boolean. // 1 = devMode ON | 0 = devMode OFF. - Dimension1 uint `url:"dimension1"` + Dimension1 uint `url:"dimension1,omitempty"` // Dimension2 internal boolean. // 1 = internal ON not supported at present | 0 = internal OFF. - Dimension2 uint `url:"dimension2"` + Dimension2 uint `url:"dimension2,omitempty"` // Dimension3 is gitpod (0 or 1). // 1 = isGitpod ON | 0 = isGitpod OFF. - Dimension3 uint `url:"dimension3"` + Dimension3 uint `url:"dimension3,omitempty"` // Dimension4 ignite version - Dimension4 string `url:"dimension4"` + Dimension4 string `url:"dimension4,omitempty"` // Dimension6 ignite config version - Dimension6 string `url:"dimension6"` + Dimension6 string `url:"dimension6,omitempty"` // Dimension7 full cli command - Dimension7 string `url:"dimension7"` + Dimension7 string `url:"dimension7,omitempty"` // Dimension11 scaffold customization type - Dimension11 string `url:"dimension11"` + Dimension11 string `url:"dimension11,omitempty"` // Dimension13 command level 1. - Dimension13 string `url:"dimension13"` + Dimension13 string `url:"dimension13,omitempty"` // Dimension14 command level 2. - Dimension14 string `url:"dimension14"` + Dimension14 string `url:"dimension14,omitempty"` // Dimension15 command level 3. - Dimension15 string `url:"dimension15"` + Dimension15 string `url:"dimension15,omitempty"` // Dimension16 command level 4. - Dimension16 string `url:"dimension16"` + Dimension16 string `url:"dimension16,omitempty"` // Dimension17 cosmos-sdk version. - Dimension17 string `url:"dimension17"` + Dimension17 string `url:"dimension17,omitempty"` // Dimension18 operational system. - Dimension18 string `url:"dimension18"` + Dimension18 string `url:"dimension18,omitempty"` // Dimension19 system architecture. - Dimension19 string `url:"dimension19"` + Dimension19 string `url:"dimension19,omitempty"` // Dimension20 golang version. - Dimension20 string `url:"dimension20"` + Dimension20 string `url:"dimension20,omitempty"` // Dimension21 command level 5. - Dimension21 string `url:"dimension21"` + Dimension21 string `url:"dimension21,omitempty"` // Dimension22 command level 6. - Dimension22 string `url:"dimension22"` + Dimension22 string `url:"dimension22,omitempty"` } // Metric represents a custom data. Metric struct { @@ -136,10 +138,18 @@ func WithTokenAuth(tokenAuth string) Option { } } +// WithSource adds a matomo URL source. +func WithSource(source string) Option { + return func(c *Client) { + c.source = source + } +} + // New creates a new Matomo client. func New(endpoint string, opts ...Option) Client { c := Client{ endpoint: endpoint, + source: endpoint, httpClient: http.Client{ Timeout: 1500 * time.Millisecond, }, @@ -185,22 +195,6 @@ func (c Client) Send(params Params) error { return nil } -func splitCMD(cmd string) []string { - slipCmd := strings.Split(cmd, " ") - result := make([]string, 6) - for i := 0; i < len(slipCmd); i++ { - if i > 5 { - break - } - result[i] = slipCmd[i] - } - return result -} - -func (c Client) metricURL(cmd string) string { - return fmt.Sprintf("%s/%s", c.endpoint, strings.ReplaceAll(cmd, " ", "_")) -} - // SendMetric build the metrics and send to analytics. func (c Client) SendMetric(sessionID string, metric Metric) error { var ( @@ -212,16 +206,7 @@ func (c Client) SendMetric(sessionID string, metric Metric) error { utmMedium = "binary" } - slipCmd := strings.Split(metric.Cmd, " ") - result := make([]string, 5) - for i := 0; i < len(result); i++ { - if i <= len(result) { - break - } - result[i] = slipCmd[i] - } - - cmd := splitCMD(metric.Cmd) + cmd := splitCommand(metric.Cmd) return c.Send(Params{ IDSite: c.idSite, @@ -231,7 +216,7 @@ func (c Client) SendMetric(sessionID string, metric Metric) error { CustomAction: 1, Rand: r.Uint64(), URL: c.metricURL(metric.Cmd), - UTMSource: c.endpoint, + UTMSource: c.source, UTMMedium: utmMedium, UTMCampaign: metric.SourceHash, UTMContent: metric.CLIVersion, @@ -268,3 +253,23 @@ func formatBool(b bool) uint { } return 0 } + +// splitCommand splice the command into a slice with length 6. +func splitCommand(cmd string) []string { + var ( + splitCmd = strings.Split(cmd, " ") + cmdLevels = make([]string, 6) + ) + for i := 0; i < len(cmdLevels); i++ { + if i >= len(splitCmd) { + break + } + cmdLevels[i] = splitCmd[i] + } + return cmdLevels +} + +// metricURL build the metric URL. +func (c Client) metricURL(cmd string) string { + return fmt.Sprintf("%s/%s", c.source, strings.ReplaceAll(cmd, " ", "_")) +} From 4df424eb26eaa9e28a11cb91a4a7da6f33c8bd8d Mon Sep 17 00:00:00 2001 From: Pantani Date: Tue, 28 May 2024 15:16:47 +0200 Subject: [PATCH 06/13] fix matomo request parameters --- ignite/internal/analytics/analytics.go | 3 +- ignite/pkg/matomo/matomo.go | 116 +++++++++++++------------ 2 files changed, 61 insertions(+), 58 deletions(-) diff --git a/ignite/internal/analytics/analytics.go b/ignite/internal/analytics/analytics.go index faddb5eac0..7cd05392a8 100644 --- a/ignite/internal/analytics/analytics.go +++ b/ignite/internal/analytics/analytics.go @@ -40,7 +40,8 @@ type anonIdentity struct { func init() { matomoClient = matomo.New( telemetryEndpoint, - matomo.WithIDSite(4), // TODO remove me + matomo.WithIDSite(4), + matomo.WithSource("https://cli.ignite.com"), ) } diff --git a/ignite/pkg/matomo/matomo.go b/ignite/pkg/matomo/matomo.go index cbd8b54198..3854bd9427 100644 --- a/ignite/pkg/matomo/matomo.go +++ b/ignite/pkg/matomo/matomo.go @@ -27,35 +27,34 @@ type ( // Params analytics metrics body. Params struct { - IDSite uint `url:"idsite"` - Rec uint `url:"rec"` - ActionName string `url:"action_name"` - APIVersion uint `url:"apiv,omitempty"` - TokenAuth string `url:"token_auth,omitempty"` - CustomAction uint `url:"ca,omitempty"` - Rand uint64 `url:"rand,omitempty"` - URL string `url:"url,omitempty"` - UTMSource string `url:"utm_source,omitempty"` - UTMMedium string `url:"utm_medium,omitempty"` - UTMCampaign string `url:"utm_campaign,omitempty"` - UTMContent string `url:"utm_content,omitempty"` - UserID string `url:"uid,omitempty"` - UserAgent string `url:"ua,omitempty"` - Hour int `url:"h,omitempty"` - Minute int `url:"m,omitempty"` - Second int `url:"s,omitempty"` + IDSite uint `url:"idsite"` + Rec uint `url:"rec"` + ActionName string `url:"action_name"` + APIVersion uint `url:"apiv"` + TokenAuth string `url:"token_auth,omitempty"` + Rand uint64 `url:"rand,omitempty"` + URL string `url:"url,omitempty"` + UTMSource string `url:"utm_source,omitempty"` + UTMMedium string `url:"utm_medium,omitempty"` + UTMCampaign string `url:"utm_campaign,omitempty"` + UTMContent string `url:"utm_content,omitempty"` + UserID string `url:"uid,omitempty"` + UserAgent string `url:"ua,omitempty"` + Hour int `url:"h,omitempty"` + Minute int `url:"m,omitempty"` + Second int `url:"s,omitempty"` // Dimension1 development mode boolean. // 1 = devMode ON | 0 = devMode OFF. - Dimension1 uint `url:"dimension1,omitempty"` + Dimension1 uint `url:"dimension1"` // Dimension2 internal boolean. // 1 = internal ON not supported at present | 0 = internal OFF. - Dimension2 uint `url:"dimension2,omitempty"` + Dimension2 uint `url:"dimension2"` // Dimension3 is gitpod (0 or 1). // 1 = isGitpod ON | 0 = isGitpod OFF. - Dimension3 uint `url:"dimension3,omitempty"` + Dimension3 uint `url:"dimension3"` // Dimension4 ignite version Dimension4 string `url:"dimension4,omitempty"` @@ -198,51 +197,54 @@ func (c Client) Send(params Params) error { // SendMetric build the metrics and send to analytics. func (c Client) SendMetric(sessionID string, metric Metric) error { var ( - now = time.Now() - r = rand.New(rand.NewSource(now.Unix())) - utmMedium = "dev" + now = time.Now() + r = rand.New(rand.NewSource(now.Unix())) + utmMedium = "dev" + isCI uint = 0 ) if !metric.BuildFromSource { utmMedium = "binary" } + if metric.IsCI { + isCI = 1 + } cmd := splitCommand(metric.Cmd) return c.Send(Params{ - IDSite: c.idSite, - Rec: 1, - APIVersion: 1, - TokenAuth: c.tokenAuth, - CustomAction: 1, - Rand: r.Uint64(), - URL: c.metricURL(metric.Cmd), - UTMSource: c.source, - UTMMedium: utmMedium, - UTMCampaign: metric.SourceHash, - UTMContent: metric.CLIVersion, - UserID: sessionID, - UserAgent: "Go-http-client", - ActionName: metric.Cmd, - Hour: now.Hour(), - Minute: now.Minute(), - Second: now.Second(), - Dimension1: 0, - Dimension2: 0, - Dimension3: formatBool(metric.IsGitPod), - Dimension4: metric.Version, - Dimension6: metric.ConfigVersion, - Dimension7: metric.Cmd, - Dimension11: metric.ScaffoldType, - Dimension13: cmd[0], - Dimension14: cmd[1], - Dimension15: cmd[2], - Dimension16: cmd[3], - Dimension17: metric.SDKVersion, - Dimension18: metric.OS, - Dimension19: metric.Arch, - Dimension20: metric.GoVersion, - Dimension21: cmd[4], - Dimension22: cmd[5], + IDSite: c.idSite, + Rec: 1, + APIVersion: 1, + TokenAuth: c.tokenAuth, + Rand: r.Uint64(), + URL: c.metricURL(metric.Cmd), + UTMSource: c.source, + UTMMedium: utmMedium, + UTMCampaign: metric.SourceHash, + UTMContent: metric.CLIVersion, + UserID: sessionID, + UserAgent: "Go-http-client", + ActionName: metric.Cmd, + Hour: now.Hour(), + Minute: now.Minute(), + Second: now.Second(), + Dimension1: 1, // TODO set to zero + Dimension2: isCI, + Dimension3: formatBool(metric.IsGitPod), + Dimension4: metric.Version, + Dimension6: metric.ConfigVersion, + Dimension7: metric.Cmd, + Dimension11: metric.ScaffoldType, + Dimension13: cmd[0], + Dimension14: cmd[1], + Dimension15: cmd[2], + Dimension16: cmd[3], + Dimension17: metric.SDKVersion, + Dimension18: metric.OS, + Dimension19: metric.Arch, + Dimension20: metric.GoVersion, + Dimension21: cmd[4], + Dimension22: cmd[5], }) } From 9f680eaa18644c61faa52b09b76f142872f06c6e Mon Sep 17 00:00:00 2001 From: Pantani Date: Tue, 28 May 2024 15:38:58 +0200 Subject: [PATCH 07/13] remove unused parameters and improve readability --- ignite/pkg/matomo/matomo.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/ignite/pkg/matomo/matomo.go b/ignite/pkg/matomo/matomo.go index 3854bd9427..1a8fed696b 100644 --- a/ignite/pkg/matomo/matomo.go +++ b/ignite/pkg/matomo/matomo.go @@ -197,17 +197,13 @@ func (c Client) Send(params Params) error { // SendMetric build the metrics and send to analytics. func (c Client) SendMetric(sessionID string, metric Metric) error { var ( - now = time.Now() - r = rand.New(rand.NewSource(now.Unix())) - utmMedium = "dev" - isCI uint = 0 + now = time.Now() + r = rand.New(rand.NewSource(now.Unix())) + utmMedium = "dev" ) if !metric.BuildFromSource { utmMedium = "binary" } - if metric.IsCI { - isCI = 1 - } cmd := splitCommand(metric.Cmd) @@ -228,8 +224,8 @@ func (c Client) SendMetric(sessionID string, metric Metric) error { Hour: now.Hour(), Minute: now.Minute(), Second: now.Second(), - Dimension1: 1, // TODO set to zero - Dimension2: isCI, + Dimension1: 0, + Dimension2: formatBool(metric.IsCI), Dimension3: formatBool(metric.IsGitPod), Dimension4: metric.Version, Dimension6: metric.ConfigVersion, From faffd9d8127ea07ac5a70f0982c3fb2fa7d3bf2e Mon Sep 17 00:00:00 2001 From: Pantani Date: Tue, 28 May 2024 16:08:00 +0200 Subject: [PATCH 08/13] remove unused matomo request response parser --- ignite/pkg/matomo/matomo.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/ignite/pkg/matomo/matomo.go b/ignite/pkg/matomo/matomo.go index 1a8fed696b..4f7019b215 100644 --- a/ignite/pkg/matomo/matomo.go +++ b/ignite/pkg/matomo/matomo.go @@ -3,7 +3,6 @@ package matomo import ( "fmt" - "io" "math/rand" "net/http" "net/url" @@ -181,12 +180,6 @@ func (c Client) Send(params Params) error { } defer resp.Body.Close() - got, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - fmt.Println(string(got)) - if resp.StatusCode != http.StatusOK { return errors.Errorf("error to add matomo analytics metric. Status code: %d", resp.StatusCode) } From ecf24242e26f9753f13aed019fd95e9eebbb8ddd Mon Sep 17 00:00:00 2001 From: Pantani Date: Wed, 29 May 2024 18:04:56 +0200 Subject: [PATCH 09/13] fix analytics data --- ignite/pkg/matomo/matomo.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ignite/pkg/matomo/matomo.go b/ignite/pkg/matomo/matomo.go index 4f7019b215..d71e9e88ea 100644 --- a/ignite/pkg/matomo/matomo.go +++ b/ignite/pkg/matomo/matomo.go @@ -207,9 +207,9 @@ func (c Client) SendMetric(sessionID string, metric Metric) error { TokenAuth: c.tokenAuth, Rand: r.Uint64(), URL: c.metricURL(metric.Cmd), - UTMSource: c.source, + UTMSource: "source", UTMMedium: utmMedium, - UTMCampaign: metric.SourceHash, + UTMCampaign: fmt.Sprintf("commit-%s", metric.SourceHash), UTMContent: metric.CLIVersion, UserID: sessionID, UserAgent: "Go-http-client", From 69a63f791c925771647412c1495aac5a61db6bae Mon Sep 17 00:00:00 2001 From: Pantani Date: Wed, 29 May 2024 18:39:00 +0200 Subject: [PATCH 10/13] change the source name to github --- ignite/pkg/matomo/matomo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ignite/pkg/matomo/matomo.go b/ignite/pkg/matomo/matomo.go index d71e9e88ea..f388203df4 100644 --- a/ignite/pkg/matomo/matomo.go +++ b/ignite/pkg/matomo/matomo.go @@ -207,7 +207,7 @@ func (c Client) SendMetric(sessionID string, metric Metric) error { TokenAuth: c.tokenAuth, Rand: r.Uint64(), URL: c.metricURL(metric.Cmd), - UTMSource: "source", + UTMSource: "github", UTMMedium: utmMedium, UTMCampaign: fmt.Sprintf("commit-%s", metric.SourceHash), UTMContent: metric.CLIVersion, From f5e216c4929eed4a0b8abde6a48ae18900ff245e Mon Sep 17 00:00:00 2001 From: Pantani Date: Fri, 31 May 2024 11:44:35 +0200 Subject: [PATCH 11/13] fix UTM values --- ignite/pkg/matomo/matomo.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ignite/pkg/matomo/matomo.go b/ignite/pkg/matomo/matomo.go index f388203df4..4c05e5967d 100644 --- a/ignite/pkg/matomo/matomo.go +++ b/ignite/pkg/matomo/matomo.go @@ -207,10 +207,10 @@ func (c Client) SendMetric(sessionID string, metric Metric) error { TokenAuth: c.tokenAuth, Rand: r.Uint64(), URL: c.metricURL(metric.Cmd), - UTMSource: "github", + UTMSource: "source-code-github", UTMMedium: utmMedium, - UTMCampaign: fmt.Sprintf("commit-%s", metric.SourceHash), - UTMContent: metric.CLIVersion, + UTMCampaign: metric.CLIVersion, + UTMContent: fmt.Sprintf("commit-%s", metric.SourceHash), UserID: sessionID, UserAgent: "Go-http-client", ActionName: metric.Cmd, From 88d1580fdcf2f5be6b964952188ba295b2d389f7 Mon Sep 17 00:00:00 2001 From: Pantani Date: Mon, 3 Jun 2024 18:28:25 +0200 Subject: [PATCH 12/13] fix scaffold type condition --- ignite/internal/analytics/analytics.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ignite/internal/analytics/analytics.go b/ignite/internal/analytics/analytics.go index 7cd05392a8..2ea1c5e538 100644 --- a/ignite/internal/analytics/analytics.go +++ b/ignite/internal/analytics/analytics.go @@ -65,10 +65,10 @@ func SendMetric(wg *sync.WaitGroup, cmd *cobra.Command) { path = cmd.CommandPath() scaffoldType = "" ) - if strings.Contains(path, "ignite scaffold type") { + if strings.Contains(path, "ignite scaffold") { splitCMD := strings.Split(path, " ") - if len(splitCMD) > 3 { - scaffoldType = splitCMD[3] + if len(splitCMD) > 2 { + scaffoldType = splitCMD[2] } } From 226722dd5268e17610cf690cb1bd5826d6e815f5 Mon Sep 17 00:00:00 2001 From: Pantani Date: Mon, 3 Jun 2024 18:28:59 +0200 Subject: [PATCH 13/13] remove gacli pkg --- ignite/pkg/gacli/gacli.go | 126 -------------------------------------- 1 file changed, 126 deletions(-) delete mode 100644 ignite/pkg/gacli/gacli.go diff --git a/ignite/pkg/gacli/gacli.go b/ignite/pkg/gacli/gacli.go deleted file mode 100644 index b6fc24f734..0000000000 --- a/ignite/pkg/gacli/gacli.go +++ /dev/null @@ -1,126 +0,0 @@ -// Package gacli is a client for Google Analytics to send data points for hint-type=event. -package gacli - -import ( - "bytes" - "encoding/json" - "net/http" - "net/url" - "strings" - "time" - - "github.com/ignite/cli/v29/ignite/pkg/errors" -) - -type ( - // Client is an analytics client. - Client struct { - endpoint string - measurementID string // Google Analytics measurement ID. - apiSecret string // Google Analytics API secret. - httpClient http.Client - } - // Body analytics metrics body. - Body struct { - ClientID string `json:"client_id"` - Events []Event `json:"events"` - } - // Event analytics event. - Event struct { - Name string `json:"name"` - Params Metric `json:"params"` - } - // Metric represents a data point. - Metric struct { - Name string `json:"name,omitempty"` - Cmd string `json:"command,omitempty"` - Tag string `json:"tag,omitempty"` - OS string `json:"os,omitempty"` - Arch string `json:"arch,omitempty"` - Version string `json:"version,omitempty"` - SessionID string `json:"session_id,omitempty"` - EngagementTimeMsec string `json:"engagement_time_msec,omitempty"` - IsGitPod bool `json:"is_git_pod,omitempty"` - IsCI bool `json:"is_ci,omitempty"` - } -) - -// Option configures code generation. -type Option func(*Client) - -// WithMeasurementID adds an analytics measurement ID. -func WithMeasurementID(measurementID string) Option { - return func(c *Client) { - c.measurementID = measurementID - } -} - -// WithAPISecret adds an analytics API secret. -func WithAPISecret(secret string) Option { - return func(c *Client) { - c.apiSecret = secret - } -} - -// New creates a new analytics client with -// measure id and secret key. -func New(endpoint string, opts ...Option) Client { - c := Client{ - endpoint: endpoint, - httpClient: http.Client{ - Timeout: 1500 * time.Millisecond, - }, - } - // apply analytics options. - for _, o := range opts { - o(&c) - } - return c -} - -// Send sends metric event to analytics. -func (c Client) Send(body Body) error { - // encode body. - encoded, err := json.Marshal(body) - if err != nil { - return err - } - - requestURL, err := url.Parse(c.endpoint) - if err != nil { - return err - } - v := requestURL.Query() - if c.measurementID != "" { - v.Set("measurement_id", c.measurementID) - } - if c.apiSecret != "" { - v.Set("api_secret", c.apiSecret) - } - requestURL.RawQuery = v.Encode() - - // Create an HTTP request with the payload. - resp, err := c.httpClient.Post(requestURL.String(), "application/json", bytes.NewBuffer(encoded)) - if err != nil { - return errors.Wrapf(err, "error creating HTTP request: %s", requestURL.String()) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK && - resp.StatusCode != http.StatusNoContent { - return errors.Errorf("error to add google analytics metric. Status code: %d", resp.StatusCode) - } - return nil -} - -// SendMetric build the metrics and send to analytics. -func (c Client) SendMetric(metric Metric) error { - metric.EngagementTimeMsec = "100" - return c.Send(Body{ - ClientID: metric.SessionID, - Events: []Event{{ - Name: strings.ReplaceAll(metric.Cmd, " ", "_"), - Params: metric, - }}, - }) -}