How to Check Uptime with a Synthetic HTTP Mock in Python
Run a mock HTTP server locally and probe it with urllib to measure synthetic uptime and response times, perfect for testing monitoring logic without external dependencies.
Python code
48 linesimport http.server
import threading
import time
import urllib.request
class MockHandler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
if self.path == "/health":
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(b'{"status": "ok"}')
else:
self.send_response(404)
self.end_headers()
def log_message(self, format, *args):
pass
def check_uptime(url, timeout=2):
try:
start = time.time()
with urllib.request.urlopen(url, timeout=timeout) as response:
elapsed = time.time() - start
return response.status == 200, elapsed
except Exception:
return False, None
def main():
server = http.server.HTTPServer(("127.0.0.1", 0), MockHandler)
port = server.server_address[1]
thread = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()
url = f"http://127.0.0.1:{port}/health"
for _ in range(3):
up, response_time = check_uptime(url)
print(f"Uptime: {up}, Response time: {response_time:.3f}s")
time.sleep(0.2)
server.shutdown()
if __name__ == "__main__":
main()
Output
Uptime: True, Response time: 0.001s
Uptime: True, Response time: 0.001s
Uptime: True, Response time: 0.001s
How it works
This script spins up a lightweight HTTP server using the standard library's http.server module, with a custom handler that returns a 200 status for /health and 404 otherwise. The check_uptime function uses urllib.request.urlopen to send a GET request and measures the round-trip time with time.time(). The server runs in a daemon thread so it stops automatically when the main thread finishes. The loop simulates repeated health checks, printing whether each probe succeeded and how long it took, mimicking a basic synthetic monitor. Because everything uses only built-in modules, this pattern is ideal for testing monitoring code in CI or local development without standing up a real service.
Common mistakes
- Forgetting to call `server.shutdown()` leads to a hanging process on exit.
- Using `http.server.HTTPServer` without a daemon thread can block program termination.
- Assuming the server port is fixed — using port 0 assigns a random free port, which is more robust for tests.
Variations
- Use `requests.get` instead of `urllib.request` if you prefer a third-party library with better error handling.
- Add a timeout and retry logic with exponential backoff to simulate production monitor behavior.
Real-world use cases
- Testing your custom uptime monitoring script against a local mock before deploying it to monitor real endpoints.
- Simulating health checks in a CI pipeline to validate that your service's /health endpoint responds correctly.
- Benchmarking response times of your application locally without needing a load balancer or external uptime service.
Sponsored
More from Observability & SRE
- Adding a Correlation ID to Log Context in Python medium
- Calculate Error Rate from Log Stream in Python easy
- Check if a Timestamp Falls in a Daily Maintenance Window in Python easy
- Export Metrics with OTLP Mock in Python medium
- Generate Mock CPU and Memory Metrics in Python easy
- Generate Prometheus Text Exposition Format in Python easy
Keep learning
Related tutorials and quizzes for this topic.