Quick Start Tutorial - PANTHER Core Utilities¤
Introduction¤
This tutorial walks you through the essential features of PANTHER's core utilities, focusing on the logging infrastructure and feature-aware capabilities. You'll learn how to set up logging, use feature detection, and monitor your application's logging behavior.
Step 1: Basic Logger Setup¤
Let's start with the simplest possible setup:
from panther.core.utils import LoggerFactory
# Initialize the logger factory with basic configuration
LoggerFactory.initialize({
"level": "INFO",
"format": "%(asctime)s [%(levelname)s] - %(module)s - %(message)s",
"enable_colors": True
})
# Get a logger for your component
logger = LoggerFactory.get_logger("my_component")
# Use the logger
logger.info("Application started successfully")
logger.debug("This debug message won't appear (level is INFO)")
logger.warning("This is a warning message")
logger.error("This is an error message")
Expected Output:
2024-07-05 10:30:15 [INFO] - my_component - Application started successfully
2024-07-05 10:30:15 [WARNING] - my_component - This is a warning message
2024-07-05 10:30:15 [ERROR] - my_component - This is an error message
What happened? - LoggerFactory configured all loggers with consistent formatting - Colors are enabled (if your terminal supports them) - DEBUG message didn't appear because level is set to INFO - All messages follow the same format pattern
Step 2: Using Feature-Aware Logging¤
PANTHER's most powerful feature is automatic feature detection and level management:
from panther.core.utils import FeatureLoggerMixin
class DockerManager(FeatureLoggerMixin):
def __init__(self):
# Logger automatically detects this is docker-related
self.__init_logger__()
def build_container(self):
self.info("Starting container build")
self.debug("Checking Docker daemon")
self.info("Build completed successfully")
def check_feature(self):
feature = self.get_effective_feature()
self.info(f"Auto-detected feature: {feature}")
# Test the feature detection
manager = DockerManager()
manager.check_feature()
manager.build_container()
Expected Output:
2024-07-05 10:30:16 [INFO] - __main__.DockerManager - Auto-detected feature: docker_operations
2024-07-05 10:30:16 [INFO] - __main__.DockerManager - Starting container build
2024-07-05 10:30:16 [INFO] - __main__.DockerManager - Build completed successfully
What happened? - PANTHER detected "docker" in the class name - Component was automatically assigned to "docker_operations" feature - DEBUG message didn't appear (still using INFO level)
Step 3: Feature-Specific Log Levels¤
Now let's set different log levels for different features:
from panther.core.utils import LoggerFactory, FeatureLoggerMixin
# Set feature-specific levels
feature_levels = {
"docker_operations": "DEBUG", # Very detailed for Docker
"config_processing": "WARNING", # Only warnings/errors for config
"event_system": "INFO" # Standard info for events
}
LoggerFactory.update_all_feature_levels(feature_levels)
class DockerManager(FeatureLoggerMixin):
def __init__(self):
self.__init_logger__()
def build_container(self):
self.info("Starting container build")
self.debug("Checking Docker daemon") # Now this will appear!
self.debug("Reading Dockerfile") # This too!
self.info("Build completed successfully")
class ConfigLoader(FeatureLoggerMixin):
def __init__(self):
self.__init_logger__()
def load_config(self):
self.info("Loading configuration") # Won't appear (WARNING level)
self.debug("Parsing config file") # Won't appear
self.warning("Missing optional setting") # Will appear
self.info("Configuration loaded") # Won't appear
# Test both components
docker_mgr = DockerManager()
config_loader = ConfigLoader()
print("=== Docker Operations (DEBUG level) ===")
docker_mgr.build_container()
print("\n=== Config Processing (WARNING level) ===")
config_loader.load_config()
Expected Output:
=== Docker Operations (DEBUG level) ===
2024-07-05 10:30:17 [INFO] - __main__.DockerManager - Starting container build
2024-07-05 10:30:17 [DEBUG] - __main__.DockerManager - Checking Docker daemon
2024-07-05 10:30:17 [DEBUG] - __main__.DockerManager - Reading Dockerfile
2024-07-05 10:30:17 [INFO] - __main__.DockerManager - Build completed successfully
=== Config Processing (WARNING level) ===
2024-07-05 10:30:17 [WARNING] - __main__.ConfigLoader - Missing optional setting
What happened? - Docker component got DEBUG level (shows all messages) - Config component got WARNING level (only warnings and errors) - Each feature can have completely different logging verbosity
Step 4: Explicit Feature Assignment¤
Sometimes auto-detection isn't perfect. You can explicitly assign features:
from panther.core.utils import FeatureLoggerMixin, LoggerFactory
class MyCustomComponent(FeatureLoggerMixin):
def __init__(self):
# Explicitly assign to event_system feature
self.__init_logger__(feature="event_system")
def process_events(self):
feature = self.get_effective_feature()
self.info(f"Using feature: {feature}")
self.debug("Processing events") # INFO level, so won't appear
# Alternative: Get feature-specific logger directly
logger = LoggerFactory.get_feature_logger("my_component", "docker_operations")
logger.debug("This debug message will appear!") # DEBUG level from docker_operations
# Test explicit assignment
component = MyCustomComponent()
component.process_events()
Expected Output:
2024-07-05 10:30:18 [DEBUG] - my_component - This debug message will appear!
2024-07-05 10:30:18 [INFO] - __main__.MyCustomComponent - Using feature: event_system
Step 5: Statistics and Monitoring¤
Track your application's logging behavior:
from panther.core.utils import LoggerFactory
# Enable statistics collection
LoggerFactory.enable_statistics({
"enabled": True,
"buffer_size": 1000,
"track_performance": True
})
# Generate some log activity
logger = LoggerFactory.get_logger("stats_demo")
for level in ["DEBUG", "INFO", "WARNING", "ERROR"]:
for i in range(5):
getattr(logger, level.lower())(f"{level} message {i+1}")
# Check the statistics
stats = LoggerFactory.get_log_statistics()
print(f"\nLogging Statistics:")
print(f"Total messages: {stats.get('total_messages', 0)}")
print(f"Messages by level: {stats.get('level_counts', {})}")
print(f"Messages by feature: {stats.get('feature_counts', {})}")
# Generate a detailed report
report = LoggerFactory.generate_statistics_report()
print(f"\nDetailed Report:")
print(f"Collection period: {report.get('collection_period', 'Unknown')}")
print(f"Performance metrics available: {report.get('has_performance_data', False)}")
Expected Output:
2024-07-05 10:30:19 [INFO] - stats_demo - INFO message 1
2024-07-05 10:30:19 [INFO] - stats_demo - INFO message 2
... (more INFO, WARNING, ERROR messages)
Logging Statistics:
Total messages: 15
Messages by level: {'INFO': 5, 'WARNING': 5, 'ERROR': 5}
Messages by feature: {'unknown': 15}
Detailed Report:
Collection period: 2.345 seconds
Performance metrics available: True
Step 6: File Logging¤
Add file output for persistent logging:
from panther.core.utils import LoggerFactory
# Initialize with file output
LoggerFactory.initialize({
"level": "INFO",
"format": "%(asctime)s [%(levelname)s] - %(module)s - %(message)s",
"enable_colors": True,
"output_file": "/tmp/panther_tutorial.log",
"debug_file_logging": True # File gets DEBUG, console gets INFO
})
logger = LoggerFactory.get_logger("file_demo")
logger.debug("This appears in file only")
logger.info("This appears in both console and file")
logger.error("This also appears in both")
print("\nCheck /tmp/panther_tutorial.log for all messages including DEBUG")
What happened? - Console still shows INFO and above - File captures ALL messages including DEBUG - Same logger, different output destinations with different levels
Step 7: Dynamic Configuration Updates¤
Change logging behavior at runtime:
from panther.core.utils import LoggerFactory
# Start with INFO level
logger = LoggerFactory.get_logger("dynamic_demo")
logger.debug("Initial debug - won't appear")
logger.info("Initial info - will appear")
# Change to DEBUG level
LoggerFactory.update_feature_level("unknown", "DEBUG") # "unknown" is default feature
logger.debug("Updated debug - now appears!")
logger.info("Updated info - still appears")
# Change specific feature level
LoggerFactory.update_feature_level("docker_operations", "ERROR")
docker_logger = LoggerFactory.get_feature_logger("docker_test", "docker_operations")
docker_logger.info("Docker info - won't appear")
docker_logger.error("Docker error - will appear")
Expected Output:
2024-07-05 10:30:20 [INFO] - dynamic_demo - Initial info - will appear
2024-07-05 10:30:20 [DEBUG] - dynamic_demo - Updated debug - now appears!
2024-07-05 10:30:20 [INFO] - dynamic_demo - Updated info - still appears
2024-07-05 10:30:20 [ERROR] - docker_test - Docker error - will appear
Complete Example: Building a Service¤
Here's a complete example showing how to use the utilities in a real service:
from panther.core.utils import FeatureLoggerMixin, LoggerFactory
# Configure logging for the entire application
LoggerFactory.initialize({
"level": "INFO",
"format": "%(asctime)s [%(levelname)s] - %(module)s - %(message)s",
"enable_colors": True,
"output_file": "/tmp/service.log"
})
# Set feature-specific levels
LoggerFactory.update_all_feature_levels({
"docker_operations": "DEBUG",
"config_processing": "WARNING",
"event_system": "INFO"
})
# Enable monitoring
LoggerFactory.enable_statistics({"enabled": True, "track_performance": True})
class ServiceManager(FeatureLoggerMixin):
def __init__(self):
self.__init_logger__()
self.info(f"ServiceManager initialized with feature: {self.get_effective_feature()}")
def start_service(self):
self.info("Starting service")
try:
self._load_config()
self._setup_docker()
self._start_event_processing()
self.info("Service started successfully")
except Exception as e:
self.error(f"Service startup failed: {e}", exc_info=True)
def _load_config(self):
# This would be detected as config_processing (WARNING level)
config_logger = LoggerFactory.get_feature_logger("config", "config_processing")
config_logger.info("Loading config") # Won't appear
config_logger.warning("Using default for missing setting") # Will appear
def _setup_docker(self):
# This would be detected as docker_operations (DEBUG level)
docker_logger = LoggerFactory.get_feature_logger("docker", "docker_operations")
docker_logger.debug("Checking Docker daemon") # Will appear
docker_logger.info("Docker setup complete") # Will appear
def _start_event_processing(self):
# This would be detected as event_system (INFO level)
event_logger = LoggerFactory.get_feature_logger("events", "event_system")
event_logger.debug("Event loop details") # Won't appear
event_logger.info("Event processing started") # Will appear
# Run the service
service = ServiceManager()
service.start_service()
# Check final statistics
stats = LoggerFactory.get_log_statistics()
print(f"\nFinal Statistics: {stats.get('total_messages', 0)} total messages")
Next Steps¤
You now understand the core concepts:
- LoggerFactory: Centralized logger management with consistent configuration
- Feature Detection: Automatic categorization of components for targeted logging
- Dynamic Configuration: Runtime updates to logging levels
- Statistics: Monitoring and analysis of logging behavior
- File Output: Persistent logging with different console/file levels
For advanced usage, see: - Developer Guide for extending the utilities - API Reference for complete method documentation - README for architecture details and integration patterns
Try experimenting with your own components and see how the feature detection works!