(ctx context.Context)
| 240 | } |
| 241 | |
| 242 | func (sc *StatsCollector) flush(ctx context.Context) (err error) { |
| 243 | sc.opts.Logger.Debug(ctx, "flushing workspace app stats") |
| 244 | defer func() { |
| 245 | if err != nil { |
| 246 | sc.opts.Logger.Error(ctx, "failed to flush workspace app stats", slog.Error(err)) |
| 247 | } else { |
| 248 | sc.opts.Logger.Debug(ctx, "flushed workspace app stats") |
| 249 | } |
| 250 | }() |
| 251 | |
| 252 | // We keep the backlog as a simple slice so that we don't need to |
| 253 | // attempt to merge it with the stats we're about to report. This |
| 254 | // is because the rollup is a one-way operation and the backlog may |
| 255 | // contain stats that are still in the statsBySessionID map and will |
| 256 | // be reported again in the future. It is possible to merge the |
| 257 | // backlog and the stats we're about to report, but it's not worth |
| 258 | // the complexity. |
| 259 | if len(sc.backlog) > 0 { |
| 260 | err = sc.opts.Reporter.ReportAppStats(ctx, sc.backlog) |
| 261 | if err != nil { |
| 262 | return xerrors.Errorf("report workspace app stats from backlog failed: %w", err) |
| 263 | } |
| 264 | sc.backlog = nil |
| 265 | } |
| 266 | |
| 267 | now := sc.opts.Now() |
| 268 | stats := sc.rollup(now) |
| 269 | if len(stats) == 0 { |
| 270 | return nil |
| 271 | } |
| 272 | |
| 273 | err = sc.opts.Reporter.ReportAppStats(ctx, stats) |
| 274 | if err != nil { |
| 275 | sc.backlog = stats |
| 276 | return xerrors.Errorf("report workspace app stats failed: %w", err) |
| 277 | } |
| 278 | |
| 279 | return nil |
| 280 | } |
| 281 | |
| 282 | func (sc *StatsCollector) Close() error { |
| 283 | sc.cancel() |
no test coverage detected