Skip to content

Commit 7459c1a

Browse files
revert(load-generator): replace k6 with Locust (#3873)
* revert(load-generator): replace k6 with Locust Reverts #3564. Restores the pre-k6 Locust-based load generator (locustfile.py, requirements, Envoy /loadgen/ route, compose service config) while keeping everything unrelated added since that commit. This reverts commit 18b36c7. Assisted-by: Claude Sonnet 5 * fix(load-generator): address Copilot review findings on Locust revert - otel-collector: restore allowed_headers (content-type, traceparent, baggage) on the OTLP HTTP receiver's CORS config, otherwise the browser's baggage-bearing preflight requests are rejected and frontend-web telemetry disappears. - locustfile.py: register the RoofBinoculars response listener before navigating instead of after, so a fast image response isn't missed. - demo.flagd.json: restore loadGeneratorTraffic and loadGeneratorVUs, which the flagd-ui scheduler tests still assert exist. - services.py: correct the frontend-web exclusion comment; browser traffic is enabled in every scope, it's just low-weighted relative to HTTP traffic, not disabled. - README.md: point to the stable Locust docs instead of the 2.16 archive, since the restored lockfile pins 2.44.4. Assisted-by: Claude Sonnet 5 * Apply suggestion from @julianocosta89 * fix(flagd-ui): exclude non-off-resting flags from generic revert tests loadGeneratorTraffic rests at "on" and loadGeneratorVUs rests at its own default variant, not "off". With the fixed seed used by these tests, the scheduler deterministically picked one of them, so the generic "reverts to off" assertions never passed. Restrict those tests to off-resting flags, matching the pattern already used elsewhere in this file. Assisted-by: Claude Sonnet 5 * fix(load-generator): remove dead k6-era load-generator flags loadGeneratorTraffic and loadGeneratorVUs were introduced by the k6 migration (#3564) and consumed only by its entrypoint.sh wrapper; the restored Locust code never observed them. Remove both flags along with the flagd-ui scheduler test cases and README section that existed only to accommodate their non-off resting state, restoring the pre-k6 flag set. Assisted-by: Claude Sonnet 5 * fix(load-generator): use registered telemetry attributes Replace unregistered span attributes (product.id, quantity, category, item.count, flood.count) with their existing demo.* registry equivalents, adding a new demo.request.flood.count attribute for the one case with no existing match, and declare all of them for service.load_generator per the telemetry-schema conventions. Assisted-by: Claude Sonnet 5 * fix(load-generator): correct changelog and telemetry schema docs - Restore the #3564 changelog bullets under 3.0.0, which was already released with them, and add a new Unreleased entry for this revert instead of rewriting released history. - Fix the service.load_generator attribute group: its brief claimed "baggage attributes" but most of its members are plain span attributes, and it was missing user.id, which locustfile.py also emits as a span attribute. Assisted-by: Claude Sonnet 5 * default flagd.json --------- Co-authored-by: Juliano Costa <julianocosta89@outlook.com> Co-authored-by: Juliano Costa <juliano.costa@datadoghq.com>
1 parent 604c461 commit 7459c1a

24 files changed

Lines changed: 1586 additions & 1058 deletions

File tree

.env

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,14 @@ IMAGE_PROVIDER_PORT=8081
100100
IMAGE_PROVIDER_DOCKERFILE=./src/image-provider/Dockerfile
101101

102102
# Load Generator
103-
LOAD_GENERATOR_VUS=5
104-
K6_TARGET_URL=http://${FRONTEND_PROXY_ADDR}
103+
LOCUST_WEB_PORT=8089
104+
LOCUST_USERS=5
105+
LOCUST_HOST=http://${FRONTEND_PROXY_ADDR}
106+
LOCUST_WEB_HOST=load-generator
107+
LOCUST_AUTOSTART=true
108+
LOCUST_HTTP_USER_WEIGHT=9
109+
LOCUST_BROWSER_USER_WEIGHT=1
110+
LOCUST_HEADLESS=false
105111
LOAD_GENERATOR_DOCKERFILE=./src/load-generator/Dockerfile
106112

107113
# Payment Service

.github/dependabot.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ updates:
321321
patterns:
322322
- "*"
323323
multi-ecosystem-group: "src-chatbot"
324-
- package-ecosystem: "gomod" # zizmor: ignore[dependabot-cooldown] cooldown prevents multi-ecosystem batching
324+
- package-ecosystem: "pip" # zizmor: ignore[dependabot-cooldown] cooldown prevents multi-ecosystem batching
325325
directories:
326326
- "/src/load-generator/**"
327327
patterns:

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ the release.
77

88
## Unreleased
99

10+
* [load-generator] Revert #3564: replace k6 with the pre-k6 Locust-based load
11+
generator, removing the now-unused `loadGeneratorTraffic` and
12+
`loadGeneratorVUs` feature flags along with it
13+
([#3873](https://github.com/open-telemetry/opentelemetry-demo/pull/3873))
1014
* [react-native-app] Catch errors from `placeOrder` in the Cart screen and
1115
show an error toast so payment failures are visible to the user instead of
1216
being silently dropped

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ Once the images are built and containers are started, visit:
118118
- **Grafana**: [http://localhost:8080/grafana/](http://localhost:8080/grafana/)
119119
- **OpAMP**: [http://localhost:8080/opamp/](http://localhost:8080/opamp/)
120120
- **Feature Flags UI**: [http://localhost:8080/feature/](http://localhost:8080/feature/)
121+
- **Load Generator UI**: [http://localhost:8080/loadgen/](http://localhost:8080/loadgen/)
121122

122123
The OpAMP UI shows the OpenTelemetry Collector as a managed agent. Click the
123124
collector instance ID to view its health status, version, attributes, and

Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ start:
283283
@echo "Go to http://localhost:8080 for the demo UI."
284284
@echo "Go to http://localhost:8080/jaeger/ui for the Jaeger UI."
285285
@echo "Go to http://localhost:8080/grafana/ for the Grafana UI."
286+
@echo "Go to http://localhost:8080/loadgen/ for the Load Generator UI."
286287
@echo "Go to http://localhost:8080/feature/ to change feature flags."
287288
@echo "Go to http://localhost:8080/telemetry/ for the Weaver generated telemetry documentation."
288289

@@ -294,6 +295,7 @@ start-minimal:
294295
@echo "Go to http://localhost:8080 for the demo UI."
295296
@echo "Go to http://localhost:8080/jaeger/ui for the Jaeger UI."
296297
@echo "Go to http://localhost:8080/grafana/ for the Grafana UI."
298+
@echo "Go to http://localhost:8080/loadgen/ for the Load Generator UI."
297299
@echo "Go to http://localhost:8080/feature/ to change feature flags."
298300
@echo "Go to http://localhost:8080/telemetry/ for the Weaver generated telemetry documentation."
299301

@@ -303,6 +305,7 @@ start-no-o11y:
303305
@echo ""
304306
@echo "OpenTelemetry Demo is running (no observability stack)."
305307
@echo "Go to http://localhost:8080 for the demo UI."
308+
@echo "Go to http://localhost:8080/loadgen/ for the Load Generator UI."
306309
@echo "Go to http://localhost:8080/feature/ to change feature flags."
307310
@echo "Go to http://localhost:8080/telemetry/ for the Weaver generated telemetry documentation."
308311

@@ -312,6 +315,7 @@ start-minimal-no-o11y:
312315
@echo ""
313316
@echo "OpenTelemetry Demo in minimal mode is running (no observability stack)."
314317
@echo "Go to http://localhost:8080 for the demo UI."
318+
@echo "Go to http://localhost:8080/loadgen/ for the Load Generator UI."
315319
@echo "Go to http://localhost:8080/feature/ to change feature flags."
316320
@echo "Go to http://localhost:8080/telemetry/ for the Weaver generated telemetry documentation."
317321

@@ -323,6 +327,7 @@ start-profiling:
323327
@echo "Go to http://localhost:8080 for the demo UI."
324328
@echo "Go to http://localhost:8080/jaeger/ui for the Jaeger UI."
325329
@echo "Go to http://localhost:8080/grafana/ for the Grafana UI."
330+
@echo "Go to http://localhost:8080/loadgen/ for the Load Generator UI."
326331
@echo "Go to http://localhost:8080/profiles/ for the Firepit UI."
327332
@echo "Go to http://localhost:8080/telemetry/ for the Weaver generated telemetry documentation."
328333

@@ -334,6 +339,7 @@ start-agentic:
334339
@echo "Go to http://localhost:8080 for the demo UI."
335340
@echo "Go to http://localhost:8080/jaeger/ui for the Jaeger UI."
336341
@echo "Go to http://localhost:8080/grafana/ for the Grafana UI."
342+
@echo "Go to http://localhost:8080/loadgen/ for the Load Generator UI."
337343
@echo "Go to http://localhost:8080/feature/ to change feature flags."
338344
@echo "Go to http://localhost:8080/telemetry/ for the Weaver generated telemetry documentation."
339345
@echo "Go to http://localhost:8080/chatbot/ for interacting with demo application using an agent."

compose.yaml

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ services:
330330
environment:
331331
- FRONTEND_PORT
332332
- FRONTEND_HOST
333+
- LOCUST_WEB_HOST
334+
- LOCUST_WEB_PORT
333335
- GRAFANA_PORT
334336
- GRAFANA_HOST
335337
- JAEGER_UI_PORT
@@ -366,6 +368,8 @@ services:
366368
depends_on:
367369
frontend:
368370
condition: service_healthy
371+
load-generator:
372+
condition: service_started
369373
flagd-ui:
370374
condition: service_healthy
371375
telemetry-docs:
@@ -417,35 +421,37 @@ services:
417421
deploy:
418422
resources:
419423
limits:
420-
memory: 512M
424+
memory: 1500M
421425
restart: unless-stopped
426+
ports:
427+
- "${LOCUST_WEB_PORT}"
422428
environment:
423-
- LOAD_GENERATOR_VUS
424-
- K6_TARGET_URL
425-
- OTEL_EXPORTER_OTLP_ENDPOINT=http://${OTEL_COLLECTOR_HOST}:${OTEL_COLLECTOR_PORT_HTTP}
426-
- OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
429+
- LOCUST_WEB_PORT
430+
- LOCUST_USERS
431+
- LOCUST_HOST
432+
- LOCUST_HEADLESS
433+
- LOCUST_AUTOSTART
434+
- LOCUST_BROWSER_TRAFFIC_ENABLED=true
435+
- LOCUST_HTTP_USER_WEIGHT
436+
- LOCUST_BROWSER_USER_WEIGHT
437+
- OTEL_EXPORTER_OTLP_ENDPOINT
438+
- OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE
427439
- OTEL_RESOURCE_ATTRIBUTES=${OTEL_RESOURCE_ATTRIBUTES},service.criticality=low
428440
- OTEL_SERVICE_NAME=load-generator
441+
- PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python
442+
- LOCUST_WEB_HOST=0.0.0.0
429443
- FLAGD_HOST
430444
- FLAGD_PORT
431445
- FLAGD_OFREP_PORT
432-
- K6_OTEL_EXPORTER_PROTOCOL=http/protobuf
433-
- K6_OTEL_HTTP_EXPORTER_ENDPOINT=${OTEL_COLLECTOR_HOST}:${OTEL_COLLECTOR_PORT_HTTP}
434-
- K6_OTEL_HTTP_EXPORTER_INSECURE=true
435-
- K6_BROWSER_ENABLED=true
436-
- K6_BROWSER_ARGS=no-sandbox,disable-dev-shm-usage
437-
- K6_OTEL_METRIC_PREFIX=k6.
438446
healthcheck:
439-
test: ["CMD-SHELL", "pgrep k6"]
440-
start_period: 10s
447+
test: ["CMD", "python3", "-c", "import socket; s=socket.create_connection(('localhost',${LOCUST_WEB_PORT}),2); s.close()"]
448+
start_period: 30s
441449
interval: 5s
442450
timeout: 5s
443-
retries: 5
451+
retries: 20
444452
depends_on:
445453
frontend:
446454
condition: service_healthy
447-
frontend-proxy:
448-
condition: service_healthy
449455
flagd:
450456
condition: service_started
451457
logging: *logging

src/flagd-ui/README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@ Each interval the scheduler activates up to a configured number of distinct
3030
randomly picked flags. Every activation gets its own hold duration between the
3131
configured minimum and maximum, and its own offset, so that the whole activation
3232
fits inside the interval. When a hold expires that flag is set back to its
33-
resting variant, the flag's own configured default. That is `off` for most
34-
failure scenarios, but `on` for `loadGeneratorTraffic` and `5` for
35-
`loadGeneratorVUs`.
33+
resting variant, the flag's own configured default, which is `off` for every
34+
failure scenario.
3635

3736
The following can be configured:
3837

src/flagd-ui/test/flagd_ui/scheduler_test.exs

Lines changed: 6 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -74,18 +74,6 @@ defmodule FlagdUi.SchedulerTest do
7474
assert {"cartFailure", ["10%", "100%", "25%", "50%", "75%", "90%"]} in flags
7575
end
7676

77-
test "offers loadGeneratorTraffic, whose resting state is on" do
78-
flags = Storage |> GenServer.call(:read) |> Scheduler.schedulable_flags()
79-
80-
assert {"loadGeneratorTraffic", ["off"]} in flags
81-
end
82-
83-
test "offers loadGeneratorVUs, whose resting state is its default variant" do
84-
flags = Storage |> GenServer.call(:read) |> Scheduler.schedulable_flags()
85-
86-
assert {"loadGeneratorVUs", ["10", "25", "50"]} in flags
87-
end
88-
8977
test "tolerates a configuration without flags" do
9078
assert Scheduler.schedulable_flags(%{}) == []
9179
assert Scheduler.schedulable_flags(%{"flags" => nil}) == []
@@ -176,52 +164,13 @@ defmodule FlagdUi.SchedulerTest do
176164
assert Enum.any?(Scheduler.state(scheduler).history, &(&1.flag == flag))
177165
end
178166

179-
test "reverts loadGeneratorTraffic to on, not off" do
180-
scheduler = start_scheduler(TrafficRevertScheduler)
181-
182-
config = immediate_config(%{flags: %{"loadGeneratorTraffic" => ["off"]}})
183-
184-
assert :ok = Scheduler.start_schedule(scheduler, config)
185-
186-
assert_receive {:scheduler_state, %{active: [%{flag: "loadGeneratorTraffic"}]}}, 2000
187-
assert eventually(fn -> variant_of("loadGeneratorTraffic") == "off" end)
188-
189-
assert :ok = Scheduler.stop_schedule(scheduler)
190-
191-
assert eventually(fn -> variant_of("loadGeneratorTraffic") == "on" end)
192-
end
193-
194-
test "reverts loadGeneratorVUs to its own default, not off" do
195-
scheduler = start_scheduler(VUsRevertScheduler)
196-
197-
config = immediate_config(%{flags: %{"loadGeneratorVUs" => ["25"]}})
198-
199-
assert :ok = Scheduler.start_schedule(scheduler, config)
200-
201-
assert_receive {:scheduler_state, %{active: [%{flag: "loadGeneratorVUs", variant: "25"}]}},
202-
2000
203-
204-
assert :ok = Scheduler.stop_schedule(scheduler)
205-
206-
assert eventually(fn -> variant_of("loadGeneratorVUs") == "5" end)
207-
end
208-
209167
test "reverts every flag it activates when holds fill the whole interval" do
210168
scheduler = start_scheduler(BackToBackScheduler)
211169

212-
# Restrict to off-resting flags: loadGeneratorTraffic and loadGeneratorVUs
213-
# rest elsewhere and are covered by their own revert tests above.
214-
selection =
215-
Storage
216-
|> GenServer.call(:read)
217-
|> Scheduler.schedulable_flags()
218-
|> Enum.reject(fn {name, _} -> name in ["loadGeneratorTraffic", "loadGeneratorVUs"] end)
219-
|> Map.new()
220-
221170
# A hold as long as the interval makes each revert land exactly on the next
222171
# interval boundary, which previously left the earlier flag switched on.
223172
assert :ok =
224-
Scheduler.start_schedule(scheduler, immediate_config(%{seed: 99, flags: selection}))
173+
Scheduler.start_schedule(scheduler, immediate_config(%{seed: 99}))
225174

226175
assert_receive {:scheduler_state, %{active: [%{flag: _}]}}, 2000
227176

@@ -367,7 +316,11 @@ defmodule FlagdUi.SchedulerTest do
367316
test "reverts every concurrently held flag when stopped" do
368317
scheduler = start_scheduler(ConcurrentStopScheduler)
369318

370-
assert :ok = Scheduler.start_schedule(scheduler, held_config(%{concurrency: 4}))
319+
assert :ok =
320+
Scheduler.start_schedule(
321+
scheduler,
322+
held_config(%{concurrency: 4})
323+
)
371324

372325
assert_receive {:scheduler_state, %{active: [_, _, _, _] = active}}, 2000
373326

src/flagd-ui/test/flagd_ui_web/live/scheduler_test.exs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ defmodule FlagdUiWeb.SchedulerTest do
2323
assert html =~ "Scheduler stopped"
2424
assert html =~ "Idle"
2525
assert html =~ "adFailure"
26-
assert html =~ "loadGeneratorVUs"
2726
end
2827

2928
test "navigating from the dashboard live redirects", %{conn: conn} do

src/flagd/demo.flagd.json

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -93,24 +93,13 @@
9393
"on": 100
9494
}
9595
},
96-
"loadGeneratorTraffic": {
97-
"defaultVariant": "on",
98-
"description": "Enable synthetic traffic from the load generator. Turn off to pause all load-generator scenarios.",
96+
"loadGeneratorFloodHomepage": {
97+
"defaultVariant": "off",
98+
"description": "Flood the frontend with a large amount of requests.",
9999
"state": "ENABLED",
100100
"variants": {
101101
"off": 0,
102-
"on": 1
103-
}
104-
},
105-
"loadGeneratorVUs": {
106-
"defaultVariant": "5",
107-
"description": "Number of concurrent virtual users the load generator's HTTP scenario runs. Changes take effect on the wrapper's next poll, restarting k6.",
108-
"state": "ENABLED",
109-
"variants": {
110-
"10": 10,
111-
"25": 25,
112-
"5": 5,
113-
"50": 50
102+
"on": 100
114103
}
115104
},
116105
"paymentFailure": {

0 commit comments

Comments
 (0)