Skip to content

Commit 5b99032

Browse files
committed
Add /burn endpoint for CPU load simulation
1 parent a3c1bb1 commit 5b99032

3 files changed

Lines changed: 47 additions & 0 deletions

File tree

src/common/core/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# Aptible health checks must be on /healthcheck and cannot redirect
1212
# see https://www.aptible.com/docs/core-concepts/apps/connecting-to-apps/app-endpoints/https-endpoints/health-checks
1313
re_path(r"^healthcheck", include("health_check.urls", namespace="health-aptible")),
14+
path("burn/", views.burn),
1415
]
1516

1617
if settings.PROMETHEUS_ENABLED:

src/common/core/views.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import time
23

34
import prometheus_client
45
from django.http import HttpResponse, JsonResponse
@@ -25,3 +26,17 @@ def metrics(request: Request) -> HttpResponse:
2526
metrics_page,
2627
content_type=prometheus_client.CONTENT_TYPE_LATEST,
2728
)
29+
30+
31+
def burn(request: Request) -> HttpResponse:
32+
"""
33+
Burn CPU for a specified duration to simulate load.
34+
35+
Usage: GET /burn?s=10 (burns CPU for 10 seconds)
36+
"""
37+
seconds = int(request.GET.get("s", 1))
38+
end_time = time.monotonic() + seconds
39+
while time.monotonic() < end_time:
40+
pass # Busy wait
41+
42+
return HttpResponse("waited")

tests/integration/core/test_views.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import prometheus_client
22
import pytest
3+
from pytest_mock import MockerFixture
34
from rest_framework.test import APIClient
45

56
from common.test_tools import SnapshotFixture
@@ -28,3 +29,33 @@ def test_metrics__return_expected(
2829
# Assert
2930
assert response.status_code == 200
3031
assert response.content.decode() == snapshot()
32+
33+
34+
def test_burn__default_duration__returns_expected(
35+
client: APIClient,
36+
mocker: MockerFixture,
37+
) -> None:
38+
# Given
39+
mocker.patch("common.core.views.time.monotonic", side_effect=[0, 1])
40+
41+
# When
42+
response = client.get("/burn/")
43+
44+
# Then
45+
assert response.status_code == 200
46+
assert response.content.decode() == "waited"
47+
48+
49+
def test_burn__custom_duration__returns_expected(
50+
client: APIClient,
51+
mocker: MockerFixture,
52+
) -> None:
53+
# Given
54+
mocker.patch("common.core.views.time.monotonic", side_effect=[0, 3])
55+
56+
# When
57+
response = client.get("/burn/?s=3")
58+
59+
# Then
60+
assert response.status_code == 200
61+
assert response.content.decode() == "waited"

0 commit comments

Comments
 (0)