Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitcacebb9

Browse files
committed
fix query joins, add basic test for app usage
1 parent98a835c commitcacebb9

File tree

3 files changed

+132
-22
lines changed

3 files changed

+132
-22
lines changed

‎coderd/database/queries.sql.go

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/queries/insights.sql

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ WITH ts AS (
9999
(wa.slugIS NOT NULL)::booleanAS is_app
100100
FROM ts
101101
JOIN workspace_app_stats wasON (
102-
(was.session_started_atBETWEENts.from_ANDts.to_)
103-
OR (was.session_ended_atBETWEENts.from_ANDts.to_)
104-
OR (was.session_started_at<ts.from_ANDwas.session_ended_at>ts.to_)
102+
(was.session_started_at>=ts.from_ANDwas.session_started_at<ts.to_)
103+
OR (was.session_ended_at>ts.from_ANDwas.session_ended_at<ts.to_)
104+
OR (was.session_started_at<ts.from_ANDwas.session_ended_at>=ts.to_)
105105
)
106106
JOIN workspaces wON (
107107
w.id=was.workspace_id
@@ -116,9 +116,9 @@ WITH ts AS (
116116
WHERE
117117
-- We already handle timeframe in the join, but we use an additional
118118
-- check against a static timeframe to help speed up the query.
119-
(was.session_started_atBETWEEN @start_timeAND @end_time)
120-
OR (was.session_ended_atBETWEEN @start_timeAND @end_time)
121-
OR (was.session_started_at< @start_timeANDwas.session_ended_at> @end_time)
119+
(was.session_started_at>= @start_timeANDwas.session_started_at< @end_time)
120+
OR (was.session_ended_at> @start_timeANDwas.session_ended_at< @end_time)
121+
OR (was.session_started_at< @start_timeANDwas.session_ended_at>= @end_time)
122122
GROUP BYts.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
123123
)
124124

@@ -180,9 +180,9 @@ WITH ts AS (
180180
was.user_id
181181
FROM ts
182182
JOIN workspace_app_stats wasON (
183-
(was.session_started_atBETWEENts.from_ANDts.to_)
184-
OR (was.session_ended_atBETWEENts.from_ANDts.to_)
185-
OR (was.session_started_at<ts.from_ANDwas.session_ended_at>ts.to_)
183+
(was.session_started_at>=ts.from_ANDwas.session_started_at<ts.to_)
184+
OR (was.session_ended_at>ts.from_ANDwas.session_ended_at<ts.to_)
185+
OR (was.session_started_at<ts.from_ANDwas.session_ended_at>=ts.to_)
186186
)
187187
JOIN workspaces wON (
188188
w.id=was.workspace_id

‎coderd/insights_test.go

Lines changed: 114 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ import (
1717
"cdr.dev/slog/sloggers/slogtest"
1818
"github.com/coder/coder/agent"
1919
"github.com/coder/coder/coderd/coderdtest"
20+
"github.com/coder/coder/coderd/database/dbauthz"
2021
"github.com/coder/coder/coderd/rbac"
22+
"github.com/coder/coder/coderd/workspaceapps"
2123
"github.com/coder/coder/codersdk"
2224
"github.com/coder/coder/codersdk/agentsdk"
2325
"github.com/coder/coder/provisioner/echo"
@@ -257,14 +259,19 @@ func TestTemplateInsights(t *testing.T) {
257259
thirdParameterOptionValue2="bbb"
258260
thirdParameterOptionName3="This is CCC"
259261
thirdParameterOptionValue3="ccc"
262+
263+
testAppSlug="test-app"
264+
testAppName="Test App"
265+
testAppIcon="/icon.png"
266+
testAppURL="http://127.1.0.1:65536"// Not used.
260267
)
261268

262269
logger:=slogtest.Make(t,nil).Leveled(slog.LevelDebug)
263270
opts:=&coderdtest.Options{
264271
IncludeProvisionerDaemon:true,
265272
AgentStatsRefreshInterval:time.Millisecond*100,
266273
}
267-
client:=coderdtest.New(t,opts)
274+
client,_,coderdAPI:=coderdtest.NewWithAPI(t,opts)
268275

269276
user:=coderdtest.CreateFirstUser(t,client)
270277
authToken:=uuid.NewString()
@@ -287,7 +294,32 @@ func TestTemplateInsights(t *testing.T) {
287294
},
288295
},
289296
},
290-
ProvisionApply:echo.ProvisionApplyWithAgent(authToken),
297+
ProvisionApply: []*proto.Provision_Response{{
298+
Type:&proto.Provision_Response_Complete{
299+
Complete:&proto.Provision_Complete{
300+
Resources: []*proto.Resource{{
301+
Name:"example",
302+
Type:"aws_instance",
303+
Agents: []*proto.Agent{{
304+
Id:uuid.NewString(),
305+
Name:"dev",
306+
Auth:&proto.Agent_Token{
307+
Token:authToken,
308+
},
309+
Apps: []*proto.App{
310+
{
311+
Slug:testAppSlug,
312+
DisplayName:testAppName,
313+
Icon:testAppIcon,
314+
SharingLevel:proto.AppSharingLevel_OWNER,
315+
Url:testAppURL,
316+
},
317+
},
318+
}},
319+
}},
320+
},
321+
},
322+
}},
291323
})
292324
template:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID)
293325
require.Empty(t,template.BuildTimeStats[codersdk.WorkspaceTransitionStart])
@@ -320,10 +352,70 @@ func TestTemplateInsights(t *testing.T) {
320352
// the day changes so that we get the relevant stats faster.
321353
y,m,d:=time.Now().UTC().Date()
322354
today:=time.Date(y,m,d,0,0,0,0,time.UTC)
355+
requestStartTime:=today
356+
requestEndTime:=time.Now().UTC().Truncate(time.Hour).Add(time.Hour)
323357

324358
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
325359
defercancel()
326360

361+
// TODO(mafredri): We should prefer to set up an app and generate
362+
// data by accessing it.
363+
// Insert entries within and outside timeframe.
364+
reporter:=workspaceapps.NewStatsDBReporter(coderdAPI.Database,workspaceapps.DefaultStatsDBReporterBatchSize)
365+
err:=reporter.Report(dbauthz.AsSystemRestricted(ctx), []workspaceapps.StatsReport{
366+
{
367+
UserID:user.UserID,
368+
WorkspaceID:workspace.ID,
369+
AgentID:resources[0].Agents[0].ID,
370+
AccessMethod:workspaceapps.AccessMethodPath,
371+
SlugOrPort:testAppSlug,
372+
SessionID:uuid.New(),
373+
// Outside report range.
374+
SessionStartedAt:requestStartTime.Add(-1*time.Minute),
375+
SessionEndedAt:requestStartTime,
376+
Requests:1,
377+
},
378+
{
379+
UserID:user.UserID,
380+
WorkspaceID:workspace.ID,
381+
AgentID:resources[0].Agents[0].ID,
382+
AccessMethod:workspaceapps.AccessMethodPath,
383+
SlugOrPort:testAppSlug,
384+
SessionID:uuid.New(),
385+
// One minute of usage (rounded up to 5 due to query intervals).
386+
// TODO(mafredri): We'll fix this in a future refactor so that it's
387+
// 1 minute increments instead of 5.
388+
SessionStartedAt:requestStartTime,
389+
SessionEndedAt:requestStartTime.Add(1*time.Minute),
390+
Requests:1,
391+
},
392+
{
393+
UserID:user.UserID,
394+
WorkspaceID:workspace.ID,
395+
AgentID:resources[0].Agents[0].ID,
396+
AccessMethod:workspaceapps.AccessMethodPath,
397+
SlugOrPort:testAppSlug,
398+
SessionID:uuid.New(),
399+
// Five additional minutes of usage.
400+
SessionStartedAt:requestStartTime.Add(10*time.Minute),
401+
SessionEndedAt:requestStartTime.Add(15*time.Minute),
402+
Requests:1,
403+
},
404+
{
405+
UserID:user.UserID,
406+
WorkspaceID:workspace.ID,
407+
AgentID:resources[0].Agents[0].ID,
408+
AccessMethod:workspaceapps.AccessMethodPath,
409+
SlugOrPort:testAppSlug,
410+
SessionID:uuid.New(),
411+
// Outside report range.
412+
SessionStartedAt:requestEndTime,
413+
SessionEndedAt:requestEndTime.Add(1*time.Minute),
414+
Requests:1,
415+
},
416+
})
417+
require.NoError(t,err,"want no error inserting stats")
418+
327419
// Connect to the agent to generate usage/latency stats.
328420
conn,err:=client.DialWorkspaceAgent(ctx,resources[0].Agents[0].ID,&codersdk.DialWorkspaceAgentOptions{
329421
Logger:logger.Named("client"),
@@ -362,8 +454,8 @@ func TestTemplateInsights(t *testing.T) {
362454
waitForAppSeconds:=func(slugstring)func()bool {
363455
returnfunc()bool {
364456
req= codersdk.TemplateInsightsRequest{
365-
StartTime:today,
366-
EndTime:time.Now().UTC().Truncate(time.Hour).Add(time.Hour),
457+
StartTime:requestStartTime,
458+
EndTime:requestEndTime,
367459
Interval:codersdk.InsightsReportIntervalDay,
368460
}
369461
resp,err=client.TemplateInsights(ctx,req)
@@ -390,13 +482,31 @@ func TestTemplateInsights(t *testing.T) {
390482
assert.WithinDuration(t,req.StartTime,resp.Report.StartTime,0)
391483
assert.WithinDuration(t,req.EndTime,resp.Report.EndTime,0)
392484
assert.Equal(t,resp.Report.ActiveUsers,int64(1),"want one active user")
485+
vargotApps []codersdk.TemplateAppUsage
486+
// Check builtin apps usage.
393487
for_,app:=rangeresp.Report.AppsUsage {
488+
ifapp.Type!=codersdk.TemplateAppsTypeBuiltin {
489+
gotApps=append(gotApps,app)
490+
continue
491+
}
394492
ifslices.Contains([]string{"reconnecting-pty","ssh"},app.Slug) {
395493
assert.Equal(t,app.Seconds,int64(300),"want app %q to have 5 minutes of usage",app.Slug)
396494
}else {
397495
assert.Equal(t,app.Seconds,int64(0),"want app %q to have 0 minutes of usage",app.Slug)
398496
}
399497
}
498+
// Check app usage.
499+
assert.Equal(t,gotApps, []codersdk.TemplateAppUsage{
500+
{
501+
TemplateIDs: []uuid.UUID{template.ID},
502+
Type:codersdk.TemplateAppsTypeApp,
503+
Slug:testAppSlug,
504+
DisplayName:testAppName,
505+
Icon:testAppIcon,
506+
Seconds:300+300,// Two times 5 minutes of usage (actually 1 + 5, but see TODO above).
507+
},
508+
},"want app usage to match")
509+
400510
// The full timeframe is <= 24h, so the interval matches exactly.
401511
require.Len(t,resp.IntervalReports,1,"want one interval report")
402512
assert.WithinDuration(t,req.StartTime,resp.IntervalReports[0].StartTime,0)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp