Skip to content

refactor: define insights interval #9693

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Use IntervalDays
  • Loading branch information
mtojek committed Sep 15, 2023
commit 22a91a451fba64ca48262341cdaa5d37e01ddfcd
6 changes: 4 additions & 2 deletions coderd/database/dbfake/dbfake.go
Original file line number Diff line number Diff line change
Expand Up @@ -2424,9 +2424,11 @@ func (q *FakeQuerier) GetTemplateInsightsByInterval(ctx context.Context, arg dat
templateIDSet map[uuid.UUID]struct{}
}

statsByInterval := []statByInterval{{arg.StartTime, arg.StartTime.Add(time.Duration(arg.Interval)), make(map[uuid.UUID]struct{}), make(map[uuid.UUID]struct{})}}
interval := time.Duration(arg.IntervalDays) * 24 * time.Hour

statsByInterval := []statByInterval{{arg.StartTime, arg.StartTime.Add(interval), make(map[uuid.UUID]struct{}), make(map[uuid.UUID]struct{})}}
Copy link
Member

@mafredri mafredri Sep 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could still use .AddDate, the reason I point it out is caution with DST. E.g. does it behave the same as an interval when crossing the DST boundary?

I think Go assumes this for you, but I think it would be good to confirm 👍🏻

So the question is: Does the clock stay 00:00 when using Add(interval) and DST is part of time range? (A good test would be both 24time.Hour and 168time.Hour.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is more like a Go question, and .Add(duration) doesn't preserve the time change (DST), so good catch! I will switch to .AddDate() to have consistent 00:00 hour windows.

func TestAddDateWithDST(t *testing.T) {
	// Set the time zone to a location that observes DST
	tz, err := time.LoadLocation("America/New_York")
	if err != nil {
		t.Fatal(err)
	}

	// Create a time in the specified time zone
	date := time.Date(2023, time.March, 11, 0, 0, 0, 0, tz)

	// Add a duration of one day to the date
	// newDate := date.Add(48 * time.Hour)
	newDate := date.AddDate(0, 0, 2)

	// Since DST starts on March 12, 2023, in America/New_York, adding one day should account for DST
	// and the resulting date should be 23 hours ahead
	expectedDate := time.Date(2023, time.March, 13, 0, 0, 0, 0, tz)

	// Compare the expected date with the actual result
	if !newDate.Equal(expectedDate) {
		t.Errorf("Expected: %s, Got: %s", expectedDate, newDate)
	}
}

for statsByInterval[len(statsByInterval)-1].endTime.Before(arg.EndTime) {
statsByInterval = append(statsByInterval, statByInterval{statsByInterval[len(statsByInterval)-1].endTime, statsByInterval[len(statsByInterval)-1].endTime.Add(time.Duration(arg.Interval)), make(map[uuid.UUID]struct{}), make(map[uuid.UUID]struct{})})
statsByInterval = append(statsByInterval, statByInterval{statsByInterval[len(statsByInterval)-1].endTime, statsByInterval[len(statsByInterval)-1].endTime.Add(interval), make(map[uuid.UUID]struct{}), make(map[uuid.UUID]struct{})})
}
if statsByInterval[len(statsByInterval)-1].endTime.After(arg.EndTime) {
statsByInterval[len(statsByInterval)-1].endTime = arg.EndTime
Expand Down
16 changes: 8 additions & 8 deletions coderd/database/queries.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions coderd/database/queries/insights.sql
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,13 @@ WITH ts AS (
SELECT
d::timestamptz AS from_,
CASE
WHEN (d::timestamptz + @interval::interval) <= @end_time::timestamptz
THEN (d::timestamptz + @interval::interval)
WHEN (d::timestamptz + (@interval_days::int || ' day')::interval) <= @end_time::timestamptz
THEN (d::timestamptz + (@interval_days::int || ' day')::interval)
ELSE @end_time::timestamptz
END AS to_
FROM
-- Subtract 1 second from end_time to avoid including the next interval in the results.
generate_series(@start_time::timestamptz, (@end_time::timestamptz) - '1 second'::interval, @interval::interval) AS d
generate_series(@start_time::timestamptz, (@end_time::timestamptz) - '1 second'::interval, (@interval_days::int || ' day')::interval) AS d
), unflattened_usage_by_interval AS (
-- We select data from both workspace agent stats and workspace app stats to
-- get a complete picture of usage. This matches how usage is calculated by
Expand Down
8 changes: 4 additions & 4 deletions coderd/insights.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,10 @@ func (api *API) insightsTemplates(rw http.ResponseWriter, r *http.Request) {
var err error
if interval != "" {
dailyUsage, err = api.Database.GetTemplateInsightsByInterval(egCtx, database.GetTemplateInsightsByIntervalParams{
StartTime: startTime,
EndTime: endTime,
TemplateIDs: templateIDs,
Interval: int64(24 * time.Hour),
StartTime: startTime,
EndTime: endTime,
TemplateIDs: templateIDs,
IntervalDays: 1,
})
if err != nil {
return xerrors.Errorf("get template daily insights: %w", err)
Expand Down