Skip to content

Commit d0d64bb

Browse files
authored
refactor: define insights interval (#9693)
1 parent 65db7a7 commit d0d64bb

File tree

8 files changed

+228
-220
lines changed

8 files changed

+228
-220
lines changed

coderd/database/dbauthz/dbauthz.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -1247,42 +1247,42 @@ func (q *querier) GetTemplateDAUs(ctx context.Context, arg database.GetTemplateD
12471247
return q.db.GetTemplateDAUs(ctx, arg)
12481248
}
12491249

1250-
func (q *querier) GetTemplateDailyInsights(ctx context.Context, arg database.GetTemplateDailyInsightsParams) ([]database.GetTemplateDailyInsightsRow, error) {
1250+
func (q *querier) GetTemplateInsights(ctx context.Context, arg database.GetTemplateInsightsParams) (database.GetTemplateInsightsRow, error) {
12511251
for _, templateID := range arg.TemplateIDs {
12521252
template, err := q.db.GetTemplateByID(ctx, templateID)
12531253
if err != nil {
1254-
return nil, err
1254+
return database.GetTemplateInsightsRow{}, err
12551255
}
12561256

12571257
if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil {
1258-
return nil, err
1258+
return database.GetTemplateInsightsRow{}, err
12591259
}
12601260
}
12611261
if len(arg.TemplateIDs) == 0 {
12621262
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTemplate.All()); err != nil {
1263-
return nil, err
1263+
return database.GetTemplateInsightsRow{}, err
12641264
}
12651265
}
1266-
return q.db.GetTemplateDailyInsights(ctx, arg)
1266+
return q.db.GetTemplateInsights(ctx, arg)
12671267
}
12681268

1269-
func (q *querier) GetTemplateInsights(ctx context.Context, arg database.GetTemplateInsightsParams) (database.GetTemplateInsightsRow, error) {
1269+
func (q *querier) GetTemplateInsightsByInterval(ctx context.Context, arg database.GetTemplateInsightsByIntervalParams) ([]database.GetTemplateInsightsByIntervalRow, error) {
12701270
for _, templateID := range arg.TemplateIDs {
12711271
template, err := q.db.GetTemplateByID(ctx, templateID)
12721272
if err != nil {
1273-
return database.GetTemplateInsightsRow{}, err
1273+
return nil, err
12741274
}
12751275

12761276
if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil {
1277-
return database.GetTemplateInsightsRow{}, err
1277+
return nil, err
12781278
}
12791279
}
12801280
if len(arg.TemplateIDs) == 0 {
12811281
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceTemplate.All()); err != nil {
1282-
return database.GetTemplateInsightsRow{}, err
1282+
return nil, err
12831283
}
12841284
}
1285-
return q.db.GetTemplateInsights(ctx, arg)
1285+
return q.db.GetTemplateInsightsByInterval(ctx, arg)
12861286
}
12871287

12881288
func (q *querier) GetTemplateParameterInsights(ctx context.Context, arg database.GetTemplateParameterInsightsParams) ([]database.GetTemplateParameterInsightsRow, error) {

coderd/database/dbfake/dbfake.go

+82-81
Original file line numberDiff line numberDiff line change
@@ -2340,7 +2340,76 @@ func (q *FakeQuerier) GetTemplateDAUs(_ context.Context, arg database.GetTemplat
23402340
return rs, nil
23412341
}
23422342

2343-
func (q *FakeQuerier) GetTemplateDailyInsights(ctx context.Context, arg database.GetTemplateDailyInsightsParams) ([]database.GetTemplateDailyInsightsRow, error) {
2343+
func (q *FakeQuerier) GetTemplateInsights(_ context.Context, arg database.GetTemplateInsightsParams) (database.GetTemplateInsightsRow, error) {
2344+
err := validateDatabaseType(arg)
2345+
if err != nil {
2346+
return database.GetTemplateInsightsRow{}, err
2347+
}
2348+
2349+
templateIDSet := make(map[uuid.UUID]struct{})
2350+
appUsageIntervalsByUser := make(map[uuid.UUID]map[time.Time]*database.GetTemplateInsightsRow)
2351+
for _, s := range q.workspaceAgentStats {
2352+
if s.CreatedAt.Before(arg.StartTime) || s.CreatedAt.Equal(arg.EndTime) || s.CreatedAt.After(arg.EndTime) {
2353+
continue
2354+
}
2355+
if len(arg.TemplateIDs) > 0 && !slices.Contains(arg.TemplateIDs, s.TemplateID) {
2356+
continue
2357+
}
2358+
if s.ConnectionCount == 0 {
2359+
continue
2360+
}
2361+
2362+
templateIDSet[s.TemplateID] = struct{}{}
2363+
if appUsageIntervalsByUser[s.UserID] == nil {
2364+
appUsageIntervalsByUser[s.UserID] = make(map[time.Time]*database.GetTemplateInsightsRow)
2365+
}
2366+
t := s.CreatedAt.Truncate(time.Minute)
2367+
if _, ok := appUsageIntervalsByUser[s.UserID][t]; !ok {
2368+
appUsageIntervalsByUser[s.UserID][t] = &database.GetTemplateInsightsRow{}
2369+
}
2370+
2371+
if s.SessionCountJetBrains > 0 {
2372+
appUsageIntervalsByUser[s.UserID][t].UsageJetbrainsSeconds = 60
2373+
}
2374+
if s.SessionCountVSCode > 0 {
2375+
appUsageIntervalsByUser[s.UserID][t].UsageVscodeSeconds = 60
2376+
}
2377+
if s.SessionCountReconnectingPTY > 0 {
2378+
appUsageIntervalsByUser[s.UserID][t].UsageReconnectingPtySeconds = 60
2379+
}
2380+
if s.SessionCountSSH > 0 {
2381+
appUsageIntervalsByUser[s.UserID][t].UsageSshSeconds = 60
2382+
}
2383+
}
2384+
2385+
templateIDs := make([]uuid.UUID, 0, len(templateIDSet))
2386+
for templateID := range templateIDSet {
2387+
templateIDs = append(templateIDs, templateID)
2388+
}
2389+
slices.SortFunc(templateIDs, func(a, b uuid.UUID) int {
2390+
return slice.Ascending(a.String(), b.String())
2391+
})
2392+
activeUserIDs := make([]uuid.UUID, 0, len(appUsageIntervalsByUser))
2393+
for userID := range appUsageIntervalsByUser {
2394+
activeUserIDs = append(activeUserIDs, userID)
2395+
}
2396+
2397+
result := database.GetTemplateInsightsRow{
2398+
TemplateIDs: templateIDs,
2399+
ActiveUserIDs: activeUserIDs,
2400+
}
2401+
for _, intervals := range appUsageIntervalsByUser {
2402+
for _, interval := range intervals {
2403+
result.UsageJetbrainsSeconds += interval.UsageJetbrainsSeconds
2404+
result.UsageVscodeSeconds += interval.UsageVscodeSeconds
2405+
result.UsageReconnectingPtySeconds += interval.UsageReconnectingPtySeconds
2406+
result.UsageSshSeconds += interval.UsageSshSeconds
2407+
}
2408+
}
2409+
return result, nil
2410+
}
2411+
2412+
func (q *FakeQuerier) GetTemplateInsightsByInterval(ctx context.Context, arg database.GetTemplateInsightsByIntervalParams) ([]database.GetTemplateInsightsByIntervalRow, error) {
23442413
err := validateDatabaseType(arg)
23452414
if err != nil {
23462415
return nil, err
@@ -2349,17 +2418,18 @@ func (q *FakeQuerier) GetTemplateDailyInsights(ctx context.Context, arg database
23492418
q.mutex.RLock()
23502419
defer q.mutex.RUnlock()
23512420

2352-
type dailyStat struct {
2421+
type statByInterval struct {
23532422
startTime, endTime time.Time
23542423
userSet map[uuid.UUID]struct{}
23552424
templateIDSet map[uuid.UUID]struct{}
23562425
}
2357-
dailyStats := []dailyStat{{arg.StartTime, arg.StartTime.AddDate(0, 0, 1), make(map[uuid.UUID]struct{}), make(map[uuid.UUID]struct{})}}
2358-
for dailyStats[len(dailyStats)-1].endTime.Before(arg.EndTime) {
2359-
dailyStats = append(dailyStats, dailyStat{dailyStats[len(dailyStats)-1].endTime, dailyStats[len(dailyStats)-1].endTime.AddDate(0, 0, 1), make(map[uuid.UUID]struct{}), make(map[uuid.UUID]struct{})})
2426+
2427+
statsByInterval := []statByInterval{{arg.StartTime, arg.StartTime.AddDate(0, 0, int(arg.IntervalDays)), make(map[uuid.UUID]struct{}), make(map[uuid.UUID]struct{})}}
2428+
for statsByInterval[len(statsByInterval)-1].endTime.Before(arg.EndTime) {
2429+
statsByInterval = append(statsByInterval, statByInterval{statsByInterval[len(statsByInterval)-1].endTime, statsByInterval[len(statsByInterval)-1].endTime.AddDate(0, 0, int(arg.IntervalDays)), make(map[uuid.UUID]struct{}), make(map[uuid.UUID]struct{})})
23602430
}
2361-
if dailyStats[len(dailyStats)-1].endTime.After(arg.EndTime) {
2362-
dailyStats[len(dailyStats)-1].endTime = arg.EndTime
2431+
if statsByInterval[len(statsByInterval)-1].endTime.After(arg.EndTime) {
2432+
statsByInterval[len(statsByInterval)-1].endTime = arg.EndTime
23632433
}
23642434

23652435
for _, s := range q.workspaceAgentStats {
@@ -2373,7 +2443,7 @@ func (q *FakeQuerier) GetTemplateDailyInsights(ctx context.Context, arg database
23732443
continue
23742444
}
23752445

2376-
for _, ds := range dailyStats {
2446+
for _, ds := range statsByInterval {
23772447
if s.CreatedAt.Before(ds.startTime) || s.CreatedAt.Equal(ds.endTime) || s.CreatedAt.After(ds.endTime) {
23782448
continue
23792449
}
@@ -2392,7 +2462,7 @@ func (q *FakeQuerier) GetTemplateDailyInsights(ctx context.Context, arg database
23922462
continue
23932463
}
23942464

2395-
for _, ds := range dailyStats {
2465+
for _, ds := range statsByInterval {
23962466
// (was.session_started_at >= ts.from_ AND was.session_started_at < ts.to_)
23972467
// OR (was.session_ended_at > ts.from_ AND was.session_ended_at < ts.to_)
23982468
// OR (was.session_started_at < ts.from_ AND was.session_ended_at >= ts.to_)
@@ -2407,16 +2477,16 @@ func (q *FakeQuerier) GetTemplateDailyInsights(ctx context.Context, arg database
24072477
}
24082478
}
24092479

2410-
var result []database.GetTemplateDailyInsightsRow
2411-
for _, ds := range dailyStats {
2480+
var result []database.GetTemplateInsightsByIntervalRow
2481+
for _, ds := range statsByInterval {
24122482
templateIDs := make([]uuid.UUID, 0, len(ds.templateIDSet))
24132483
for templateID := range ds.templateIDSet {
24142484
templateIDs = append(templateIDs, templateID)
24152485
}
24162486
slices.SortFunc(templateIDs, func(a, b uuid.UUID) int {
24172487
return slice.Ascending(a.String(), b.String())
24182488
})
2419-
result = append(result, database.GetTemplateDailyInsightsRow{
2489+
result = append(result, database.GetTemplateInsightsByIntervalRow{
24202490
StartTime: ds.startTime,
24212491
EndTime: ds.endTime,
24222492
TemplateIDs: templateIDs,
@@ -2426,75 +2496,6 @@ func (q *FakeQuerier) GetTemplateDailyInsights(ctx context.Context, arg database
24262496
return result, nil
24272497
}
24282498

2429-
func (q *FakeQuerier) GetTemplateInsights(_ context.Context, arg database.GetTemplateInsightsParams) (database.GetTemplateInsightsRow, error) {
2430-
err := validateDatabaseType(arg)
2431-
if err != nil {
2432-
return database.GetTemplateInsightsRow{}, err
2433-
}
2434-
2435-
templateIDSet := make(map[uuid.UUID]struct{})
2436-
appUsageIntervalsByUser := make(map[uuid.UUID]map[time.Time]*database.GetTemplateInsightsRow)
2437-
for _, s := range q.workspaceAgentStats {
2438-
if s.CreatedAt.Before(arg.StartTime) || s.CreatedAt.Equal(arg.EndTime) || s.CreatedAt.After(arg.EndTime) {
2439-
continue
2440-
}
2441-
if len(arg.TemplateIDs) > 0 && !slices.Contains(arg.TemplateIDs, s.TemplateID) {
2442-
continue
2443-
}
2444-
if s.ConnectionCount == 0 {
2445-
continue
2446-
}
2447-
2448-
templateIDSet[s.TemplateID] = struct{}{}
2449-
if appUsageIntervalsByUser[s.UserID] == nil {
2450-
appUsageIntervalsByUser[s.UserID] = make(map[time.Time]*database.GetTemplateInsightsRow)
2451-
}
2452-
t := s.CreatedAt.Truncate(time.Minute)
2453-
if _, ok := appUsageIntervalsByUser[s.UserID][t]; !ok {
2454-
appUsageIntervalsByUser[s.UserID][t] = &database.GetTemplateInsightsRow{}
2455-
}
2456-
2457-
if s.SessionCountJetBrains > 0 {
2458-
appUsageIntervalsByUser[s.UserID][t].UsageJetbrainsSeconds = 60
2459-
}
2460-
if s.SessionCountVSCode > 0 {
2461-
appUsageIntervalsByUser[s.UserID][t].UsageVscodeSeconds = 60
2462-
}
2463-
if s.SessionCountReconnectingPTY > 0 {
2464-
appUsageIntervalsByUser[s.UserID][t].UsageReconnectingPtySeconds = 60
2465-
}
2466-
if s.SessionCountSSH > 0 {
2467-
appUsageIntervalsByUser[s.UserID][t].UsageSshSeconds = 60
2468-
}
2469-
}
2470-
2471-
templateIDs := make([]uuid.UUID, 0, len(templateIDSet))
2472-
for templateID := range templateIDSet {
2473-
templateIDs = append(templateIDs, templateID)
2474-
}
2475-
slices.SortFunc(templateIDs, func(a, b uuid.UUID) int {
2476-
return slice.Ascending(a.String(), b.String())
2477-
})
2478-
activeUserIDs := make([]uuid.UUID, 0, len(appUsageIntervalsByUser))
2479-
for userID := range appUsageIntervalsByUser {
2480-
activeUserIDs = append(activeUserIDs, userID)
2481-
}
2482-
2483-
result := database.GetTemplateInsightsRow{
2484-
TemplateIDs: templateIDs,
2485-
ActiveUserIDs: activeUserIDs,
2486-
}
2487-
for _, intervals := range appUsageIntervalsByUser {
2488-
for _, interval := range intervals {
2489-
result.UsageJetbrainsSeconds += interval.UsageJetbrainsSeconds
2490-
result.UsageVscodeSeconds += interval.UsageVscodeSeconds
2491-
result.UsageReconnectingPtySeconds += interval.UsageReconnectingPtySeconds
2492-
result.UsageSshSeconds += interval.UsageSshSeconds
2493-
}
2494-
}
2495-
return result, nil
2496-
}
2497-
24982499
func (q *FakeQuerier) GetTemplateParameterInsights(ctx context.Context, arg database.GetTemplateParameterInsightsParams) ([]database.GetTemplateParameterInsightsRow, error) {
24992500
err := validateDatabaseType(arg)
25002501
if err != nil {

coderd/database/dbmetrics/dbmetrics.go

+6-6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbmock/dbmock.go

+15-15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/querier.go

+5-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)