talk2me/test_error_logging.py
Adolfo Delorenzo 92b7c41f61 Implement proper error logging - Critical for debugging production issues
This comprehensive error logging system provides structured logging, automatic rotation, and detailed tracking for production debugging.

Key features:
- Structured JSON logging for easy parsing and analysis
- Multiple log streams: app, errors, access, security, performance
- Automatic log rotation to prevent disk space exhaustion
- Request tracing with unique IDs for debugging
- Performance metrics collection with slow request tracking
- Security event logging for suspicious activities
- Error deduplication and frequency tracking
- Full exception details with stack traces

Implementation details:
- StructuredFormatter outputs JSON-formatted logs
- ErrorLogger manages multiple specialized loggers
- Rotating file handlers prevent disk space issues
- Request context automatically included in logs
- Performance decorator tracks execution times
- Security events logged for audit trails
- Admin endpoints for log analysis

Admin endpoints:
- GET /admin/logs/errors - View recent errors and frequencies
- GET /admin/logs/performance - View performance metrics
- GET /admin/logs/security - View security events

Log types:
- talk2me.log - General application logs
- errors.log - Dedicated error logging with stack traces
- access.log - HTTP request/response logs
- security.log - Security events and suspicious activities
- performance.log - Performance metrics and timing

This provides production-grade observability critical for debugging issues, monitoring performance, and maintaining security in production environments.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-03 08:11:26 -06:00

168 lines
5.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Test script for error logging system
"""
import logging
import json
import os
import time
from error_logger import ErrorLogger, log_errors, log_performance, get_logger
def test_basic_logging():
"""Test basic logging functionality"""
print("\n=== Testing Basic Logging ===")
# Get logger
logger = get_logger('test')
# Test different log levels
logger.debug("This is a debug message")
logger.info("This is an info message")
logger.warning("This is a warning message")
logger.error("This is an error message")
print("✓ Basic logging test completed")
def test_error_logging():
"""Test error logging with exceptions"""
print("\n=== Testing Error Logging ===")
@log_errors('test.functions')
def failing_function():
raise ValueError("This is a test error")
try:
failing_function()
except ValueError:
print("✓ Error was logged")
# Check if error log exists
if os.path.exists('logs/errors.log'):
print("✓ Error log file created")
# Read last line
with open('logs/errors.log', 'r') as f:
lines = f.readlines()
if lines:
try:
error_entry = json.loads(lines[-1])
print(f"✓ Error logged with level: {error_entry.get('level')}")
print(f"✓ Error type: {error_entry.get('exception', {}).get('type')}")
except json.JSONDecodeError:
print("✗ Error log entry is not valid JSON")
else:
print("✗ Error log file not created")
def test_performance_logging():
"""Test performance logging"""
print("\n=== Testing Performance Logging ===")
@log_performance('test_operation')
def slow_function():
time.sleep(0.1) # Simulate slow operation
return "result"
result = slow_function()
print(f"✓ Function returned: {result}")
# Check performance log
if os.path.exists('logs/performance.log'):
print("✓ Performance log file created")
# Read last line
with open('logs/performance.log', 'r') as f:
lines = f.readlines()
if lines:
try:
perf_entry = json.loads(lines[-1])
duration = perf_entry.get('extra_fields', {}).get('duration_ms', 0)
print(f"✓ Performance logged with duration: {duration}ms")
except json.JSONDecodeError:
print("✗ Performance log entry is not valid JSON")
else:
print("✗ Performance log file not created")
def test_structured_logging():
"""Test structured logging format"""
print("\n=== Testing Structured Logging ===")
logger = get_logger('test.structured')
# Log with extra fields
logger.info("Structured log test", extra={
'extra_fields': {
'user_id': 123,
'action': 'test_action',
'metadata': {'key': 'value'}
}
})
# Check main log
if os.path.exists('logs/talk2me.log'):
with open('logs/talk2me.log', 'r') as f:
lines = f.readlines()
if lines:
try:
# Find our test entry
for line in reversed(lines):
entry = json.loads(line)
if entry.get('message') == 'Structured log test':
print("✓ Structured log entry found")
print(f"✓ Contains timestamp: {'timestamp' in entry}")
print(f"✓ Contains hostname: {'hostname' in entry}")
print(f"✓ Contains extra fields: {'user_id' in entry}")
break
except json.JSONDecodeError:
print("✗ Log entry is not valid JSON")
def test_log_rotation():
"""Test log rotation settings"""
print("\n=== Testing Log Rotation ===")
# Check if log files exist and their sizes
log_files = {
'talk2me.log': 'logs/talk2me.log',
'errors.log': 'logs/errors.log',
'access.log': 'logs/access.log',
'security.log': 'logs/security.log',
'performance.log': 'logs/performance.log'
}
for name, path in log_files.items():
if os.path.exists(path):
size = os.path.getsize(path)
print(f"{name}: {size} bytes")
else:
print(f"- {name}: not created yet")
def main():
"""Run all tests"""
print("Error Logging System Tests")
print("==========================")
# Create a test Flask app
from flask import Flask
app = Flask(__name__)
app.config['LOG_LEVEL'] = 'DEBUG'
app.config['FLASK_ENV'] = 'testing'
# Initialize error logger
error_logger = ErrorLogger(app)
# Run tests
test_basic_logging()
test_error_logging()
test_performance_logging()
test_structured_logging()
test_log_rotation()
print("\n✅ All tests completed!")
print("\nCheck the logs directory for generated log files:")
print("- logs/talk2me.log - Main application log")
print("- logs/errors.log - Error log with stack traces")
print("- logs/performance.log - Performance metrics")
print("- logs/access.log - HTTP access log")
print("- logs/security.log - Security events")
if __name__ == "__main__":
main()