Pranav Mishra
Initial backend deployment - Flask API with ML models
1772a46
import logging
import time
from typing import Dict, List, Any
from collections import defaultdict, deque
import json
class PerformanceLogger:
"""
Performance logger for tracking audio processing metrics.
Provides detailed logging and statistics for each processing method.
"""
def __init__(self, max_history: int = 100):
self.max_history = max_history
self.method_stats = defaultdict(lambda: {
'predictions': deque(maxlen=max_history),
'inference_times': deque(maxlen=max_history),
'errors': deque(maxlen=max_history),
'total_calls': 0,
'total_errors': 0
})
# Setup structured logging
self.setup_logging()
def setup_logging(self):
"""Setup structured logging with proper formatting."""
# Create custom formatter
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# Setup console handler
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
# Setup file handler
file_handler = logging.FileHandler('audio_digit_classifier.log')
file_handler.setFormatter(formatter)
# Configure root logger
logging.basicConfig(
level=logging.DEBUG,
handlers=[console_handler, file_handler]
)
self.logger = logging.getLogger(__name__)
def log_prediction(self, method: str, result: Dict[str, Any]):
"""
Log a prediction result with performance metrics.
Args:
method: Processing method name
result: Prediction result dictionary
"""
stats = self.method_stats[method]
stats['total_calls'] += 1
if result.get('success', True):
stats['predictions'].append({
'digit': result.get('predicted_digit'),
'timestamp': result.get('timestamp', time.time()),
'inference_time': result.get('inference_time', 0)
})
stats['inference_times'].append(result.get('inference_time', 0))
self.logger.info(json.dumps({
'event': 'prediction',
'method': method,
'digit': result.get('predicted_digit'),
'inference_time': result.get('inference_time'),
'timestamp': result.get('timestamp')
}))
else:
stats['total_errors'] += 1
stats['errors'].append({
'error': result.get('error'),
'timestamp': result.get('timestamp', time.time()),
'inference_time': result.get('inference_time', 0)
})
self.logger.error(json.dumps({
'event': 'error',
'method': method,
'error': result.get('error'),
'timestamp': result.get('timestamp')
}))
def get_method_stats(self, method: str) -> Dict[str, Any]:
"""
Get performance statistics for a specific method.
Args:
method: Processing method name
Returns:
Dictionary with performance statistics
"""
stats = self.method_stats[method]
inference_times = list(stats['inference_times'])
if not inference_times:
return {
'method': method,
'total_calls': stats['total_calls'],
'successful_predictions': 0,
'error_rate': 0.0,
'avg_inference_time': 0.0,
'min_inference_time': 0.0,
'max_inference_time': 0.0
}
successful_predictions = len(inference_times)
error_rate = stats['total_errors'] / stats['total_calls'] if stats['total_calls'] > 0 else 0
return {
'method': method,
'total_calls': stats['total_calls'],
'successful_predictions': successful_predictions,
'error_rate': round(error_rate * 100, 2),
'avg_inference_time': round(sum(inference_times) / len(inference_times), 3),
'min_inference_time': round(min(inference_times), 3),
'max_inference_time': round(max(inference_times), 3),
'recent_predictions': list(stats['predictions'])[-10:] # Last 10 predictions
}
def get_all_stats(self) -> Dict[str, Any]:
"""Get statistics for all processing methods."""
all_stats = {}
for method in self.method_stats.keys():
all_stats[method] = self.get_method_stats(method)
return all_stats
def get_comparison_report(self) -> str:
"""
Generate a comparison report of all processing methods.
Returns:
Formatted string with method comparison
"""
all_stats = self.get_all_stats()
if not all_stats:
return "No statistics available yet."
report = "\n=== Audio Processing Method Comparison ===\n\n"
for method, stats in all_stats.items():
report += f"Method: {method}\n"
report += f" Total Calls: {stats['total_calls']}\n"
report += f" Successful: {stats['successful_predictions']}\n"
report += f" Error Rate: {stats['error_rate']}%\n"
report += f" Avg Time: {stats['avg_inference_time']}s\n"
report += f" Min/Max: {stats['min_inference_time']}s / {stats['max_inference_time']}s\n"
report += "\n"
# Find best performing method
if len(all_stats) > 1:
best_speed = min(all_stats.items(), key=lambda x: x[1]['avg_inference_time'])
best_accuracy = min(all_stats.items(), key=lambda x: x[1]['error_rate'])
report += f"Fastest Method: {best_speed[0]} ({best_speed[1]['avg_inference_time']}s avg)\n"
report += f"Most Accurate: {best_accuracy[0]} ({best_accuracy[1]['error_rate']}% error rate)\n"
return report
def log_system_info(self, info: Dict[str, Any]):
"""Log system information for debugging."""
self.logger.info(json.dumps({
'event': 'system_info',
'timestamp': time.time(),
**info
}))
def log_audio_info(self, duration: float, format_info: Dict[str, Any]):
"""Log audio input information."""
self.logger.debug(json.dumps({
'event': 'audio_input',
'duration': duration,
'format': format_info,
'timestamp': time.time()
}))
# Global performance logger instance
performance_logger = PerformanceLogger()
def setup_flask_logging(app):
"""Setup logging configuration for Flask application."""
if not app.debug:
# Production logging
file_handler = logging.FileHandler('flask_app.log')
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s %(name)s %(message)s'
))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
app.logger.info('Audio Digit Classifier startup')