Skip to content

Commit

Permalink
feat: track cli setup step started event (#215)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sunny Guduru authored Apr 30, 2024
1 parent ffa9fb3 commit 25b9f2e
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 10 deletions.
7 changes: 6 additions & 1 deletion cmd/quickstart.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -42,9 +45,11 @@ func runQuickStart(
defer f.Close()

_, err = tea.NewProgram(quickstart.NewContainerModel(
analyticsTracker,
environmentsClient,
flagsClient,
viper.GetString(cliflags.AccessTokenFlag),
viper.GetBool(cliflags.AnalyticsOptOut),
viper.GetString(cliflags.BaseURIFlag),
)).Run()
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,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, analyticsTracker)

Expand Down
48 changes: 48 additions & 0 deletions internal/analytics/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ type Tracker interface {
optOut bool,
outcome string,
)
SendSetupStepStartedEvent(
accessToken,
baseURI string,
optOut bool,
step string,
)
}

type Client struct {
Expand Down Expand Up @@ -128,6 +134,23 @@ func (c *Client) SendCommandCompletedEvent(
}
}

func (c *Client) SendSetupStepStartedEvent(
accessToken,
baseURI string,
optOut bool,
step string,
) {
c.sendEvent(
accessToken,
baseURI,
optOut,
"CLI Setup Step Started",
map[string]interface{}{
"step": step,
},
)
}

func (a *Client) Wait() {
a.wg.Wait()
}
Expand All @@ -150,6 +173,14 @@ func (c *NoopClient) SendCommandCompletedEvent(
) {
}

func (c *NoopClient) SendSetupStepStartedEvent(
accessToken,
baseURI string,
optOut bool,
step string,
) {
}

type MockTracker struct {
mock.Mock
ID string
Expand Down Expand Up @@ -197,3 +228,20 @@ func (m *MockTracker) SendCommandCompletedEvent(
},
)
}

func (m *MockTracker) SendSetupStepStartedEvent(
accessToken,
baseURI string,
optOut bool,
step string,
) {
m.sendEvent(
accessToken,
baseURI,
optOut,
"CLI Setup Step Started",
map[string]interface{}{
"step": step,
},
)
}
56 changes: 48 additions & 8 deletions internal/quickstart/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
tea "github.com/charmbracelet/bubbletea"
"github.com/muesli/reflow/wordwrap"

"ldcli/internal/analytics"
"ldcli/internal/environments"
"ldcli/internal/flags"
)
Expand All @@ -18,21 +19,35 @@ const (
defaultEnvKey = "test"
)

type step int

const (
_ = iota
_ step = iota
stepCreateFlag
stepChooseSDK
stepShowSDKInstructions
stepToggleFlag
)

func (s step) String() string {
return []string{
"_",
"1 - feature flag name",
"2 - sdk selection",
"3 - sdk installation",
"4 - flag toggle",
}[s]
}

// ContainerModel is a high level container model that controls the nested models where each
// represents a step in the quick-start flow.
type ContainerModel struct {
accessToken string
analyticsOptOut bool
analyticsTracker analytics.Tracker
baseUri string
currentModel tea.Model
currentStep int
currentStep step
environment *environment
environmentsClient environments.Client
err error
Expand All @@ -46,13 +61,17 @@ type ContainerModel struct {
}

func NewContainerModel(
analyticsTracker analytics.Tracker,
environmentsClient environments.Client,
flagsClient flags.Client,
accessToken string,
analyticsOptOut bool,
baseUri string,
) tea.Model {
return ContainerModel{
accessToken: accessToken,
analyticsOptOut: analyticsOptOut,
analyticsTracker: analyticsTracker,
baseUri: baseUri,
currentModel: NewCreateFlagModel(flagsClient, accessToken, baseUri),
currentStep: 1,
Expand All @@ -64,11 +83,18 @@ func NewContainerModel(
}

func (m ContainerModel) Init() tea.Cmd {
return nil
return trackSetupStepStartedEvent(
m.analyticsTracker,
m.accessToken,
m.baseUri,
m.analyticsOptOut,
m.currentStep.String(),
)
}

func (m ContainerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmd tea.Cmd
var sendEvent bool
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.width = msg.Width
Expand Down Expand Up @@ -103,11 +129,18 @@ func (m ContainerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.environment,
)
cmd = m.currentModel.Init()
sendEvent = true
}
default:
// delegate all other input to the current model
m.currentModel, cmd = m.currentModel.Update(msg)
}
case confirmedFlagMsg:
m.currentModel = NewChooseSDKModel(0)
m.flagKey = msg.flag.key
m.currentStep += 1
m.err = nil
sendEvent = true
case choseSDKMsg:
m.currentModel = NewShowSDKInstructionsModel(
m.environmentsClient,
Expand All @@ -122,11 +155,7 @@ func (m ContainerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
cmd = m.currentModel.Init()
m.sdk = msg.sdk
m.currentStep += 1
case confirmedFlagMsg:
m.currentModel = NewChooseSDKModel(0)
m.flagKey = msg.flag.key
m.currentStep += 1
m.err = nil
sendEvent = true
case errMsg:
m.currentModel, cmd = m.currentModel.Update(msg)
case fetchedEnvMsg:
Expand All @@ -150,10 +179,21 @@ func (m ContainerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
)
cmd = m.currentModel.Init()
m.currentStep += 1
sendEvent = true
default:
log.Printf("container default: %T\n", msg)
}

if sendEvent {
cmd = tea.Batch(cmd, trackSetupStepStartedEvent(
m.analyticsTracker,
m.accessToken,
m.baseUri,
m.analyticsOptOut,
m.currentStep.String(),
))
}

return m, cmd
}

Expand Down
11 changes: 11 additions & 0 deletions internal/quickstart/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

tea "github.com/charmbracelet/bubbletea"

"ldcli/internal/analytics"
"ldcli/internal/environments"
"ldcli/internal/errors"
"ldcli/internal/flags"
Expand Down Expand Up @@ -240,3 +241,13 @@ func selectedSDK(index int) tea.Cmd {
return selectedSDKMsg{index: index}
}
}

type eventTrackedMsg struct{}

func trackSetupStepStartedEvent(tracker analytics.Tracker, accessToken, baseURI string, optOut bool, step string) tea.Cmd {
return func() tea.Msg {
tracker.SendSetupStepStartedEvent(accessToken, baseURI, optOut, step)

return eventTrackedMsg{}
}
}

0 comments on commit 25b9f2e

Please sign in to comment.