Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/project/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ func runCreateCommand(clients *shared.ClientFactory, cmd *cobra.Command, args []
Subdir: subdir,
}
clients.EventTracker.SetAppTemplate(template.GetTemplatePath())
clients.EventTracker.SetAppTemplateShortcut(categoryShortcut)
clients.EventTracker.SetAppTemplateSubdir(subdir)

appDirPath, err := CreateFunc(ctx, clients, createArgs)
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions cmd/project/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ func TestCreateCommand(t *testing.T) {
Subdir: "claude-agent-sdk",
}
createClientMock.AssertCalled(t, "Create", mock.Anything, mock.Anything, expected)
cm.EventTracker.AssertCalled(t, "SetAppTemplate", "slack-samples/bolt-js-starter-agent")
cm.EventTracker.AssertCalled(t, "SetAppTemplateShortcut", "agent")
cm.EventTracker.AssertCalled(t, "SetAppTemplateSubdir", "claude-agent-sdk")
// Verify that category prompt was NOT called
cm.IO.AssertNotCalled(t, "SelectPrompt", mock.Anything, "Select a category:", mock.Anything, mock.Anything)
cm.IO.AssertCalled(t, "InputPrompt", mock.Anything, "Name your app:", mock.Anything)
Expand Down Expand Up @@ -279,6 +282,8 @@ func TestCreateCommand(t *testing.T) {
Template: template,
}
createClientMock.AssertCalled(t, "Create", mock.Anything, mock.Anything, expected)
cm.EventTracker.AssertCalled(t, "SetAppTemplateShortcut", "")
cm.EventTracker.AssertCalled(t, "SetAppTemplateSubdir", "")
// Verify that name prompt was NOT called since name was provided as arg
cm.IO.AssertNotCalled(t, "InputPrompt", mock.Anything, "Name your app:", mock.Anything)
},
Expand Down Expand Up @@ -648,6 +653,7 @@ func TestCreateCommand(t *testing.T) {
createClientMock.AssertCalled(t, "Create", mock.Anything, mock.Anything, mock.MatchedBy(func(args create.CreateArgs) bool {
return args.AppPath != "" && args.Template == template && args.Subdir == "apps/my-app"
}))
cm.EventTracker.AssertCalled(t, "SetAppTemplateSubdir", "apps/my-app")
},
},
"list flag ignores subdir": {
Expand Down
4 changes: 4 additions & 0 deletions internal/tracking/logstash_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,8 @@ type AppEventData struct {
UserID string `json:"user_id,omitempty"`
// Template holds information for the sample app template used as part of the `create` command
Template string `json:"template,omitempty"`
// TemplateShortcut holds the category shortcut argument used with the `create` command, such as "agent"
TemplateShortcut string `json:"template_shortcut,omitempty"`
// TemplateSubdir holds the subdirectory of the template used as part of the `create` command
TemplateSubdir string `json:"template_subdir,omitempty"`
}
19 changes: 19 additions & 0 deletions internal/tracking/tracking.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ type TrackingManager interface {
SetAppTeamID(id string)
SetAppUserID(id string)
SetAppTemplate(template string)
SetAppTemplateShortcut(shortcut string)
SetAppTemplateSubdir(subdir string)
}

type EventTracker struct {
Expand Down Expand Up @@ -146,6 +148,20 @@ func (e *EventTracker) SetAppTemplate(template string) {
e.setSessionData(data)
}

// SetAppTemplateShortcut sets the category shortcut used to select an app template in this CLI execution for metrics
func (e *EventTracker) SetAppTemplateShortcut(shortcut string) {
data := e.getSessionData()
data.App.TemplateShortcut = shortcut
e.setSessionData(data)
}

// SetAppTemplateSubdir sets the subdirectory of the app template used in this CLI execution for metrics
func (e *EventTracker) SetAppTemplateSubdir(subdir string) {
data := e.getSessionData()
data.App.TemplateSubdir = subdir
e.setSessionData(data)
}

// cleanSessionData ensures every string value the provided object has PII redacted
func (e *EventTracker) cleanSessionData(data EventData) EventData {
if len(data.ErrorMessage) > 0 {
Expand All @@ -154,6 +170,9 @@ func (e *EventTracker) cleanSessionData(data EventData) EventData {
if len(data.App.Template) > 0 {
data.App.Template = goutils.RedactPII(data.App.Template)
}
if len(data.App.TemplateSubdir) > 0 {
data.App.TemplateSubdir = goutils.RedactPII(data.App.TemplateSubdir)
}

return data
}
Expand Down
10 changes: 10 additions & 0 deletions internal/tracking/tracking_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ func (m *EventTrackerMock) AddDefaultMocks() {
m.On("SetAppEnterpriseID", mock.Anything)
m.On("SetAppTeamID", mock.Anything)
m.On("SetAppTemplate", mock.Anything)
m.On("SetAppTemplateShortcut", mock.Anything)
m.On("SetAppTemplateSubdir", mock.Anything)
m.On("SetAppUserID", mock.Anything)
m.On("SetAuthEnterpriseID", mock.Anything)
m.On("SetAuthTeamID", mock.Anything)
Expand Down Expand Up @@ -88,3 +90,11 @@ func (m *EventTrackerMock) SetAppUserID(id string) {
func (m *EventTrackerMock) SetAppTemplate(template string) {
m.Called(template)
}

func (m *EventTrackerMock) SetAppTemplateShortcut(shortcut string) {
m.Called(shortcut)
}

func (m *EventTrackerMock) SetAppTemplateSubdir(subdir string) {
m.Called(subdir)
}
30 changes: 30 additions & 0 deletions internal/tracking/tracking_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ func Test_Tracking_cleanSessionData(t *testing.T) {
},
},
},
"should redact app template subdir": {
input: EventData{
App: AppEventData{
TemplateSubdir: "apps/my-xapp-example",
},
},
expectedOutput: EventData{
App: AppEventData{
TemplateSubdir: "apps/my-...",
},
},
},
}

for name, tc := range tests {
Expand Down Expand Up @@ -272,6 +284,24 @@ func Test_Tracking_SetSessionData(t *testing.T) {
},
value: "slack-samples/deno-hello-world",
},
"app template shortcut can be retrieved": {
setterFunc: func(e *EventTracker, value string) {
e.SetAppTemplateShortcut(value)
},
getterFunc: func(e *EventTracker) string {
return e.getSessionData().App.TemplateShortcut
},
value: "agent",
},
"app template subdir can be retrieved": {
setterFunc: func(e *EventTracker, value string) {
e.SetAppTemplateSubdir(value)
},
getterFunc: func(e *EventTracker) string {
return e.getSessionData().App.TemplateSubdir
},
value: "claude-agent-sdk",
},
}

for name, tc := range tests {
Expand Down
Loading