Replace more print logs with proper logger usage
This commit is contained in:
parent
ac17bc8d87
commit
fe7ae29b8a
8 changed files with 131 additions and 129 deletions
|
|
@ -5,6 +5,10 @@ import sqlite3
|
|||
from typing import Dict, Any, Optional
|
||||
from cryptography.fernet import Fernet, InvalidToken
|
||||
from pathlib import Path
|
||||
from utils.logging_config import get_logger
|
||||
|
||||
|
||||
logger = get_logger("config")
|
||||
|
||||
class ConfigManager:
|
||||
def __init__(self, config_path: str = "config/config.json"):
|
||||
|
|
@ -33,7 +37,7 @@ class ConfigManager:
|
|||
# Default to project path even if it doesn't exist yet (for creation/fallback)
|
||||
self.config_path = project_path
|
||||
|
||||
print(f"ConfigManager initialized with path: {self.config_path}")
|
||||
logger.info(f"ConfigManager initialized with path: {self.config_path}")
|
||||
|
||||
self.config_data: Dict[str, Any] = {}
|
||||
self._fernet: Optional[Fernet] = None
|
||||
|
|
@ -45,7 +49,7 @@ class ConfigManager:
|
|||
else:
|
||||
self.database_path = self.base_dir / "database" / "music_library.db"
|
||||
|
||||
print(f"Database path set to: {self.database_path}")
|
||||
logger.info(f"Database path set to: {self.database_path}")
|
||||
|
||||
self.load_config(str(self.config_path))
|
||||
|
||||
|
|
@ -107,7 +111,7 @@ class ConfigManager:
|
|||
try:
|
||||
import shutil
|
||||
shutil.move(str(old_key_file), str(key_file))
|
||||
print(f"[MIGRATE] Moved encryption key to {key_file}")
|
||||
logger.info(f"Moved encryption key to {key_file}")
|
||||
except Exception:
|
||||
key_file = old_key_file # Fall back to old location
|
||||
if key_file.exists():
|
||||
|
|
@ -155,8 +159,10 @@ class ConfigManager:
|
|||
return decrypted
|
||||
except InvalidToken:
|
||||
# Key mismatch — encrypted with a different key (key file deleted/replaced)
|
||||
print(f"[ERROR] Failed to decrypt a config value — encryption key may have changed. "
|
||||
f"Re-enter credentials in Settings or restore the original .encryption_key file.")
|
||||
logger.error(
|
||||
"Failed to decrypt a config value — encryption key may have changed. "
|
||||
"Re-enter credentials in Settings or restore the original .encryption_key file."
|
||||
)
|
||||
return value
|
||||
except Exception:
|
||||
return value
|
||||
|
|
@ -243,11 +249,11 @@ class ConfigManager:
|
|||
needs_migration = True
|
||||
break
|
||||
if needs_migration:
|
||||
print("[MIGRATE] Encrypting sensitive config values at rest...")
|
||||
logger.info("Encrypting sensitive config values at rest...")
|
||||
self._save_to_database(self.config_data)
|
||||
print("[OK] Sensitive config values encrypted successfully")
|
||||
logger.info("Sensitive config values encrypted successfully")
|
||||
except Exception as e:
|
||||
print(f"[WARN] Could not migrate encryption: {e}")
|
||||
logger.warning(f"Could not migrate encryption: {e}")
|
||||
|
||||
def _ensure_database_exists(self):
|
||||
"""Ensure database file and metadata table exist"""
|
||||
|
|
@ -271,7 +277,7 @@ class ConfigManager:
|
|||
conn.commit()
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not ensure database exists: {e}")
|
||||
logger.warning(f"Could not ensure database exists: {e}")
|
||||
|
||||
def _load_from_database(self) -> Optional[Dict[str, Any]]:
|
||||
"""Load configuration from database, decrypting sensitive values."""
|
||||
|
|
@ -289,13 +295,13 @@ class ConfigManager:
|
|||
config_data = json.loads(row[0])
|
||||
# Decrypt sensitive values (gracefully handles plaintext migration)
|
||||
config_data = self._decrypt_sensitive(config_data)
|
||||
print("[OK] Configuration loaded from database")
|
||||
logger.info("Configuration loaded from database")
|
||||
return config_data
|
||||
else:
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not load config from database: {e}")
|
||||
logger.warning(f"Could not load config from database: {e}")
|
||||
return None
|
||||
finally:
|
||||
if conn:
|
||||
|
|
@ -325,7 +331,7 @@ class ConfigManager:
|
|||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: Could not save config to database: {e}")
|
||||
logger.error(f"Could not save config to database: {e}")
|
||||
return False
|
||||
finally:
|
||||
if conn:
|
||||
|
|
@ -337,12 +343,12 @@ class ConfigManager:
|
|||
if self.config_path.exists():
|
||||
with open(self.config_path, 'r') as f:
|
||||
config_data = json.load(f)
|
||||
print(f"[OK] Configuration loaded from {self.config_path}")
|
||||
logger.info(f"Configuration loaded from {self.config_path}")
|
||||
return config_data
|
||||
else:
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not load config from file: {e}")
|
||||
logger.warning(f"Could not load config from file: {e}")
|
||||
return None
|
||||
|
||||
def _get_default_config(self) -> Dict[str, Any]:
|
||||
|
|
@ -506,7 +512,7 @@ class ConfigManager:
|
|||
2. config.json (migration from file-based config)
|
||||
3. Defaults (fresh install)
|
||||
"""
|
||||
print(f"Loading configuration...")
|
||||
logger.info("Loading configuration...")
|
||||
|
||||
# Try loading from database first
|
||||
config_data = self._load_from_database()
|
||||
|
|
@ -519,30 +525,30 @@ class ConfigManager:
|
|||
return
|
||||
|
||||
# Database is empty - try migration from config.json
|
||||
print(f"Configuration not found in database. Attempting migration from: {self.config_path}")
|
||||
logger.info(f"Configuration not found in database. Attempting migration from: {self.config_path}")
|
||||
config_data = self._load_from_config_file()
|
||||
|
||||
if config_data:
|
||||
# Migrate from config.json to database
|
||||
print("[MIGRATE] Migrating configuration from config.json to database...")
|
||||
logger.info("Migrating configuration from config.json to database...")
|
||||
if self._save_to_database(config_data):
|
||||
print("[OK] Configuration migrated successfully to database.")
|
||||
logger.info("Configuration migrated successfully to database.")
|
||||
self.config_data = config_data
|
||||
return
|
||||
else:
|
||||
print("[WARN] Migration failed - using file-based config temporarily.")
|
||||
logger.warning("Migration failed - using file-based config temporarily.")
|
||||
self.config_data = config_data
|
||||
return
|
||||
|
||||
# No config.json either - use defaults
|
||||
print("[INFO] ℹ️ No existing configuration found (DB or File) - using defaults")
|
||||
logger.info("No existing configuration found (DB or File) - using defaults")
|
||||
config_data = self._get_default_config()
|
||||
|
||||
# Try to save defaults to database
|
||||
if self._save_to_database(config_data):
|
||||
print("[OK] Default configuration saved to database")
|
||||
logger.info("Default configuration saved to database")
|
||||
else:
|
||||
print("[WARN] Could not save defaults to database - using in-memory config")
|
||||
logger.warning("Could not save defaults to database - using in-memory config")
|
||||
|
||||
self.config_data = config_data
|
||||
|
||||
|
|
@ -558,14 +564,14 @@ class ConfigManager:
|
|||
|
||||
if not success:
|
||||
# Fallback: Try to save to config.json if database fails
|
||||
print("[WARN] Database save failed - attempting file fallback")
|
||||
logger.warning("Database save failed - attempting file fallback")
|
||||
try:
|
||||
self.config_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(self.config_path, 'w') as f:
|
||||
json.dump(self.config_data, f, indent=2)
|
||||
print("[OK] Configuration saved to config.json as fallback")
|
||||
logger.info("Configuration saved to config.json as fallback")
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Failed to save configuration: {e}")
|
||||
logger.error(f"Failed to save configuration: {e}")
|
||||
|
||||
def get(self, key: str, default: Any = None) -> Any:
|
||||
keys = key.split('.')
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ class AcoustIDClient:
|
|||
result = client.fingerprint_and_lookup("/path/to/audio.mp3")
|
||||
if result:
|
||||
for mbid in result['recording_mbids']:
|
||||
print(f"Match: {mbid}")
|
||||
logger.info(f"Match: {mbid}")
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@ import threading
|
|||
import time
|
||||
from collections import deque, defaultdict
|
||||
|
||||
from utils.logging_config import get_logger
|
||||
|
||||
|
||||
logger = get_logger("api_call_tracker")
|
||||
|
||||
|
||||
# Known rate limits per service (calls/minute)
|
||||
RATE_LIMITS = {
|
||||
|
|
@ -281,7 +286,7 @@ class ApiCallTracker:
|
|||
with open(_PERSIST_PATH, 'w') as f:
|
||||
json.dump({'ts': now, 'history': data, 'events': events}, f)
|
||||
except Exception as e:
|
||||
print(f"[ApiCallTracker] Failed to save history: {e}")
|
||||
logger.error(f"[ApiCallTracker] Failed to save history: {e}")
|
||||
|
||||
def _load(self):
|
||||
"""Restore 24h minute history from disk. Called on init."""
|
||||
|
|
@ -305,9 +310,9 @@ class ApiCallTracker:
|
|||
for e in events:
|
||||
if e.get('ts', 0) >= cutoff:
|
||||
self._events.append(e)
|
||||
print(f"[ApiCallTracker] Restored history for {len(history)} services, {len(events)} events")
|
||||
logger.info(f"[ApiCallTracker] Restored history for {len(history)} services, {len(events)} events")
|
||||
except Exception as e:
|
||||
print(f"[ApiCallTracker] Failed to load history: {e}")
|
||||
logger.error(f"[ApiCallTracker] Failed to load history: {e}")
|
||||
|
||||
|
||||
# Singleton instance
|
||||
|
|
|
|||
|
|
@ -421,7 +421,7 @@ class MusicMatchingEngine:
|
|||
|
||||
if is_likely_album and 4 <= len(potential_album_part) <= 30:
|
||||
cleaned_title = re.sub(dash_pattern, '', track_title).strip()
|
||||
print(f"Heuristic album detection: '{original_title}' → '{cleaned_title}' (removed: '{potential_album_part}')")
|
||||
logger.debug(f"Heuristic album detection: '{original_title}' → '{cleaned_title}' (removed: '{potential_album_part}')")
|
||||
return cleaned_title, True
|
||||
|
||||
return track_title, False
|
||||
|
|
@ -1004,13 +1004,13 @@ class MusicMatchingEngine:
|
|||
|
||||
# Debug logging for troubleshooting
|
||||
if scored_results and not confident_results:
|
||||
print(f"DEBUG: Found {len(scored_results)} scored results but none met confidence threshold 0.58")
|
||||
logger.debug(f"Found {len(scored_results)} scored results but none met confidence threshold 0.58")
|
||||
for i, result in enumerate(sorted_results[:3]): # Show top 3
|
||||
print(f" {i+1}. {result.confidence:.3f} - {getattr(result, 'version_type', 'unknown')} - {result.filename[:60]}...")
|
||||
logger.debug(f" {i+1}. {result.confidence:.3f} - {getattr(result, 'version_type', 'unknown')} - {result.filename[:60]}...")
|
||||
elif confident_results:
|
||||
print(f"DEBUG: {len(confident_results)} results passed confidence threshold 0.58")
|
||||
logger.debug(f"{len(confident_results)} results passed confidence threshold 0.58")
|
||||
for i, result in enumerate(confident_results[:3]): # Show top 3
|
||||
print(f" {i+1}. {result.confidence:.3f} - {getattr(result, 'version_type', 'unknown')} - {result.filename[:60]}...")
|
||||
logger.debug(f" {i+1}. {result.confidence:.3f} - {getattr(result, 'version_type', 'unknown')} - {result.filename[:60]}...")
|
||||
|
||||
return confident_results
|
||||
|
||||
|
|
|
|||
|
|
@ -1045,7 +1045,7 @@ def check_album_completion(
|
|||
if total_tracks == 0 and album_id:
|
||||
logger.debug("No track count found for '%s' (%s)", album_name, album_id)
|
||||
|
||||
print(f"Checking album: '{album_name}' ({total_tracks} tracks)")
|
||||
logger.debug(f"Checking album: '{album_name}' ({total_tracks} tracks)")
|
||||
|
||||
formats = []
|
||||
# Check if album exists in database with completeness info
|
||||
|
|
@ -1060,7 +1060,7 @@ def check_album_completion(
|
|||
server_source=active_server
|
||||
)
|
||||
except Exception as db_error:
|
||||
print(f"Database error for album '{album_name}': {db_error}")
|
||||
logger.error(f"Database error for album '{album_name}': {db_error}")
|
||||
return {
|
||||
"id": album_id,
|
||||
"name": album_name,
|
||||
|
|
@ -1088,7 +1088,7 @@ def check_album_completion(
|
|||
else:
|
||||
status = "missing"
|
||||
|
||||
print(f" Result: {owned_tracks}/{expected_tracks or total_tracks} tracks ({completion_percentage:.1f}%) - {status}")
|
||||
logger.debug(f" Result: {owned_tracks}/{expected_tracks or total_tracks} tracks ({completion_percentage:.1f}%) - {status}")
|
||||
|
||||
return {
|
||||
"id": album_id,
|
||||
|
|
@ -1103,7 +1103,7 @@ def check_album_completion(
|
|||
}
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error checking album completion for '{album_data.get('name', 'Unknown')}': {e}")
|
||||
logger.error(f"Error checking album completion for '{album_data.get('name', 'Unknown')}': {e}")
|
||||
return {
|
||||
"id": album_data.get('id', ''),
|
||||
"name": album_data.get('name', 'Unknown'),
|
||||
|
|
@ -1137,7 +1137,7 @@ def check_single_completion(
|
|||
if total_tracks == 0:
|
||||
total_tracks = _resolve_completion_track_total(single_data, source_chain) or 1
|
||||
|
||||
print(f"Checking {album_type}: '{single_name}' ({total_tracks} tracks)")
|
||||
logger.debug(f"Checking {album_type}: '{single_name}' ({total_tracks} tracks)")
|
||||
|
||||
if album_type == 'ep' or total_tracks > 1:
|
||||
try:
|
||||
|
|
@ -1151,7 +1151,7 @@ def check_single_completion(
|
|||
server_source=active_server
|
||||
)
|
||||
except Exception as db_error:
|
||||
print(f"Database error for EP '{single_name}': {db_error}")
|
||||
logger.error(f"Database error for EP '{single_name}': {db_error}")
|
||||
owned_tracks, expected_tracks, confidence = 0, total_tracks, 0.0
|
||||
db_album = None
|
||||
|
||||
|
|
@ -1167,7 +1167,7 @@ def check_single_completion(
|
|||
else:
|
||||
status = "missing"
|
||||
|
||||
print(f" EP Result: {owned_tracks}/{expected_tracks or total_tracks} tracks ({completion_percentage:.1f}%) - {status}")
|
||||
logger.debug(f" EP Result: {owned_tracks}/{expected_tracks or total_tracks} tracks ({completion_percentage:.1f}%) - {status}")
|
||||
|
||||
return {
|
||||
"id": single_id,
|
||||
|
|
@ -1192,7 +1192,7 @@ def check_single_completion(
|
|||
server_source=active_server
|
||||
)
|
||||
except Exception as db_error:
|
||||
print(f"Database error for single '{single_name}': {db_error}")
|
||||
logger.error(f"Database error for single '{single_name}': {db_error}")
|
||||
db_track, confidence = None, 0.0
|
||||
|
||||
owned_tracks = 1 if db_track else 0
|
||||
|
|
@ -1208,7 +1208,7 @@ def check_single_completion(
|
|||
elif ext:
|
||||
formats = [ext]
|
||||
|
||||
print(f" Single Result: {owned_tracks}/1 tracks ({completion_percentage:.1f}%) - {status}")
|
||||
logger.debug(f" Single Result: {owned_tracks}/1 tracks ({completion_percentage:.1f}%) - {status}")
|
||||
|
||||
return {
|
||||
"id": single_id,
|
||||
|
|
@ -1224,7 +1224,7 @@ def check_single_completion(
|
|||
}
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error checking single/EP completion for '{single_data.get('name', 'Unknown')}': {e}")
|
||||
logger.error(f"Error checking single/EP completion for '{single_data.get('name', 'Unknown')}': {e}")
|
||||
return {
|
||||
"id": single_data.get('id', ''),
|
||||
"name": single_data.get('name', 'Unknown'),
|
||||
|
|
|
|||
|
|
@ -1,12 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Reports basic system info — useful for debugging Docker setups."""
|
||||
import logging
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
|
||||
print(f"Platform: {platform.system()} {platform.release()}")
|
||||
print(f"Python: {platform.python_version()}")
|
||||
print(f"Working Dir: {os.getcwd()}")
|
||||
if not logging.getLogger().handlers:
|
||||
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
||||
|
||||
logger = logging.getLogger("system_info")
|
||||
|
||||
logger.info(f"Platform: {platform.system()} {platform.release()}")
|
||||
logger.info(f"Python: {platform.python_version()}")
|
||||
logger.info(f"Working Dir: {os.getcwd()}")
|
||||
|
||||
# Disk usage for common SoulSync paths
|
||||
for path in ['/app/downloads', '/app/Transfer', '/app/data', './downloads', './Transfer']:
|
||||
|
|
@ -14,4 +20,4 @@ for path in ['/app/downloads', '/app/Transfer', '/app/data', './downloads', './T
|
|||
usage = shutil.disk_usage(path)
|
||||
free_gb = usage.free / (1024**3)
|
||||
total_gb = usage.total / (1024**3)
|
||||
print(f"Disk {path}: {free_gb:.1f} GB free / {total_gb:.1f} GB total")
|
||||
logger.info(f"Disk {path}: {free_gb:.1f} GB free / {total_gb:.1f} GB total")
|
||||
|
|
|
|||
|
|
@ -7,14 +7,12 @@ Run this script to identify issues with iTunes data population:
|
|||
- Discovery pool tracks by source
|
||||
- Recent albums by source
|
||||
- Curated playlists status
|
||||
|
||||
Usage:
|
||||
python tools/diagnose_itunes_discover.py
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Add parent directory to path for imports
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
|
@ -22,36 +20,42 @@ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|||
from database.music_database import MusicDatabase
|
||||
|
||||
|
||||
if not logging.getLogger().handlers:
|
||||
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
||||
|
||||
logger = logging.getLogger("diagnose_itunes_discover")
|
||||
|
||||
|
||||
def _section(title: str) -> None:
|
||||
logger.info("")
|
||||
logger.info(title)
|
||||
logger.info("-" * 40)
|
||||
|
||||
|
||||
def diagnose_itunes_discover():
|
||||
"""Run diagnostic checks for iTunes discover data."""
|
||||
|
||||
print("=" * 60)
|
||||
print("iTunes Discover Page Diagnostic Report")
|
||||
print("=" * 60)
|
||||
logger.info("=" * 60)
|
||||
logger.info("iTunes Discover Page Diagnostic Report")
|
||||
logger.info("=" * 60)
|
||||
|
||||
db = MusicDatabase()
|
||||
|
||||
# 1. Check Similar Artists
|
||||
print("\n[1] SIMILAR ARTISTS")
|
||||
print("-" * 40)
|
||||
|
||||
_section("[1] SIMILAR ARTISTS")
|
||||
try:
|
||||
with db._get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Total similar artists
|
||||
cursor.execute("SELECT COUNT(*) as total FROM similar_artists")
|
||||
total = cursor.fetchone()['total']
|
||||
|
||||
# With iTunes IDs
|
||||
cursor.execute("SELECT COUNT(*) as count FROM similar_artists WHERE similar_artist_itunes_id IS NOT NULL")
|
||||
with_itunes = cursor.fetchone()['count']
|
||||
|
||||
# With Spotify IDs
|
||||
cursor.execute("SELECT COUNT(*) as count FROM similar_artists WHERE similar_artist_spotify_id IS NOT NULL")
|
||||
with_spotify = cursor.fetchone()['count']
|
||||
|
||||
# With both
|
||||
cursor.execute("""
|
||||
SELECT COUNT(*) as count FROM similar_artists
|
||||
WHERE similar_artist_itunes_id IS NOT NULL
|
||||
|
|
@ -59,34 +63,29 @@ def diagnose_itunes_discover():
|
|||
""")
|
||||
with_both = cursor.fetchone()['count']
|
||||
|
||||
print(f" Total similar artists: {total}")
|
||||
print(f" With iTunes ID: {with_itunes} ({100*with_itunes/total:.1f}%)" if total > 0 else " With iTunes ID: 0")
|
||||
print(f" With Spotify ID: {with_spotify} ({100*with_spotify/total:.1f}%)" if total > 0 else " With Spotify ID: 0")
|
||||
print(f" With BOTH IDs: {with_both} ({100*with_both/total:.1f}%)" if total > 0 else " With BOTH IDs: 0")
|
||||
logger.info(f" Total similar artists: {total}")
|
||||
logger.info(f" With iTunes ID: {with_itunes} ({100 * with_itunes / total:.1f}%)" if total > 0 else " With iTunes ID: 0")
|
||||
logger.info(f" With Spotify ID: {with_spotify} ({100 * with_spotify / total:.1f}%)" if total > 0 else " With Spotify ID: 0")
|
||||
logger.info(f" With BOTH IDs: {with_both} ({100 * with_both / total:.1f}%)" if total > 0 else " With BOTH IDs: 0")
|
||||
|
||||
if with_itunes == 0 and total > 0:
|
||||
print(" [CRITICAL] No similar artists have iTunes IDs - Hero section will be empty!")
|
||||
logger.critical("No similar artists have iTunes IDs - Hero section will be empty!")
|
||||
elif with_itunes < total * 0.5:
|
||||
print(" [WARNING] Less than 50% of similar artists have iTunes IDs")
|
||||
logger.warning("Less than 50% of similar artists have iTunes IDs")
|
||||
else:
|
||||
print(" [OK] iTunes coverage is adequate")
|
||||
|
||||
logger.info("iTunes coverage is adequate")
|
||||
except Exception as e:
|
||||
print(f" [ERROR] Could not check similar artists: {e}")
|
||||
logger.error(f"Could not check similar artists: {e}")
|
||||
|
||||
# 2. Check Discovery Pool
|
||||
print("\n[2] DISCOVERY POOL")
|
||||
print("-" * 40)
|
||||
|
||||
_section("[2] DISCOVERY POOL")
|
||||
try:
|
||||
with db._get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Total tracks
|
||||
cursor.execute("SELECT COUNT(*) as total FROM discovery_pool")
|
||||
total = cursor.fetchone()['total']
|
||||
|
||||
# By source
|
||||
cursor.execute("""
|
||||
SELECT source, COUNT(*) as count
|
||||
FROM discovery_pool
|
||||
|
|
@ -94,33 +93,28 @@ def diagnose_itunes_discover():
|
|||
""")
|
||||
source_counts = {row['source']: row['count'] for row in cursor.fetchall()}
|
||||
|
||||
print(f" Total tracks: {total}")
|
||||
print(f" Spotify tracks: {source_counts.get('spotify', 0)}")
|
||||
print(f" iTunes tracks: {source_counts.get('itunes', 0)}")
|
||||
logger.info(f" Total tracks: {total}")
|
||||
logger.info(f" Spotify tracks: {source_counts.get('spotify', 0)}")
|
||||
logger.info(f" iTunes tracks: {source_counts.get('itunes', 0)}")
|
||||
|
||||
if source_counts.get('itunes', 0) == 0 and total > 0:
|
||||
print(" [CRITICAL] No iTunes tracks in discovery pool - Fresh Tape/Archives will be empty!")
|
||||
logger.critical("No iTunes tracks in discovery pool - Fresh Tape/Archives will be empty!")
|
||||
elif source_counts.get('itunes', 0) < total * 0.3:
|
||||
print(" [WARNING] Low iTunes track count in discovery pool")
|
||||
logger.warning("Low iTunes track count in discovery pool")
|
||||
else:
|
||||
print(" [OK] iTunes tracks present")
|
||||
|
||||
logger.info("iTunes tracks present")
|
||||
except Exception as e:
|
||||
print(f" [ERROR] Could not check discovery pool: {e}")
|
||||
logger.error(f"Could not check discovery pool: {e}")
|
||||
|
||||
# 3. Check Recent Albums
|
||||
print("\n[3] RECENT ALBUMS CACHE")
|
||||
print("-" * 40)
|
||||
|
||||
_section("[3] RECENT ALBUMS CACHE")
|
||||
try:
|
||||
with db._get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Total albums
|
||||
cursor.execute("SELECT COUNT(*) as total FROM discovery_recent_albums")
|
||||
total = cursor.fetchone()['total']
|
||||
|
||||
# By source
|
||||
cursor.execute("""
|
||||
SELECT source, COUNT(*) as count
|
||||
FROM discovery_recent_albums
|
||||
|
|
@ -128,24 +122,21 @@ def diagnose_itunes_discover():
|
|||
""")
|
||||
source_counts = {row['source']: row['count'] for row in cursor.fetchall()}
|
||||
|
||||
print(f" Total recent albums: {total}")
|
||||
print(f" Spotify albums: {source_counts.get('spotify', 0)}")
|
||||
print(f" iTunes albums: {source_counts.get('itunes', 0)}")
|
||||
logger.info(f" Total recent albums: {total}")
|
||||
logger.info(f" Spotify albums: {source_counts.get('spotify', 0)}")
|
||||
logger.info(f" iTunes albums: {source_counts.get('itunes', 0)}")
|
||||
|
||||
if source_counts.get('itunes', 0) == 0 and total > 0:
|
||||
print(" [CRITICAL] No iTunes albums cached - Recent Releases section will be empty!")
|
||||
logger.critical("No iTunes albums cached - Recent Releases section will be empty!")
|
||||
elif source_counts.get('itunes', 0) < 5:
|
||||
print(" [WARNING] Very few iTunes albums cached")
|
||||
logger.warning("Very few iTunes albums cached")
|
||||
else:
|
||||
print(" [OK] iTunes albums cached")
|
||||
|
||||
logger.info("iTunes albums cached")
|
||||
except Exception as e:
|
||||
print(f" [ERROR] Could not check recent albums: {e}")
|
||||
logger.error(f"Could not check recent albums: {e}")
|
||||
|
||||
# 4. Check Curated Playlists
|
||||
print("\n[4] CURATED PLAYLISTS")
|
||||
print("-" * 40)
|
||||
|
||||
_section("[4] CURATED PLAYLISTS")
|
||||
try:
|
||||
with db._get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
|
|
@ -156,7 +147,7 @@ def diagnose_itunes_discover():
|
|||
'release_radar_itunes',
|
||||
'discovery_weekly',
|
||||
'discovery_weekly_spotify',
|
||||
'discovery_weekly_itunes'
|
||||
'discovery_weekly_itunes',
|
||||
]
|
||||
|
||||
for playlist_type in playlists_to_check:
|
||||
|
|
@ -174,9 +165,8 @@ def diagnose_itunes_discover():
|
|||
else:
|
||||
status = "[NOT FOUND]"
|
||||
|
||||
print(f" {playlist_type}: {status}")
|
||||
logger.info(f" {playlist_type}: {status}")
|
||||
|
||||
# Check iTunes-specific playlists
|
||||
cursor.execute("""
|
||||
SELECT track_ids_json FROM discovery_curated_playlists
|
||||
WHERE playlist_type = 'release_radar_itunes'
|
||||
|
|
@ -190,49 +180,43 @@ def diagnose_itunes_discover():
|
|||
itunes_dw = cursor.fetchone()
|
||||
|
||||
if not itunes_rr or len(json.loads(itunes_rr['track_ids_json'])) == 0:
|
||||
print("\n [CRITICAL] release_radar_itunes is empty or missing!")
|
||||
logger.critical("release_radar_itunes is empty or missing!")
|
||||
if not itunes_dw or len(json.loads(itunes_dw['track_ids_json'])) == 0:
|
||||
print(" [CRITICAL] discovery_weekly_itunes is empty or missing!")
|
||||
|
||||
logger.critical("discovery_weekly_itunes is empty or missing!")
|
||||
except Exception as e:
|
||||
print(f" [ERROR] Could not check curated playlists: {e}")
|
||||
logger.error(f"Could not check curated playlists: {e}")
|
||||
|
||||
# 5. Check Watchlist Artists
|
||||
print("\n[5] WATCHLIST ARTISTS")
|
||||
print("-" * 40)
|
||||
|
||||
_section("[5] WATCHLIST ARTISTS")
|
||||
try:
|
||||
with db._get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Total artists
|
||||
cursor.execute("SELECT COUNT(*) as total FROM watchlist_artists")
|
||||
total = cursor.fetchone()['total']
|
||||
|
||||
# With iTunes IDs
|
||||
cursor.execute("SELECT COUNT(*) as count FROM watchlist_artists WHERE itunes_artist_id IS NOT NULL")
|
||||
with_itunes = cursor.fetchone()['count']
|
||||
|
||||
# With Spotify IDs
|
||||
cursor.execute("SELECT COUNT(*) as count FROM watchlist_artists WHERE spotify_artist_id IS NOT NULL")
|
||||
with_spotify = cursor.fetchone()['count']
|
||||
|
||||
print(f" Total watchlist artists: {total}")
|
||||
print(f" With iTunes ID: {with_itunes} ({100*with_itunes/total:.1f}%)" if total > 0 else " With iTunes ID: 0")
|
||||
print(f" With Spotify ID: {with_spotify} ({100*with_spotify/total:.1f}%)" if total > 0 else " With Spotify ID: 0")
|
||||
logger.info(f" Total watchlist artists: {total}")
|
||||
logger.info(f" With iTunes ID: {with_itunes} ({100 * with_itunes / total:.1f}%)" if total > 0 else " With iTunes ID: 0")
|
||||
logger.info(f" With Spotify ID: {with_spotify} ({100 * with_spotify / total:.1f}%)" if total > 0 else " With Spotify ID: 0")
|
||||
|
||||
if with_itunes == 0 and total > 0:
|
||||
print(" [WARNING] No watchlist artists have iTunes IDs - source artist data limited")
|
||||
|
||||
logger.warning("No watchlist artists have iTunes IDs - source artist data limited")
|
||||
except Exception as e:
|
||||
print(f" [ERROR] Could not check watchlist artists: {e}")
|
||||
logger.error(f"Could not check watchlist artists: {e}")
|
||||
|
||||
# Summary
|
||||
print("\n" + "=" * 60)
|
||||
print("SUMMARY & RECOMMENDED ACTIONS")
|
||||
print("=" * 60)
|
||||
print("""
|
||||
If you see [CRITICAL] or [WARNING] messages above, follow these steps:
|
||||
logger.info("")
|
||||
logger.info("=" * 60)
|
||||
logger.info("SUMMARY & RECOMMENDED ACTIONS")
|
||||
logger.info("=" * 60)
|
||||
logger.info(
|
||||
"""
|
||||
If you see critical or warning messages above, follow these steps:
|
||||
|
||||
QUICK FIX - Force Refresh Discover Data:
|
||||
-----------------------------------------
|
||||
|
|
@ -263,7 +247,8 @@ ROOT CAUSE NOTES:
|
|||
|
||||
The discover page will now fall back to watchlist artists if similar
|
||||
artists are not available, so basic functionality should still work.
|
||||
""")
|
||||
""".strip()
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ def set_log_level(level: str) -> bool:
|
|||
root_logger.info(f"Log level changed to: {level.upper()}")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Error setting log level: {e}")
|
||||
logging.getLogger("newmusic").error(f"Error setting log level: {e}")
|
||||
return False
|
||||
|
||||
def get_current_log_level() -> str:
|
||||
|
|
@ -117,4 +117,4 @@ def get_current_log_level() -> str:
|
|||
root_logger = logging.getLogger("newmusic")
|
||||
return logging.getLevelName(root_logger.level)
|
||||
|
||||
main_logger = get_logger("main")
|
||||
main_logger = get_logger("main")
|
||||
|
|
|
|||
Loading…
Reference in a new issue