Initial commit: Complete DevServer monitoring framework

- FastAPI application with OpenTelemetry instrumentation
- Redis caching and Celery task processing
- Docker Compose setup with monitoring stack
- Grafana dashboards and Prometheus metrics
- Jaeger distributed tracing
- Comprehensive documentation in docs/ folder
- Monitoring configuration and troubleshooting guides
This commit is contained in:
Hardik Sankhla
2025-10-13 09:55:17 +05:30
commit 2304c3ed12
32 changed files with 7146 additions and 0 deletions

229
test_cache_apis.py Normal file
View File

@@ -0,0 +1,229 @@
"""
Test script demonstrating Redis caching in Dice Roll and Fibonacci APIs
"""
import requests
import time
BASE_URL = "http://localhost:8000"
def print_header(title):
print("\n" + "=" * 70)
print(f" {title}")
print("=" * 70)
def print_section(title):
print(f"\n{title}")
print("-" * 70)
def test_dice_with_caching():
"""Test dice roll API with Redis caching"""
print_header("DICE ROLL API - Redis Caching Test")
session_id = "player_123"
# First roll - should generate fresh results and cache them
print_section("1️⃣ First Roll (Fresh - should cache)")
response = requests.get(f"{BASE_URL}/api/dice/roll", params={
"session_id": session_id,
"use_cache": True
})
data1 = response.json()
print(f" Session ID: {data1['session_id']}")
print(f" Total Rolls: {data1['total']}")
print(f" Statistics: {data1['statistics']}")
print(f" Source: {data1['source']}")
print(f" Cache Key: {data1['cache_key']}")
print(f" Status: {response.status_code}")
# Second roll - should return cached results (same rolls)
print_section("2️⃣ Second Roll (Same Session - should hit cache)")
response = requests.get(f"{BASE_URL}/api/dice/roll", params={
"session_id": session_id,
"use_cache": True
})
data2 = response.json()
print(f" Source: {data2['source']}")
print(f" Total Rolls: {data2['total']}")
print(f" Statistics: {data2['statistics']}")
print(f" Same results as first roll: {data1['dice_rolls'] == data2['dice_rolls']}")
print(f" Status: {response.status_code}")
# Third roll - different session, fresh results
print_section("3️⃣ Third Roll (Different Session - fresh)")
response = requests.get(f"{BASE_URL}/api/dice/roll", params={
"session_id": "player_456",
"use_cache": True
})
data3 = response.json()
print(f" Session ID: {data3['session_id']}")
print(f" Source: {data3['source']}")
print(f" Total Rolls: {data3['total']}")
print(f" Statistics: {data3['statistics']}")
print(f" Status: {response.status_code}")
# Fourth roll - cache disabled
print_section("4️⃣ Fourth Roll (Cache Disabled)")
response = requests.get(f"{BASE_URL}/api/dice/roll", params={
"session_id": session_id,
"use_cache": False
})
data4 = response.json()
print(f" Source: {data4['source']}")
print(f" Statistics: {data4['statistics']}")
print(f" Different from cached: {data1['dice_rolls'] != data4['dice_rolls']}")
print(f" Status: {response.status_code}")
def test_fibonacci_with_caching():
"""Test Fibonacci API with Redis caching"""
print_header("FIBONACCI API - Redis Caching Test")
# Test with n=10
n = 10
# First request - should compute and cache
print_section(f"1️⃣ First Request (n={n}) - Fresh Computation")
start = time.time()
response = requests.post(f"{BASE_URL}/api/tasks/fibonacci", params={
"n": n,
"use_cache": True
})
elapsed1 = time.time() - start
data1 = response.json()
print(f" n: {data1['n']}")
print(f" Status: {data1['status']}")
print(f" Source: {data1['source']}")
print(f" Response Time: {elapsed1:.3f}s")
print(f" Cache Key: {data1['cache_key']}")
if data1['source'] == 'celery_task':
print(f" Task ID: {data1['task_id']}")
print(f" Check result at: {data1['check_result_at']}")
# Wait for task completion
print("\n ⏳ Waiting for task to complete...")
time.sleep(2)
# Get result
task_response = requests.get(f"{BASE_URL}/api/tasks/{data1['task_id']}")
task_data = task_response.json()
print(f" ✅ Task Status: {task_data['status']}")
if task_data['status'] == 'completed':
result = task_data['result']
print(f" Result: Fibonacci({n}) = {result.get('result', result.get('fibonacci'))}")
print(f" Computation Time: {result.get('computation_time_seconds', 'N/A')}s")
else:
print(f" ✅ Result: Fibonacci({n}) = {data1['result']}")
# Second request - should hit cache immediately
print_section(f"2️⃣ Second Request (n={n}) - Should Hit Cache")
start = time.time()
response = requests.post(f"{BASE_URL}/api/tasks/fibonacci", params={
"n": n,
"use_cache": True
})
elapsed2 = time.time() - start
data2 = response.json()
print(f" Status: {data2['status']}")
print(f" Source: {data2['source']}")
print(f" Response Time: {elapsed2:.3f}s")
print(f" Result: Fibonacci({n}) = {data2.get('result', 'N/A')}")
print(f" 🚀 Speedup: {elapsed1/elapsed2:.1f}x faster!")
# Third request - cache disabled, force recomputation
print_section(f"3️⃣ Third Request (n={n}) - Cache Disabled")
start = time.time()
response = requests.post(f"{BASE_URL}/api/tasks/fibonacci", params={
"n": n,
"use_cache": False
})
elapsed3 = time.time() - start
data3 = response.json()
print(f" Status: {data3['status']}")
print(f" Source: {data3['source']}")
print(f" Response Time: {elapsed3:.3f}s")
# Test with larger number
n_large = 20
print_section(f"4️⃣ Large Fibonacci (n={n_large}) - First Request")
start = time.time()
response = requests.post(f"{BASE_URL}/api/tasks/fibonacci", params={
"n": n_large,
"use_cache": True
})
elapsed_large1 = time.time() - start
data_large = response.json()
print(f" Source: {data_large['source']}")
print(f" Response Time: {elapsed_large1:.3f}s")
if data_large['source'] == 'celery_task':
print(f" Task ID: {data_large['task_id']}")
print("\n ⏳ Waiting for computation...")
time.sleep(3)
task_response = requests.get(f"{BASE_URL}/api/tasks/{data_large['task_id']}")
task_data = task_response.json()
if task_data['status'] == 'completed':
result = task_data['result']
print(f" ✅ Result: Fibonacci({n_large}) = {result.get('result', result.get('fibonacci'))}")
# Cached request for large number
print_section(f"5️⃣ Large Fibonacci (n={n_large}) - Cached Request")
start = time.time()
response = requests.post(f"{BASE_URL}/api/tasks/fibonacci", params={
"n": n_large,
"use_cache": True
})
elapsed_large2 = time.time() - start
data_large2 = response.json()
print(f" Source: {data_large2['source']}")
print(f" Response Time: {elapsed_large2:.3f}s")
if data_large2['source'] == 'cache':
print(f" ✅ Result: Fibonacci({n_large}) = {data_large2['result']}")
print(f" 🚀 Much faster with cache!")
def test_cache_stats():
"""Display Redis cache statistics"""
print_header("REDIS CACHE STATISTICS")
response = requests.get(f"{BASE_URL}/api/cache/stats")
data = response.json()
stats = data['stats']
print(f"\n Memory Used: {stats['used_memory']}")
print(f" Total Keys: {stats['total_keys']}")
print(f" Connected Clients: {stats['connected_clients']}")
print(f" Cache Hits: {stats['hits']}")
print(f" Cache Misses: {stats['misses']}")
print(f" Hit Ratio: {stats['hit_ratio_percent']}%")
print(f" Uptime: {stats['uptime_seconds']} seconds")
def main():
print("\n" + "🎲" * 35)
print(" Redis Caching Test Suite for DevServer API")
print("🎲" * 35)
try:
# Test Dice Roll API
test_dice_with_caching()
# Test Fibonacci API
test_fibonacci_with_caching()
# Display cache statistics
test_cache_stats()
print("\n" + "=" * 70)
print(" ✅ All tests completed successfully!")
print("=" * 70)
print("\n💡 Key Takeaways:")
print(" • Dice rolls are cached per session (5 min TTL)")
print(" • Fibonacci results are cached globally (1 hour TTL)")
print(" • Cache dramatically improves response times")
print(" • Both APIs support cache bypass with use_cache=false")
print("\n")
except Exception as e:
print(f"\n❌ Error: {e}")
if __name__ == "__main__":
main()