From 94f6e59afc810051d75d356a22d56455de769694 Mon Sep 17 00:00:00 2001 From: s-hamdananwar Date: Fri, 16 Jan 2026 14:53:27 -0500 Subject: [PATCH] feat: add participant attributes for agent load test --- README.md | 1 + cmd/lk/perf.go | 40 +++++++++++++++++++++++++++++++ pkg/loadtester/agentloadtest.go | 1 + pkg/loadtester/agentloadtester.go | 1 + 4 files changed, 43 insertions(+) diff --git a/README.md b/README.md index e5a77941..e85dce59 100644 --- a/README.md +++ b/README.md @@ -425,6 +425,7 @@ lk perf agent-load-test \ --agent-name test-agent \ --echo-speech-delay 10s \ --duration 5m + --attribute key1=value1 ``` The above simulates 5 concurrent rooms, where each room has: diff --git a/cmd/lk/perf.go b/cmd/lk/perf.go index 35828f28..04ed02fd 100644 --- a/cmd/lk/perf.go +++ b/cmd/lk/perf.go @@ -2,7 +2,10 @@ package main import ( "context" + "encoding/json" "log" + "maps" + "os" "time" "github.com/go-logr/logr" @@ -107,6 +110,15 @@ var ( Usage: "`TIME` duration to run, 1m, 1h (by default will run until canceled)", Value: 0, }, + &cli.StringSliceFlag{ + Name: "attribute", + Usage: "set attributes in key=value format, can be used multiple times", + }, + &cli.StringFlag{ + Name: "attribute-file", + Usage: "read attributes from a `JSON` file", + TakesFile: true, + }, }, }, }, @@ -236,6 +248,33 @@ func agentLoadTest(ctx context.Context, cmd *cli.Command) error { } _ = raiseULimit() + participantAttributes, err := parseKeyValuePairs(cmd, "attribute") + if err != nil { + log.Printf("failed to parse participant attributes: %v", err) + return err + } + + // Read attributes from JSON file if specified + if attrFile := cmd.String("attribute-file"); attrFile != "" { + fileData, err := os.ReadFile(attrFile) + if err != nil { + log.Printf("failed to read attribute file: %v", err) + return err + } + + var fileAttrs map[string]string + if err := json.Unmarshal(fileData, &fileAttrs); err != nil { + log.Printf("failed to parse attribute file as JSON: %v", err) + return err + } + + // Add attributes from file to the existing ones + if participantAttributes == nil { + participantAttributes = make(map[string]string) + } + maps.Copy(participantAttributes, fileAttrs) + } + params := loadtester.AgentLoadTestParams{ URL: pc.URL, APIKey: pc.APIKey, @@ -244,6 +283,7 @@ func agentLoadTest(ctx context.Context, cmd *cli.Command) error { AgentName: cmd.String("agent-name"), EchoSpeechDelay: cmd.Duration("echo-speech-delay"), Duration: cmd.Duration("duration"), + ParticipantAttributes: participantAttributes, } test := loadtester.NewAgentLoadTest(params) diff --git a/pkg/loadtester/agentloadtest.go b/pkg/loadtester/agentloadtest.go index 5e40c63f..3c077a21 100644 --- a/pkg/loadtester/agentloadtest.go +++ b/pkg/loadtester/agentloadtest.go @@ -28,6 +28,7 @@ type AgentLoadTestParams struct { URL string APIKey string APISecret string + ParticipantAttributes map[string]string } type AgentLoadTest struct { diff --git a/pkg/loadtester/agentloadtester.go b/pkg/loadtester/agentloadtester.go index 78e87008..43d8e950 100644 --- a/pkg/loadtester/agentloadtester.go +++ b/pkg/loadtester/agentloadtester.go @@ -176,6 +176,7 @@ func (r *LoadTestRoom) start(roomName string) error { APISecret: r.params.APISecret, RoomName: roomName, ParticipantIdentity: identity, + ParticipantAttributes: r.params.ParticipantAttributes, }) if err == nil { break