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:
2026-01-10 20:46:19 +02:00
parent ce00f9bd95
commit 32c2a7b930
34 changed files with 2766 additions and 936 deletions

View File

@@ -8,6 +8,9 @@ import time
from pathlib import Path
from typing import Dict, Optional
from datetime import datetime, timezone
from utils.logger import get_logger
logger = get_logger('autonomous')
CONTEXT_FILE = Path("memory/autonomous_context.json")
@@ -48,9 +51,9 @@ def save_autonomous_context(server_contexts: dict, server_last_action: dict):
CONTEXT_FILE.parent.mkdir(parents=True, exist_ok=True)
with open(CONTEXT_FILE, 'w') as f:
json.dump(data, f, indent=2)
print(f"💾 [V2] Saved autonomous context for {len(server_contexts)} servers")
logger.info(f"[V2] Saved autonomous context for {len(server_contexts)} servers")
except Exception as e:
print(f"⚠️ [V2] Failed to save autonomous context: {e}")
logger.error(f"[V2] Failed to save autonomous context: {e}")
def load_autonomous_context() -> tuple[Dict[int, dict], Dict[int, float]]:
@@ -63,7 +66,7 @@ def load_autonomous_context() -> tuple[Dict[int, dict], Dict[int, float]]:
- Timestamps are adjusted for elapsed time
"""
if not CONTEXT_FILE.exists():
print(" [V2] No saved context found, starting fresh")
logger.info("[V2] No saved context found, starting fresh")
return {}, {}
try:
@@ -74,7 +77,7 @@ def load_autonomous_context() -> tuple[Dict[int, dict], Dict[int, float]]:
downtime = time.time() - saved_at
downtime_minutes = downtime / 60
print(f"📂 [V2] Loading context from {downtime_minutes:.1f} minutes ago")
logger.info(f"[V2] Loading context from {downtime_minutes:.1f} minutes ago")
context_data = {}
last_action = {}
@@ -106,13 +109,13 @@ def load_autonomous_context() -> tuple[Dict[int, dict], Dict[int, float]]:
if last_action_timestamp > 0:
last_action[guild_id] = last_action_timestamp
print(f"[V2] Restored context for {len(context_data)} servers")
print(f" └─ Momentum decay factor: {decay_factor:.3f} (from {downtime_minutes:.1f}min downtime)")
logger.info(f"[V2] Restored context for {len(context_data)} servers")
logger.debug(f" └─ Momentum decay factor: {decay_factor:.3f} (from {downtime_minutes:.1f}min downtime)")
return context_data, last_action
except Exception as e:
print(f"⚠️ [V2] Failed to load autonomous context: {e}")
logger.error(f"[V2] Failed to load autonomous context: {e}")
return {}, {}