Spaces:
Runtime error
Runtime error
Download scripts/locustfile.py from yusufcalisir/Collaborative-Fraud-Intelligence-Simulator: direct link, hf CLI and curl.
- Browser
- Download file 6.77 kB
-
https://huggingface.co/spaces/yusufcalisir/Collaborative-Fraud-Intelligence-Simulator/resolve/main/scripts/locustfile.py
- Command line
-
hf download hf://spaces/yusufcalisir/Collaborative-Fraud-Intelligence-Simulator/scripts/locustfile.py
-
curl -L -o locustfile.py https://huggingface.co/spaces/yusufcalisir/Collaborative-Fraud-Intelligence-Simulator/resolve/main/scripts/locustfile.py
6.77 kB
| """Locust Load Testing Suite for Real-Time Inference Gateway & API Layer. | |
| Simulates concurrent banking client nodes, automated payment streams, | |
| and compliance investigators to benchmark SLA adherence (<100ms p99 latency), | |
| throughput capacity (TPS), and error rates. | |
| Usage: | |
| # Headless 60-second load test with 50 concurrent users | |
| locust -f scripts/locustfile.py --headless -u 50 -r 10 --run-time 60s --host http://localhost:8000 | |
| # Web UI mode | |
| locust -f scripts/locustfile.py --host http://localhost:8000 | |
| """ | |
| from __future__ import annotations | |
| # gevent monkey-patching: ensure socket and ssl are safely patched before standard networking modules | |
| # to prevent RecursionError on Python 3.12 under high-concurrency load tests. | |
| try: | |
| import gevent.monkey | |
| if not gevent.monkey.is_module_patched("socket"): | |
| gevent.monkey.patch_all() | |
| except (ImportError, Exception): | |
| pass | |
| import random | |
| import uuid | |
| from typing import Any | |
| try: | |
| from locust import FastHttpUser, between, task | |
| except ImportError: | |
| class FastHttpUser: # type: ignore[no-redef] | |
| pass | |
| def between(a: float, b: float) -> Any: # type: ignore[no-redef] | |
| return None | |
| def task(weight: int = 1) -> Any: # type: ignore[no-redef] | |
| def decorator(f: Any) -> Any: | |
| return f | |
| return decorator | |
| _BANK_IDS = ["bank_alpha", "bank_beta", "bank_gamma"] | |
| _CURRENCIES = ["EUR", "USD", "GBP", "CHF"] | |
| _MERCHANTS = ["crypto_exchange", "electronics", "wire_transfer", "gambling", "retail", "jewelry"] | |
| class BankingNodeUser(FastHttpUser): | |
| """Simulates active banking nodes streaming real-time transactions for scoring.""" | |
| wait_time = between(0.01, 0.05) # High frequency payment stream (20-100 req/s per user) | |
| def score_realtime_transaction(self) -> None: | |
| """Benchmark /api/v1/predict endpoint for real-time <100ms inference SLA.""" | |
| tx_id = f"txn_{uuid.uuid4().hex[:12]}" | |
| bank_id = random.choice(_BANK_IDS) | |
| amount = round(random.uniform(5.0, 50000.0), 2) | |
| merchant = random.choice(_MERCHANTS) | |
| payload: dict[str, Any] = { | |
| "transaction_id": tx_id, | |
| "bank_id": bank_id, | |
| "source_bank_id": bank_id, | |
| "amount": amount, | |
| "currency": random.choice(_CURRENCIES), | |
| "merchant_category": merchant, | |
| "sender_account": f"DE893704004405320130{random.randint(10, 99)}", | |
| "receiver_account": f"GB29NWBK601613319268{random.randint(10, 99)}", | |
| "device_fingerprint": f"dev_fp_{uuid.uuid4().hex[:8]}", | |
| "country_code": random.choice(["DE", "FR", "US", "GB", "NL", "TR"]), | |
| "timestamp": "2026-09-02T05:00:00Z", | |
| } | |
| headers = { | |
| "X-Tenant-ID": bank_id, | |
| "X-Bank-ID": bank_id, | |
| "Content-Type": "application/json", | |
| } | |
| with self.client.post( | |
| "/api/v1/predict", | |
| json=payload, | |
| headers=headers, | |
| name="POST /api/v1/predict", | |
| catch_response=True, | |
| ) as response: | |
| if response.status_code == 200: | |
| data = response.json() | |
| if "risk_score" in data or "composite_risk_score" in data: | |
| response.success() | |
| else: | |
| response.failure(f"Missing risk score in payload: {response.text}") | |
| elif response.status_code == 429: | |
| # Rate limited under extreme burst (expected at high concurrency) | |
| response.success() | |
| else: | |
| response.failure(f"Unexpected status code: {response.status_code}") | |
| def score_v1_inference_endpoint(self) -> None: | |
| """Benchmark /v1/inference/score endpoint.""" | |
| bank_id = random.choice(_BANK_IDS) | |
| payload = { | |
| "transaction_id": f"txn_{uuid.uuid4().hex[:12]}", | |
| "source_bank_id": bank_id, | |
| "amount": round(random.uniform(10.0, 150000.0), 2), | |
| "currency": "EUR", | |
| "sender_account": f"DE893704004405320130{random.randint(10, 99)}", | |
| "receiver_account": f"GB29NWBK601613319268{random.randint(10, 99)}", | |
| "merchant_category": random.choice(_MERCHANTS), | |
| "device_fingerprint": f"dev_fp_{uuid.uuid4().hex[:8]}", | |
| } | |
| self.client.post( | |
| "/v1/inference/score", | |
| json=payload, | |
| headers={"X-Tenant-ID": bank_id, "X-Bank-ID": bank_id}, | |
| name="POST /v1/inference/score", | |
| ) | |
| def check_health_readiness(self) -> None: | |
| """Verify low-overhead liveness & readiness probes.""" | |
| self.client.get("/health", name="GET /health") | |
| self.client.get("/ready", name="GET /ready") | |
| class ComplianceAnalystUser(FastHttpUser): | |
| """Simulates compliance officers reviewing cases and authenticating.""" | |
| wait_time = between(0.1, 0.5) | |
| def on_start(self) -> None: | |
| """Log in on session start.""" | |
| self.auth_token = "" | |
| res = self.client.post( | |
| "/api/v1/auth/login", | |
| json={"username": "investigator_alpha", "password": "DemoPassword123!"}, | |
| name="POST /api/v1/auth/login", | |
| ) | |
| if res.status_code == 200: | |
| self.auth_token = res.json().get("access_token", "") | |
| def fetch_cases_list(self) -> None: | |
| """Query case workbench cases with tenant isolation.""" | |
| headers = { | |
| "Authorization": f"Bearer {self.auth_token}" if self.auth_token else "", | |
| "X-Tenant-ID": "bank_alpha", | |
| "X-Bank-ID": "bank_alpha", | |
| } | |
| self.client.get("/api/v1/cases", headers=headers, name="GET /api/v1/cases") | |
| def check_lockout_status(self) -> None: | |
| """Query brute-force lockout status.""" | |
| self.client.get( | |
| "/api/v1/auth/lockout-status?username=investigator_alpha", | |
| name="GET /api/v1/auth/lockout-status", | |
| ) | |
| if __name__ == "__main__": | |
| import sys | |
| try: | |
| from locust import main | |
| # Default to this locustfile if -f / --locustfile not explicitly given | |
| if "-f" not in sys.argv and "--locustfile" not in sys.argv: | |
| sys.argv.insert(1, "-f") | |
| sys.argv.insert(2, __file__) | |
| main.main() | |
| except ImportError: | |
| if "--help" in sys.argv or "-h" in sys.argv: | |
| print("locustfile.py: Load testing suite using Locust.") | |
| print("Usage: python scripts/locustfile.py [options]") | |
| print("\nNote: Locust is not installed in the current environment (pip install locust).") | |
| sys.exit(0) | |
| print("[ERROR] Locust is not installed. Run: pip install locust") | |
| sys.exit(1) | |