261 lines
11 KiB
Python
261 lines
11 KiB
Python
# logging_config.py
|
|
"""
|
|
THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
Configures logging for the application.
|
|
|
|
Includes a custom filter (DebugControlFilter) to control DEBUG messages based on
|
|
flags in the config module, and a setup function (setup_logging) to configure
|
|
the root logger, handlers, formatters, and apply the filter.
|
|
"""
|
|
|
|
# Standard library imports
|
|
import logging
|
|
import sys
|
|
|
|
# Local application imports
|
|
import config # For DEBUG flags and logging levels
|
|
|
|
|
|
# --- Custom Logging Filter ---
|
|
class DebugControlFilter(logging.Filter):
|
|
"""
|
|
Filters log messages based on level and specific DEBUG flags in `config`.
|
|
|
|
Allows all messages with level > DEBUG.
|
|
Filters DEBUG messages based on message prefixes and corresponding
|
|
boolean flags defined in the `config` module.
|
|
"""
|
|
|
|
def filter(self, record):
|
|
"""
|
|
Determines if the specified log record should be processed.
|
|
|
|
Args:
|
|
record (logging.LogRecord): The log record to check.
|
|
|
|
Returns:
|
|
bool: True if the record should be logged, False otherwise.
|
|
"""
|
|
# Allow levels higher than DEBUG unconditionally
|
|
if record.levelno > logging.DEBUG:
|
|
return True
|
|
|
|
# Block levels lower than DEBUG (shouldn't happen if root is DEBUG)
|
|
if record.levelno < logging.DEBUG:
|
|
return False
|
|
|
|
# --- Filter DEBUG messages based on prefixes and config flags ---
|
|
if record.levelno == logging.DEBUG:
|
|
msg = record.getMessage() # Get the formatted message content
|
|
|
|
# Check Map related prefixes first
|
|
map_prefixes = (
|
|
"[Map", # Cattura [MapTileManager], [MapIntegrationManager], [MapUtils], [MapService], [MapDisplay]
|
|
# Aggiungi altri prefissi specifici se necessario (es. da helper interni)
|
|
)
|
|
if msg.startswith(map_prefixes):
|
|
# Se il messaggio inizia con un prefisso mappa E il flag è True, mostralo
|
|
if config.DEBUG_MAP_DETAILS:
|
|
return True
|
|
else:
|
|
# Altrimenti, se il flag è False, blocca questo messaggio DEBUG mappa
|
|
return False
|
|
|
|
# Check prefixes against corresponding config flags
|
|
# App General & Lifecycle
|
|
if msg.startswith("[App Init]") and config.DEBUG_APP_LIFECYCLE:
|
|
return True
|
|
elif msg.startswith("[ImageRecorder") and config.DEBUG_IMAGE_RECORDER:
|
|
return True # Allow if ImageRecorder prefix and flag is True
|
|
elif msg.startswith("[App Shutdown]") and config.DEBUG_APP_LIFECYCLE:
|
|
return True
|
|
elif msg.startswith("[App Status]") and config.DEBUG_APP_STATUS:
|
|
return True
|
|
elif msg.startswith("[AppState") and config.DEBUG_APP_LIFECYCLE:
|
|
return True # AppState logs
|
|
elif msg.startswith("[App MainThread") and config.DEBUG_APP_LIFECYCLE:
|
|
return True # Main thread processing logs
|
|
|
|
# App Callbacks & Processing
|
|
elif msg.startswith("[App CB") and config.DEBUG_APP_CALLBACKS:
|
|
if msg.startswith("[App CB MFD Param]") and config.DEBUG_APP_MFD_PARAMS:
|
|
return True
|
|
elif not msg.startswith("[App CB MFD Param]"):
|
|
return True # Allow general CB if not MFD specific
|
|
elif msg.startswith("[App QProc") and config.DEBUG_APP_QUEUE_PROCESSING:
|
|
return True
|
|
elif msg.startswith("[App Proc") and config.DEBUG_APP_IMG_PROCESSING:
|
|
return True
|
|
|
|
# App Specific Features
|
|
elif msg.startswith("[App Test") and config.DEBUG_APP_TEST_MODE:
|
|
return True
|
|
elif msg.startswith("[App GeoCalc]") and config.DEBUG_APP_GEO_CALC:
|
|
return True
|
|
elif msg.startswith("[MFD LUT Update]") and config.DEBUG_APP_MFD_PARAMS:
|
|
return True
|
|
elif msg.startswith("[App Trigger") and config.DEBUG_APP_TRIGGER:
|
|
return True
|
|
|
|
# Map related App logs
|
|
elif msg.startswith("[App Init Map") and config.DEBUG_APP_LIFECYCLE:
|
|
return True
|
|
elif msg.startswith("[App Map Update]") and config.DEBUG_APP_LIFECYCLE:
|
|
return True
|
|
|
|
# Receiver Related
|
|
elif msg.startswith("[Receiver Loop]") and config.DEBUG_RECEIVER_LOOP:
|
|
return True
|
|
elif msg.startswith("[Receiver ACK]") and config.DEBUG_RECEIVER_ACK:
|
|
return True
|
|
elif msg.startswith("[Receiver Cleanup]") and config.DEBUG_RECEIVER_CLEANUP:
|
|
return True
|
|
elif "Rcvd: Key=" in msg and config.DEBUG_RECEIVER_PACKETS:
|
|
return True # Raw packet header
|
|
elif (
|
|
msg.startswith("[Worker")
|
|
or msg.startswith("[Receiver Reassembly]")
|
|
or "Reassembling" in msg
|
|
or "Identified" in msg
|
|
or "reassemble" in msg.lower()
|
|
or "New TX" in msg
|
|
or "All frags" in msg
|
|
or "Cleaned Key=" in msg
|
|
or "Submit" in msg
|
|
or "pixel data offset" in msg
|
|
or "cleanup" in msg.lower()
|
|
) and config.DEBUG_RECEIVER_REASSEMBLY:
|
|
return True # Reassembly logs
|
|
elif (
|
|
msg.startswith("[Geo extract]")
|
|
or "GeoInfo:" in msg
|
|
or "Invalid GeoInfo" in msg
|
|
or "Invalid SAR meta" in msg
|
|
or "Invalid MFD meta" in msg
|
|
or "GeoData extraction" in msg
|
|
) and config.DEBUG_RECEIVER_GEO:
|
|
return True # Geo extraction logs
|
|
|
|
# Display/UI Related
|
|
elif msg.startswith("[DisplayMgr]") and config.DEBUG_DISPLAY_MANAGER:
|
|
return True
|
|
elif msg.startswith("[MapDisplay]") and config.DEBUG_DISPLAY_MANAGER:
|
|
return True
|
|
elif msg.startswith("[UI Setup]") and config.DEBUG_APP_LIFECYCLE:
|
|
return True # UI creation logs
|
|
elif msg.startswith("[UI Update]") and config.DEBUG_APP_CALLBACKS:
|
|
return True # General UI updates
|
|
elif msg.startswith("[UI Status]") and config.DEBUG_APP_STATUS:
|
|
return True # Status bar updates
|
|
|
|
# Utility Modules
|
|
elif msg.startswith("[Utils") and config.DEBUG_UTILS:
|
|
return True
|
|
elif msg.startswith("[Network") and config.DEBUG_NETWORK:
|
|
return True
|
|
elif msg.startswith("[ImageProcessing") and config.DEBUG_IMAGE_PROCESSING:
|
|
return True
|
|
elif msg.startswith("[MapUtils") and config.DEBUG_UTILS:
|
|
return True
|
|
elif msg.startswith("[MapTileManager") and config.DEBUG_UTILS:
|
|
return True
|
|
elif msg.startswith("[MapService") and config.DEBUG_UTILS:
|
|
return True
|
|
|
|
# Default: Block DEBUG message if no specific flag allows it
|
|
return False
|
|
|
|
# Should not be reached if handler level > DEBUG, but return False defensively
|
|
return False
|
|
|
|
|
|
# --- Logging Setup Function ---
|
|
def setup_logging():
|
|
"""Configures the root logger for the application using DebugControlFilter."""
|
|
log_prefix = "[Log Setup]" # Prefix for this function's messages
|
|
|
|
# Check if logging is already configured (simple check based on handlers)
|
|
root_logger = logging.getLogger()
|
|
if root_logger.hasHandlers():
|
|
# Check if our specific handler/filter is already present
|
|
has_our_filter = any(
|
|
isinstance(f, DebugControlFilter)
|
|
for h in root_logger.handlers
|
|
for f in h.filters
|
|
)
|
|
if has_our_filter:
|
|
logging.debug(
|
|
f"{log_prefix} Logging seems already configured with DebugControlFilter. Skipping setup."
|
|
)
|
|
return # Avoid re-configuring if already done
|
|
|
|
# Include thread name in the log format
|
|
log_format = "%(asctime)s - %(levelname)s - [%(threadName)s] - %(filename)s:%(lineno)d - %(message)s"
|
|
log_formatter = logging.Formatter(log_format)
|
|
|
|
# Re-configure root logger if needed (e.g., level changed)
|
|
# Ensure root level is low enough to allow filter to work on DEBUG messages
|
|
root_logger.setLevel(config.LOG_ROOT_LEVEL)
|
|
|
|
# Remove existing handlers before adding new ones to prevent duplication
|
|
# (More robust reconfiguration)
|
|
# Use print here as logging might be in an intermediate state
|
|
if root_logger.handlers:
|
|
print(
|
|
f"{log_prefix} Removing existing logging handlers before reconfiguration."
|
|
)
|
|
for handler in root_logger.handlers[:]: # Iterate over a copy
|
|
root_logger.removeHandler(handler)
|
|
handler.close() # Close the handler properly
|
|
|
|
# Configure console handler
|
|
# Use stderr by default for logs? Or keep stdout? Default is stderr for StreamHandler.
|
|
console_handler = logging.StreamHandler(
|
|
sys.stdout
|
|
) # Explicitly use stdout for visibility? Or stderr?
|
|
console_handler.setLevel(config.LOG_HANDLER_LEVEL) # Use level from config
|
|
console_handler.setFormatter(log_formatter)
|
|
|
|
# Add custom filter
|
|
debug_filter = DebugControlFilter()
|
|
console_handler.addFilter(debug_filter)
|
|
|
|
# Add the configured handler to the root logger
|
|
root_logger.addHandler(console_handler)
|
|
|
|
# Use INFO level for confirmation messages after setup
|
|
logging.info(f"{log_prefix} Console log handler added and configured.")
|
|
logging.info(
|
|
f"{log_prefix} Logging configured: Root Level={logging.getLevelName(root_logger.level)}, "
|
|
f"Handler Level={logging.getLevelName(console_handler.level)}"
|
|
)
|
|
# Log status of all current debug flags
|
|
log_flags_status = (
|
|
f"{log_prefix} Debug Flags: Rcv["
|
|
f"Pkt:{config.DEBUG_RECEIVER_PACKETS},"
|
|
f"Rsm:{config.DEBUG_RECEIVER_REASSEMBLY},"
|
|
f"Geo:{config.DEBUG_RECEIVER_GEO},"
|
|
f"Loop:{config.DEBUG_RECEIVER_LOOP},"
|
|
f"Ack:{config.DEBUG_RECEIVER_ACK},"
|
|
f"Cln:{config.DEBUG_RECEIVER_CLEANUP}], "
|
|
f"App["
|
|
f"Life:{config.DEBUG_APP_LIFECYCLE},"
|
|
f"CB:{config.DEBUG_APP_CALLBACKS},"
|
|
f"Q:{config.DEBUG_APP_QUEUE_PROCESSING},"
|
|
f"Proc:{config.DEBUG_APP_IMG_PROCESSING},"
|
|
f"Test:{config.DEBUG_APP_TEST_MODE},"
|
|
f"GeoCalc:{config.DEBUG_APP_GEO_CALC},"
|
|
f"MFDParam:{config.DEBUG_APP_MFD_PARAMS},"
|
|
f"Stat:{config.DEBUG_APP_STATUS},"
|
|
f"Trig:{config.DEBUG_APP_TRIGGER}], "
|
|
f"Disp:{config.DEBUG_DISPLAY_MANAGER}, "
|
|
f"Map:{config.DEBUG_MAP_DETAILS}, "
|
|
f"Util:{config.DEBUG_UTILS}, "
|
|
f"Net:{config.DEBUG_NETWORK}, "
|
|
f"ImgProc:{config.DEBUG_IMAGE_PROCESSING}, "
|
|
f"ImgRec:{config.DEBUG_IMAGE_RECORDER}"
|
|
"]"
|
|
)
|
|
logging.info(log_flags_status)
|