From 79bf231f5523ad09395e6841bc258f1e0e72ed28 Mon Sep 17 00:00:00 2001 From: Sunny Guduru Date: Wed, 24 Apr 2024 15:26:43 -0700 Subject: [PATCH 1/9] added quickstart tracking --- cmd/quickstart.go | 6 ++- cmd/root.go | 2 +- internal/quickstart/container.go | 13 ++++++ internal/quickstart/show_sdk_instructions.go | 13 ++++++ internal/quickstart/toggle_flag.go | 47 ++++++++++++-------- 5 files changed, 61 insertions(+), 20 deletions(-) diff --git a/cmd/quickstart.go b/cmd/quickstart.go index 51a38f67..9e3dd2ef 100644 --- a/cmd/quickstart.go +++ b/cmd/quickstart.go @@ -11,25 +11,28 @@ import ( "ldcli/cmd/cliflags" "ldcli/cmd/validators" + "ldcli/internal/analytics" "ldcli/internal/environments" "ldcli/internal/flags" "ldcli/internal/quickstart" ) func NewQuickStartCmd( + analyticsTracker analytics.Tracker, environmentsClient environments.Client, flagsClient flags.Client, ) *cobra.Command { return &cobra.Command{ Args: validators.Validate(), Long: "", - RunE: runQuickStart(environmentsClient, flagsClient), + RunE: runQuickStart(analyticsTracker, environmentsClient, flagsClient), Short: "Setup guide to create your first feature flag", Use: "setup", } } func runQuickStart( + analyticsTracker analytics.Tracker, environmentsClient environments.Client, flagsClient flags.Client, ) func(*cobra.Command, []string) error { @@ -42,6 +45,7 @@ func runQuickStart( defer f.Close() _, err = tea.NewProgram(quickstart.NewContainerModel( + analyticsTracker, environmentsClient, flagsClient, viper.GetString(cliflags.AccessTokenFlag), diff --git a/cmd/root.go b/cmd/root.go index 48e09319..588712ca 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -132,7 +132,7 @@ func NewRootCommand( cmd.AddCommand(flagsCmd) cmd.AddCommand(membersCmd) cmd.AddCommand(projectsCmd) - cmd.AddCommand(NewQuickStartCmd(clients.EnvironmentsClient, clients.FlagsClient)) + cmd.AddCommand(NewQuickStartCmd(analyticsTracker, clients.EnvironmentsClient, clients.FlagsClient)) addAllResourceCmds(cmd, clients.GenericClient) diff --git a/internal/quickstart/container.go b/internal/quickstart/container.go index 9562bc50..f7a61c94 100644 --- a/internal/quickstart/container.go +++ b/internal/quickstart/container.go @@ -9,6 +9,7 @@ import ( tea "github.com/charmbracelet/bubbletea" "github.com/muesli/reflow/wordwrap" + "ldcli/internal/analytics" "ldcli/internal/environments" "ldcli/internal/flags" ) @@ -43,15 +44,18 @@ type ContainerModel struct { sdk sdkDetail totalSteps int width int + analyticsTracker analytics.Tracker } func NewContainerModel( + analyticsTracker analytics.Tracker, environmentsClient environments.Client, flagsClient flags.Client, accessToken string, baseUri string, ) tea.Model { return ContainerModel{ + analyticsTracker: analyticsTracker, accessToken: accessToken, baseUri: baseUri, currentModel: NewCreateFlagModel(flagsClient, accessToken, baseUri), @@ -64,6 +68,14 @@ func NewContainerModel( } func (m ContainerModel) Init() tea.Cmd { + m.analyticsTracker.SendEvent( + m.accessToken, + m.baseUri, + "CLI Setup Started", + map[string]interface{}{ + "step": "0", + }, + ) return nil } @@ -110,6 +122,7 @@ func (m ContainerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } case choseSDKMsg: m.currentModel = NewShowSDKInstructionsModel( + m.analyticsTracker, m.environmentsClient, m.accessToken, m.baseUri, diff --git a/internal/quickstart/show_sdk_instructions.go b/internal/quickstart/show_sdk_instructions.go index 1c791129..b83a184f 100644 --- a/internal/quickstart/show_sdk_instructions.go +++ b/internal/quickstart/show_sdk_instructions.go @@ -11,6 +11,7 @@ import ( "github.com/charmbracelet/glamour" "github.com/charmbracelet/lipgloss" + "ldcli/internal/analytics" "ldcli/internal/environments" "ldcli/internal/sdks" ) @@ -41,9 +42,11 @@ type showSDKInstructionsModel struct { spinner spinner.Model url string viewport viewport.Model + analyticsTracker analytics.Tracker } func NewShowSDKInstructionsModel( + analyticsTracker analytics.Tracker, environmentsClient environments.Client, accessToken string, baseUri string, @@ -67,6 +70,7 @@ func NewShowSDKInstructionsModel( h := help.New() return showSDKInstructionsModel{ + analyticsTracker: analyticsTracker, accessToken: accessToken, baseUri: baseUri, canonicalName: canonicalName, @@ -92,6 +96,15 @@ func NewShowSDKInstructionsModel( // fetch SDK instructions // fetch the environment to get values to interpolate into the instructions func (m showSDKInstructionsModel) Init() tea.Cmd { + m.analyticsTracker.SendEvent( + m.accessToken, + m.baseUri, + "CLI Setup SDK Selected", + map[string]interface{}{ + "sdk": m.canonicalName, + }, + ) + cmds := []tea.Cmd{m.spinner.Tick, readSDKInstructions(m.canonicalName)} if m.environment == nil { diff --git a/internal/quickstart/toggle_flag.go b/internal/quickstart/toggle_flag.go index 9041b0f6..5705d902 100644 --- a/internal/quickstart/toggle_flag.go +++ b/internal/quickstart/toggle_flag.go @@ -9,35 +9,38 @@ import ( tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" + "ldcli/internal/analytics" "ldcli/internal/errors" "ldcli/internal/flags" ) type toggleFlagModel struct { - accessToken string - baseUri string - client flags.Client - enabled bool - err error - flagKey string - flagWasEnabled bool - flagWasFetched bool - help help.Model - helpKeys keyMap - sdkKind string - spinner spinner.Model + accessToken string + baseUri string + client flags.Client + enabled bool + err error + flagKey string + flagWasEnabled bool + flagWasFetched bool + help help.Model + helpKeys keyMap + sdkKind string + spinner spinner.Model + analyticsTracker analytics.Tracker } -func NewToggleFlagModel(client flags.Client, accessToken string, baseUri string, flagKey string, sdkKind string) tea.Model { +func NewToggleFlagModel(analyticsTracker analytics.Tracker, client flags.Client, accessToken string, baseUri string, flagKey string, sdkKind string) tea.Model { s := spinner.New() s.Spinner = spinner.Points return toggleFlagModel{ - accessToken: accessToken, - baseUri: baseUri, - client: client, - flagKey: flagKey, - help: help.New(), + analyticsTracker: analyticsTracker, + accessToken: accessToken, + baseUri: baseUri, + client: client, + flagKey: flagKey, + help: help.New(), helpKeys: keyMap{ Back: BindingBack, Quit: BindingQuit, @@ -75,6 +78,14 @@ func (m toggleFlagModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case fetchedFlagStatusMsg: m.enabled = msg.enabled m.flagWasFetched = true + m.analyticsTracker.SendEvent( + m.accessToken, + m.baseUri, + "CLI Setup Flag Toggled", + map[string]interface{}{ + "on": m.enabled, + }, + ) case spinner.TickMsg: m.spinner, cmd = m.spinner.Update(msg) case errMsg: From 4c35140c3610c04e3a4341aae7256f917cd23961 Mon Sep 17 00:00:00 2001 From: Sunny Guduru Date: Wed, 24 Apr 2024 15:26:43 -0700 Subject: [PATCH 2/9] added quickstart tracking --- internal/quickstart/container.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/quickstart/container.go b/internal/quickstart/container.go index f7a61c94..d2e74c40 100644 --- a/internal/quickstart/container.go +++ b/internal/quickstart/container.go @@ -155,6 +155,7 @@ func (m ContainerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.err = nil case showToggleFlagMsg: m.currentModel = NewToggleFlagModel( + m.analyticsTracker, m.flagsClient, m.accessToken, m.baseUri, From 1941efc08dc6818738811761a07abf18016adcf5 Mon Sep 17 00:00:00 2001 From: Sunny Guduru Date: Wed, 24 Apr 2024 15:31:22 -0700 Subject: [PATCH 3/9] fix error by passing in tracker --- internal/quickstart/container.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/quickstart/container.go b/internal/quickstart/container.go index d2e74c40..fe7c77b9 100644 --- a/internal/quickstart/container.go +++ b/internal/quickstart/container.go @@ -105,6 +105,7 @@ func (m ContainerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case stepToggleFlag: m.currentStep -= 1 m.currentModel = NewShowSDKInstructionsModel( + m.analyticsTracker, m.environmentsClient, m.accessToken, m.baseUri, From 78f4742146790572af1dbb5ec35686b75dcd5af9 Mon Sep 17 00:00:00 2001 From: Sunny Guduru Date: Wed, 24 Apr 2024 16:04:39 -0700 Subject: [PATCH 4/9] alphabitize and also put events in inits --- internal/quickstart/choose_sdk.go | 29 +++++++++++++++----- internal/quickstart/container.go | 21 ++++++-------- internal/quickstart/create_flag.go | 22 +++++++++++---- internal/quickstart/show_sdk_instructions.go | 10 ++++++- internal/quickstart/toggle_flag.go | 16 +++++++++-- 5 files changed, 70 insertions(+), 28 deletions(-) diff --git a/internal/quickstart/choose_sdk.go b/internal/quickstart/choose_sdk.go index 303f1907..74291f12 100644 --- a/internal/quickstart/choose_sdk.go +++ b/internal/quickstart/choose_sdk.go @@ -3,6 +3,7 @@ package quickstart import ( "fmt" "io" + "ldcli/internal/analytics" "strings" "github.com/charmbracelet/bubbles/help" @@ -24,14 +25,17 @@ const ( ) type chooseSDKModel struct { - help help.Model - helpKeys keyMap - list list.Model - selectedIndex int - selectedSDK sdkDetail + accessToken string + analyticsTracker analytics.Tracker + baseUri string + help help.Model + helpKeys keyMap + list list.Model + selectedIndex int + selectedSDK sdkDetail } -func NewChooseSDKModel(selectedIndex int) tea.Model { +func NewChooseSDKModel(analyticsTracker analytics.Tracker, accessToken, baseUri string, selectedIndex int) tea.Model { l := list.New(sdksToItems(), sdkDelegate{}, 30, 9) l.Title = "Select your SDK:\n" // reset title styles @@ -43,7 +47,10 @@ func NewChooseSDKModel(selectedIndex int) tea.Model { l.SetFilteringEnabled(false) // TODO: try to get filtering working return chooseSDKModel{ - help: help.New(), + analyticsTracker: analyticsTracker, + accessToken: accessToken, + baseUri: baseUri, + help: help.New(), helpKeys: keyMap{ Back: BindingBack, CursorUp: BindingCursorUp, @@ -64,6 +71,14 @@ func NewChooseSDKModel(selectedIndex int) tea.Model { // Init sends commands when the model is created that will: // * select an SDK if it's already been selected func (m chooseSDKModel) Init() tea.Cmd { + m.analyticsTracker.SendEvent( + m.accessToken, + m.baseUri, + "CLI Setup Started", + map[string]interface{}{ + "step": "2 - sdk selection", + }, + ) return selectedSDK(m.selectedIndex) } diff --git a/internal/quickstart/container.go b/internal/quickstart/container.go index fe7c77b9..0551dd06 100644 --- a/internal/quickstart/container.go +++ b/internal/quickstart/container.go @@ -31,6 +31,7 @@ const ( // represents a step in the quick-start flow. type ContainerModel struct { accessToken string + analyticsTracker analytics.Tracker baseUri string currentModel tea.Model currentStep int @@ -44,7 +45,6 @@ type ContainerModel struct { sdk sdkDetail totalSteps int width int - analyticsTracker analytics.Tracker } func NewContainerModel( @@ -58,7 +58,7 @@ func NewContainerModel( analyticsTracker: analyticsTracker, accessToken: accessToken, baseUri: baseUri, - currentModel: NewCreateFlagModel(flagsClient, accessToken, baseUri), + currentModel: NewCreateFlagModel(analyticsTracker, flagsClient, accessToken, baseUri), currentStep: 1, environmentsClient: environmentsClient, flagsClient: flagsClient, @@ -68,14 +68,7 @@ func NewContainerModel( } func (m ContainerModel) Init() tea.Cmd { - m.analyticsTracker.SendEvent( - m.accessToken, - m.baseUri, - "CLI Setup Started", - map[string]interface{}{ - "step": "0", - }, - ) + m.currentModel.Init() return nil } @@ -97,10 +90,11 @@ func (m ContainerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.currentModel, cmd = m.currentModel.Update(msg) case stepChooseSDK: m.currentStep -= 1 - m.currentModel = NewCreateFlagModel(m.flagsClient, m.accessToken, m.baseUri) + m.currentModel = NewCreateFlagModel(m.analyticsTracker, m.flagsClient, m.accessToken, m.baseUri) + cmd = m.currentModel.Init() case stepShowSDKInstructions: m.currentStep -= 1 - m.currentModel = NewChooseSDKModel(m.sdk.index) + m.currentModel = NewChooseSDKModel(m.analyticsTracker, m.accessToken, m.baseUri, m.sdk.index) cmd = m.currentModel.Init() case stepToggleFlag: m.currentStep -= 1 @@ -137,7 +131,8 @@ func (m ContainerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.sdk = msg.sdk m.currentStep += 1 case confirmedFlagMsg: - m.currentModel = NewChooseSDKModel(0) + m.currentModel = NewChooseSDKModel(m.analyticsTracker, m.accessToken, m.baseUri, 0) + cmd = m.currentModel.Init() m.flagKey = msg.flag.key m.currentStep += 1 m.err = nil diff --git a/internal/quickstart/create_flag.go b/internal/quickstart/create_flag.go index d7bc76aa..d77a393b 100644 --- a/internal/quickstart/create_flag.go +++ b/internal/quickstart/create_flag.go @@ -9,6 +9,7 @@ import ( tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" + "ldcli/internal/analytics" "ldcli/internal/flags" ) @@ -21,6 +22,7 @@ type flag struct { type createFlagModel struct { accessToken string + analyticsTracker analytics.Tracker baseUri string client flags.Client err error @@ -32,7 +34,7 @@ type createFlagModel struct { textInput textinput.Model } -func NewCreateFlagModel(client flags.Client, accessToken, baseUri string) tea.Model { +func NewCreateFlagModel(analyticsTracker analytics.Tracker, client flags.Client, accessToken, baseUri string) tea.Model { ti := textinput.New() ti.Focus() ti.CharLimit = 156 @@ -40,10 +42,11 @@ func NewCreateFlagModel(client flags.Client, accessToken, baseUri string) tea.Mo ti.Prompt = "" return createFlagModel{ - accessToken: accessToken, - baseUri: baseUri, - client: client, - help: help.New(), + analyticsTracker: analyticsTracker, + accessToken: accessToken, + baseUri: baseUri, + client: client, + help: help.New(), helpKeys: keyMap{ Quit: BindingQuit, }, @@ -52,6 +55,15 @@ func NewCreateFlagModel(client flags.Client, accessToken, baseUri string) tea.Mo } func (m createFlagModel) Init() tea.Cmd { + m.analyticsTracker.SendEvent( + m.accessToken, + m.baseUri, + "CLI Setup Started", + map[string]interface{}{ + "step": "1 - feature flag name", + }, + ) + return nil } diff --git a/internal/quickstart/show_sdk_instructions.go b/internal/quickstart/show_sdk_instructions.go index b83a184f..f8709cf2 100644 --- a/internal/quickstart/show_sdk_instructions.go +++ b/internal/quickstart/show_sdk_instructions.go @@ -29,6 +29,7 @@ type environment struct { type showSDKInstructionsModel struct { accessToken string + analyticsTracker analytics.Tracker baseUri string canonicalName string displayName string @@ -42,7 +43,6 @@ type showSDKInstructionsModel struct { spinner spinner.Model url string viewport viewport.Model - analyticsTracker analytics.Tracker } func NewShowSDKInstructionsModel( @@ -96,6 +96,14 @@ func NewShowSDKInstructionsModel( // fetch SDK instructions // fetch the environment to get values to interpolate into the instructions func (m showSDKInstructionsModel) Init() tea.Cmd { + m.analyticsTracker.SendEvent( + m.accessToken, + m.baseUri, + "CLI Setup Started", + map[string]interface{}{ + "step": "3 - sdk installation", + }, + ) m.analyticsTracker.SendEvent( m.accessToken, m.baseUri, diff --git a/internal/quickstart/toggle_flag.go b/internal/quickstart/toggle_flag.go index 5705d902..c2de7cf5 100644 --- a/internal/quickstart/toggle_flag.go +++ b/internal/quickstart/toggle_flag.go @@ -16,6 +16,7 @@ import ( type toggleFlagModel struct { accessToken string + analyticsTracker analytics.Tracker baseUri string client flags.Client enabled bool @@ -27,7 +28,7 @@ type toggleFlagModel struct { helpKeys keyMap sdkKind string spinner spinner.Model - analyticsTracker analytics.Tracker + toggleCount int } func NewToggleFlagModel(analyticsTracker analytics.Tracker, client flags.Client, accessToken string, baseUri string, flagKey string, sdkKind string) tea.Model { @@ -51,6 +52,15 @@ func NewToggleFlagModel(analyticsTracker analytics.Tracker, client flags.Client, } func (m toggleFlagModel) Init() tea.Cmd { + m.analyticsTracker.SendEvent( + m.accessToken, + m.baseUri, + "CLI Setup Started", + map[string]interface{}{ + "step": "4 - flag toggle", + }, + ) + cmds := []tea.Cmd{ m.spinner.Tick, fetchFlagStatus(m.client, m.accessToken, m.baseUri, m.flagKey, defaultEnvKey, defaultProjKey), @@ -78,12 +88,14 @@ func (m toggleFlagModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case fetchedFlagStatusMsg: m.enabled = msg.enabled m.flagWasFetched = true + m.toggleCount++ m.analyticsTracker.SendEvent( m.accessToken, m.baseUri, "CLI Setup Flag Toggled", map[string]interface{}{ - "on": m.enabled, + "on": m.enabled, + "count": m.toggleCount, }, ) case spinner.TickMsg: From cf2b822bb052ca1fd4f731e1e5df6777d6d7ddfc Mon Sep 17 00:00:00 2001 From: Sunny Guduru Date: Wed, 24 Apr 2024 16:16:50 -0700 Subject: [PATCH 5/9] add duriation ms --- internal/quickstart/container.go | 4 ++++ internal/quickstart/toggle_flag.go | 20 ++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/internal/quickstart/container.go b/internal/quickstart/container.go index 0551dd06..996b5953 100644 --- a/internal/quickstart/container.go +++ b/internal/quickstart/container.go @@ -3,6 +3,7 @@ package quickstart import ( "fmt" "log" + "time" "github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/spinner" @@ -43,6 +44,7 @@ type ContainerModel struct { gettingStarted bool quitting bool sdk sdkDetail + startTime time.Time totalSteps int width int } @@ -63,6 +65,7 @@ func NewContainerModel( environmentsClient: environmentsClient, flagsClient: flagsClient, gettingStarted: true, + startTime: time.Now(), totalSteps: 4, } } @@ -157,6 +160,7 @@ func (m ContainerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.baseUri, m.flagKey, m.sdk.kind, + m.startTime, ) cmd = m.currentModel.Init() m.currentStep += 1 diff --git a/internal/quickstart/toggle_flag.go b/internal/quickstart/toggle_flag.go index c2de7cf5..1cc709fa 100644 --- a/internal/quickstart/toggle_flag.go +++ b/internal/quickstart/toggle_flag.go @@ -2,6 +2,7 @@ package quickstart import ( "fmt" + "time" "github.com/charmbracelet/bubbles/help" "github.com/charmbracelet/bubbles/key" @@ -18,6 +19,7 @@ type toggleFlagModel struct { accessToken string analyticsTracker analytics.Tracker baseUri string + endTime time.Time client flags.Client enabled bool err error @@ -28,10 +30,11 @@ type toggleFlagModel struct { helpKeys keyMap sdkKind string spinner spinner.Model + setupStartTime time.Time toggleCount int } -func NewToggleFlagModel(analyticsTracker analytics.Tracker, client flags.Client, accessToken string, baseUri string, flagKey string, sdkKind string) tea.Model { +func NewToggleFlagModel(analyticsTracker analytics.Tracker, client flags.Client, accessToken string, baseUri string, flagKey string, sdkKind string, startTime time.Time) tea.Model { s := spinner.New() s.Spinner = spinner.Points @@ -46,8 +49,9 @@ func NewToggleFlagModel(analyticsTracker analytics.Tracker, client flags.Client, Back: BindingBack, Quit: BindingQuit, }, - sdkKind: sdkKind, - spinner: s, + sdkKind: sdkKind, + spinner: s, + setupStartTime: startTime, } } @@ -86,16 +90,20 @@ func (m toggleFlagModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, toggleFlag(m.client, m.accessToken, m.baseUri, m.flagKey, m.enabled) } case fetchedFlagStatusMsg: - m.enabled = msg.enabled + if !m.flagWasFetched { + m.endTime = time.Now() + } m.flagWasFetched = true + m.enabled = msg.enabled m.toggleCount++ m.analyticsTracker.SendEvent( m.accessToken, m.baseUri, "CLI Setup Flag Toggled", map[string]interface{}{ - "on": m.enabled, - "count": m.toggleCount, + "on": m.enabled, + "count": m.toggleCount, + "duration_ms": m.endTime.Sub(m.setupStartTime).Milliseconds(), }, ) case spinner.TickMsg: From f8c16cf50be27d12da6ac45d86c38f4d9f80a015 Mon Sep 17 00:00:00 2001 From: Sunny Guduru Date: Thu, 25 Apr 2024 11:31:10 -0700 Subject: [PATCH 6/9] abstract send event away --- internal/analytics/client.go | 144 +++++++++++++++++++ internal/quickstart/choose_sdk.go | 9 +- internal/quickstart/create_flag.go | 9 +- internal/quickstart/show_sdk_instructions.go | 18 +-- internal/quickstart/toggle_flag.go | 20 +-- 5 files changed, 153 insertions(+), 47 deletions(-) diff --git a/internal/analytics/client.go b/internal/analytics/client.go index 0bce52c3..9b316a53 100644 --- a/internal/analytics/client.go +++ b/internal/analytics/client.go @@ -24,6 +24,23 @@ type Tracker interface { optOut bool, outcome string, ) + SendSetupStartedEvent( + accessToken, + baseURI, + step string, + ) + SendSetupSDKSelectedEvent( + accessToken, + baseURI, + sdk string, + ) + SendSetupFlagToggledEvent( + accessToken, + baseURI string, + on bool, + count int, + duration_ms int64, + ) } type Client struct { @@ -128,6 +145,58 @@ func (c *Client) SendCommandCompletedEvent( } } +func (c *Client) SendSetupStartedEvent( + accessToken, + baseURI, + step string, +) { + c.sendEvent( + accessToken, + baseURI, + false, + "CLI Setup Started", + map[string]interface{}{ + "step": step, + }, + ) +} + +func (c *Client) SendSetupSDKSelectedEvent( + accessToken, + baseURI, + sdk string, +) { + c.sendEvent( + accessToken, + baseURI, + false, + "CLI Setup SDK Selected", + map[string]interface{}{ + "sdk": sdk, + }, + ) +} + +func (c *Client) SendSetupFlagToggledEvent( + accessToken, + baseURI string, + on bool, + count int, + duration_ms int64, +) { + c.sendEvent( + accessToken, + baseURI, + false, + "CLI Setup Flag Toggled", + map[string]interface{}{ + "on": on, + "count": count, + "duration_ms": duration_ms, + }, + ) +} + func (a *Client) Wait() { a.wg.Wait() } @@ -150,6 +219,29 @@ func (c *NoopClient) SendCommandCompletedEvent( ) { } +func (c *NoopClient) SendSetupStartedEvent( + accessToken, + baseURI, + step string, +) { +} + +func (c *NoopClient) SendSetupSDKSelectedEvent( + accessToken, + baseURI, + sdk string, +) { +} + +func (c *NoopClient) SendSetupFlagToggledEvent( + accessToken, + baseURI string, + on bool, + count int, + duration_ms int64, +) { +} + type MockTracker struct { mock.Mock ID string @@ -197,3 +289,55 @@ func (m *MockTracker) SendCommandCompletedEvent( }, ) } + +func (m *MockTracker) SendSetupStartedEvent( + accessToken, + baseURI, + step string, +) { + m.sendEvent( + accessToken, + baseURI, + false, + "CLI Setup Started", + map[string]interface{}{ + "step": step, + }, + ) +} + +func (m *MockTracker) SendSetupSDKSelectedEvent( + accessToken, + baseURI, + sdk string, +) { + m.sendEvent( + accessToken, + baseURI, + false, + "CLI Setup SDK Selected", + map[string]interface{}{ + "sdk": sdk, + }, + ) +} + +func (m *MockTracker) SendSetupFlagToggledEvent( + accessToken, + baseURI string, + on bool, + count int, + duration_ms int64, +) { + m.sendEvent( + accessToken, + baseURI, + false, + "CLI Setup Flag Toggled", + map[string]interface{}{ + "on": on, + "count": count, + "duration_ms": duration_ms, + }, + ) +} diff --git a/internal/quickstart/choose_sdk.go b/internal/quickstart/choose_sdk.go index 74291f12..c516fd1c 100644 --- a/internal/quickstart/choose_sdk.go +++ b/internal/quickstart/choose_sdk.go @@ -71,14 +71,7 @@ func NewChooseSDKModel(analyticsTracker analytics.Tracker, accessToken, baseUri // Init sends commands when the model is created that will: // * select an SDK if it's already been selected func (m chooseSDKModel) Init() tea.Cmd { - m.analyticsTracker.SendEvent( - m.accessToken, - m.baseUri, - "CLI Setup Started", - map[string]interface{}{ - "step": "2 - sdk selection", - }, - ) + m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, "2 - sdk selection") return selectedSDK(m.selectedIndex) } diff --git a/internal/quickstart/create_flag.go b/internal/quickstart/create_flag.go index d77a393b..9ceeacb7 100644 --- a/internal/quickstart/create_flag.go +++ b/internal/quickstart/create_flag.go @@ -55,14 +55,7 @@ func NewCreateFlagModel(analyticsTracker analytics.Tracker, client flags.Client, } func (m createFlagModel) Init() tea.Cmd { - m.analyticsTracker.SendEvent( - m.accessToken, - m.baseUri, - "CLI Setup Started", - map[string]interface{}{ - "step": "1 - feature flag name", - }, - ) + m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, "1 - feature flag name") return nil } diff --git a/internal/quickstart/show_sdk_instructions.go b/internal/quickstart/show_sdk_instructions.go index f8709cf2..de12c090 100644 --- a/internal/quickstart/show_sdk_instructions.go +++ b/internal/quickstart/show_sdk_instructions.go @@ -96,22 +96,8 @@ func NewShowSDKInstructionsModel( // fetch SDK instructions // fetch the environment to get values to interpolate into the instructions func (m showSDKInstructionsModel) Init() tea.Cmd { - m.analyticsTracker.SendEvent( - m.accessToken, - m.baseUri, - "CLI Setup Started", - map[string]interface{}{ - "step": "3 - sdk installation", - }, - ) - m.analyticsTracker.SendEvent( - m.accessToken, - m.baseUri, - "CLI Setup SDK Selected", - map[string]interface{}{ - "sdk": m.canonicalName, - }, - ) + m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, "3 - sdk installation") + m.analyticsTracker.SendSetupSDKSelectedEvent(m.accessToken, m.baseUri, m.canonicalName) cmds := []tea.Cmd{m.spinner.Tick, readSDKInstructions(m.canonicalName)} diff --git a/internal/quickstart/toggle_flag.go b/internal/quickstart/toggle_flag.go index 1cc709fa..7117c348 100644 --- a/internal/quickstart/toggle_flag.go +++ b/internal/quickstart/toggle_flag.go @@ -56,14 +56,7 @@ func NewToggleFlagModel(analyticsTracker analytics.Tracker, client flags.Client, } func (m toggleFlagModel) Init() tea.Cmd { - m.analyticsTracker.SendEvent( - m.accessToken, - m.baseUri, - "CLI Setup Started", - map[string]interface{}{ - "step": "4 - flag toggle", - }, - ) + m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, "4 - flag toggle") cmds := []tea.Cmd{ m.spinner.Tick, @@ -96,15 +89,12 @@ func (m toggleFlagModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.flagWasFetched = true m.enabled = msg.enabled m.toggleCount++ - m.analyticsTracker.SendEvent( + m.analyticsTracker.SendSetupFlagToggledEvent( m.accessToken, m.baseUri, - "CLI Setup Flag Toggled", - map[string]interface{}{ - "on": m.enabled, - "count": m.toggleCount, - "duration_ms": m.endTime.Sub(m.setupStartTime).Milliseconds(), - }, + m.enabled, + m.toggleCount, + m.endTime.Sub(m.setupStartTime).Milliseconds(), ) case spinner.TickMsg: m.spinner, cmd = m.spinner.Update(msg) From 897a572d18b328a0a9692263544dbeddf91f0713 Mon Sep 17 00:00:00 2001 From: Sunny Guduru Date: Thu, 25 Apr 2024 11:36:58 -0700 Subject: [PATCH 7/9] added optout to setup started event --- cmd/quickstart.go | 1 + internal/analytics/client.go | 12 ++++++++---- internal/quickstart/choose_sdk.go | 4 +++- internal/quickstart/create_flag.go | 4 +++- internal/quickstart/show_sdk_instructions.go | 4 +++- internal/quickstart/toggle_flag.go | 4 +++- 6 files changed, 21 insertions(+), 8 deletions(-) diff --git a/cmd/quickstart.go b/cmd/quickstart.go index 9e3dd2ef..a451e244 100644 --- a/cmd/quickstart.go +++ b/cmd/quickstart.go @@ -50,6 +50,7 @@ func runQuickStart( flagsClient, viper.GetString(cliflags.AccessTokenFlag), viper.GetString(cliflags.BaseURIFlag), + viper.GetBool(cliflags.AnalyticsOptOut), )).Run() if err != nil { log.Fatal(err) diff --git a/internal/analytics/client.go b/internal/analytics/client.go index 9b316a53..520827c6 100644 --- a/internal/analytics/client.go +++ b/internal/analytics/client.go @@ -26,7 +26,8 @@ type Tracker interface { ) SendSetupStartedEvent( accessToken, - baseURI, + baseURI string, + optOut bool, step string, ) SendSetupSDKSelectedEvent( @@ -147,7 +148,8 @@ func (c *Client) SendCommandCompletedEvent( func (c *Client) SendSetupStartedEvent( accessToken, - baseURI, + baseURI string, + optOut bool, step string, ) { c.sendEvent( @@ -221,7 +223,8 @@ func (c *NoopClient) SendCommandCompletedEvent( func (c *NoopClient) SendSetupStartedEvent( accessToken, - baseURI, + baseURI string, + optOut bool, step string, ) { } @@ -292,7 +295,8 @@ func (m *MockTracker) SendCommandCompletedEvent( func (m *MockTracker) SendSetupStartedEvent( accessToken, - baseURI, + baseURI string, + outOpt bool, step string, ) { m.sendEvent( diff --git a/internal/quickstart/choose_sdk.go b/internal/quickstart/choose_sdk.go index c516fd1c..07a0eb9d 100644 --- a/internal/quickstart/choose_sdk.go +++ b/internal/quickstart/choose_sdk.go @@ -3,6 +3,7 @@ package quickstart import ( "fmt" "io" + "ldcli/cmd/cliflags" "ldcli/internal/analytics" "strings" @@ -11,6 +12,7 @@ import ( "github.com/charmbracelet/bubbles/list" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" + "github.com/spf13/viper" ) var ( @@ -71,7 +73,7 @@ func NewChooseSDKModel(analyticsTracker analytics.Tracker, accessToken, baseUri // Init sends commands when the model is created that will: // * select an SDK if it's already been selected func (m chooseSDKModel) Init() tea.Cmd { - m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, "2 - sdk selection") + m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.OutputFlag), "2 - sdk selection") return selectedSDK(m.selectedIndex) } diff --git a/internal/quickstart/create_flag.go b/internal/quickstart/create_flag.go index 9ceeacb7..aa36938e 100644 --- a/internal/quickstart/create_flag.go +++ b/internal/quickstart/create_flag.go @@ -8,7 +8,9 @@ import ( "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" + "github.com/spf13/viper" + "ldcli/cmd/cliflags" "ldcli/internal/analytics" "ldcli/internal/flags" ) @@ -55,7 +57,7 @@ func NewCreateFlagModel(analyticsTracker analytics.Tracker, client flags.Client, } func (m createFlagModel) Init() tea.Cmd { - m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, "1 - feature flag name") + m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.OutputFlag), "1 - feature flag name") return nil } diff --git a/internal/quickstart/show_sdk_instructions.go b/internal/quickstart/show_sdk_instructions.go index de12c090..d8103baf 100644 --- a/internal/quickstart/show_sdk_instructions.go +++ b/internal/quickstart/show_sdk_instructions.go @@ -10,7 +10,9 @@ import ( tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/glamour" "github.com/charmbracelet/lipgloss" + "github.com/spf13/viper" + "ldcli/cmd/cliflags" "ldcli/internal/analytics" "ldcli/internal/environments" "ldcli/internal/sdks" @@ -96,7 +98,7 @@ func NewShowSDKInstructionsModel( // fetch SDK instructions // fetch the environment to get values to interpolate into the instructions func (m showSDKInstructionsModel) Init() tea.Cmd { - m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, "3 - sdk installation") + m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.OutputFlag), "3 - sdk installation") m.analyticsTracker.SendSetupSDKSelectedEvent(m.accessToken, m.baseUri, m.canonicalName) cmds := []tea.Cmd{m.spinner.Tick, readSDKInstructions(m.canonicalName)} diff --git a/internal/quickstart/toggle_flag.go b/internal/quickstart/toggle_flag.go index 7117c348..866fa359 100644 --- a/internal/quickstart/toggle_flag.go +++ b/internal/quickstart/toggle_flag.go @@ -9,7 +9,9 @@ import ( "github.com/charmbracelet/bubbles/spinner" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" + "github.com/spf13/viper" + "ldcli/cmd/cliflags" "ldcli/internal/analytics" "ldcli/internal/errors" "ldcli/internal/flags" @@ -56,7 +58,7 @@ func NewToggleFlagModel(analyticsTracker analytics.Tracker, client flags.Client, } func (m toggleFlagModel) Init() tea.Cmd { - m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, "4 - flag toggle") + m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.OutputFlag), "4 - flag toggle") cmds := []tea.Cmd{ m.spinner.Tick, From fec0016757f5100fe9c6e02515c9dc1e272f0910 Mon Sep 17 00:00:00 2001 From: Sunny Guduru Date: Thu, 25 Apr 2024 11:40:29 -0700 Subject: [PATCH 8/9] fix bug, add optout to everything --- cmd/quickstart.go | 1 - internal/analytics/client.go | 30 +++++++++++++------- internal/quickstart/show_sdk_instructions.go | 2 +- internal/quickstart/toggle_flag.go | 1 + 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/cmd/quickstart.go b/cmd/quickstart.go index a451e244..9e3dd2ef 100644 --- a/cmd/quickstart.go +++ b/cmd/quickstart.go @@ -50,7 +50,6 @@ func runQuickStart( flagsClient, viper.GetString(cliflags.AccessTokenFlag), viper.GetString(cliflags.BaseURIFlag), - viper.GetBool(cliflags.AnalyticsOptOut), )).Run() if err != nil { log.Fatal(err) diff --git a/internal/analytics/client.go b/internal/analytics/client.go index 520827c6..51a4e45b 100644 --- a/internal/analytics/client.go +++ b/internal/analytics/client.go @@ -32,12 +32,14 @@ type Tracker interface { ) SendSetupSDKSelectedEvent( accessToken, - baseURI, + baseURI string, + optOut bool, sdk string, ) SendSetupFlagToggledEvent( accessToken, baseURI string, + optOut bool, on bool, count int, duration_ms int64, @@ -155,7 +157,7 @@ func (c *Client) SendSetupStartedEvent( c.sendEvent( accessToken, baseURI, - false, + optOut, "CLI Setup Started", map[string]interface{}{ "step": step, @@ -165,13 +167,14 @@ func (c *Client) SendSetupStartedEvent( func (c *Client) SendSetupSDKSelectedEvent( accessToken, - baseURI, + baseURI string, + optOut bool, sdk string, ) { c.sendEvent( accessToken, baseURI, - false, + optOut, "CLI Setup SDK Selected", map[string]interface{}{ "sdk": sdk, @@ -182,6 +185,7 @@ func (c *Client) SendSetupSDKSelectedEvent( func (c *Client) SendSetupFlagToggledEvent( accessToken, baseURI string, + optOut bool, on bool, count int, duration_ms int64, @@ -189,7 +193,7 @@ func (c *Client) SendSetupFlagToggledEvent( c.sendEvent( accessToken, baseURI, - false, + optOut, "CLI Setup Flag Toggled", map[string]interface{}{ "on": on, @@ -231,7 +235,8 @@ func (c *NoopClient) SendSetupStartedEvent( func (c *NoopClient) SendSetupSDKSelectedEvent( accessToken, - baseURI, + baseURI string, + optOut bool, sdk string, ) { } @@ -239,6 +244,7 @@ func (c *NoopClient) SendSetupSDKSelectedEvent( func (c *NoopClient) SendSetupFlagToggledEvent( accessToken, baseURI string, + optOut bool, on bool, count int, duration_ms int64, @@ -296,13 +302,13 @@ func (m *MockTracker) SendCommandCompletedEvent( func (m *MockTracker) SendSetupStartedEvent( accessToken, baseURI string, - outOpt bool, + optOut bool, step string, ) { m.sendEvent( accessToken, baseURI, - false, + optOut, "CLI Setup Started", map[string]interface{}{ "step": step, @@ -312,13 +318,14 @@ func (m *MockTracker) SendSetupStartedEvent( func (m *MockTracker) SendSetupSDKSelectedEvent( accessToken, - baseURI, + baseURI string, + optOut bool, sdk string, ) { m.sendEvent( accessToken, baseURI, - false, + optOut, "CLI Setup SDK Selected", map[string]interface{}{ "sdk": sdk, @@ -329,6 +336,7 @@ func (m *MockTracker) SendSetupSDKSelectedEvent( func (m *MockTracker) SendSetupFlagToggledEvent( accessToken, baseURI string, + optOut bool, on bool, count int, duration_ms int64, @@ -336,7 +344,7 @@ func (m *MockTracker) SendSetupFlagToggledEvent( m.sendEvent( accessToken, baseURI, - false, + optOut, "CLI Setup Flag Toggled", map[string]interface{}{ "on": on, diff --git a/internal/quickstart/show_sdk_instructions.go b/internal/quickstart/show_sdk_instructions.go index d8103baf..7d81894f 100644 --- a/internal/quickstart/show_sdk_instructions.go +++ b/internal/quickstart/show_sdk_instructions.go @@ -99,7 +99,7 @@ func NewShowSDKInstructionsModel( // fetch the environment to get values to interpolate into the instructions func (m showSDKInstructionsModel) Init() tea.Cmd { m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.OutputFlag), "3 - sdk installation") - m.analyticsTracker.SendSetupSDKSelectedEvent(m.accessToken, m.baseUri, m.canonicalName) + m.analyticsTracker.SendSetupSDKSelectedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.OutputFlag), m.canonicalName) cmds := []tea.Cmd{m.spinner.Tick, readSDKInstructions(m.canonicalName)} diff --git a/internal/quickstart/toggle_flag.go b/internal/quickstart/toggle_flag.go index 866fa359..9396ad89 100644 --- a/internal/quickstart/toggle_flag.go +++ b/internal/quickstart/toggle_flag.go @@ -94,6 +94,7 @@ func (m toggleFlagModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.analyticsTracker.SendSetupFlagToggledEvent( m.accessToken, m.baseUri, + viper.GetBool(cliflags.OutputFlag), m.enabled, m.toggleCount, m.endTime.Sub(m.setupStartTime).Milliseconds(), From ab6ff124f2c83978e4330c9ab0dc8fced83ee61c Mon Sep 17 00:00:00 2001 From: Sunny Guduru Date: Thu, 25 Apr 2024 14:10:42 -0700 Subject: [PATCH 9/9] analytics flag passed in --- internal/quickstart/choose_sdk.go | 2 +- internal/quickstart/create_flag.go | 2 +- internal/quickstart/show_sdk_instructions.go | 4 ++-- internal/quickstart/toggle_flag.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/quickstart/choose_sdk.go b/internal/quickstart/choose_sdk.go index 07a0eb9d..89b8b3c4 100644 --- a/internal/quickstart/choose_sdk.go +++ b/internal/quickstart/choose_sdk.go @@ -73,7 +73,7 @@ func NewChooseSDKModel(analyticsTracker analytics.Tracker, accessToken, baseUri // Init sends commands when the model is created that will: // * select an SDK if it's already been selected func (m chooseSDKModel) Init() tea.Cmd { - m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.OutputFlag), "2 - sdk selection") + m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.AnalyticsOptOut), "2 - sdk selection") return selectedSDK(m.selectedIndex) } diff --git a/internal/quickstart/create_flag.go b/internal/quickstart/create_flag.go index aa36938e..a419536d 100644 --- a/internal/quickstart/create_flag.go +++ b/internal/quickstart/create_flag.go @@ -57,7 +57,7 @@ func NewCreateFlagModel(analyticsTracker analytics.Tracker, client flags.Client, } func (m createFlagModel) Init() tea.Cmd { - m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.OutputFlag), "1 - feature flag name") + m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.AnalyticsOptOut), "1 - feature flag name") return nil } diff --git a/internal/quickstart/show_sdk_instructions.go b/internal/quickstart/show_sdk_instructions.go index 7d81894f..70eb7f28 100644 --- a/internal/quickstart/show_sdk_instructions.go +++ b/internal/quickstart/show_sdk_instructions.go @@ -98,8 +98,8 @@ func NewShowSDKInstructionsModel( // fetch SDK instructions // fetch the environment to get values to interpolate into the instructions func (m showSDKInstructionsModel) Init() tea.Cmd { - m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.OutputFlag), "3 - sdk installation") - m.analyticsTracker.SendSetupSDKSelectedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.OutputFlag), m.canonicalName) + m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.AnalyticsOptOut), "3 - sdk installation") + m.analyticsTracker.SendSetupSDKSelectedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.AnalyticsOptOut), m.canonicalName) cmds := []tea.Cmd{m.spinner.Tick, readSDKInstructions(m.canonicalName)} diff --git a/internal/quickstart/toggle_flag.go b/internal/quickstart/toggle_flag.go index 9396ad89..e753a041 100644 --- a/internal/quickstart/toggle_flag.go +++ b/internal/quickstart/toggle_flag.go @@ -58,7 +58,7 @@ func NewToggleFlagModel(analyticsTracker analytics.Tracker, client flags.Client, } func (m toggleFlagModel) Init() tea.Cmd { - m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.OutputFlag), "4 - flag toggle") + m.analyticsTracker.SendSetupStartedEvent(m.accessToken, m.baseUri, viper.GetBool(cliflags.AnalyticsOptOut), "4 - flag toggle") cmds := []tea.Cmd{ m.spinner.Tick, @@ -94,7 +94,7 @@ func (m toggleFlagModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.analyticsTracker.SendSetupFlagToggledEvent( m.accessToken, m.baseUri, - viper.GetBool(cliflags.OutputFlag), + viper.GetBool(cliflags.AnalyticsOptOut), m.enabled, m.toggleCount, m.endTime.Sub(m.setupStartTime).Milliseconds(),