Skip to content

Commit 4fc5e47

Browse files
committed
save
1 parent a60de2b commit 4fc5e47

File tree

4 files changed

+38
-50
lines changed

4 files changed

+38
-50
lines changed

coderd/batchstats/batcher.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const (
2525
)
2626

2727
// Batcher holds a buffer of agent stats and periodically flushes them to
28-
// its configured store. It also updates the workspace's last used time.
28+
// its configured store.
2929
type Batcher struct {
3030
store database.Store
3131
log slog.Logger

coderd/coderd.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -1275,7 +1275,8 @@ type API struct {
12751275
healthCheckGroup *singleflight.Group[string, *healthsdk.HealthcheckReport]
12761276
healthCheckCache atomic.Pointer[healthsdk.HealthcheckReport]
12771277

1278-
statsBatcher *batchstats.Batcher
1278+
statsBatcher *batchstats.Batcher
1279+
statsCollector workspaceapps.StatsCollector
12791280

12801281
Acquirer *provisionerdserver.Acquirer
12811282
// dbRolluper rolls up template usage stats from raw agent and app

coderd/workspaceagents.go

+6-43
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import (
3636
"github.com/coder/coder/v2/coderd/httpmw"
3737
"github.com/coder/coder/v2/coderd/prometheusmetrics"
3838
"github.com/coder/coder/v2/coderd/rbac/policy"
39-
"github.com/coder/coder/v2/coderd/schedule"
39+
"github.com/coder/coder/v2/coderd/workspaceapps"
4040
"github.com/coder/coder/v2/codersdk"
4141
"github.com/coder/coder/v2/codersdk/agentsdk"
4242
"github.com/coder/coder/v2/codersdk/workspacesdk"
@@ -1167,35 +1167,6 @@ func (api *API) workspaceAgentReportStats(rw http.ResponseWriter, r *http.Reques
11671167
slog.F("payload", req),
11681168
)
11691169

1170-
if req.ConnectionCount > 0 {
1171-
var nextAutostart time.Time
1172-
if workspace.AutostartSchedule.String != "" {
1173-
templateSchedule, err := (*(api.TemplateScheduleStore.Load())).Get(ctx, api.Database, workspace.TemplateID)
1174-
// If the template schedule fails to load, just default to bumping without the next transition and log it.
1175-
if err != nil {
1176-
// There's nothing we can do if the query was canceled, the
1177-
// client most likely went away so we just return an internal
1178-
// server error.
1179-
if database.IsQueryCanceledError(err) {
1180-
httpapi.InternalServerError(rw, err)
1181-
return
1182-
}
1183-
api.Logger.Error(ctx, "failed to load template schedule bumping activity, defaulting to bumping by 60min",
1184-
slog.F("workspace_id", workspace.ID),
1185-
slog.F("template_id", workspace.TemplateID),
1186-
slog.Error(err),
1187-
)
1188-
} else {
1189-
next, allowed := schedule.NextAutostart(time.Now(), workspace.AutostartSchedule.String, templateSchedule)
1190-
if allowed {
1191-
nextAutostart = next
1192-
}
1193-
}
1194-
}
1195-
agentapi.ActivityBumpWorkspace(ctx, api.Logger.Named("activity_bump"), api.Database, workspace.ID, nextAutostart)
1196-
}
1197-
1198-
now := dbtime.Now()
11991170
protoStats := &agentproto.Stats{
12001171
ConnectionsByProto: req.ConnectionsByProto,
12011172
ConnectionCount: req.ConnectionCount,
@@ -1242,19 +1213,6 @@ func (api *API) workspaceAgentReportStats(rw http.ResponseWriter, r *http.Reques
12421213
}
12431214
return nil
12441215
})
1245-
if req.SessionCount() > 0 {
1246-
errGroup.Go(func() error {
1247-
// nolint:gocritic // (#13146) Will be moved soon as part of refactor.
1248-
err := api.Database.UpdateWorkspaceLastUsedAt(ctx, database.UpdateWorkspaceLastUsedAtParams{
1249-
ID: workspace.ID,
1250-
LastUsedAt: now,
1251-
})
1252-
if err != nil {
1253-
return xerrors.Errorf("can't update workspace LastUsedAt: %w", err)
1254-
}
1255-
return nil
1256-
})
1257-
}
12581216
if api.Options.UpdateAgentMetrics != nil {
12591217
errGroup.Go(func() error {
12601218
user, err := api.Database.GetUserByID(ctx, workspace.OwnerID)
@@ -1277,6 +1235,11 @@ func (api *API) workspaceAgentReportStats(rw http.ResponseWriter, r *http.Reques
12771235
return
12781236
}
12791237

1238+
api.statsCollector.CollectAndFlush(ctx, workspaceapps.StatsReport{
1239+
WorkspaceID: workspace.ID,
1240+
// TODO: fill out
1241+
})
1242+
12801243
httpapi.Write(ctx, rw, http.StatusOK, agentsdk.StatsResponse{
12811244
ReportInterval: api.AgentStatsRefreshInterval,
12821245
})

coderd/workspaceapps/stats.go

+29-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"cdr.dev/slog"
1313

14+
agentproto "github.com/coder/coder/v2/agent/proto"
1415
"github.com/coder/coder/v2/coderd/database"
1516
"github.com/coder/coder/v2/coderd/database/dbauthz"
1617
"github.com/coder/coder/v2/coderd/database/dbtime"
@@ -236,7 +237,10 @@ type StatsCollectorOptions struct {
236237
// RollupWindow is the window size for rolling up stats, session shorter
237238
// than this will be rolled up and longer than this will be tracked
238239
// individually.
239-
RollupWindow time.Duration
240+
RollupWindow time.Duration
241+
DB database.Store
242+
Pubsub pubsub.Pubsub
243+
TemplateScheduleStore *atomic.Pointer[schedule.TemplateScheduleStore]
240244

241245
// Options for tests.
242246
Flush <-chan chan<- struct{}
@@ -295,11 +299,31 @@ func (sc *StatsCollector) Collect(report StatsReport) {
295299
sc.opts.Logger.Debug(sc.ctx, "collected workspace app stats", slog.F("report", report))
296300
}
297301

298-
func (sc *StatsCollector) CollectAndFlush(ctx context.Context, report StatsReport) error {
299-
sc.Collect(report)
300-
err := sc.flush(ctx)
302+
func (sc *StatsCollector) CollectAgentStat(ctx context.Context, now time.Time, agentID uuid.UUID, workspace database.Workspace, st *agentproto.Stats) error {
303+
var nextAutostart time.Time
304+
if workspace.AutostartSchedule.String != "" {
305+
templateSchedule, err := (*(sc.opts.TemplateScheduleStore.Load())).Get(ctx, sc.opts.DB, workspace.TemplateID)
306+
// If the template schedule fails to load, just default to bumping
307+
// without the next transition and log it.
308+
if err != nil {
309+
sc.opts.Logger.Error(ctx, "failed to load template schedule bumping activity, defaulting to bumping by 60min",
310+
slog.F("workspace_id", workspace.ID),
311+
slog.F("template_id", workspace.TemplateID),
312+
slog.Error(err),
313+
)
314+
} else {
315+
next, allowed := schedule.NextAutostart(dbtime.Now(), workspace.AutostartSchedule.String, templateSchedule)
316+
if allowed {
317+
nextAutostart = next
318+
}
319+
}
320+
}
321+
ActivityBumpWorkspace(ctx, sc.opts.Logger.Named("activity_bump"), sc.opts.DB, workspace.ID, nextAutostart)
322+
323+
err := sc.opts.Pubsub.Publish(codersdk.WorkspaceNotifyChannel(workspace.ID), []byte{})
301324
if err != nil {
302-
return xerrors.Errorf("flushing collector: %w", err)
325+
sc.opts.Logger.Warn(ctx, "failed to publish workspace agent stats",
326+
slog.F("workspace_id", workspace.ID), slog.Error(err))
303327
}
304328

305329
return nil

0 commit comments

Comments
 (0)