use logger
This commit is contained in:
parent
0ca2211f69
commit
e341ef423e
|
|
@ -8,6 +8,7 @@ replaced with placeholder HTML since they would make exports too large.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
|
import logging
|
||||||
import re
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, Tuple
|
from typing import Optional, Tuple
|
||||||
|
|
@ -16,6 +17,8 @@ import mimetypes
|
||||||
# Import shared media type definitions and scanner from utils to avoid duplication
|
# Import shared media type definitions and scanner from utils to avoid duplication
|
||||||
from backend.utils import MEDIA_EXTENSIONS, get_media_type, scan_notes_fast_walk
|
from backend.utils import MEDIA_EXTENSIONS, get_media_type, scan_notes_fast_walk
|
||||||
|
|
||||||
|
logger = logging.getLogger("uvicorn.error")
|
||||||
|
|
||||||
|
|
||||||
def get_media_as_base64(media_path: Path) -> Optional[Tuple[str, str]]:
|
def get_media_as_base64(media_path: Path) -> Optional[Tuple[str, str]]:
|
||||||
"""
|
"""
|
||||||
|
|
@ -41,7 +44,7 @@ def get_media_as_base64(media_path: Path) -> Optional[Tuple[str, str]]:
|
||||||
base64_data = base64.b64encode(media_data).decode('utf-8')
|
base64_data = base64.b64encode(media_data).decode('utf-8')
|
||||||
return (f"data:{mime_type};base64,{base64_data}", media_type)
|
return (f"data:{mime_type};base64,{base64_data}", media_type)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Failed to read media {media_path}: {e}")
|
logger.error("Failed to read media %s: %s", media_path, e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ facades at the bottom of this file.
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import threading
|
import threading
|
||||||
|
|
@ -21,6 +22,8 @@ from datetime import datetime, timezone
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, Iterable, List, Optional, Set, Tuple
|
from typing import Any, Dict, Iterable, List, Optional, Set, Tuple
|
||||||
|
|
||||||
|
logger = logging.getLogger("uvicorn.error")
|
||||||
|
|
||||||
|
|
||||||
# Below this many markdown files, parallel tag extraction adds more overhead
|
# Below this many markdown files, parallel tag extraction adds more overhead
|
||||||
# than it saves.
|
# than it saves.
|
||||||
|
|
@ -899,7 +902,7 @@ def on_note_saved(notes_dir: str, full_path: Path, content: str) -> None:
|
||||||
)
|
)
|
||||||
_index.update_note(record, extract_links_from_content(content), content=content)
|
_index.update_note(record, extract_links_from_content(content), content=content)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"note_index: on_note_saved failed for {full_path}: {e}")
|
logger.error("note_index: on_note_saved failed for %s: %s", full_path, e)
|
||||||
|
|
||||||
|
|
||||||
def on_note_deleted(notes_dir: str, full_path: Path) -> None:
|
def on_note_deleted(notes_dir: str, full_path: Path) -> None:
|
||||||
|
|
@ -907,7 +910,7 @@ def on_note_deleted(notes_dir: str, full_path: Path) -> None:
|
||||||
rel_path = full_path.relative_to(Path(notes_dir)).as_posix()
|
rel_path = full_path.relative_to(Path(notes_dir)).as_posix()
|
||||||
_index.remove_note(rel_path)
|
_index.remove_note(rel_path)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"note_index: on_note_deleted failed for {full_path}: {e}")
|
logger.error("note_index: on_note_deleted failed for %s: %s", full_path, e)
|
||||||
|
|
||||||
|
|
||||||
def on_note_renamed(notes_dir: str, old_full_path: Path, new_full_path: Path) -> None:
|
def on_note_renamed(notes_dir: str, old_full_path: Path, new_full_path: Path) -> None:
|
||||||
|
|
@ -918,7 +921,7 @@ def on_note_renamed(notes_dir: str, old_full_path: Path, new_full_path: Path) ->
|
||||||
new_full_path.relative_to(base).as_posix(),
|
new_full_path.relative_to(base).as_posix(),
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"note_index: on_note_renamed failed: {e}")
|
logger.error("note_index: on_note_renamed failed: %s", e)
|
||||||
|
|
||||||
|
|
||||||
def on_folder_renamed(notes_dir: str, old_full_path: Path, new_full_path: Path) -> None:
|
def on_folder_renamed(notes_dir: str, old_full_path: Path, new_full_path: Path) -> None:
|
||||||
|
|
@ -930,7 +933,7 @@ def on_folder_renamed(notes_dir: str, old_full_path: Path, new_full_path: Path)
|
||||||
new_full_path.relative_to(base).as_posix(),
|
new_full_path.relative_to(base).as_posix(),
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"note_index: on_folder_renamed failed: {e}")
|
logger.error("note_index: on_folder_renamed failed: %s", e)
|
||||||
_index.invalidate()
|
_index.invalidate()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -939,7 +942,7 @@ def on_folder_deleted(notes_dir: str, full_path: Path) -> None:
|
||||||
rel_prefix = full_path.relative_to(Path(notes_dir)).as_posix()
|
rel_prefix = full_path.relative_to(Path(notes_dir)).as_posix()
|
||||||
_index.remove_folder_prefix(rel_prefix)
|
_index.remove_folder_prefix(rel_prefix)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"note_index: on_folder_deleted failed: {e}")
|
logger.error("note_index: on_folder_deleted failed: %s", e)
|
||||||
_index.invalidate()
|
_index.invalidate()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -952,7 +955,7 @@ def populate_from_scan(
|
||||||
try:
|
try:
|
||||||
_index.bulk_set(notes_meta, folders, sources_raw)
|
_index.bulk_set(notes_meta, folders, sources_raw)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"note_index: populate_from_scan failed: {e}")
|
logger.error("note_index: populate_from_scan failed: %s", e)
|
||||||
|
|
||||||
|
|
||||||
def ensure_search_index(notes_dir: str) -> bool:
|
def ensure_search_index(notes_dir: str) -> bool:
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ Handles creating, storing, and revoking share tokens for public note access.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
import secrets
|
import secrets
|
||||||
import string
|
import string
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
@ -13,6 +14,8 @@ import threading
|
||||||
|
|
||||||
from .utils import validate_path_security
|
from .utils import validate_path_security
|
||||||
|
|
||||||
|
logger = logging.getLogger("uvicorn.error")
|
||||||
|
|
||||||
# Thread lock for safe concurrent access
|
# Thread lock for safe concurrent access
|
||||||
_lock = threading.Lock()
|
_lock = threading.Lock()
|
||||||
|
|
||||||
|
|
@ -99,7 +102,7 @@ def save_tokens(data_dir: str, tokens: Dict[str, Dict[str, Any]]) -> bool:
|
||||||
json.dump(tokens, f, indent=2, ensure_ascii=False)
|
json.dump(tokens, f, indent=2, ensure_ascii=False)
|
||||||
return True
|
return True
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
print(f"Failed to save share tokens: {e}")
|
logger.error("Failed to save share tokens: %s", e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,13 @@
|
||||||
Theme management for NoteDiscovery
|
Theme management for NoteDiscovery
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Dict
|
from typing import List, Dict
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
logger = logging.getLogger("uvicorn.error")
|
||||||
|
|
||||||
|
|
||||||
def parse_theme_metadata(theme_path: Path) -> Dict[str, str]:
|
def parse_theme_metadata(theme_path: Path) -> Dict[str, str]:
|
||||||
"""Parse theme metadata from CSS file comments"""
|
"""Parse theme metadata from CSS file comments"""
|
||||||
|
|
@ -28,7 +31,7 @@ def parse_theme_metadata(theme_path: Path) -> Dict[str, str]:
|
||||||
metadata["type"] = match.group(1)
|
metadata["type"] = match.group(1)
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error parsing theme metadata from {theme_path}: {e}")
|
logger.error("Error parsing theme metadata from %s: %s", theme_path, e)
|
||||||
|
|
||||||
return metadata
|
return metadata
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ Heavy work (backlinks, graph, full-text search, tag aggregation) is delegated
|
||||||
to the in-memory index in note_index.py.
|
to the in-memory index in note_index.py.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
|
|
@ -21,6 +22,8 @@ from datetime import datetime, timezone
|
||||||
from . import note_index
|
from . import note_index
|
||||||
from .note_index import NoteRecord, extract_links_from_content
|
from .note_index import NoteRecord, extract_links_from_content
|
||||||
|
|
||||||
|
logger = logging.getLogger("uvicorn.error")
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Pagination Support
|
# Pagination Support
|
||||||
|
|
@ -443,13 +446,13 @@ def delete_folder(notes_dir: str, folder_path: str) -> bool:
|
||||||
full_path = Path(notes_dir) / folder_path
|
full_path = Path(notes_dir) / folder_path
|
||||||
|
|
||||||
if not validate_path_security(notes_dir, full_path):
|
if not validate_path_security(notes_dir, full_path):
|
||||||
print(f"Security: Path is outside notes directory: {full_path}")
|
logger.warning("Security: Path is outside notes directory: %s", full_path)
|
||||||
return False
|
return False
|
||||||
if not full_path.exists():
|
if not full_path.exists():
|
||||||
print(f"Folder does not exist: {full_path}")
|
logger.warning("Folder does not exist: %s", full_path)
|
||||||
return False
|
return False
|
||||||
if not full_path.is_dir():
|
if not full_path.is_dir():
|
||||||
print(f"Path is not a directory: {full_path}")
|
logger.warning("Path is not a directory: %s", full_path)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
_drop_prefix_caches(full_path)
|
_drop_prefix_caches(full_path)
|
||||||
|
|
@ -458,8 +461,8 @@ def delete_folder(notes_dir: str, folder_path: str) -> bool:
|
||||||
_scan_cache_invalidate()
|
_scan_cache_invalidate()
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error deleting folder '{folder_path}': {e}")
|
logger.error("Error deleting folder '%s': %s", folder_path, e)
|
||||||
traceback.print_exc()
|
logger.error(traceback.format_exc())
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -734,7 +737,7 @@ def save_uploaded_image(
|
||||||
f.write(file_data)
|
f.write(file_data)
|
||||||
return str(full_path.relative_to(base).as_posix())
|
return str(full_path.relative_to(base).as_posix())
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
print(f"Error saving image: {e}")
|
logger.error("Error saving image: %s", e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
sanitized_name = sanitize_filename(filename)
|
sanitized_name = sanitize_filename(filename)
|
||||||
|
|
@ -746,14 +749,14 @@ def save_uploaded_image(
|
||||||
attachments_dir.mkdir(parents=True, exist_ok=True)
|
attachments_dir.mkdir(parents=True, exist_ok=True)
|
||||||
full_path = attachments_dir / final_filename
|
full_path = attachments_dir / final_filename
|
||||||
if not validate_path_security(notes_dir, full_path):
|
if not validate_path_security(notes_dir, full_path):
|
||||||
print(f"Security: Attempted to save image outside notes directory: {full_path}")
|
logger.warning("Security: Attempted to save image outside notes directory: %s", full_path)
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
with open(full_path, "wb") as f:
|
with open(full_path, "wb") as f:
|
||||||
f.write(file_data)
|
f.write(file_data)
|
||||||
return str(full_path.relative_to(base).as_posix())
|
return str(full_path.relative_to(base).as_posix())
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
print(f"Error saving image: {e}")
|
logger.error("Error saving image: %s", e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -869,8 +872,7 @@ def parse_tags(content: str) -> List[str]:
|
||||||
return sorted(list(set(tags)))
|
return sorted(list(set(tags)))
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# If parsing fails, return empty list
|
logger.error("Error parsing tags: %s", e)
|
||||||
print(f"Error parsing tags: {e}")
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -923,15 +925,14 @@ def get_templates(notes_dir: str) -> List[Dict]:
|
||||||
|
|
||||||
# Security check: ensure _templates folder is within notes directory
|
# Security check: ensure _templates folder is within notes directory
|
||||||
if not validate_path_security(notes_dir, templates_path):
|
if not validate_path_security(notes_dir, templates_path):
|
||||||
print(f"Security: Templates directory is outside notes directory: {templates_path}")
|
logger.warning("Security: Templates directory is outside notes directory: %s", templates_path)
|
||||||
return templates
|
return templates
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for template_file in templates_path.glob("*.md"):
|
for template_file in templates_path.glob("*.md"):
|
||||||
try:
|
try:
|
||||||
# Security check: ensure each template is within notes directory
|
|
||||||
if not validate_path_security(notes_dir, template_file):
|
if not validate_path_security(notes_dir, template_file):
|
||||||
print(f"Security: Skipping template outside notes directory: {template_file}")
|
logger.warning("Security: Skipping template outside notes directory: %s", template_file)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
stat = template_file.stat()
|
stat = template_file.stat()
|
||||||
|
|
@ -941,10 +942,10 @@ def get_templates(notes_dir: str) -> List[Dict]:
|
||||||
"modified": datetime.fromtimestamp(stat.st_mtime, tz=timezone.utc).isoformat()
|
"modified": datetime.fromtimestamp(stat.st_mtime, tz=timezone.utc).isoformat()
|
||||||
})
|
})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error reading template {template_file}: {e}")
|
logger.error("Error reading template %s: %s", template_file, e)
|
||||||
continue
|
continue
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error accessing templates directory: {e}")
|
logger.error("Error accessing templates directory: %s", e)
|
||||||
|
|
||||||
return sorted(templates, key=lambda x: x['name'])
|
return sorted(templates, key=lambda x: x['name'])
|
||||||
|
|
||||||
|
|
@ -967,14 +968,14 @@ def get_template_content(notes_dir: str, template_name: str) -> Optional[str]:
|
||||||
|
|
||||||
# Security check: ensure template is within notes directory
|
# Security check: ensure template is within notes directory
|
||||||
if not validate_path_security(notes_dir, template_path):
|
if not validate_path_security(notes_dir, template_path):
|
||||||
print(f"Security: Template path is outside notes directory: {template_path}")
|
logger.warning("Security: Template path is outside notes directory: %s", template_path)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(template_path, 'r', encoding='utf-8') as f:
|
with open(template_path, 'r', encoding='utf-8') as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error reading template {template_name}: {e}")
|
logger.error("Error reading template %s: %s", template_name, e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue