diff --git a/coderd/telemetry/telemetry.go b/coderd/telemetry/telemetry.go index 747cf2cb47de1..8f203126c99ba 100644 --- a/coderd/telemetry/telemetry.go +++ b/coderd/telemetry/telemetry.go @@ -768,7 +768,7 @@ func ConvertWorkspace(workspace database.Workspace) Workspace { // ConvertWorkspaceBuild anonymizes a workspace build. func ConvertWorkspaceBuild(build database.WorkspaceBuild) WorkspaceBuild { - return WorkspaceBuild{ + wb := WorkspaceBuild{ ID: build.ID, CreatedAt: build.CreatedAt, WorkspaceID: build.WorkspaceID, @@ -777,6 +777,10 @@ func ConvertWorkspaceBuild(build database.WorkspaceBuild) WorkspaceBuild { // #nosec G115 - Safe conversion as build numbers are expected to be positive and within uint32 range BuildNumber: uint32(build.BuildNumber), } + if build.HasAITask.Valid { + wb.HasAITask = ptr.Ref(build.HasAITask.Bool) + } + return wb } // ConvertProvisionerJob anonymizes a provisioner job. @@ -1105,6 +1109,9 @@ func ConvertTemplateVersion(version database.TemplateVersion) TemplateVersion { if version.SourceExampleID.Valid { snapVersion.SourceExampleID = &version.SourceExampleID.String } + if version.HasAITask.Valid { + snapVersion.HasAITask = ptr.Ref(version.HasAITask.Bool) + } return snapVersion } @@ -1357,6 +1364,7 @@ type WorkspaceBuild struct { TemplateVersionID uuid.UUID `json:"template_version_id"` JobID uuid.UUID `json:"job_id"` BuildNumber uint32 `json:"build_number"` + HasAITask *bool `json:"has_ai_task"` } type Workspace struct { @@ -1404,6 +1412,7 @@ type TemplateVersion struct { OrganizationID uuid.UUID `json:"organization_id"` JobID uuid.UUID `json:"job_id"` SourceExampleID *string `json:"source_example_id,omitempty"` + HasAITask *bool `json:"has_ai_task"` } type ProvisionerJob struct { diff --git a/coderd/telemetry/telemetry_test.go b/coderd/telemetry/telemetry_test.go index 63bdc12870cb3..5508a7d8816f5 100644 --- a/coderd/telemetry/telemetry_test.go +++ b/coderd/telemetry/telemetry_test.go @@ -7,6 +7,7 @@ import ( "net/http" "net/http/httptest" "net/url" + "slices" "sort" "testing" "time" @@ -105,6 +106,52 @@ func TestTelemetry(t *testing.T) { OpenIn: database.WorkspaceAppOpenInSlimWindow, AgentID: wsagent.ID, }) + + taskJob := dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{ + Provisioner: database.ProvisionerTypeTerraform, + StorageMethod: database.ProvisionerStorageMethodFile, + Type: database.ProvisionerJobTypeTemplateVersionDryRun, + OrganizationID: org.ID, + }) + taskTpl := dbgen.Template(t, db, database.Template{ + Provisioner: database.ProvisionerTypeTerraform, + OrganizationID: org.ID, + CreatedBy: user.ID, + }) + taskTV := dbgen.TemplateVersion(t, db, database.TemplateVersion{ + OrganizationID: org.ID, + TemplateID: uuid.NullUUID{UUID: taskTpl.ID, Valid: true}, + CreatedBy: user.ID, + JobID: taskJob.ID, + HasAITask: sql.NullBool{Bool: true, Valid: true}, + }) + taskWs := dbgen.Workspace(t, db, database.WorkspaceTable{ + OwnerID: user.ID, + OrganizationID: org.ID, + TemplateID: taskTpl.ID, + }) + taskWsResource := dbgen.WorkspaceResource(t, db, database.WorkspaceResource{ + JobID: taskJob.ID, + }) + taskWsAgent := dbgen.WorkspaceAgent(t, db, database.WorkspaceAgent{ + ResourceID: taskWsResource.ID, + }) + taskWsApp := dbgen.WorkspaceApp(t, db, database.WorkspaceApp{ + SharingLevel: database.AppSharingLevelOwner, + Health: database.WorkspaceAppHealthDisabled, + OpenIn: database.WorkspaceAppOpenInSlimWindow, + AgentID: taskWsAgent.ID, + }) + taskWB := dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{ + Transition: database.WorkspaceTransitionStart, + Reason: database.BuildReasonAutostart, + WorkspaceID: taskWs.ID, + TemplateVersionID: tv.ID, + JobID: taskJob.ID, + HasAITask: sql.NullBool{Valid: true, Bool: true}, + AITaskSidebarAppID: uuid.NullUUID{Valid: true, UUID: taskWsApp.ID}, + }) + group := dbgen.Group(t, db, database.Group{ OrganizationID: org.ID, }) @@ -148,19 +195,19 @@ func TestTelemetry(t *testing.T) { }) _, snapshot := collectSnapshot(ctx, t, db, nil) - require.Len(t, snapshot.ProvisionerJobs, 1) + require.Len(t, snapshot.ProvisionerJobs, 2) require.Len(t, snapshot.Licenses, 1) - require.Len(t, snapshot.Templates, 1) - require.Len(t, snapshot.TemplateVersions, 2) + require.Len(t, snapshot.Templates, 2) + require.Len(t, snapshot.TemplateVersions, 3) require.Len(t, snapshot.Users, 1) require.Len(t, snapshot.Groups, 2) // 1 member in the everyone group + 1 member in the custom group require.Len(t, snapshot.GroupMembers, 2) - require.Len(t, snapshot.Workspaces, 1) - require.Len(t, snapshot.WorkspaceApps, 1) - require.Len(t, snapshot.WorkspaceAgents, 1) - require.Len(t, snapshot.WorkspaceBuilds, 1) - require.Len(t, snapshot.WorkspaceResources, 1) + require.Len(t, snapshot.Workspaces, 2) + require.Len(t, snapshot.WorkspaceApps, 2) + require.Len(t, snapshot.WorkspaceAgents, 2) + require.Len(t, snapshot.WorkspaceBuilds, 2) + require.Len(t, snapshot.WorkspaceResources, 2) require.Len(t, snapshot.WorkspaceAgentStats, 1) require.Len(t, snapshot.WorkspaceProxies, 1) require.Len(t, snapshot.WorkspaceModules, 1) @@ -169,11 +216,24 @@ func TestTelemetry(t *testing.T) { require.Len(t, snapshot.TelemetryItems, 2) require.Len(t, snapshot.WorkspaceAgentMemoryResourceMonitors, 1) require.Len(t, snapshot.WorkspaceAgentVolumeResourceMonitors, 1) - wsa := snapshot.WorkspaceAgents[0] + wsa := snapshot.WorkspaceAgents[1] require.Len(t, wsa.Subsystems, 2) require.Equal(t, string(database.WorkspaceAgentSubsystemEnvbox), wsa.Subsystems[0]) require.Equal(t, string(database.WorkspaceAgentSubsystemExectrace), wsa.Subsystems[1]) + require.True(t, slices.ContainsFunc(snapshot.TemplateVersions, func(ttv telemetry.TemplateVersion) bool { + if ttv.ID != taskTV.ID { + return false + } + return assert.NotNil(t, ttv.HasAITask) && assert.True(t, *ttv.HasAITask) + })) + require.True(t, slices.ContainsFunc(snapshot.WorkspaceBuilds, func(twb telemetry.WorkspaceBuild) bool { + if twb.ID != taskWB.ID { + return false + } + return assert.NotNil(t, twb.HasAITask) && assert.True(t, *twb.HasAITask) + })) + tvs := snapshot.TemplateVersions sort.Slice(tvs, func(i, j int) bool { // Sort by SourceExampleID presence (non-nil comes before nil) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy