mukan-ignite/ignite/internal/analytics/analytics.go
Mukan Erkin Törük 26b204bd04
Some checks are pending
Docs Deploy / build_and_deploy (push) Waiting to run
Generate Docs / cli (push) Waiting to run
Generate Config Doc / cli (push) Waiting to run
Go formatting / go-formatting (push) Waiting to run
Check links / markdown-link-check (push) Waiting to run
Integration / pre-test (push) Waiting to run
Integration / test on (push) Blocked by required conditions
Integration / status (push) Blocked by required conditions
Lint / Lint Go code (push) Waiting to run
Test / test (ubuntu-latest) (push) Waiting to run
feat: fork Ignite CLI v29 as Mukan Ignite — remove cosmos-sdk restrictions
2026-05-11 03:31:37 +03:00

190 lines
4.4 KiB
Go

package analytics
import (
"context"
"encoding/json"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
"github.com/spf13/cobra"
"github.com/ignite/cli/v29/ignite/config"
"github.com/ignite/cli/v29/ignite/internal/sentry"
"github.com/ignite/cli/v29/ignite/pkg/cliui"
"github.com/ignite/cli/v29/ignite/pkg/errors"
"github.com/ignite/cli/v29/ignite/pkg/randstr"
"github.com/ignite/cli/v29/ignite/version"
)
const (
telemetryEndpoint = "https://api.ignite.com/v1/telemetry"
envDoNotTrack = "DO_NOT_TRACK"
envCI = "CI"
envGitHubActions = "GITHUB_ACTIONS"
igniteAnonIdentity = "anon_identity.json"
)
var matomoClient MatomoClient
// anonIdentity represents an analytics identity file.
type anonIdentity struct {
// Name represents the username.
Name string `json:"name" yaml:"name"`
// DoNotTrack represents the user track choice.
DoNotTrack bool `json:"doNotTrack" yaml:"doNotTrack"`
}
func init() {
matomoClient = NewMatomoClient(
telemetryEndpoint,
WithIDSite(4),
WithSource("https://cli.ignite.com"),
)
}
// SendMetric send command metrics to analytics.
func SendMetric(wg *sync.WaitGroup, cmd *cobra.Command) {
if cmd.Name() == "version" {
return
}
dntInfo, err := checkDNT()
if err != nil || dntInfo.DoNotTrack {
return
}
versionInfo, err := version.GetInfo(context.Background())
if err != nil {
return
}
var (
path = cmd.CommandPath()
scaffoldType = ""
)
if strings.Contains(path, "ignite scaffold") {
splitCMD := strings.Split(path, " ")
if len(splitCMD) > 2 {
scaffoldType = splitCMD[2]
}
}
met := Metric{
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,
IsCI: getIsCI(),
}
wg.Add(1)
go func() {
defer wg.Done()
_ = matomoClient.SendMetric(dntInfo.Name, met)
}()
}
// EnableSentry enable errors reporting to Sentry.
func EnableSentry(ctx context.Context, wg *sync.WaitGroup) {
dntInfo, err := checkDNT()
if err != nil || dntInfo.DoNotTrack {
return
}
closeSentry, err := sentry.InitSentry(ctx)
wg.Add(1)
go func() {
defer wg.Done()
if err == nil {
defer closeSentry()
}
}()
}
// checkDNT check if the user allow to track data or if the DO_NOT_TRACK
// env var is set https://consoledonottrack.com/
func checkDNT() (anonIdentity, error) {
if dnt := os.Getenv(envDoNotTrack); dnt != "" {
if dnt, err := strconv.ParseBool(dnt); err != nil || dnt {
return anonIdentity{DoNotTrack: true}, nil
}
}
globalPath, err := config.DirPath()
if err != nil {
return anonIdentity{}, err
}
if err := os.Mkdir(globalPath, 0o700); err != nil && !os.IsExist(err) {
return anonIdentity{}, err
}
identityPath := filepath.Join(globalPath, igniteAnonIdentity)
data, err := os.ReadFile(identityPath)
if err != nil && !os.IsNotExist(err) {
return anonIdentity{}, err
}
var i anonIdentity
if err := json.Unmarshal(data, &i); err == nil {
return i, nil
}
i.Name = randstr.Runes(16)
i.DoNotTrack = false
message := "Ignite uses anonymized metrics to enhance the application, " +
"focusing on features such as command usage. We do not collect " +
"identifiable personal information. Your privacy is important to us. " +
"For more details, please visit our Privacy Policy at https://ignite.com/privacy " +
"and our Terms of Use at https://ignite.com/terms-of-use. " +
"Do you consent to the collection of these usage metrics for analytics purposes?"
session := cliui.New()
err = session.AskConfirm(message)
if err != nil && !errors.Is(err, cliui.ErrAbort) {
return anonIdentity{}, err
}
if errors.Is(err, cliui.ErrAbort) {
i.DoNotTrack = true
}
data, err = json.Marshal(&i)
if err != nil {
return i, err
}
return i, os.WriteFile(identityPath, data, 0o600)
}
func getIsCI() bool {
ci, err := strconv.ParseBool(os.Getenv(envCI))
if err != nil {
return false
}
if ci {
return true
}
ci, err = strconv.ParseBool(os.Getenv(envGitHubActions))
if err != nil {
return false
}
return ci
}