nolint:revive // usage is a control flag while we have the experiment
(ctx context.Context, now time.Time, workspace database.WorkspaceIdentity, agentID uuid.UUID, agentName string, stats *agentproto.Stats, usage bool)
| 138 | |
| 139 | // nolint:revive // usage is a control flag while we have the experiment |
| 140 | func (r *Reporter) ReportAgentStats(ctx context.Context, now time.Time, workspace database.WorkspaceIdentity, agentID uuid.UUID, agentName string, stats *agentproto.Stats, usage bool) error { |
| 141 | // update agent stats |
| 142 | if !r.opts.DisableDatabaseInserts { |
| 143 | r.opts.StatsBatcher.Add(now, agentID, workspace.TemplateID, workspace.OwnerID, workspace.ID, stats, usage) |
| 144 | } |
| 145 | |
| 146 | // update prometheus metrics (even if template insights are disabled) |
| 147 | if r.opts.UpdateAgentMetricsFn != nil { |
| 148 | r.opts.UpdateAgentMetricsFn(ctx, prometheusmetrics.AgentMetricLabels{ |
| 149 | Username: workspace.OwnerUsername, |
| 150 | WorkspaceName: workspace.Name, |
| 151 | AgentName: agentName, |
| 152 | TemplateName: workspace.TemplateName, |
| 153 | }, stats.Metrics) |
| 154 | } |
| 155 | |
| 156 | // workspace activity: if no sessions we do not bump activity |
| 157 | if usage && stats.SessionCountVscode == 0 && |
| 158 | stats.SessionCountJetbrains == 0 && |
| 159 | stats.SessionCountReconnectingPty == 0 && |
| 160 | stats.SessionCountSsh == 0 { |
| 161 | return nil |
| 162 | } |
| 163 | |
| 164 | // legacy stats: if no active connections we do not bump activity |
| 165 | if !usage && stats.ConnectionCount == 0 { |
| 166 | return nil |
| 167 | } |
| 168 | |
| 169 | // Prebuilds are not subject to activity-based deadline bumps |
| 170 | if !workspace.IsPrebuild() { |
| 171 | // check next autostart |
| 172 | var nextAutostart time.Time |
| 173 | if workspace.AutostartSchedule.String != "" { |
| 174 | templateSchedule, err := (*(r.opts.TemplateScheduleStore.Load())).Get(ctx, r.opts.Database, workspace.TemplateID) |
| 175 | // If the template schedule fails to load, just default to bumping |
| 176 | // without the next transition and log it. |
| 177 | switch { |
| 178 | case err == nil: |
| 179 | next, allowed := schedule.NextAutostart(now, workspace.AutostartSchedule.String, templateSchedule) |
| 180 | if allowed { |
| 181 | nextAutostart = next |
| 182 | } |
| 183 | case database.IsQueryCanceledError(err): |
| 184 | r.opts.Logger.Debug(ctx, "query canceled while loading template schedule", |
| 185 | slog.F("workspace_id", workspace.ID), |
| 186 | slog.F("template_id", workspace.TemplateID)) |
| 187 | default: |
| 188 | r.opts.Logger.Error(ctx, "failed to load template schedule bumping activity, defaulting to bumping by 60min", |
| 189 | slog.F("workspace_id", workspace.ID), |
| 190 | slog.F("template_id", workspace.TemplateID), |
| 191 | slog.Error(err), |
| 192 | ) |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | // bump workspace activity |
| 197 | ActivityBumpWorkspace(ctx, r.opts.Logger.Named("activity_bump"), r.opts.Database, workspace.ID, nextAutostart, ActivityBumpReasonWorkspaceStats) |
no test coverage detected