Skip to content

Commit af939d1

Browse files
authored
fix(coderd): optimize template app insights query for speed and decrease intervals (coder#9302)
1 parent 67c8635 commit af939d1

8 files changed

+63
-52
lines changed

coderd/database/dbfake/dbfake.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -2048,8 +2048,8 @@ func (q *FakeQuerier) GetTemplateAppInsights(ctx context.Context, arg database.G
20482048
t = arg.StartTime
20492049
}
20502050
for t.Before(s.SessionEndedAt) && t.Before(arg.EndTime) {
2051-
appUsageIntervalsByUserAgentApp[key][t] = 300 // 5 minutes.
2052-
t = t.Add(5 * time.Minute)
2051+
appUsageIntervalsByUserAgentApp[key][t] = 60 // 1 minute.
2052+
t = t.Add(1 * time.Minute)
20532053
}
20542054
}
20552055

coderd/database/queries.sql.go

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

coderd/database/queries/insights.sql

+18-19
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,10 @@ FROM agent_stats_by_interval_and_user;
6161
-- GetTemplateAppInsights returns the aggregate usage of each app in a given
6262
-- timeframe. The result can be filtered on template_ids, meaning only user data
6363
-- from workspaces based on those templates will be included.
64-
WITH ts AS (
65-
SELECT
66-
d::timestamptz AS from_,
67-
(d::timestamptz + '5 minute'::interval) AS to_,
68-
EXTRACT(epoch FROM '5 minute'::interval) AS seconds
69-
FROM
70-
-- Subtract 1 second from end_time to avoid including the next interval in the results.
71-
generate_series(@start_time::timestamptz, (@end_time::timestamptz) - '1 second'::interval, '5 minute'::interval) d
72-
), app_stats_by_user_and_agent AS (
64+
WITH app_stats_by_user_and_agent AS (
7365
SELECT
74-
ts.from_,
75-
ts.to_,
76-
ts.seconds,
66+
s.start_time,
67+
60 as seconds,
7768
w.template_id,
7869
was.user_id,
7970
was.agent_id,
@@ -82,12 +73,7 @@ WITH ts AS (
8273
wa.display_name,
8374
wa.icon,
8475
(wa.slug IS NOT NULL)::boolean AS is_app
85-
FROM ts
86-
JOIN workspace_app_stats was ON (
87-
(was.session_started_at >= ts.from_ AND was.session_started_at < ts.to_)
88-
OR (was.session_ended_at > ts.from_ AND was.session_ended_at < ts.to_)
89-
OR (was.session_started_at < ts.from_ AND was.session_ended_at >= ts.to_)
90-
)
76+
FROM workspace_app_stats was
9177
JOIN workspaces w ON (
9278
w.id = was.workspace_id
9379
AND CASE WHEN COALESCE(array_length(@template_ids::uuid[], 1), 0) > 0 THEN w.template_id = ANY(@template_ids::uuid[]) ELSE TRUE END
@@ -98,7 +84,20 @@ WITH ts AS (
9884
wa.agent_id = was.agent_id
9985
AND wa.slug = was.slug_or_port
10086
)
101-
GROUP BY ts.from_, ts.to_, ts.seconds, w.template_id, was.user_id, was.agent_id, was.access_method, was.slug_or_port, wa.display_name, wa.icon, wa.slug
87+
-- This table contains both 1 minute entries and >1 minute entries,
88+
-- to calculate this with our uniqueness constraints, we generate series
89+
-- for the longer intervals.
90+
CROSS JOIN LATERAL generate_series(
91+
date_trunc('minute', was.session_started_at),
92+
-- Subtract 1 microsecond to avoid creating an extra series.
93+
date_trunc('minute', was.session_ended_at - '1 microsecond'::interval),
94+
'1 minute'::interval
95+
) s(start_time)
96+
WHERE
97+
s.start_time >= @start_time::timestamptz
98+
-- Subtract one minute because the series only contains the start time.
99+
AND s.start_time < (@end_time::timestamptz) - '1 minute'::interval
100+
GROUP BY s.start_time, w.template_id, was.user_id, was.agent_id, was.access_method, was.slug_or_port, wa.display_name, wa.icon, wa.slug
102101
)
103102

104103
SELECT

coderd/insights_test.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,19 @@ func TestTemplateInsights_Golden(t *testing.T) {
778778
endedAt: frozenWeekAgo.Add(time.Hour),
779779
requests: 1,
780780
},
781-
{ // used an app on the last day, counts as active user, 12m -> 15m rounded.
781+
{ // 30s of app usage -> 1m rounded.
782+
app: users[0].workspaces[0].apps[0],
783+
startedAt: frozenWeekAgo.Add(2*time.Hour + 10*time.Second),
784+
endedAt: frozenWeekAgo.Add(2*time.Hour + 40*time.Second),
785+
requests: 1,
786+
},
787+
{ // 1m30s of app usage -> 2m rounded (included in São Paulo).
788+
app: users[0].workspaces[0].apps[0],
789+
startedAt: frozenWeekAgo.Add(3*time.Hour + 30*time.Second),
790+
endedAt: frozenWeekAgo.Add(3*time.Hour + 90*time.Second),
791+
requests: 1,
792+
},
793+
{ // used an app on the last day, counts as active user, 12m.
782794
app: users[0].workspaces[0].apps[2],
783795
startedAt: frozenWeekAgo.AddDate(0, 0, 6),
784796
endedAt: frozenWeekAgo.AddDate(0, 0, 6).Add(12 * time.Minute),

coderd/testdata/insights/multiple_users_and_workspaces_week_all_templates.json.golden

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
"display_name": "app1",
6767
"slug": "app1",
6868
"icon": "/icon1.png",
69-
"seconds": 25200
69+
"seconds": 25380
7070
},
7171
{
7272
"template_ids": [
@@ -76,7 +76,7 @@
7676
"display_name": "app3",
7777
"slug": "app3",
7878
"icon": "/icon2.png",
79-
"seconds": 900
79+
"seconds": 720
8080
},
8181
{
8282
"template_ids": [

coderd/testdata/insights/multiple_users_and_workspaces_week_deployment_wide.json.golden

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
"display_name": "app1",
6767
"slug": "app1",
6868
"icon": "/icon1.png",
69-
"seconds": 25200
69+
"seconds": 25380
7070
},
7171
{
7272
"template_ids": [
@@ -76,7 +76,7 @@
7676
"display_name": "app3",
7777
"slug": "app3",
7878
"icon": "/icon2.png",
79-
"seconds": 900
79+
"seconds": 720
8080
},
8181
{
8282
"template_ids": [

coderd/testdata/insights/multiple_users_and_workspaces_week_first_template.json.golden

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
"display_name": "app1",
5656
"slug": "app1",
5757
"icon": "/icon1.png",
58-
"seconds": 3600
58+
"seconds": 3780
5959
},
6060
{
6161
"template_ids": [
@@ -65,7 +65,7 @@
6565
"display_name": "app3",
6666
"slug": "app3",
6767
"icon": "/icon2.png",
68-
"seconds": 900
68+
"seconds": 720
6969
}
7070
],
7171
"parameters_usage": []

coderd/testdata/insights/multiple_users_and_workspaces_week_other_timezone_(São_Paulo).json.golden

+3-2
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,14 @@
5151
},
5252
{
5353
"template_ids": [
54+
"00000000-0000-0000-0000-000000000001",
5455
"00000000-0000-0000-0000-000000000002"
5556
],
5657
"type": "app",
5758
"display_name": "app1",
5859
"slug": "app1",
5960
"icon": "/icon1.png",
60-
"seconds": 21600
61+
"seconds": 21720
6162
},
6263
{
6364
"template_ids": [
@@ -67,7 +68,7 @@
6768
"display_name": "app3",
6869
"slug": "app3",
6970
"icon": "/icon2.png",
70-
"seconds": 4500
71+
"seconds": 4320
7172
},
7273
{
7374
"template_ids": [

0 commit comments

Comments
 (0)