fix(coderd): fix template insight intervals (#8662)

This commit is contained in:
Mathias Fredriksson
2023-07-21 23:51:35 +03:00
committed by GitHub
parent 65583eca47
commit e0c1aacac1
4 changed files with 33 additions and 14 deletions

View File

@ -2326,12 +2326,15 @@ func (q *FakeQuerier) GetUserLatencyInsights(_ context.Context, arg database.Get
if len(arg.TemplateIDs) > 0 && !slices.Contains(arg.TemplateIDs, s.TemplateID) { if len(arg.TemplateIDs) > 0 && !slices.Contains(arg.TemplateIDs, s.TemplateID) {
continue continue
} }
if !arg.StartTime.Equal(s.CreatedAt) && !(s.CreatedAt.After(arg.StartTime) && s.CreatedAt.Before(arg.EndTime)) { if !arg.StartTime.Equal(s.CreatedAt) && (s.CreatedAt.Before(arg.StartTime) || s.CreatedAt.After(arg.EndTime)) {
continue continue
} }
if s.ConnectionCount == 0 { if s.ConnectionCount == 0 {
continue continue
} }
if s.ConnectionMedianLatencyMS <= 0 {
continue
}
latenciesByUserID[s.UserID] = append(latenciesByUserID[s.UserID], s.ConnectionMedianLatencyMS) latenciesByUserID[s.UserID] = append(latenciesByUserID[s.UserID], s.ConnectionMedianLatencyMS)
if seenTemplatesByUserID[s.UserID] == nil { if seenTemplatesByUserID[s.UserID] == nil {

View File

@ -1378,7 +1378,8 @@ func (q *sqlQuerier) UpdateGroupByID(ctx context.Context, arg UpdateGroupByIDPar
const getTemplateDailyInsights = `-- name: GetTemplateDailyInsights :many const getTemplateDailyInsights = `-- name: GetTemplateDailyInsights :many
WITH d AS ( WITH d AS (
-- sqlc workaround, use SELECT generate_series instead of SELECT * FROM generate_series. -- sqlc workaround, use SELECT generate_series instead of SELECT * FROM generate_series.
SELECT generate_series($1::timestamptz, $2::timestamptz, '1 day'::interval) AS d -- Subtract 1 second from end_time to avoid including the next interval in the results.
SELECT generate_series($1::timestamptz, ($2::timestamptz) - '1 second'::interval, '1 day'::interval) AS d
), ts AS ( ), ts AS (
SELECT SELECT
d::timestamptz AS from_, d::timestamptz AS from_,
@ -1398,17 +1399,20 @@ WITH d AS (
) )
GROUP BY ts.from_, ts.to_, was.user_id GROUP BY ts.from_, ts.to_, was.user_id
), template_ids AS ( ), template_ids AS (
SELECT array_agg(DISTINCT template_id) AS ids SELECT
from_,
array_agg(DISTINCT template_id) AS ids
FROM usage_by_day, unnest(template_ids) template_id FROM usage_by_day, unnest(template_ids) template_id
WHERE template_id IS NOT NULL WHERE template_id IS NOT NULL
GROUP BY from_, template_ids
) )
SELECT SELECT
from_ AS start_time, from_ AS start_time,
to_ AS end_time, to_ AS end_time,
COALESCE((SELECT ids FROM template_ids), '{}')::uuid[] AS template_ids, COALESCE((SELECT template_ids.ids FROM template_ids WHERE template_ids.from_ = usage_by_day.from_), '{}')::uuid[] AS template_ids,
COUNT(DISTINCT user_id) AS active_users COUNT(DISTINCT user_id) AS active_users
FROM usage_by_day, unnest(template_ids) as template_id FROM usage_by_day
GROUP BY from_, to_ GROUP BY from_, to_
` `
@ -1459,7 +1463,8 @@ func (q *sqlQuerier) GetTemplateDailyInsights(ctx context.Context, arg GetTempla
const getTemplateInsights = `-- name: GetTemplateInsights :one const getTemplateInsights = `-- name: GetTemplateInsights :one
WITH d AS ( WITH d AS (
SELECT generate_series($1::timestamptz, $2::timestamptz, '5 minute'::interval) AS d -- Subtract 1 second from end_time to avoid including the next interval in the results.
SELECT generate_series($1::timestamptz, ($2::timestamptz) - '1 second'::interval, '5 minute'::interval) AS d
), ts AS ( ), ts AS (
SELECT SELECT
d::timestamptz AS from_, d::timestamptz AS from_,

View File

@ -24,7 +24,8 @@ ORDER BY user_id ASC;
-- GetTemplateInsights has a granularity of 5 minutes where if a session/app was -- GetTemplateInsights has a granularity of 5 minutes where if a session/app was
-- in use, we will add 5 minutes to the total usage for that session (per user). -- in use, we will add 5 minutes to the total usage for that session (per user).
WITH d AS ( WITH d AS (
SELECT generate_series(@start_time::timestamptz, @end_time::timestamptz, '5 minute'::interval) AS d -- Subtract 1 second from end_time to avoid including the next interval in the results.
SELECT generate_series(@start_time::timestamptz, (@end_time::timestamptz) - '1 second'::interval, '5 minute'::interval) AS d
), ts AS ( ), ts AS (
SELECT SELECT
d::timestamptz AS from_, d::timestamptz AS from_,
@ -71,7 +72,8 @@ FROM usage_by_user;
-- interval/template, it will be included in the results with 0 active users. -- interval/template, it will be included in the results with 0 active users.
WITH d AS ( WITH d AS (
-- sqlc workaround, use SELECT generate_series instead of SELECT * FROM generate_series. -- sqlc workaround, use SELECT generate_series instead of SELECT * FROM generate_series.
SELECT generate_series(@start_time::timestamptz, @end_time::timestamptz, '1 day'::interval) AS d -- Subtract 1 second from end_time to avoid including the next interval in the results.
SELECT generate_series(@start_time::timestamptz, (@end_time::timestamptz) - '1 second'::interval, '1 day'::interval) AS d
), ts AS ( ), ts AS (
SELECT SELECT
d::timestamptz AS from_, d::timestamptz AS from_,
@ -91,15 +93,18 @@ WITH d AS (
) )
GROUP BY ts.from_, ts.to_, was.user_id GROUP BY ts.from_, ts.to_, was.user_id
), template_ids AS ( ), template_ids AS (
SELECT array_agg(DISTINCT template_id) AS ids SELECT
from_,
array_agg(DISTINCT template_id) AS ids
FROM usage_by_day, unnest(template_ids) template_id FROM usage_by_day, unnest(template_ids) template_id
WHERE template_id IS NOT NULL WHERE template_id IS NOT NULL
GROUP BY from_, template_ids
) )
SELECT SELECT
from_ AS start_time, from_ AS start_time,
to_ AS end_time, to_ AS end_time,
COALESCE((SELECT ids FROM template_ids), '{}')::uuid[] AS template_ids, COALESCE((SELECT template_ids.ids FROM template_ids WHERE template_ids.from_ = usage_by_day.from_), '{}')::uuid[] AS template_ids,
COUNT(DISTINCT user_id) AS active_users COUNT(DISTINCT user_id) AS active_users
FROM usage_by_day, unnest(template_ids) as template_id FROM usage_by_day
GROUP BY from_, to_; GROUP BY from_, to_;

View File

@ -168,11 +168,17 @@ func TestUserLatencyInsights(t *testing.T) {
defer r.Close() defer r.Close()
defer w.Close() defer w.Close()
sess.Stdin = r sess.Stdin = r
sess.Stdout = io.Discard
err = sess.Start("cat") err = sess.Start("cat")
require.NoError(t, err) require.NoError(t, err)
var userLatencies codersdk.UserLatencyInsightsResponse var userLatencies codersdk.UserLatencyInsightsResponse
require.Eventuallyf(t, func() bool { require.Eventuallyf(t, func() bool {
// Keep connection active.
_, err := w.Write([]byte("hello world\n"))
if !assert.NoError(t, err) {
return false
}
userLatencies, err = client.UserLatencyInsights(ctx, codersdk.UserLatencyInsightsRequest{ userLatencies, err = client.UserLatencyInsights(ctx, codersdk.UserLatencyInsightsRequest{
StartTime: today, StartTime: today,
EndTime: time.Now().UTC().Truncate(time.Hour).Add(time.Hour), // Round up to include the current hour. EndTime: time.Now().UTC().Truncate(time.Hour).Add(time.Hour), // Round up to include the current hour.
@ -182,7 +188,7 @@ func TestUserLatencyInsights(t *testing.T) {
return false return false
} }
return len(userLatencies.Report.Users) > 0 && userLatencies.Report.Users[0].LatencyMS.P50 > 0 return len(userLatencies.Report.Users) > 0 && userLatencies.Report.Users[0].LatencyMS.P50 > 0
}, testutil.WaitShort, testutil.IntervalFast, "user latency is missing") }, testutil.WaitMedium, testutil.IntervalFast, "user latency is missing")
// We got our latency data, close the connection. // We got our latency data, close the connection.
_ = sess.Close() _ = sess.Close()
@ -318,8 +324,8 @@ func TestTemplateInsights(t *testing.T) {
return false return false
} }
} }
require.Eventually(t, waitForAppSeconds("reconnecting-pty"), testutil.WaitShort, testutil.IntervalFast, "reconnecting-pty seconds missing") require.Eventually(t, waitForAppSeconds("reconnecting-pty"), testutil.WaitMedium, testutil.IntervalFast, "reconnecting-pty seconds missing")
require.Eventually(t, waitForAppSeconds("ssh"), testutil.WaitShort, testutil.IntervalFast, "ssh seconds missing") require.Eventually(t, waitForAppSeconds("ssh"), testutil.WaitMedium, testutil.IntervalFast, "ssh seconds missing")
// We got our data, close down sessions and connections. // We got our data, close down sessions and connections.
_ = rpty.Close() _ = rpty.Close()