Skip to content

Commit

Permalink
tiltfile: add experimental_analytics_report (#3751)
Browse files Browse the repository at this point in the history
  • Loading branch information
landism committed Sep 3, 2020
1 parent 9a3c2bd commit 10045df
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 12 deletions.
39 changes: 36 additions & 3 deletions internal/tiltfile/analytics/analytics.go
Expand Up @@ -5,10 +5,12 @@ import (
"go.starlark.net/starlark"

"github.com/tilt-dev/tilt/internal/tiltfile/starkit"
"github.com/tilt-dev/tilt/internal/tiltfile/value"
)

type Settings struct {
Opt analytics.Opt
Opt analytics.Opt
CustomTagsToReport map[string]string
}

type Extension struct {
Expand All @@ -20,12 +22,26 @@ func NewExtension() Extension {

func (e Extension) NewState() interface{} {
return Settings{
Opt: analytics.OptDefault,
Opt: analytics.OptDefault,
CustomTagsToReport: make(map[string]string),
}
}

func (Extension) OnStart(env *starkit.Environment) error {
return env.AddBuiltin("analytics_settings", setAnalyticsSettings)
err := env.AddBuiltin("analytics_settings", setAnalyticsSettings)
if err != nil {
return err
}

// This is an experimental feature to allow Tiltfiles to specify custom data to report to analytics
// to allow teams to get more visibility into, e.g., who's using Tilt or what k8s distributions are
// their members using. It is not intended for use without coordinating with the Tilt team.
err = env.AddBuiltin("experimental_analytics_report", reportCustomTags)
if err != nil {
return err
}

return nil
}

func setAnalyticsSettings(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
Expand All @@ -47,6 +63,23 @@ func setAnalyticsSettings(thread *starlark.Thread, fn *starlark.Builtin, args st
return starlark.None, err
}

func reportCustomTags(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
var tags value.StringStringMap
if err := starkit.UnpackArgs(thread, fn.Name(), args, kwargs, "tags", &tags); err != nil {
return nil, err
}

err := starkit.SetState(thread, func(settings Settings) Settings {
for k, v := range tags {
settings.CustomTagsToReport[k] = v
}

return settings
})

return starlark.None, err
}

var _ starkit.StatefulExtension = Extension{}

func MustState(model starkit.Model) Settings {
Expand Down
12 changes: 12 additions & 0 deletions internal/tiltfile/analytics/analytics_test.go
Expand Up @@ -39,6 +39,18 @@ analytics_settings(enable=False)
assert.Equal(t, analytics.OptOut, MustState(result).Opt)
}

func TestReportToAnalytics(t *testing.T) {
f := NewFixture(t)
f.File("Tiltfile", `
experimental_analytics_report({'1': '2'})
# the second call's "1" value replaces the first
experimental_analytics_report({'1': '2a', '3': '4'})
`)
result, err := f.ExecFile("Tiltfile")
assert.NoError(t, err)
assert.Equal(t, map[string]string{"1": "2a", "3": "4"}, MustState(result).CustomTagsToReport)
}

func NewFixture(tb testing.TB) *starkit.Fixture {
return starkit.NewFixture(tb, NewExtension())
}
8 changes: 8 additions & 0 deletions internal/tiltfile/tiltfile.go
Expand Up @@ -220,6 +220,10 @@ func (tfl tiltfileLoader) Load(ctx context.Context, filename string, userConfigS
s.logger.Infof("Successfully loaded Tiltfile (%s)", duration)
tfl.reportTiltfileLoaded(s.builtinCallCounts, s.builtinArgCounts, duration)

if len(aSettings.CustomTagsToReport) > 0 {
reportCustomTags(tfl.analytics, aSettings.CustomTagsToReport)
}

return tlr
}

Expand All @@ -232,6 +236,10 @@ func starlarkValueOrSequenceToSlice(v starlark.Value) []starlark.Value {
return value.ValueOrSequenceToSlice(v)
}

func reportCustomTags(a *analytics.TiltAnalytics, tags map[string]string) {
a.Incr("tiltfile.custom.report", tags)
}

func (tfl *tiltfileLoader) reportTiltfileLoaded(callCounts map[string]int,
argCounts map[string]map[string]int, loadDur time.Duration) {
tags := make(map[string]string)
Expand Down
38 changes: 29 additions & 9 deletions internal/tiltfile/tiltfile_test.go
Expand Up @@ -4850,15 +4850,7 @@ allow_k8s_contexts("hello")

f.load()

// get the exactly one CountEvent named tiltfile.loaded
var countEvent analytics.CountEvent
for _, ce := range f.an.Counts {
if ce.Name == "tiltfile.loaded" {
require.Equal(t, "", countEvent.Name, "two count events named tiltfile.loaded")
countEvent = ce
}
}
require.NotEqual(t, "", countEvent.Name, "no count event named tiltfile.loaded")
countEvent := f.SingleAnalyticsEvent("tiltfile.loaded")

// make sure it has all the expected builtin call counts
expectedCounts := map[string]string{
Expand All @@ -4874,6 +4866,21 @@ allow_k8s_contexts("hello")
}
}

func TestCustomTagsReported(t *testing.T) {
f := newFixture(t)
defer f.TearDown()

f.file("Tiltfile", `
experimental_analytics_report({'foo': 'bar'})
`)

f.load()

countEvent := f.SingleAnalyticsEvent("tiltfile.custom.report")

require.Equal(t, map[string]string{"foo": "bar"}, countEvent.Tags)
}

func TestK8sResourceObjectsAddsNonWorkload(t *testing.T) {
f := newFixture(t)
defer f.TearDown()
Expand Down Expand Up @@ -6394,3 +6401,16 @@ func overwriteSelectorsForService(entity *k8s.K8sEntity, labels map[string]strin
svc.Spec.Selector = labels
return nil
}

func (f *fixture) SingleAnalyticsEvent(name string) analytics.CountEvent {
var ret analytics.CountEvent
for _, ce := range f.an.Counts {
if ce.Name == name {
require.Equalf(f.t, "", ret.Name, "two count events named %s", name)
ret = ce
}
}
require.NotEqualf(f.t, "", ret.Name, "no count event named %s", name)

return ret
}

0 comments on commit 10045df

Please sign in to comment.