Skip to content

Commit 6fd9975

Browse files
authored
feat(coderd): add coder_app usage stats (#9001)
Updates #8658
1 parent f3c7076 commit 6fd9975

31 files changed

+1730
-62
lines changed

coderd/apidoc/docs.go

+80
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

+76
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/coderd.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ type Options struct {
162162

163163
UpdateAgentMetrics func(ctx context.Context, username, workspaceName, agentName string, metrics []agentsdk.AgentMetric)
164164
StatsBatcher *batchstats.Batcher
165+
166+
WorkspaceAppsStatsCollectorOptions workspaceapps.StatsCollectorOptions
165167
}
166168

167169
// @title Coder API
@@ -418,8 +420,17 @@ func New(options *Options) *API {
418420
}
419421
}
420422

423+
workspaceAppsLogger := options.Logger.Named("workspaceapps")
424+
if options.WorkspaceAppsStatsCollectorOptions.Logger == nil {
425+
named := workspaceAppsLogger.Named("stats_collector")
426+
options.WorkspaceAppsStatsCollectorOptions.Logger = &named
427+
}
428+
if options.WorkspaceAppsStatsCollectorOptions.Reporter == nil {
429+
options.WorkspaceAppsStatsCollectorOptions.Reporter = workspaceapps.NewStatsDBReporter(options.Database, workspaceapps.DefaultStatsDBReporterBatchSize)
430+
}
431+
421432
api.workspaceAppServer = &workspaceapps.Server{
422-
Logger: options.Logger.Named("workspaceapps"),
433+
Logger: workspaceAppsLogger,
423434

424435
DashboardURL: api.AccessURL,
425436
AccessURL: api.AccessURL,
@@ -430,6 +441,7 @@ func New(options *Options) *API {
430441
SignedTokenProvider: api.WorkspaceAppsProvider,
431442
AgentProvider: api.agentProvider,
432443
AppSecurityKey: options.AppSecurityKey,
444+
StatsCollector: workspaceapps.NewStatsCollector(options.WorkspaceAppsStatsCollectorOptions),
433445

434446
DisablePathApps: options.DeploymentValues.DisablePathApps.Value(),
435447
SecureAuthCookie: options.DeploymentValues.SecureAuthCookie.Value(),
@@ -1020,6 +1032,7 @@ func (api *API) Close() error {
10201032
if api.updateChecker != nil {
10211033
api.updateChecker.Close()
10221034
}
1035+
_ = api.workspaceAppServer.Close()
10231036
coordinator := api.TailnetCoordinator.Load()
10241037
if coordinator != nil {
10251038
_ = (*coordinator).Close()

coderd/coderdtest/coderdtest.go

+34-31
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ type Options struct {
144144
// as part of your test.
145145
Logger *slog.Logger
146146
StatsBatcher *batchstats.Batcher
147+
148+
WorkspaceAppsStatsCollectorOptions workspaceapps.StatsCollectorOptions
147149
}
148150

149151
// New constructs a codersdk client connected to an in-memory API instance.
@@ -394,37 +396,38 @@ func NewOptions(t testing.TB, options *Options) (func(http.Handler), context.Can
394396
Pubsub: options.Pubsub,
395397
GitAuthConfigs: options.GitAuthConfigs,
396398

397-
Auditor: options.Auditor,
398-
AWSCertificates: options.AWSCertificates,
399-
AzureCertificates: options.AzureCertificates,
400-
GithubOAuth2Config: options.GithubOAuth2Config,
401-
RealIPConfig: options.RealIPConfig,
402-
OIDCConfig: options.OIDCConfig,
403-
GoogleTokenValidator: options.GoogleTokenValidator,
404-
SSHKeygenAlgorithm: options.SSHKeygenAlgorithm,
405-
DERPServer: derpServer,
406-
APIRateLimit: options.APIRateLimit,
407-
LoginRateLimit: options.LoginRateLimit,
408-
FilesRateLimit: options.FilesRateLimit,
409-
Authorizer: options.Authorizer,
410-
Telemetry: telemetry.NewNoop(),
411-
TemplateScheduleStore: &templateScheduleStore,
412-
TLSCertificates: options.TLSCertificates,
413-
TrialGenerator: options.TrialGenerator,
414-
TailnetCoordinator: options.Coordinator,
415-
BaseDERPMap: derpMap,
416-
DERPMapUpdateFrequency: 150 * time.Millisecond,
417-
MetricsCacheRefreshInterval: options.MetricsCacheRefreshInterval,
418-
AgentStatsRefreshInterval: options.AgentStatsRefreshInterval,
419-
DeploymentValues: options.DeploymentValues,
420-
UpdateCheckOptions: options.UpdateCheckOptions,
421-
SwaggerEndpoint: options.SwaggerEndpoint,
422-
AppSecurityKey: AppSecurityKey,
423-
SSHConfig: options.ConfigSSH,
424-
HealthcheckFunc: options.HealthcheckFunc,
425-
HealthcheckTimeout: options.HealthcheckTimeout,
426-
HealthcheckRefresh: options.HealthcheckRefresh,
427-
StatsBatcher: options.StatsBatcher,
399+
Auditor: options.Auditor,
400+
AWSCertificates: options.AWSCertificates,
401+
AzureCertificates: options.AzureCertificates,
402+
GithubOAuth2Config: options.GithubOAuth2Config,
403+
RealIPConfig: options.RealIPConfig,
404+
OIDCConfig: options.OIDCConfig,
405+
GoogleTokenValidator: options.GoogleTokenValidator,
406+
SSHKeygenAlgorithm: options.SSHKeygenAlgorithm,
407+
DERPServer: derpServer,
408+
APIRateLimit: options.APIRateLimit,
409+
LoginRateLimit: options.LoginRateLimit,
410+
FilesRateLimit: options.FilesRateLimit,
411+
Authorizer: options.Authorizer,
412+
Telemetry: telemetry.NewNoop(),
413+
TemplateScheduleStore: &templateScheduleStore,
414+
TLSCertificates: options.TLSCertificates,
415+
TrialGenerator: options.TrialGenerator,
416+
TailnetCoordinator: options.Coordinator,
417+
BaseDERPMap: derpMap,
418+
DERPMapUpdateFrequency: 150 * time.Millisecond,
419+
MetricsCacheRefreshInterval: options.MetricsCacheRefreshInterval,
420+
AgentStatsRefreshInterval: options.AgentStatsRefreshInterval,
421+
DeploymentValues: options.DeploymentValues,
422+
UpdateCheckOptions: options.UpdateCheckOptions,
423+
SwaggerEndpoint: options.SwaggerEndpoint,
424+
AppSecurityKey: AppSecurityKey,
425+
SSHConfig: options.ConfigSSH,
426+
HealthcheckFunc: options.HealthcheckFunc,
427+
HealthcheckTimeout: options.HealthcheckTimeout,
428+
HealthcheckRefresh: options.HealthcheckRefresh,
429+
StatsBatcher: options.StatsBatcher,
430+
WorkspaceAppsStatsCollectorOptions: options.WorkspaceAppsStatsCollectorOptions,
428431
}
429432
}
430433

coderd/database/dbauthz/dbauthz.go

+7
Original file line numberDiff line numberDiff line change
@@ -2046,6 +2046,13 @@ func (q *querier) InsertWorkspaceApp(ctx context.Context, arg database.InsertWor
20462046
return q.db.InsertWorkspaceApp(ctx, arg)
20472047
}
20482048

2049+
func (q *querier) InsertWorkspaceAppStats(ctx context.Context, arg database.InsertWorkspaceAppStatsParams) error {
2050+
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceSystem); err != nil {
2051+
return err
2052+
}
2053+
return q.db.InsertWorkspaceAppStats(ctx, arg)
2054+
}
2055+
20492056
func (q *querier) InsertWorkspaceBuild(ctx context.Context, arg database.InsertWorkspaceBuildParams) error {
20502057
w, err := q.db.GetWorkspaceByID(ctx, arg.WorkspaceID)
20512058
if err != nil {

0 commit comments

Comments
 (0)