@@ -6,17 +6,13 @@ package apiv1
6
6
7
7
import (
8
8
"context"
9
- "database/sql"
10
9
"errors"
11
- "fmt"
12
10
"math"
13
11
"time"
14
12
15
13
"github.com/google/uuid"
16
14
17
15
"github.com/gitpod-io/gitpod/common-go/log"
18
- "github.com/gitpod-io/gitpod/usage/pkg/contentservice"
19
-
20
16
v1 "github.com/gitpod-io/gitpod/usage-api/v1"
21
17
"github.com/gitpod-io/gitpod/usage/pkg/db"
22
18
"google.golang.org/grpc/codes"
@@ -32,96 +28,11 @@ type UsageService struct {
32
28
nowFunc func () time.Time
33
29
pricer * WorkspacePricer
34
30
35
- contentService contentservice.Interface
36
-
37
- reportGenerator * ReportGenerator
38
-
39
31
v1.UnimplementedUsageServiceServer
40
32
}
41
33
42
34
const maxQuerySize = 31 * 24 * time .Hour
43
35
44
- func (s * UsageService ) ListBilledUsage (ctx context.Context , in * v1.ListBilledUsageRequest ) (* v1.ListBilledUsageResponse , error ) {
45
- to := time .Now ()
46
- if in .To != nil {
47
- to = in .To .AsTime ()
48
- }
49
- from := to .Add (- maxQuerySize )
50
- if in .From != nil {
51
- from = in .From .AsTime ()
52
- }
53
-
54
- if from .After (to ) {
55
- return nil , status .Errorf (codes .InvalidArgument , "Specified From timestamp is after To. Please ensure From is always before To" )
56
- }
57
-
58
- if to .Sub (from ) > maxQuerySize {
59
- return nil , status .Errorf (codes .InvalidArgument , "Maximum range exceeded. Range specified can be at most %s" , maxQuerySize .String ())
60
- }
61
-
62
- var order db.Order = db .DescendingOrder
63
- if in .Order == v1 .ListBilledUsageRequest_ORDERING_ASCENDING {
64
- order = db .AscendingOrder
65
- }
66
-
67
- var limit int64 = 1000
68
- var page int64 = 0
69
- var offset int64 = 0
70
- if in .Pagination != nil {
71
- limit = in .Pagination .PerPage
72
- page = in .Pagination .Page
73
- offset = limit * (int64 (math .Max (0 , float64 (page - 1 ))))
74
- }
75
-
76
- listUsageResult , err := db .ListUsage (ctx , s .conn , db .AttributionID (in .GetAttributionId ()), from , to , order , offset , limit )
77
- if err != nil {
78
- log .Log .
79
- WithField ("attribution_id" , in .AttributionId ).
80
- WithField ("perPage" , limit ).
81
- WithField ("page" , page ).
82
- WithField ("from" , from ).
83
- WithField ("to" , to ).
84
- WithError (err ).Error ("Failed to list usage." )
85
- return nil , status .Error (codes .Internal , "unable to retrieve billed usage" )
86
- }
87
-
88
- var billedSessions []* v1.BilledSession
89
- for _ , usageRecord := range listUsageResult .UsageRecords {
90
- var endTime * timestamppb.Timestamp
91
- if usageRecord .StoppedAt .Valid {
92
- endTime = timestamppb .New (usageRecord .StoppedAt .Time )
93
- }
94
- billedSession := & v1.BilledSession {
95
- AttributionId : string (usageRecord .AttributionID ),
96
- UserId : usageRecord .UserID .String (),
97
- WorkspaceId : usageRecord .WorkspaceID ,
98
- WorkspaceType : string (usageRecord .WorkspaceType ),
99
- ProjectId : usageRecord .ProjectID ,
100
- InstanceId : usageRecord .InstanceID .String (),
101
- WorkspaceClass : usageRecord .WorkspaceClass ,
102
- StartTime : timestamppb .New (usageRecord .StartedAt ),
103
- EndTime : endTime ,
104
- Credits : usageRecord .CreditsUsed ,
105
- }
106
- billedSessions = append (billedSessions , billedSession )
107
- }
108
-
109
- var totalPages = int64 (math .Ceil (float64 (listUsageResult .Count ) / float64 (limit )))
110
-
111
- var pagination = v1.PaginatedResponse {
112
- PerPage : limit ,
113
- Page : page ,
114
- TotalPages : totalPages ,
115
- Total : listUsageResult .Count ,
116
- }
117
-
118
- return & v1.ListBilledUsageResponse {
119
- Sessions : billedSessions ,
120
- TotalCreditsUsed : listUsageResult .TotalCreditsUsed ,
121
- Pagination : & pagination ,
122
- }, nil
123
- }
124
-
125
36
func (s * UsageService ) ListUsage (ctx context.Context , in * v1.ListUsageRequest ) (* v1.ListUsageResponse , error ) {
126
37
to := time .Now ()
127
38
if in .To != nil {
@@ -232,39 +143,6 @@ func (s *UsageService) ListUsage(ctx context.Context, in *v1.ListUsageRequest) (
232
143
}, nil
233
144
}
234
145
235
- func (s * UsageService ) ReconcileUsage (ctx context.Context , req * v1.ReconcileUsageRequest ) (* v1.ReconcileUsageResponse , error ) {
236
- from := req .GetStartTime ().AsTime ()
237
- to := req .GetEndTime ().AsTime ()
238
-
239
- if to .Before (from ) {
240
- return nil , status .Errorf (codes .InvalidArgument , "End time must be after start time" )
241
- }
242
-
243
- report , err := s .reportGenerator .GenerateUsageReport (ctx , from , to )
244
- if err != nil {
245
- log .Log .WithError (err ).Error ("Failed to reconcile time range." )
246
- return nil , status .Error (codes .Internal , "failed to reconcile time range" )
247
- }
248
-
249
- err = db .CreateUsageRecords (ctx , s .conn , report .UsageRecords )
250
- if err != nil {
251
- log .Log .WithError (err ).Error ("Failed to persist usage records." )
252
- return nil , status .Error (codes .Internal , "failed to persist usage records" )
253
- }
254
-
255
- filename := fmt .Sprintf ("%s.gz" , time .Now ().Format (time .RFC3339 ))
256
- err = s .contentService .UploadUsageReport (ctx , filename , report )
257
- if err != nil {
258
- log .Log .WithError (err ).Error ("Failed to persist usage report to content service." )
259
- return nil , status .Error (codes .Internal , "failed to persist usage report to content service" )
260
- }
261
-
262
- return & v1.ReconcileUsageResponse {
263
- ReportId : filename ,
264
- }, nil
265
-
266
- }
267
-
268
146
func (s * UsageService ) GetCostCenter (ctx context.Context , in * v1.GetCostCenterRequest ) (* v1.GetCostCenterResponse , error ) {
269
147
var attributionIdReq string
270
148
@@ -475,46 +353,12 @@ func dedupeWorkspaceInstancesForUsage(instances []db.WorkspaceInstanceForUsage)
475
353
return set
476
354
}
477
355
478
- func NewUsageService (conn * gorm.DB , reportGenerator * ReportGenerator , contentSvc contentservice. Interface , pricer * WorkspacePricer ) * UsageService {
356
+ func NewUsageService (conn * gorm.DB , pricer * WorkspacePricer ) * UsageService {
479
357
return & UsageService {
480
358
conn : conn ,
481
359
nowFunc : func () time.Time {
482
360
return time .Now ().UTC ()
483
361
},
484
- pricer : pricer ,
485
- reportGenerator : reportGenerator ,
486
- contentService : contentSvc ,
362
+ pricer : pricer ,
487
363
}
488
364
}
489
-
490
- func instancesToUsageRecords (instances []db.WorkspaceInstanceForUsage , pricer * WorkspacePricer , now time.Time ) []db.WorkspaceInstanceUsage {
491
- var usageRecords []db.WorkspaceInstanceUsage
492
-
493
- for _ , instance := range instances {
494
- var stoppedAt sql.NullTime
495
- if instance .StoppingTime .IsSet () {
496
- stoppedAt = sql.NullTime {Time : instance .StoppingTime .Time (), Valid : true }
497
- }
498
-
499
- projectID := ""
500
- if instance .ProjectID .Valid {
501
- projectID = instance .ProjectID .String
502
- }
503
-
504
- usageRecords = append (usageRecords , db.WorkspaceInstanceUsage {
505
- InstanceID : instance .ID ,
506
- AttributionID : instance .UsageAttributionID ,
507
- WorkspaceID : instance .WorkspaceID ,
508
- ProjectID : projectID ,
509
- UserID : instance .OwnerID ,
510
- WorkspaceType : instance .Type ,
511
- WorkspaceClass : instance .WorkspaceClass ,
512
- StartedAt : instance .StartedTime .Time (),
513
- StoppedAt : stoppedAt ,
514
- CreditsUsed : pricer .CreditsUsedByInstance (& instance , now ),
515
- GenerationID : 0 ,
516
- })
517
- }
518
-
519
- return usageRecords
520
- }
0 commit comments