diff --git a/coderd/coderd.go b/coderd/coderd.go index 0cc0962316571..caba0dd4a9a85 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -541,7 +541,7 @@ func New(options *Options) *API { options.WorkspaceAppsStatsCollectorOptions.Logger = &named } if options.WorkspaceAppsStatsCollectorOptions.Reporter == nil { - options.WorkspaceAppsStatsCollectorOptions.Reporter = workspaceapps.NewStatsDBReporter(options.Database, workspaceapps.DefaultStatsDBReporterBatchSize) + options.WorkspaceAppsStatsCollectorOptions.Reporter = workspaceapps.NewStatsDBReporter(options.Database, options.Logger.Named("stats-reporter"), workspaceapps.DefaultStatsDBReporterBatchSize) } api.workspaceAppServer = &workspaceapps.Server{ diff --git a/coderd/insights_test.go b/coderd/insights_test.go index 83be460dbdd8e..16377ee55e6d2 100644 --- a/coderd/insights_test.go +++ b/coderd/insights_test.go @@ -735,7 +735,7 @@ func TestTemplateInsights_Golden(t *testing.T) { }) } } - reporter := workspaceapps.NewStatsDBReporter(db, workspaceapps.DefaultStatsDBReporterBatchSize) + reporter := workspaceapps.NewStatsDBReporter(db, slogtest.Make(t, nil), workspaceapps.DefaultStatsDBReporterBatchSize) //nolint:gocritic // This is a test. err = reporter.Report(dbauthz.AsSystemRestricted(ctx), stats) require.NoError(t, err, "want no error inserting app stats") @@ -1631,7 +1631,7 @@ func TestUserActivityInsights_Golden(t *testing.T) { }) } } - reporter := workspaceapps.NewStatsDBReporter(db, workspaceapps.DefaultStatsDBReporterBatchSize) + reporter := workspaceapps.NewStatsDBReporter(db, slogtest.Make(t, nil),workspaceapps.DefaultStatsDBReporterBatchSize) //nolint:gocritic // This is a test. err = reporter.Report(dbauthz.AsSystemRestricted(ctx), stats) require.NoError(t, err, "want no error inserting app stats") diff --git a/coderd/prometheusmetrics/insights/metricscollector_test.go b/coderd/prometheusmetrics/insights/metricscollector_test.go index 598c154db08d8..583857fb16851 100644 --- a/coderd/prometheusmetrics/insights/metricscollector_test.go +++ b/coderd/prometheusmetrics/insights/metricscollector_test.go @@ -109,7 +109,7 @@ func TestCollectInsights(t *testing.T) { require.NoError(t, err, "unable to post fake stats") // Fake app usage - reporter := workspaceapps.NewStatsDBReporter(db, workspaceapps.DefaultStatsDBReporterBatchSize) + reporter := workspaceapps.NewStatsDBReporter(db, slogtest.Make(t, nil), workspaceapps.DefaultStatsDBReporterBatchSize) refTime := time.Now().Add(-3 * time.Minute).Truncate(time.Minute) //nolint:gocritic // This is a test. err = reporter.Report(dbauthz.AsSystemRestricted(context.Background()), []workspaceapps.StatsReport{ diff --git a/coderd/workspaceapps/stats.go b/coderd/workspaceapps/stats.go index 76a60c6fbb5df..1fa9600afdfcc 100644 --- a/coderd/workspaceapps/stats.go +++ b/coderd/workspaceapps/stats.go @@ -9,6 +9,7 @@ import ( "golang.org/x/xerrors" "cdr.dev/slog" + "github.com/coder/coder/v2/coderd/agentapi" "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/database/dbauthz" @@ -60,13 +61,15 @@ var _ StatsReporter = (*StatsDBReporter)(nil) // StatsDBReporter writes workspace app StatsReports to the database. type StatsDBReporter struct { db database.Store + logger slog.Logger batchSize int } // NewStatsDBReporter returns a new StatsDBReporter. -func NewStatsDBReporter(db database.Store, batchSize int) *StatsDBReporter { +func NewStatsDBReporter(db database.Store, logger slog.Logger, batchSize int) *StatsDBReporter { return &StatsDBReporter{ db: db, + logger: logger, batchSize: batchSize, } } @@ -139,6 +142,19 @@ func (r *StatsDBReporter) Report(ctx context.Context, stats []StatsReport) error return err } + // This is very inefficient to loop over all workspaces with activity. + // The 'ActivityBumpWorkspace' sql query is not built to be easily turned + // in a batch. + for _, id := range uniqueIDs { + // Passing in a zero time will default bump the workspace by 1hr. + // The correct behavior is to fetch the template settings, and pass + // in the calculated autostart time. But that requires an extra db + // call per workspace. + // + // This function will log any failures. + agentapi.ActivityBumpWorkspace(ctx, r.logger, r.db, id, time.Time{}) + } + return nil }, nil) if err != nil {