@@ -3,6 +3,9 @@ package prometheusmetrics_test
3
3
import (
4
4
"context"
5
5
"database/sql"
6
+ "encoding/json"
7
+ "fmt"
8
+ "os"
6
9
"sync/atomic"
7
10
"testing"
8
11
"time"
@@ -357,24 +360,15 @@ func TestAgents(t *testing.T) {
357
360
func TestAgentStats (t * testing.T ) {
358
361
t .Parallel ()
359
362
360
- // Build a sample workspace with test agent and fake agent client
363
+ // Build sample workspaces with test agents and fake agent client
361
364
client , _ , api := coderdtest .NewWithAPI (t , & coderdtest.Options {IncludeProvisionerDaemon : true })
362
365
db := api .Database
363
366
364
367
user := coderdtest .CreateFirstUser (t , client )
365
- authToken := uuid .NewString ()
366
- version := coderdtest .CreateTemplateVersion (t , client , user .OrganizationID , & echo.Responses {
367
- Parse : echo .ParseComplete ,
368
- ProvisionPlan : echo .ProvisionComplete ,
369
- ProvisionApply : echo .ProvisionApplyWithAgent (authToken ),
370
- })
371
- template := coderdtest .CreateTemplate (t , client , user .OrganizationID , version .ID )
372
- coderdtest .AwaitTemplateVersionJob (t , client , version .ID )
373
- workspace := coderdtest .CreateWorkspace (t , client , user .OrganizationID , template .ID )
374
- coderdtest .AwaitWorkspaceBuildJob (t , client , workspace .LatestBuild .ID )
375
368
376
- agentClient := agentsdk .New (client .URL )
377
- agentClient .SetSessionToken (authToken )
369
+ agent1 , _ := prepareWorkspaceAndAgent (t , client , user , 1 )
370
+ agent2 , _ := prepareWorkspaceAndAgent (t , client , user , 2 )
371
+ agent3 , _ := prepareWorkspaceAndAgent (t , client , user , 3 )
378
372
379
373
registry := prometheus .NewRegistry ()
380
374
@@ -384,24 +378,45 @@ func TestAgentStats(t *testing.T) {
384
378
t .Cleanup (cancel )
385
379
386
380
// when
387
- _ , err = agentClient .PostStats (context .Background (), & agentsdk.Stats {
388
- ConnectionsByProto : map [string ]int64 {"TCP" : 1 },
389
- ConnectionCount : 2 ,
390
- RxPackets : 3 ,
391
- RxBytes : 4 ,
392
- TxPackets : 5 ,
393
- TxBytes : 6 ,
394
- SessionCountVSCode : 7 ,
395
- SessionCountJetBrains : 8 ,
396
- SessionCountReconnectingPTY : 9 ,
397
- SessionCountSSH : 10 ,
398
- ConnectionMedianLatencyMS : 10000 ,
399
- })
381
+ var i int64
382
+ for i = 0 ; i < 3 ; i ++ {
383
+ _ , err = agent1 .PostStats (context .Background (), & agentsdk.Stats {
384
+ TxBytes : 1 + i , RxBytes : 2 + i ,
385
+ SessionCountVSCode : 3 + i , SessionCountJetBrains : 4 + i , SessionCountReconnectingPTY : 5 + i , SessionCountSSH : 6 + i ,
386
+ ConnectionCount : 7 + i , ConnectionMedianLatencyMS : 8000 ,
387
+ ConnectionsByProto : map [string ]int64 {"TCP" : 1 },
388
+ })
389
+ require .NoError (t , err )
390
+
391
+ _ , err = agent2 .PostStats (context .Background (), & agentsdk.Stats {
392
+ TxBytes : 2 + i , RxBytes : 4 + i ,
393
+ SessionCountVSCode : 6 + i , SessionCountJetBrains : 8 + i , SessionCountReconnectingPTY : 10 + i , SessionCountSSH : 12 + i ,
394
+ ConnectionCount : 8 + i , ConnectionMedianLatencyMS : 10000 ,
395
+ ConnectionsByProto : map [string ]int64 {"TCP" : 1 },
396
+ })
397
+ require .NoError (t , err )
398
+
399
+ _ , err = agent3 .PostStats (context .Background (), & agentsdk.Stats {
400
+ TxBytes : 3 + i , RxBytes : 6 + i ,
401
+ SessionCountVSCode : 12 + i , SessionCountJetBrains : 14 + i , SessionCountReconnectingPTY : 16 + i , SessionCountSSH : 18 + i ,
402
+ ConnectionCount : 9 + i , ConnectionMedianLatencyMS : 12000 ,
403
+ ConnectionsByProto : map [string ]int64 {"TCP" : 1 },
404
+ })
405
+ require .NoError (t , err )
406
+ }
400
407
401
408
// then
409
+ goldenFile , err := os .ReadFile ("testdata/agent-stats.json" )
402
410
require .NoError (t , err )
411
+ areMetricsValid := func (collected map [string ]int ) bool {
412
+ out , err := json .MarshalIndent (collected , " " , " " )
413
+ require .NoError (t , err )
414
+ os .WriteFile ("testdata/agent-stats.json" , out , 0644 )
415
+ return string (goldenFile ) == string (out )
416
+ }
403
417
404
- collectedMetrics := map [string ]struct {}{}
418
+ collected := map [string ]int {}
419
+ var executionSeconds bool
405
420
require .Eventually (t , func () bool {
406
421
metrics , err := registry .Gather ()
407
422
assert .NoError (t , err )
@@ -413,7 +428,7 @@ func TestAgentStats(t *testing.T) {
413
428
for _ , metric := range metrics {
414
429
switch metric .GetName () {
415
430
case "coderd_prometheusmetrics_agentstats_execution_seconds" :
416
- collectedMetrics [ metric . GetName ()] = struct {}{}
431
+ executionSeconds = true
417
432
case "coderd_agentstats_connection_count" ,
418
433
"coderd_agentstats_connection_median_latency_seconds" ,
419
434
"coderd_agentstats_rx_bytes" ,
@@ -422,16 +437,35 @@ func TestAgentStats(t *testing.T) {
422
437
"coderd_agentstats_session_count_reconnecting_pty" ,
423
438
"coderd_agentstats_session_count_ssh" ,
424
439
"coderd_agentstats_session_count_vscode" :
425
- collectedMetrics [metric .GetName ()] = struct {}{}
426
- assert .Equal (t , "example" , metric .Metric [0 ].Label [0 ].GetValue ()) // Agent name
427
- assert .Equal (t , "testuser" , metric .Metric [0 ].Label [1 ].GetValue ()) // Username
428
- assert .Equal (t , workspace .Name , metric .Metric [0 ].Label [2 ].GetValue ()) // Workspace name
429
- assert .NotZero (t , int (metric .Metric [0 ].Gauge .GetValue ()), metric .GetName ()) // Metric value
440
+ for _ , m := range metric .Metric {
441
+ // username:workspace:agent:metric = value
442
+ collected [m .Label [1 ].GetValue ()+ ":" + m .Label [2 ].GetValue ()+ ":" + m .Label [0 ].GetValue ()+ ":" + metric .GetName ()] = int (m .Gauge .GetValue ())
443
+ }
430
444
default :
431
445
require .FailNowf (t , "unexpected metric collected" , "metric: %s" , metric .GetName ())
432
446
}
433
447
}
448
+ return executionSeconds && areMetricsValid (collected )
449
+ }, testutil .WaitLong , testutil .IntervalMedium )
450
+ }
451
+
452
+ func prepareWorkspaceAndAgent (t * testing.T , client * codersdk.Client , user codersdk.CreateFirstUserResponse , workspaceNum int ) (* agentsdk.Client , codersdk.Workspace ) {
453
+ authToken := uuid .NewString ()
454
+
455
+ version := coderdtest .CreateTemplateVersion (t , client , user .OrganizationID , & echo.Responses {
456
+ Parse : echo .ParseComplete ,
457
+ ProvisionPlan : echo .ProvisionComplete ,
458
+ ProvisionApply : echo .ProvisionApplyWithAgent (authToken ),
459
+ })
460
+ template := coderdtest .CreateTemplate (t , client , user .OrganizationID , version .ID )
461
+ coderdtest .AwaitTemplateVersionJob (t , client , version .ID )
462
+ workspace := coderdtest .CreateWorkspace (t , client , user .OrganizationID , template .ID , func (cwr * codersdk.CreateWorkspaceRequest ) {
463
+ cwr .Name = fmt .Sprintf ("workspace-%d" , workspaceNum )
464
+ })
465
+ coderdtest .AwaitWorkspaceBuildJob (t , client , workspace .LatestBuild .ID )
466
+
467
+ agentClient := agentsdk .New (client .URL )
468
+ agentClient .SetSessionToken (authToken )
434
469
435
- return len (collectedMetrics ) == 9
436
- }, testutil .WaitShort , testutil .IntervalFast , "collected metrics: %v" , collectedMetrics )
470
+ return agentClient , workspace
437
471
}
0 commit comments