mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: Add anonymized telemetry to report product usage (#2273)
* feat: Add anonymized telemetry to report product usage This adds a background service to report telemetry to a Coder server for usage data. There will be realtime event data sent in the future, but for now usage will report on a CRON. * Fix flake and requested changes * Add reporting options for setup * Add reporting for workspaces * Add resources as they are reported * Track API key usage * Ensure telemetry is tracked prior to exit
This commit is contained in:
@@ -66,6 +66,8 @@ type fakeQuerier struct {
|
||||
workspaceBuilds []database.WorkspaceBuild
|
||||
workspaceApps []database.WorkspaceApp
|
||||
workspaces []database.Workspace
|
||||
|
||||
deploymentID string
|
||||
}
|
||||
|
||||
// InTx doesn't rollback data properly for in-memory yet.
|
||||
@@ -128,6 +130,19 @@ func (q *fakeQuerier) GetAPIKeyByID(_ context.Context, id string) (database.APIK
|
||||
return database.APIKey{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetAPIKeysLastUsedAfter(_ context.Context, after time.Time) ([]database.APIKey, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
apiKeys := make([]database.APIKey, 0)
|
||||
for _, key := range q.apiKeys {
|
||||
if key.LastUsed.After(after) {
|
||||
apiKeys = append(apiKeys, key)
|
||||
}
|
||||
}
|
||||
return apiKeys, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) DeleteAPIKeyByID(_ context.Context, id string) error {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
@@ -315,7 +330,7 @@ func (q *fakeQuerier) GetAuthorizationUserRoles(_ context.Context, userID uuid.U
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetWorkspacesWithFilter(_ context.Context, arg database.GetWorkspacesWithFilterParams) ([]database.Workspace, error) {
|
||||
func (q *fakeQuerier) GetWorkspaces(_ context.Context, arg database.GetWorkspacesParams) ([]database.Workspace, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
@@ -421,6 +436,19 @@ func (q *fakeQuerier) GetWorkspaceAppsByAgentID(_ context.Context, id uuid.UUID)
|
||||
return apps, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetWorkspaceAppsCreatedAfter(_ context.Context, after time.Time) ([]database.WorkspaceApp, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
apps := make([]database.WorkspaceApp, 0)
|
||||
for _, app := range q.workspaceApps {
|
||||
if app.CreatedAt.After(after) {
|
||||
apps = append(apps, app)
|
||||
}
|
||||
}
|
||||
return apps, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetWorkspaceAppsByAgentIDs(_ context.Context, ids []uuid.UUID) ([]database.WorkspaceApp, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
@@ -647,6 +675,19 @@ func (q *fakeQuerier) GetWorkspaceBuildByWorkspaceIDAndBuildNumber(_ context.Con
|
||||
return database.WorkspaceBuild{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetWorkspaceBuildsCreatedAfter(_ context.Context, after time.Time) ([]database.WorkspaceBuild, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
workspaceBuilds := make([]database.WorkspaceBuild, 0)
|
||||
for _, workspaceBuild := range q.workspaceBuilds {
|
||||
if workspaceBuild.CreatedAt.After(after) {
|
||||
workspaceBuilds = append(workspaceBuilds, workspaceBuild)
|
||||
}
|
||||
}
|
||||
return workspaceBuilds, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetOrganizations(_ context.Context) ([]database.Organization, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
@@ -870,6 +911,19 @@ func (q *fakeQuerier) GetTemplateVersionsByTemplateID(_ context.Context, arg dat
|
||||
return version, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetTemplateVersionsCreatedAfter(_ context.Context, after time.Time) ([]database.TemplateVersion, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
versions := make([]database.TemplateVersion, 0)
|
||||
for _, version := range q.templateVersions {
|
||||
if version.CreatedAt.After(after) {
|
||||
versions = append(versions, version)
|
||||
}
|
||||
}
|
||||
return versions, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetTemplateVersionByTemplateIDAndName(_ context.Context, arg database.GetTemplateVersionByTemplateIDAndNameParams) (database.TemplateVersion, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
@@ -929,6 +983,19 @@ func (q *fakeQuerier) GetParameterSchemasByJobID(_ context.Context, jobID uuid.U
|
||||
return parameters, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetParameterSchemasCreatedAfter(_ context.Context, after time.Time) ([]database.ParameterSchema, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
parameters := make([]database.ParameterSchema, 0)
|
||||
for _, parameterSchema := range q.parameterSchemas {
|
||||
if parameterSchema.CreatedAt.After(after) {
|
||||
parameters = append(parameters, parameterSchema)
|
||||
}
|
||||
}
|
||||
return parameters, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetParameterValueByScopeAndName(_ context.Context, arg database.GetParameterValueByScopeAndNameParams) (database.ParameterValue, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
@@ -948,6 +1015,13 @@ func (q *fakeQuerier) GetParameterValueByScopeAndName(_ context.Context, arg dat
|
||||
return database.ParameterValue{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetTemplates(_ context.Context) ([]database.Template, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
return q.templates[:], nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetOrganizationMemberByUserID(_ context.Context, arg database.GetOrganizationMemberByUserIDParams) (database.OrganizationMember, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
@@ -1095,6 +1169,19 @@ func (q *fakeQuerier) GetWorkspaceAgentsByResourceIDs(_ context.Context, resourc
|
||||
return workspaceAgents, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetWorkspaceAgentsCreatedAfter(_ context.Context, after time.Time) ([]database.WorkspaceAgent, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
workspaceAgents := make([]database.WorkspaceAgent, 0)
|
||||
for _, agent := range q.provisionerJobAgents {
|
||||
if agent.CreatedAt.After(after) {
|
||||
workspaceAgents = append(workspaceAgents, agent)
|
||||
}
|
||||
}
|
||||
return workspaceAgents, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetWorkspaceAppByAgentIDAndName(_ context.Context, arg database.GetWorkspaceAppByAgentIDAndNameParams) (database.WorkspaceApp, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
@@ -1166,6 +1253,19 @@ func (q *fakeQuerier) GetWorkspaceResourcesByJobID(_ context.Context, jobID uuid
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetWorkspaceResourcesCreatedAfter(_ context.Context, after time.Time) ([]database.WorkspaceResource, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
resources := make([]database.WorkspaceResource, 0)
|
||||
for _, resource := range q.provisionerJobResources {
|
||||
if resource.CreatedAt.After(after) {
|
||||
resources = append(resources, resource)
|
||||
}
|
||||
}
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetProvisionerJobsByIDs(_ context.Context, ids []uuid.UUID) ([]database.ProvisionerJob, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
@@ -1186,6 +1286,19 @@ func (q *fakeQuerier) GetProvisionerJobsByIDs(_ context.Context, ids []uuid.UUID
|
||||
return jobs, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetProvisionerJobsCreatedAfter(_ context.Context, after time.Time) ([]database.ProvisionerJob, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
jobs := make([]database.ProvisionerJob, 0)
|
||||
for _, job := range q.provisionerJobs {
|
||||
if job.CreatedAt.After(after) {
|
||||
jobs = append(jobs, job)
|
||||
}
|
||||
}
|
||||
return jobs, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetProvisionerLogsByIDBetween(_ context.Context, arg database.GetProvisionerLogsByIDBetweenParams) ([]database.ProvisionerJobLog, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
@@ -1966,3 +2079,18 @@ func (q *fakeQuerier) InsertAuditLog(_ context.Context, arg database.InsertAudit
|
||||
|
||||
return alog, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) InsertDeploymentID(_ context.Context, id string) error {
|
||||
q.mutex.Lock()
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
q.deploymentID = id
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetDeploymentID(_ context.Context) (string, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
return q.deploymentID, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user