| 63 | } |
| 64 | |
| 65 | func (r *Reporter) ReportAppStats(ctx context.Context, stats []workspaceapps.StatsReport) error { |
| 66 | err := r.opts.Database.InTx(func(tx database.Store) error { |
| 67 | maxBatchSize := r.opts.AppStatBatchSize |
| 68 | if len(stats) < maxBatchSize { |
| 69 | maxBatchSize = len(stats) |
| 70 | } |
| 71 | batch := database.InsertWorkspaceAppStatsParams{ |
| 72 | UserID: make([]uuid.UUID, 0, maxBatchSize), |
| 73 | WorkspaceID: make([]uuid.UUID, 0, maxBatchSize), |
| 74 | AgentID: make([]uuid.UUID, 0, maxBatchSize), |
| 75 | AccessMethod: make([]string, 0, maxBatchSize), |
| 76 | SlugOrPort: make([]string, 0, maxBatchSize), |
| 77 | SessionID: make([]uuid.UUID, 0, maxBatchSize), |
| 78 | SessionStartedAt: make([]time.Time, 0, maxBatchSize), |
| 79 | SessionEndedAt: make([]time.Time, 0, maxBatchSize), |
| 80 | Requests: make([]int32, 0, maxBatchSize), |
| 81 | } |
| 82 | for _, stat := range stats { |
| 83 | batch.UserID = append(batch.UserID, stat.UserID) |
| 84 | batch.WorkspaceID = append(batch.WorkspaceID, stat.WorkspaceID) |
| 85 | batch.AgentID = append(batch.AgentID, stat.AgentID) |
| 86 | batch.AccessMethod = append(batch.AccessMethod, string(stat.AccessMethod)) |
| 87 | batch.SlugOrPort = append(batch.SlugOrPort, stat.SlugOrPort) |
| 88 | batch.SessionID = append(batch.SessionID, stat.SessionID) |
| 89 | batch.SessionStartedAt = append(batch.SessionStartedAt, stat.SessionStartedAt) |
| 90 | batch.SessionEndedAt = append(batch.SessionEndedAt, stat.SessionEndedAt) |
| 91 | // #nosec G115 - Safe conversion as request count is expected to be within int32 range |
| 92 | batch.Requests = append(batch.Requests, int32(stat.Requests)) |
| 93 | |
| 94 | if len(batch.UserID) >= r.opts.AppStatBatchSize { |
| 95 | err := tx.InsertWorkspaceAppStats(ctx, batch) |
| 96 | if err != nil { |
| 97 | return err |
| 98 | } |
| 99 | |
| 100 | // Reset batch. |
| 101 | batch.UserID = batch.UserID[:0] |
| 102 | batch.WorkspaceID = batch.WorkspaceID[:0] |
| 103 | batch.AgentID = batch.AgentID[:0] |
| 104 | batch.AccessMethod = batch.AccessMethod[:0] |
| 105 | batch.SlugOrPort = batch.SlugOrPort[:0] |
| 106 | batch.SessionID = batch.SessionID[:0] |
| 107 | batch.SessionStartedAt = batch.SessionStartedAt[:0] |
| 108 | batch.SessionEndedAt = batch.SessionEndedAt[:0] |
| 109 | batch.Requests = batch.Requests[:0] |
| 110 | } |
| 111 | } |
| 112 | if len(batch.UserID) == 0 { |
| 113 | return nil |
| 114 | } |
| 115 | |
| 116 | if !r.opts.DisableDatabaseInserts { |
| 117 | if err := tx.InsertWorkspaceAppStats(ctx, batch); err != nil { |
| 118 | return err |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | uniqueIDs := slice.Unique(batch.WorkspaceID) |