mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-09 03:04:54 -04:00
feat(backend): ➕ Add Rich for Development Logging
This commit is contained in:
parent
9386cc320b
commit
cb85b14e01
@ -1,4 +1,3 @@
|
|||||||
from mealie.services.recipe.all_recipes import subscripte_to_recipe_events
|
|
||||||
import uvicorn
|
import uvicorn
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from fastapi.middleware.gzip import GZipMiddleware
|
from fastapi.middleware.gzip import GZipMiddleware
|
||||||
@ -15,6 +14,7 @@ from mealie.routes.shopping_list import shopping_list_router
|
|||||||
from mealie.routes.site_settings import settings_router
|
from mealie.routes.site_settings import settings_router
|
||||||
from mealie.routes.users import user_router
|
from mealie.routes.users import user_router
|
||||||
from mealie.services.events import create_general_event
|
from mealie.services.events import create_general_event
|
||||||
|
from mealie.services.recipe.all_recipes import subscripte_to_recipe_events
|
||||||
|
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
@ -86,7 +86,6 @@ def system_startup():
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
uvicorn.run(
|
uvicorn.run(
|
||||||
"app:app",
|
"app:app",
|
||||||
host="0.0.0.0",
|
host="0.0.0.0",
|
||||||
@ -94,7 +93,8 @@ def main():
|
|||||||
reload=True,
|
reload=True,
|
||||||
reload_dirs=["mealie"],
|
reload_dirs=["mealie"],
|
||||||
debug=True,
|
debug=True,
|
||||||
log_level="info",
|
log_level="debug",
|
||||||
|
use_colors=True,
|
||||||
log_config=None,
|
log_config=None,
|
||||||
workers=1,
|
workers=1,
|
||||||
forwarded_allow_ips="*",
|
forwarded_allow_ips="*",
|
||||||
|
@ -1,36 +1,66 @@
|
|||||||
import logging
|
import logging
|
||||||
import sys
|
from dataclasses import dataclass
|
||||||
|
from functools import lru_cache
|
||||||
|
|
||||||
from mealie.core.config import DATA_DIR
|
from mealie.core.config import DATA_DIR
|
||||||
|
|
||||||
|
from .config import settings
|
||||||
|
|
||||||
LOGGER_FILE = DATA_DIR.joinpath("mealie.log")
|
LOGGER_FILE = DATA_DIR.joinpath("mealie.log")
|
||||||
DATE_FORMAT = "%d-%b-%y %H:%M:%S"
|
DATE_FORMAT = "%d-%b-%y %H:%M:%S"
|
||||||
LOGGER_FORMAT = "%(levelname)s: %(asctime)s \t%(message)s"
|
LOGGER_FORMAT = "%(levelname)s: %(asctime)s \t%(message)s"
|
||||||
|
LOGGER_HANDLER = None
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO, format=LOGGER_FORMAT, datefmt="%d-%b-%y %H:%M:%S")
|
|
||||||
|
@dataclass
|
||||||
|
class LoggerConfig:
|
||||||
|
handlers: list
|
||||||
|
format: str
|
||||||
|
date_format: str
|
||||||
|
logger_file: str
|
||||||
|
level: str = logging.INFO
|
||||||
|
|
||||||
|
|
||||||
|
@lru_cache
|
||||||
|
def get_logger_config():
|
||||||
|
if not settings.PRODUCTION:
|
||||||
|
from rich.logging import RichHandler
|
||||||
|
|
||||||
|
return LoggerConfig(
|
||||||
|
handlers=[RichHandler(rich_tracebacks=True)],
|
||||||
|
format=None,
|
||||||
|
date_format=None,
|
||||||
|
logger_file=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
return LoggerConfig(
|
||||||
|
handlers=[
|
||||||
|
logging.FileHandler(LOGGER_FILE),
|
||||||
|
logging.Formatter(LOGGER_FORMAT, datefmt=DATE_FORMAT),
|
||||||
|
],
|
||||||
|
format="%(levelname)s: %(asctime)s \t%(message)s",
|
||||||
|
date_format="%d-%b-%y %H:%M:%S",
|
||||||
|
logger_file=LOGGER_FILE,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
logger_config = get_logger_config()
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logger_config.level,
|
||||||
|
format=logger_config.format,
|
||||||
|
datefmt=logger_config.date_format,
|
||||||
|
handlers=logger_config.handlers,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def logger_init() -> logging.Logger:
|
def logger_init() -> logging.Logger:
|
||||||
""" Returns the Root Loggin Object for Mealie """
|
""" Returns the Root Loggin Object for Mealie """
|
||||||
logger = logging.getLogger("mealie")
|
return logging.getLogger("mealie")
|
||||||
logger.propagate = False
|
|
||||||
|
|
||||||
# File Handler
|
|
||||||
output_file_handler = logging.FileHandler(LOGGER_FILE)
|
|
||||||
handler_format = logging.Formatter(LOGGER_FORMAT, datefmt=DATE_FORMAT)
|
|
||||||
output_file_handler.setFormatter(handler_format)
|
|
||||||
|
|
||||||
# Stdout
|
|
||||||
stdout_handler = logging.StreamHandler(sys.stdout)
|
|
||||||
stdout_handler.setFormatter(handler_format)
|
|
||||||
|
|
||||||
logger.addHandler(output_file_handler)
|
|
||||||
logger.addHandler(stdout_handler)
|
|
||||||
|
|
||||||
return logger
|
|
||||||
|
|
||||||
|
|
||||||
root_logger = logger_init()
|
root_logger = logger_init()
|
||||||
|
root_logger.info("Testing Root Logger")
|
||||||
|
|
||||||
|
|
||||||
def get_logger(module=None) -> logging.Logger:
|
def get_logger(module=None) -> logging.Logger:
|
||||||
|
@ -92,11 +92,9 @@ class _Recipes(BaseDocument):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def subscribe(self, func: Callable) -> None:
|
def subscribe(self, func: Callable) -> None:
|
||||||
print("Subscripe", func)
|
|
||||||
self.observers.append(func)
|
self.observers.append(func)
|
||||||
|
|
||||||
def update_observers(self) -> None:
|
def update_observers(self) -> None:
|
||||||
print("Updating Observers", self.observers)
|
|
||||||
for observer in self.observers:
|
for observer in self.observers:
|
||||||
observer()
|
observer()
|
||||||
|
|
||||||
|
@ -21,19 +21,16 @@ class BaseDocument:
|
|||||||
def get_all(
|
def get_all(
|
||||||
self, session: Session, limit: int = None, order_by: str = None, start=0, end=9999, override_schema=None
|
self, session: Session, limit: int = None, order_by: str = None, start=0, end=9999, override_schema=None
|
||||||
) -> list[dict]:
|
) -> list[dict]:
|
||||||
logger.info("Starting Query")
|
|
||||||
eff_schema = override_schema or self.schema
|
eff_schema = override_schema or self.schema
|
||||||
|
|
||||||
if order_by:
|
if order_by:
|
||||||
order_attr = getattr(self.sql_model, str(order_by))
|
order_attr = getattr(self.sql_model, str(order_by))
|
||||||
logger.info("Ending Query")
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
eff_schema.from_orm(x)
|
eff_schema.from_orm(x)
|
||||||
for x in session.query(self.sql_model).order_by(order_attr.desc()).offset(start).limit(limit).all()
|
for x in session.query(self.sql_model).order_by(order_attr.desc()).offset(start).limit(limit).all()
|
||||||
]
|
]
|
||||||
|
|
||||||
logger.info("Ending Query")
|
|
||||||
return [eff_schema.from_orm(x) for x in session.query(self.sql_model).offset(start).limit(limit).all()]
|
return [eff_schema.from_orm(x) for x in session.query(self.sql_model).offset(start).limit(limit).all()]
|
||||||
|
|
||||||
def get_all_limit_columns(self, session: Session, fields: list[str], limit: int = None) -> list[SqlAlchemyBase]:
|
def get_all_limit_columns(self, session: Session, fields: list[str], limit: int = None) -> list[SqlAlchemyBase]:
|
||||||
|
@ -70,9 +70,9 @@ def main():
|
|||||||
session = create_session()
|
session = create_session()
|
||||||
init_user = db.users.get(session, "1", "id")
|
init_user = db.users.get(session, "1", "id")
|
||||||
if init_user:
|
if init_user:
|
||||||
print("Database Exists")
|
logger.info("Database Exists")
|
||||||
else:
|
else:
|
||||||
print("Database Doesn't Exists, Initializing...")
|
logger.info("Database Doesn't Exists, Initializing...")
|
||||||
init_db()
|
init_db()
|
||||||
create_general_event("Initialize Database", "Initialize database with default values", session)
|
create_general_event("Initialize Database", "Initialize database with default values", session)
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ def get_all_meals(
|
|||||||
def get_this_week(session: Session = Depends(generate_session), current_user: UserInDB = Depends(get_current_user)):
|
def get_this_week(session: Session = Depends(generate_session), current_user: UserInDB = Depends(get_current_user)):
|
||||||
""" Returns the meal plan data for this week """
|
""" Returns the meal plan data for this week """
|
||||||
plans = db.groups.get_meals(session, current_user.group)
|
plans = db.groups.get_meals(session, current_user.group)
|
||||||
print(plans)
|
|
||||||
if plans:
|
if plans:
|
||||||
return plans[0]
|
return plans[0]
|
||||||
|
|
||||||
|
@ -47,7 +47,6 @@ async def delete_comment(
|
|||||||
):
|
):
|
||||||
""" Delete comment from the Database """
|
""" Delete comment from the Database """
|
||||||
comment: CommentOut = db.comments.get(session, id)
|
comment: CommentOut = db.comments.get(session, id)
|
||||||
print(current_user.id, comment.user.id, current_user.admin)
|
|
||||||
if current_user.id == comment.user.id or current_user.admin:
|
if current_user.id == comment.user.id or current_user.admin:
|
||||||
db.comments.delete(session, id)
|
db.comments.delete(session, id)
|
||||||
return
|
return
|
||||||
|
@ -109,7 +109,6 @@ def get_recipe(recipe_slug: str, session: Session = Depends(generate_session), i
|
|||||||
|
|
||||||
if not recipe:
|
if not recipe:
|
||||||
raise HTTPException(status.HTTP_404_NOT_FOUND)
|
raise HTTPException(status.HTTP_404_NOT_FOUND)
|
||||||
print(recipe.settings.public, is_user)
|
|
||||||
if recipe.settings.public or is_user:
|
if recipe.settings.public or is_user:
|
||||||
|
|
||||||
return recipe
|
return recipe
|
||||||
|
@ -6,8 +6,7 @@ from mealie.db.database import db
|
|||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.routes.deps import get_admin_user
|
from mealie.routes.deps import get_admin_user
|
||||||
from mealie.routes.routers import AdminAPIRouter
|
from mealie.routes.routers import AdminAPIRouter
|
||||||
from mealie.schema.user import (SignUpIn, SignUpOut, SignUpToken, UserIn,
|
from mealie.schema.user import SignUpIn, SignUpOut, SignUpToken, UserIn, UserInDB
|
||||||
UserInDB)
|
|
||||||
from mealie.services.events import create_user_event
|
from mealie.services.events import create_user_event
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ router = APIRouter(prefix="/api/utils", tags=["Utils"], include_in_schema=True)
|
|||||||
async def download_file(file_path: Optional[Path] = Depends(validate_file_token)):
|
async def download_file(file_path: Optional[Path] = Depends(validate_file_token)):
|
||||||
"""Uses a file token obtained by an active user to retrieve a file from the operating
|
"""Uses a file token obtained by an active user to retrieve a file from the operating
|
||||||
system."""
|
system."""
|
||||||
print("File Name:", file_path)
|
|
||||||
if not file_path.is_file():
|
if not file_path.is_file():
|
||||||
raise HTTPException(status.HTTP_400_BAD_REQUEST)
|
raise HTTPException(status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
@ -97,8 +97,7 @@ class ExportDatabase:
|
|||||||
zip_path = app_dirs.BACKUP_DIR.joinpath(f"{self.main_dir.name}")
|
zip_path = app_dirs.BACKUP_DIR.joinpath(f"{self.main_dir.name}")
|
||||||
shutil.make_archive(zip_path, "zip", self.main_dir)
|
shutil.make_archive(zip_path, "zip", self.main_dir)
|
||||||
|
|
||||||
shutil.rmtree(app_dirs.TEMP_DIR)
|
shutil.rmtree(app_dirs.TEMP_DIR, ignore_errors=True)
|
||||||
|
|
||||||
return str(zip_path.absolute()) + ".zip"
|
return str(zip_path.absolute()) + ".zip"
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,18 +6,10 @@ from typing import Callable
|
|||||||
|
|
||||||
from mealie.core.config import app_dirs
|
from mealie.core.config import app_dirs
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.schema.admin import (
|
from mealie.schema.admin import (CustomPageImport, CustomPageOut, GroupImport,
|
||||||
CustomPageImport,
|
NotificationImport, RecipeImport,
|
||||||
CustomPageOut,
|
SettingsImport, SiteSettings, SiteTheme,
|
||||||
GroupImport,
|
ThemeImport, UserImport)
|
||||||
NotificationImport,
|
|
||||||
RecipeImport,
|
|
||||||
SettingsImport,
|
|
||||||
SiteSettings,
|
|
||||||
SiteTheme,
|
|
||||||
ThemeImport,
|
|
||||||
UserImport,
|
|
||||||
)
|
|
||||||
from mealie.schema.events import EventNotificationIn
|
from mealie.schema.events import EventNotificationIn
|
||||||
from mealie.schema.recipe import CommentOut, Recipe
|
from mealie.schema.recipe import CommentOut, Recipe
|
||||||
from mealie.schema.user import UpdateGroup, UserInDB
|
from mealie.schema.user import UpdateGroup, UserInDB
|
||||||
@ -369,6 +361,7 @@ def import_database(
|
|||||||
if import_themes:
|
if import_themes:
|
||||||
theme_report = import_session.import_themes()
|
theme_report = import_session.import_themes()
|
||||||
|
|
||||||
|
page_report = []
|
||||||
if import_pages:
|
if import_pages:
|
||||||
page_report = import_session.import_pages()
|
page_report = import_session.import_pages()
|
||||||
|
|
||||||
|
@ -27,8 +27,6 @@ def post_notifications(event: Event, notification_urls=list[str], hard_fail=Fals
|
|||||||
if not status and hard_fail:
|
if not status and hard_fail:
|
||||||
raise Exception("Apprise URL Add Failed")
|
raise Exception("Apprise URL Add Failed")
|
||||||
|
|
||||||
print(attachment)
|
|
||||||
|
|
||||||
apobj.notify(
|
apobj.notify(
|
||||||
body=event.text,
|
body=event.text,
|
||||||
title=event.title,
|
title=event.title,
|
||||||
|
@ -35,7 +35,6 @@ def write_image(recipe_slug: str, file_data: bytes, extension: str) -> Path:
|
|||||||
with open(image_path, "ab") as f:
|
with open(image_path, "ab") as f:
|
||||||
shutil.copyfileobj(file_data, f)
|
shutil.copyfileobj(file_data, f)
|
||||||
|
|
||||||
print(image_path)
|
|
||||||
minify.minify_image(image_path, force=True)
|
minify.minify_image(image_path, force=True)
|
||||||
|
|
||||||
return image_path
|
return image_path
|
||||||
|
@ -45,7 +45,6 @@ class MigrationBase(BaseModel):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def json_reader(json_file: Path) -> dict:
|
def json_reader(json_file: Path) -> dict:
|
||||||
print(json_file)
|
|
||||||
with open(json_file, "r") as f:
|
with open(json_file, "r") as f:
|
||||||
return json.loads(f.read())
|
return json.loads(f.read())
|
||||||
|
|
||||||
|
@ -4,8 +4,7 @@ from typing import Optional
|
|||||||
from mealie.core.config import app_dirs
|
from mealie.core.config import app_dirs
|
||||||
from mealie.schema.admin import MigrationImport
|
from mealie.schema.admin import MigrationImport
|
||||||
from mealie.services.migrations import helpers
|
from mealie.services.migrations import helpers
|
||||||
from mealie.services.migrations._migration_base import (MigrationAlias,
|
from mealie.services.migrations._migration_base import MigrationAlias, MigrationBase
|
||||||
MigrationBase)
|
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,10 +3,13 @@ from functools import lru_cache
|
|||||||
|
|
||||||
from fastapi import Response
|
from fastapi import Response
|
||||||
from fastapi.encoders import jsonable_encoder
|
from fastapi.encoders import jsonable_encoder
|
||||||
|
from mealie.core.root_logger import get_logger
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import SessionLocal
|
from mealie.db.db_setup import SessionLocal
|
||||||
from mealie.schema.recipe import RecipeSummary
|
from mealie.schema.recipe import RecipeSummary
|
||||||
|
|
||||||
|
logger = get_logger()
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=1)
|
@lru_cache(maxsize=1)
|
||||||
def get_all_recipes_user(limit, start):
|
def get_all_recipes_user(limit, start):
|
||||||
@ -29,10 +32,11 @@ def get_all_recipes_public(limit, start):
|
|||||||
|
|
||||||
|
|
||||||
def clear_all_cache():
|
def clear_all_cache():
|
||||||
print("Cache Cleared")
|
|
||||||
get_all_recipes_user.cache_clear()
|
get_all_recipes_user.cache_clear()
|
||||||
get_all_recipes_public.cache_clear()
|
get_all_recipes_public.cache_clear()
|
||||||
|
logger.info("All Recipes Cache Cleared")
|
||||||
|
|
||||||
|
|
||||||
def subscripte_to_recipe_events():
|
def subscripte_to_recipe_events():
|
||||||
db.recipes.subscribe(clear_all_cache)
|
db.recipes.subscribe(clear_all_cache)
|
||||||
|
logger.info("All Recipes Subscribed to Database Events")
|
||||||
|
@ -4,8 +4,11 @@ import re
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
from mealie.core.root_logger import get_logger
|
||||||
from slugify import slugify
|
from slugify import slugify
|
||||||
|
|
||||||
|
logger = get_logger()
|
||||||
|
|
||||||
|
|
||||||
def clean(recipe_data: dict, url=None) -> dict:
|
def clean(recipe_data: dict, url=None) -> dict:
|
||||||
"""Main entrypoint to clean a recipe extracted from the web
|
"""Main entrypoint to clean a recipe extracted from the web
|
||||||
@ -39,13 +42,9 @@ def clean_string(text: str) -> str:
|
|||||||
if isinstance(text, list):
|
if isinstance(text, list):
|
||||||
text = text[0]
|
text = text[0]
|
||||||
|
|
||||||
print(type(text))
|
|
||||||
|
|
||||||
if text == "" or text is None:
|
if text == "" or text is None:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
print(text)
|
|
||||||
|
|
||||||
cleaned_text = html.unescape(text)
|
cleaned_text = html.unescape(text)
|
||||||
cleaned_text = re.sub("<[^<]+?>", "", cleaned_text)
|
cleaned_text = re.sub("<[^<]+?>", "", cleaned_text)
|
||||||
cleaned_text = re.sub(" +", " ", cleaned_text)
|
cleaned_text = re.sub(" +", " ", cleaned_text)
|
||||||
@ -122,7 +121,7 @@ def instructions(instructions) -> List[dict]:
|
|||||||
|
|
||||||
return [{"text": _instruction(step["text"])} for step in instructions if step["@type"] == "HowToStep"]
|
return [{"text": _instruction(step["text"])} for step in instructions if step["@type"] == "HowToStep"]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
logger.error(e)
|
||||||
# Not "@type", try "type"
|
# Not "@type", try "type"
|
||||||
try:
|
try:
|
||||||
return [
|
return [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user