Mock a Sidecar Logger with Python Metrics
Simulate a sidecar logger that tracks request counts, error rates, and endpoint hits, producing a metrics snapshot.
Python code
46 linesimport random
import time
from collections import defaultdict
class SidecarLogger:
def __init__(self):
self.metrics = defaultdict(int)
self.total_requests = 0
self.error_count = 0
def log_request(self, endpoint, status_code):
"""Simulate logging a request and updating metrics."""
self.total_requests += 1
self.metrics[endpoint] += 1
if status_code >= 400:
self.error_count += 1
def _generate_mock_log(self):
"""Generate a simulated log entry from app."""
endpoints = ["/api/users", "/api/products", "/health"]
statuses = [200, 200, 200, 201, 404, 500]
return random.choice(endpoints), random.choice(statuses)
def run_mock_session(self, num_requests=100):
"""Simulate sidecar logging for a batch of requests."""
for _ in range(num_requests):
endpoint, status = self._generate_mock_log()
self.log_request(endpoint, status)
time.sleep(0.001)
def get_metrics_snapshot(self):
"""Return a snapshot of collected metrics."""
return {
"total_requests": self.total_requests,
"error_count": self.error_count,
"error_rate": round(self.error_count / self.total_requests * 100, 2) if self.total_requests else 0.0,
"endpoint_hits": dict(self.metrics),
}
if __name__ == "__main__":
logger = SidecarLogger()
logger.run_mock_session(num_requests=1000)
snapshot = logger.get_metrics_snapshot()
print(snapshot)
Output
{'total_requests': 1000, 'error_count': 317, 'error_rate': 31.7, 'endpoint_hits': {'/api/users': 340, '/api/products': 331, '/health': 329}}
How it works
The SidecarLogger class mimics a sidecar proxy that intercepts requests and collects metrics without blocking the main application. Each logged request increments counters and updates endpoint-specific hit maps, all stored in a defaultdict for automatic key creation. The error rate is computed as a percentage of failed requests over total requests, rounded to two decimals. The mock session generates random endpoints and status codes to simulate realistic traffic, and get_metrics_snapshot returns a clean dictionary for downstream consumers. Using defaultdict(int) simplifies counting because missing keys default to zero, avoiding manual dictionary initialization.
Common mistakes
- Forgetting to handle division by zero when total_requests is zero
- Using `time.sleep` with large values makes the mock slow and unrealistic
- Not resetting metrics between sessions, causing cumulative counts
- Assuming status codes are always valid integers without validation
Variations
- Use `threading` to simulate concurrent requests from multiple services
- Replace `random` with a seeded generator for reproducible test runs
Real-world use cases
- Testing sidecar proxies in development by generating synthetic traffic metrics without a real service.
- Validating metric aggregation logic before integrating with Prometheus or Datadog exporters.
- Simulating load to verify monitoring dashboards and alerting thresholds in staging environments.
Sponsored
More from Microservices patterns
- BFF aggregation pattern: combine multiple service responses in Python easy
- Backward Compatible Schema Evolution in Python medium
- Bulkhead Thread Pool per Service Mock in Python medium
- CQRS with Separate Read and Write Repositories in Python medium
- Cache-Aside Pattern in Python: Per-Service Mock easy
- Consumer Driven Contract Pact Mock in Python medium
Keep learning
Related tutorials and quizzes for this topic.