Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/pr-env-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -300,10 +300,10 @@ jobs:
run: make test-performance-prepare TF_WORKSPACE_NAME=${{ needs.set-environment-id.outputs.environment_id }}

- name: Run Performance Test - Baseline
run: make test-performance-baseline HOST=${{ needs.set-environment-id.outputs.environment_id }}.api.record-locator.dev.national.nhs.uk ENV_TYPE=dev
run: make test-performance-baseline-internal HOST=${{ needs.set-environment-id.outputs.environment_id }}.api.record-locator.dev.national.nhs.uk ENV_TYPE=dev

- name: Run Performance Test - Stress
run: make test-performance-stress HOST=${{ needs.set-environment-id.outputs.environment_id }}.api.record-locator.dev.national.nhs.uk ENV_TYPE=dev
run: make test-performance-stress-internal HOST=${{ needs.set-environment-id.outputs.environment_id }}.api.record-locator.dev.national.nhs.uk ENV_TYPE=dev

- name: Process Performance Test Outputs
run: make test-performance-output
Expand Down
72 changes: 61 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -152,20 +152,58 @@ test-performance-prepare:
mkdir -p $(DIST_PATH)
PYTHONPATH=. poetry run python tests/performance/environment.py setup $(TF_WORKSPACE_NAME)

test-performance: check-warn test-performance-baseline test-performance-stress ## Run the performance tests
test-performance-internal: check-warn test-performance-baseline-internal test-performance-stress-internal ## Run the performance tests against the internal access points

test-performance-baseline:
@echo "Running consumer performance baseline test"
k6 run --out csv=$(DIST_PATH)/consumer-baseline.csv tests/performance/consumer/baseline.js -e HOST=$(HOST) -e ENV_TYPE=$(ENV_TYPE)

test-performance-stress:
@echo "Running consumer performance stress test"
test-performance-baseline-internal: check-warn ## Run the performance baseline tests for the internal access points
@echo "Running internal consumer performance baseline test"
TEST_CONNECT_MODE=internal \
TEST_STACK_DOMAIN=$(shell terraform -chdir=terraform/infrastructure output -raw domain 2>/dev/null) \
k6 run --out csv=$(DIST_PATH)/consumer-baseline.csv tests/performance/consumer/baseline.js -e HOST=$(HOST) -e ENV_TYPE=$(ENV_TYPE)

test-performance-baseline-public: check-warn ## Run the baseline performance tests for the external access points
@echo "Fetching public mode configuration and bearer token..."
@CONFIG_FILE=$$(mktemp /tmp/perf_config_XXXXXX); \
trap "rm -f $$CONFIG_FILE" EXIT; \
PYTHONPATH=. python3 tests/performance/get_test_config.py $(ENV_TYPE) 2>&1 | tail -n 1 > $$CONFIG_FILE; \
PUBLIC_BASE_URL=$$(jq -r '.public_base_url' $$CONFIG_FILE); \
echo "Running consumer performance baseline test against the external access points"; \
TEST_CONNECT_MODE=public \
TEST_PUBLIC_BASE_URL=$$PUBLIC_BASE_URL \
TEST_CONFIG_FILE=$$CONFIG_FILE \
k6 run --out csv=$(DIST_PATH)/consumer-baseline-public.csv tests/performance/consumer/baseline.js -e ENV_TYPE=$(ENV_TYPE)

test-performance-stress-internal: ## Run the performance stress tests for the internal access points
@echo "Running internal consumer performance stress test"
k6 run --out csv=$(DIST_PATH)/consumer-stress.csv tests/performance/consumer/stress.js -e HOST=$(HOST) -e ENV_TYPE=$(ENV_TYPE)

test-performance-soak:
@echo "Running consumer performance soak test"
test-performance-stress-public: check-warn ## Run the stress performance tests for the external access points
@echo "Fetching public mode configuration and bearer token..."
@CONFIG_FILE=$$(mktemp /tmp/perf_config_XXXXXX); \
trap "rm -f $$CONFIG_FILE" EXIT; \
PYTHONPATH=. python3 tests/performance/get_test_config.py $(ENV_TYPE) 2>&1 | tail -n 1 > $$CONFIG_FILE; \
PUBLIC_BASE_URL=$$(jq -r '.public_base_url' $$CONFIG_FILE); \
echo "Running consumer performance stress test against the external access points"; \
TEST_CONNECT_MODE=public \
TEST_PUBLIC_BASE_URL=$$PUBLIC_BASE_URL \
TEST_CONFIG_FILE=$$CONFIG_FILE \
k6 run --out csv=$(DIST_PATH)/consumer-stress-public.csv tests/performance/consumer/stress.js -e ENV_TYPE=$(ENV_TYPE)

test-performance-soak-internal:
@echo "Running internal consumer performance soak test"
k6 run --out csv=$(DIST_PATH)/consumer-soak.csv tests/performance/consumer/soak.js -e HOST=$(HOST) -e ENV_TYPE=$(ENV_TYPE)

test-performance-soak-public: check-warn ## Run the soak performance tests for the external access points
@echo "Fetching public mode configuration and bearer token..."
@CONFIG_FILE=$$(mktemp /tmp/perf_config_XXXXXX); \
trap "rm -f $$CONFIG_FILE" EXIT; \
PYTHONPATH=. python3 tests/performance/get_test_config.py $(ENV_TYPE) 2>&1 | tail -n 1 > $$CONFIG_FILE; \
PUBLIC_BASE_URL=$$(jq -r '.public_base_url' $$CONFIG_FILE); \
echo "Running consumer performance soak test against the external access points"; \
TEST_CONNECT_MODE=public \
TEST_PUBLIC_BASE_URL=$$PUBLIC_BASE_URL \
TEST_CONFIG_FILE=$$CONFIG_FILE \
k6 run --out csv=$(DIST_PATH)/consumer-soak-public.csv tests/performance/consumer/soak.js -e ENV_TYPE=$(ENV_TYPE)

test-performance-output: ## Process outputs from the performance tests
@echo "Processing performance test outputs"
poetry run python tests/performance/process_results.py baseline $(DIST_PATH)/consumer-baseline.csv
Expand Down Expand Up @@ -250,16 +288,28 @@ generate-models: check-warn ## Generate Pydantic Models


generate-perftest-permissions: ## Generate perftest permissions and add to nrlf_permissions
poetry run python tests/performance/producer/generate_permissions.py --output_dir="$(DIST_PATH)/nrlf_permissions/K6PerformanceTest"
PYTHONPATH=. poetry run python tests/performance/producer/generate_permissions.py --output_dir="$(DIST_PATH)/nrlf_permissions/K6PerformanceTest"

perftest-producer:
@echo "Running producer performance tests with HOST=$(PERFTEST_HOST) and ENV_TYPE=$(ENV_TYPE) and DIST_PATH=$(DIST_PATH)"
k6 run tests/performance/producer/perftest.js -e HOST=$(PERFTEST_HOST) -e ENV_TYPE=$(ENV_TYPE) -e DIST_PATH=$(DIST_PATH)

perftest-consumer:
perftest-consumer-internal:
@echo "Running consumer performance tests with HOST=$(PERFTEST_HOST) and ENV_TYPE=$(ENV_TYPE) and DIST_PATH=$(DIST_PATH)"
k6 run tests/performance/consumer/perftest.js -e HOST=$(PERFTEST_HOST) -e ENV_TYPE=$(ENV_TYPE) -e DIST_PATH=$(DIST_PATH)

perftest-consumer-public: check-warn ## Run the consumer perftests for the external access points
@echo "Fetching public mode configuration and bearer token..."
@CONFIG_FILE=$$(mktemp /tmp/perf_config_XXXXXX); \
trap "rm -f $$CONFIG_FILE" EXIT; \
PYTHONPATH=. poetry run python tests/performance/get_test_config.py $(ENV_TYPE) 2>&1 | tail -n 1 > $$CONFIG_FILE; \
PUBLIC_BASE_URL=$$(jq -r '.public_base_url' $$CONFIG_FILE); \
echo "Running public consumer perftests with ENV_TYPE=$(ENV_TYPE) and DIST_PATH=$(DIST_PATH)"; \
TEST_CONNECT_MODE=public \
TEST_PUBLIC_BASE_URL=$$PUBLIC_BASE_URL \
TEST_CONFIG_FILE=$$CONFIG_FILE \
k6 run tests/performance/consumer/perftest.js -e ENV_TYPE=$(ENV_TYPE) -e DIST_PATH=$(DIST_PATH)

perftest-prep-generate-producer-data:
@echo "Generating producer reference with PERFTEST_TABLE_NAME=$(PERFTEST_TABLE_NAME) and DIST_PATH=$(DIST_PATH)"
mkdir -p $(DIST_PATH)
Expand Down
2 changes: 1 addition & 1 deletion tests/performance/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const NHS_NUMBERS = REFERENCE_DATA["nhs_numbers"];

// filter only 736253001, 736253002, 1363501000000100, 861421000000109, 749001000000101 for now
export const FILTERED_POINTER_TYPES = [
"736253001",
// "736253001",
"736253002",
"1363501000000100",
"861421000000109",
Expand Down
99 changes: 33 additions & 66 deletions tests/performance/consumer/client.js
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these need applying to the client_perftest.js file rather than in here? For the new perf tests

Original file line number Diff line number Diff line change
@@ -1,32 +1,14 @@
import { getHeaders, getFullUrl } from "../test-config.js";
import {
POINTER_TYPES,
CATEGORIES,
NHS_NUMBERS,
POINTER_IDS,
POINTER_TYPES,
ODS_CODE,
CATEGORIES,
} from "../constants.js";
import http from "k6/http";
import { check } from "k6";

function getHeaders(odsCode = ODS_CODE) {
return {
"Content-Type": "application/fhir+json",
"X-Request-Id": "K6PerformanceTest",
"NHSD-Correlation-Id": "K6PerformanceTest",
"NHSD-Connection-Metadata": JSON.stringify({
"nrl.ods-code": odsCode,
"nrl.pointer-types": POINTER_TYPES.map(
(type) => `http://snomed.info/sct|${type}`
),
"nrl.app-id": "K6PerformanceTest",
}),
"NHSD-Client-RP-Details": JSON.stringify({
"developer.app.name": "K6PerformanceTest",
"developer.app.id": "K6PerformanceTest",
}),
};
}

function checkResponse(res) {
const is_success = check(res, { "status is 200": (r) => r.status === 200 });
if (!is_success) {
Expand All @@ -41,25 +23,22 @@ export function countDocumentReference() {
const identifier = encodeURIComponent(
`https://fhir.nhs.uk/Id/nhs-number|${nhsNumber}`
);
const res = http.get(
`https://${__ENV.HOST}/consumer/DocumentReference?_summary=count&subject:identifier=${identifier}`,
{
headers: getHeaders(),
}
);

const path = `/DocumentReference?_summary=count&subject:identifier=${identifier}`;
const res = http.get(getFullUrl(path, "consumer"), {
headers: getHeaders(ODS_CODE, "consumer"),
});
checkResponse(res);
}

export function readDocumentReference() {
const choice = Math.floor(Math.random() * POINTER_IDS.length);
const id = POINTER_IDS[choice];

const res = http.get(
`https://${__ENV.HOST}/consumer/DocumentReference/${id}`,
{
headers: getHeaders(),
}
);
const path = `/DocumentReference/${id}`;
const res = http.get(getFullUrl(path, "consumer"), {
headers: getHeaders(ODS_CODE, "consumer"),
});

checkResponse(res);
}
Expand All @@ -74,12 +53,10 @@ export function searchDocumentReference() {
);
const type = encodeURIComponent(`http://snomed.info/sct|${pointer_type}`);

const res = http.get(
`https://${__ENV.HOST}/consumer/DocumentReference?subject:identifier=${identifier}&type=${type}`,
{
headers: getHeaders(),
}
);
const path = `/DocumentReference?subject:identifier=${identifier}&type=${type}`;
const res = http.get(getFullUrl(path, "consumer"), {
headers: getHeaders(ODS_CODE, "consumer"),
});
checkResponse(res);
}

Expand All @@ -95,12 +72,10 @@ export function searchDocumentReferenceByCategory() {
`http://snomed.info/sct|${randomCategory}`
);

const res = http.get(
`https://${__ENV.HOST}/consumer/DocumentReference?subject:identifier=${identifier}&category=${category}`,
{
headers: getHeaders(),
}
);
const path = `/DocumentReference?subject:identifier=${identifier}&category=${category}`;
const res = http.get(getFullUrl(path, "consumer"), {
headers: getHeaders(ODS_CODE, "consumer"),
});
checkResponse(res);
}

Expand All @@ -114,13 +89,10 @@ export function searchPostDocumentReference() {
type: `http://snomed.info/sct|${pointer_type}`,
});

const res = http.post(
`https://${__ENV.HOST}/consumer/DocumentReference/_search`,
body,
{
headers: getHeaders(),
}
);
const path = `/DocumentReference/_search`;
const res = http.post(getFullUrl(path, "consumer"), body, {
headers: getHeaders(ODS_CODE, "consumer"),
});
checkResponse(res);
}

Expand All @@ -133,13 +105,10 @@ export function searchPostDocumentReferenceByCategory() {
category: `http://snomed.info/sct|${category}`,
});

const res = http.post(
`https://${__ENV.HOST}/consumer/DocumentReference/_search`,
body,
{
headers: getHeaders(),
}
);
const path = `/DocumentReference/_search`;
const res = http.post(getFullUrl(path, "consumer"), body, {
headers: getHeaders(ODS_CODE, "consumer"),
});
checkResponse(res);
}

Expand All @@ -150,12 +119,10 @@ export function countPostDocumentReference() {
const body = JSON.stringify({
"subject:identifier": `https://fhir.nhs.uk/Id/nhs-number|${nhsNumber}`,
});
const res = http.post(
`https://${__ENV.HOST}/consumer/DocumentReference/_search?_summary=count`,
body,
{
headers: getHeaders(),
}
);

const path = `/DocumentReference/_search?_summary=count`;
const res = http.post(getFullUrl(path, "consumer"), body, {
headers: getHeaders(ODS_CODE, "consumer"),
});
checkResponse(res);
}
Loading
Loading