feat: Implement comprehensive non-hierarchical logging system
- Created new logging infrastructure with per-component filtering - Added 6 log levels: DEBUG, INFO, API, WARNING, ERROR, CRITICAL - Implemented non-hierarchical level control (any combination can be enabled) - Migrated 917 print() statements across 31 files to structured logging - Created web UI (system.html) for runtime configuration with dark theme - Added global level controls to enable/disable levels across all components - Added timestamp format control (off/time/date/datetime options) - Implemented log rotation (10MB per file, 5 backups) - Added API endpoints for dynamic log configuration - Configured HTTP request logging with filtering via api.requests component - Intercepted APScheduler logs with proper formatting - Fixed persistence paths to use /app/memory for Docker volume compatibility - Fixed checkbox display bug in web UI (enabled_levels now properly shown) - Changed System Settings button to open in same tab instead of new window Components: bot, api, api.requests, autonomous, persona, vision, llm, conversation, mood, dm, scheduled, gpu, media, server, commands, sentiment, core, apscheduler All settings persist across container restarts via JSON config.
This commit is contained in:
@@ -14,6 +14,9 @@ import time
|
||||
from typing import Optional, Tuple
|
||||
import globals
|
||||
from utils.llm import query_llama
|
||||
from utils.logger import get_logger
|
||||
|
||||
logger = get_logger('media')
|
||||
|
||||
# Image generation detection patterns
|
||||
IMAGE_REQUEST_PATTERNS = [
|
||||
@@ -133,11 +136,11 @@ def find_latest_generated_image(prompt_id: str, expected_filename: str = None) -
|
||||
recent_threshold = time.time() - 600 # 10 minutes
|
||||
for file_path in all_files:
|
||||
if os.path.getmtime(file_path) > recent_threshold:
|
||||
print(f"🎨 Found recent image: {file_path}")
|
||||
logger.debug(f"Found recent image: {file_path}")
|
||||
return file_path
|
||||
|
||||
except Exception as e:
|
||||
print(f"⚠️ Error searching in {output_dir}: {e}")
|
||||
logger.error(f"Error searching in {output_dir}: {e}")
|
||||
continue
|
||||
|
||||
return None
|
||||
@@ -156,7 +159,7 @@ async def generate_image_with_comfyui(prompt: str) -> Optional[str]:
|
||||
# Load the workflow template
|
||||
workflow_path = "Miku_BasicWorkflow.json"
|
||||
if not os.path.exists(workflow_path):
|
||||
print(f"❌ Workflow template not found: {workflow_path}")
|
||||
logger.error(f"Workflow template not found: {workflow_path}")
|
||||
return None
|
||||
|
||||
with open(workflow_path, 'r') as f:
|
||||
@@ -186,29 +189,29 @@ async def generate_image_with_comfyui(prompt: str) -> Optional[str]:
|
||||
async with test_session.get(f"{url}/system_stats", timeout=timeout) as test_response:
|
||||
if test_response.status == 200:
|
||||
comfyui_url = url
|
||||
print(f"✅ ComfyUI found at: {url}")
|
||||
logger.debug(f"ComfyUI found at: {url}")
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
if not comfyui_url:
|
||||
print(f"❌ ComfyUI not reachable at any of: {comfyui_urls}")
|
||||
logger.error(f"ComfyUI not reachable at any of: {comfyui_urls}")
|
||||
return None
|
||||
async with aiohttp.ClientSession() as session:
|
||||
# Submit the generation request
|
||||
async with session.post(f"{comfyui_url}/prompt", json=payload) as response:
|
||||
if response.status != 200:
|
||||
print(f"❌ ComfyUI request failed: {response.status}")
|
||||
logger.error(f"ComfyUI request failed: {response.status}")
|
||||
return None
|
||||
|
||||
result = await response.json()
|
||||
prompt_id = result.get("prompt_id")
|
||||
|
||||
if not prompt_id:
|
||||
print("❌ No prompt_id received from ComfyUI")
|
||||
logger.error("No prompt_id received from ComfyUI")
|
||||
return None
|
||||
|
||||
print(f"🎨 ComfyUI generation started with prompt_id: {prompt_id}")
|
||||
logger.info(f"ComfyUI generation started with prompt_id: {prompt_id}")
|
||||
|
||||
# Poll for completion (timeout after 5 minutes)
|
||||
timeout = 300 # 5 minutes
|
||||
@@ -242,20 +245,20 @@ async def generate_image_with_comfyui(prompt: str) -> Optional[str]:
|
||||
|
||||
# Verify the file exists before returning
|
||||
if os.path.exists(image_path):
|
||||
print(f"✅ Image generated successfully: {image_path}")
|
||||
logger.info(f"Image generated successfully: {image_path}")
|
||||
return image_path
|
||||
else:
|
||||
# Try alternative paths in case of different mounting
|
||||
alt_path = os.path.join("/app/ComfyUI/output", filename)
|
||||
if os.path.exists(alt_path):
|
||||
print(f"✅ Image generated successfully: {alt_path}")
|
||||
logger.info(f"Image generated successfully: {alt_path}")
|
||||
return alt_path
|
||||
else:
|
||||
print(f"⚠️ Generated image not found at expected paths: {image_path} or {alt_path}")
|
||||
logger.warning(f"Generated image not found at expected paths: {image_path} or {alt_path}")
|
||||
continue
|
||||
|
||||
# If we couldn't find the image via API, try the fallback method
|
||||
print("🔍 Image not found via API, trying fallback method...")
|
||||
logger.debug("Image not found via API, trying fallback method...")
|
||||
fallback_image = find_latest_generated_image(prompt_id)
|
||||
if fallback_image:
|
||||
return fallback_image
|
||||
@@ -263,19 +266,19 @@ async def generate_image_with_comfyui(prompt: str) -> Optional[str]:
|
||||
# Wait before polling again
|
||||
await asyncio.sleep(2)
|
||||
|
||||
print("❌ ComfyUI generation timed out")
|
||||
logger.error("ComfyUI generation timed out")
|
||||
|
||||
# Final fallback: look for the most recent image
|
||||
print("🔍 Trying final fallback: most recent image...")
|
||||
logger.debug("Trying final fallback: most recent image...")
|
||||
fallback_image = find_latest_generated_image(prompt_id)
|
||||
if fallback_image:
|
||||
print(f"✅ Found image via fallback method: {fallback_image}")
|
||||
logger.info(f"Found image via fallback method: {fallback_image}")
|
||||
return fallback_image
|
||||
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error in generate_image_with_comfyui: {e}")
|
||||
logger.error(f"Error in generate_image_with_comfyui: {e}")
|
||||
return None
|
||||
|
||||
async def handle_image_generation_request(message, prompt: str) -> bool:
|
||||
@@ -307,7 +310,7 @@ async def handle_image_generation_request(message, prompt: str) -> bool:
|
||||
# Start typing to show we're working
|
||||
async with message.channel.typing():
|
||||
# Generate the image
|
||||
print(f"🎨 Starting image generation for prompt: {prompt}")
|
||||
logger.info(f"Starting image generation for prompt: {prompt}")
|
||||
image_path = await generate_image_with_comfyui(prompt)
|
||||
|
||||
if image_path and os.path.exists(image_path):
|
||||
@@ -322,7 +325,7 @@ async def handle_image_generation_request(message, prompt: str) -> bool:
|
||||
|
||||
await message.channel.send(completion_response, file=file)
|
||||
|
||||
print(f"✅ Image sent successfully to {message.author.display_name}")
|
||||
logger.info(f"Image sent successfully to {message.author.display_name}")
|
||||
|
||||
# Log to DM history if it's a DM
|
||||
if is_dm:
|
||||
@@ -336,11 +339,11 @@ async def handle_image_generation_request(message, prompt: str) -> bool:
|
||||
error_response = await query_llama(error_prompt, user_id=user_id, guild_id=guild_id, response_type=response_type)
|
||||
await message.channel.send(error_response)
|
||||
|
||||
print(f"❌ Image generation failed for prompt: {prompt}")
|
||||
logger.error(f"Image generation failed for prompt: {prompt}")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error in handle_image_generation_request: {e}")
|
||||
logger.error(f"Error in handle_image_generation_request: {e}")
|
||||
|
||||
# Send error message
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user