github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/analytics/tilt_analytics.go (about)

     1  package analytics
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/tilt-dev/wmclient/pkg/analytics"
     7  )
     8  
     9  const TagVersion = "version"
    10  const TagOS = "os"
    11  const TagGitRepoHash = "git.origin"
    12  const TagSubcommand = "subcommand"
    13  
    14  // An Analytics that allows opting in/out at runtime.
    15  type TiltAnalytics struct {
    16  	opter       AnalyticsOpter
    17  	a           analytics.Analytics
    18  	tiltVersion string
    19  
    20  	// We make this a constant pointer to a struct.
    21  	// That way, the struct returned by WithoutGlobalTags() can
    22  	// point to the same opt set.
    23  	opt *optSet
    24  }
    25  
    26  type optSet struct {
    27  	env      analytics.Opt
    28  	user     analytics.Opt
    29  	tiltfile analytics.Opt
    30  }
    31  
    32  // An AnalyticsOpter can record a user's choice (opt-in or opt-out)
    33  // in re: Tilt recording analytics.
    34  type AnalyticsOpter interface {
    35  	SetUserOpt(opt analytics.Opt) error
    36  	ReadUserOpt() (analytics.Opt, error)
    37  }
    38  
    39  func NewTiltAnalytics(opter AnalyticsOpter, a analytics.Analytics, tiltVersion string) (*TiltAnalytics, error) {
    40  	userOpt, err := opter.ReadUserOpt()
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	envOpt := analytics.OptDefault
    45  	if ok, _ := IsAnalyticsDisabledFromEnv(); ok {
    46  		envOpt = analytics.OptOut
    47  	}
    48  	return &TiltAnalytics{
    49  		opter:       opter,
    50  		a:           a,
    51  		tiltVersion: tiltVersion,
    52  		opt: &optSet{
    53  			env:      envOpt,
    54  			user:     userOpt,
    55  			tiltfile: analytics.OptDefault,
    56  		},
    57  	}, nil
    58  }
    59  
    60  // NOTE: if you need a ctx as well, use testutils.CtxAndAnalyticsForTest so that you get
    61  // a ctx with the correct analytics baked in.
    62  func NewMemoryTiltAnalyticsForTest(opter AnalyticsOpter) (*analytics.MemoryAnalytics, *TiltAnalytics) {
    63  	ma := analytics.NewMemoryAnalytics()
    64  	ta, err := NewTiltAnalytics(opter, ma, "v0.0.0")
    65  	if err != nil {
    66  		panic(err)
    67  	}
    68  	ta.opt.env = analytics.OptDefault
    69  	return ma, ta
    70  }
    71  
    72  func (ta *TiltAnalytics) GlobalTag(name string) (string, bool) {
    73  	return ta.a.GlobalTag(name)
    74  }
    75  func (ta *TiltAnalytics) MachineHash() string {
    76  	id, _ := ta.GlobalTag(analytics.TagMachine)
    77  	return id
    78  }
    79  func (ta *TiltAnalytics) GitRepoHash() string {
    80  	id, _ := ta.GlobalTag(TagGitRepoHash)
    81  	return id
    82  }
    83  func (ta *TiltAnalytics) Count(name string, tags map[string]string, n int) {
    84  	if ta.EffectiveOpt() != analytics.OptOut {
    85  		ta.a.Count(name, tags, n)
    86  	}
    87  }
    88  
    89  func (ta *TiltAnalytics) Incr(name string, tags map[string]string) {
    90  	if ta.EffectiveOpt() != analytics.OptOut {
    91  		ta.a.Incr(name, tags)
    92  	}
    93  }
    94  
    95  func (ta *TiltAnalytics) Timer(name string, dur time.Duration, tags map[string]string) {
    96  	if ta.EffectiveOpt() != analytics.OptOut {
    97  		ta.a.Timer(name, dur, tags)
    98  	}
    99  }
   100  
   101  func (ta *TiltAnalytics) Flush(timeout time.Duration) {
   102  	ta.a.Flush(timeout)
   103  }
   104  
   105  func (ta *TiltAnalytics) UserOpt() analytics.Opt {
   106  	return ta.opt.user
   107  }
   108  
   109  func (ta *TiltAnalytics) TiltfileOpt() analytics.Opt {
   110  	return ta.opt.tiltfile
   111  }
   112  
   113  func (ta *TiltAnalytics) EffectiveOpt() analytics.Opt {
   114  	if ta.opt.env != analytics.OptDefault {
   115  		return ta.opt.env
   116  	}
   117  	if ta.opt.tiltfile != analytics.OptDefault {
   118  		return ta.opt.tiltfile
   119  	}
   120  	return ta.opt.user
   121  }
   122  
   123  func (ta *TiltAnalytics) SetUserOpt(opt analytics.Opt) error {
   124  	if opt == ta.opt.user {
   125  		return nil
   126  	}
   127  	ta.opt.user = opt
   128  	return ta.opter.SetUserOpt(opt)
   129  }
   130  
   131  func (ta *TiltAnalytics) SetTiltfileOpt(opt analytics.Opt) {
   132  	ta.opt.tiltfile = opt
   133  }
   134  
   135  func (ta *TiltAnalytics) WithoutGlobalTags() analytics.Analytics {
   136  	return &TiltAnalytics{
   137  		opter:       ta.opter,
   138  		a:           ta.a.WithoutGlobalTags(),
   139  		tiltVersion: ta.tiltVersion,
   140  		opt:         ta.opt,
   141  	}
   142  }
   143  
   144  var _ analytics.Analytics = &TiltAnalytics{}