From 299441525730fe33f67dd17bafaa56c4313241dc Mon Sep 17 00:00:00 2001 From: hay-kot Date: Sat, 10 Apr 2021 14:45:19 -0800 Subject: [PATCH] refactor to unify logger + log to file --- mealie/app.py | 16 +++++-- mealie/core/config.py | 1 - mealie/core/root_logger.py | 43 +++++++++++++++++++ mealie/db/init_db.py | 8 +++- mealie/db/models/recipe/category.py | 4 +- mealie/db/models/recipe/tag.py | 4 +- mealie/routes/debug_routes.py | 3 +- mealie/routes/recipe/tag_routes.py | 1 + mealie/schema/debug.py | 3 +- mealie/services/backups/exports.py | 4 +- mealie/services/image/image.py | 5 ++- mealie/services/image/minify.py | 4 +- mealie/services/migrations/_migration_base.py | 5 ++- mealie/services/migrations/migration.py | 6 ++- mealie/services/migrations/nextcloud.py | 3 +- mealie/services/scheduler/scheduled_jobs.py | 5 ++- mealie/services/scraper/scraper.py | 6 ++- tests/unit_tests/test_cleaner.py | 2 +- tests/unit_tests/test_config.py | 2 +- 19 files changed, 100 insertions(+), 25 deletions(-) create mode 100644 mealie/core/root_logger.py diff --git a/mealie/app.py b/mealie/app.py index e6223d503..443d8780a 100644 --- a/mealie/app.py +++ b/mealie/app.py @@ -1,6 +1,7 @@ import uvicorn from fastapi import FastAPI -from fastapi.logger import logger + +from mealie.core import root_logger # import utils.startup as startup from mealie.core.config import APP_VERSION, settings @@ -11,6 +12,8 @@ from mealie.routes.recipe import all_recipe_routes, category_routes, recipe_crud from mealie.routes.site_settings import all_settings from mealie.routes.users import users +logger = root_logger.get_logger() + app = FastAPI( title="Mealie", description="A place for all your recipes", @@ -50,8 +53,15 @@ api_routers() start_scheduler() +@app.on_event("startup") +def system_startup(): + logger.info("-----SYSTEM STARTUP----- \n") + logger.info("------APP SETTINGS------") + logger.info(settings.json(indent=4, exclude={"SECRET", "DEFAULT_PASSWORD", "SFTP_PASSWORD", "SFTP_USERNAME"})) + + def main(): - + uvicorn.run( "app:app", host="0.0.0.0", @@ -60,11 +70,11 @@ def main(): reload_dirs=["mealie"], debug=True, log_level="info", + log_config=None, workers=1, forwarded_allow_ips="*", ) if __name__ == "__main__": - logger.info("-----SYSTEM STARTUP-----") main() diff --git a/mealie/core/config.py b/mealie/core/config.py index b876ae9bb..185aa47b7 100644 --- a/mealie/core/config.py +++ b/mealie/core/config.py @@ -40,7 +40,6 @@ def determine_secrets(data_dir: Path, production: bool) -> str: # General DATA_DIR = determine_data_dir(PRODUCTION) -LOGGER_FILE = DATA_DIR.joinpath("mealie.log") class AppDirectories: diff --git a/mealie/core/root_logger.py b/mealie/core/root_logger.py new file mode 100644 index 000000000..dfa652f40 --- /dev/null +++ b/mealie/core/root_logger.py @@ -0,0 +1,43 @@ +import logging +import sys + +from mealie.core.config import DATA_DIR + +LOGGER_FILE = DATA_DIR.joinpath("mealie.log") +LOGGER_FORMAT = "%(levelname)s: \t%(message)s" +DATE_FORMAT = "%d-%b-%y %H:%M:%S" + +logging.basicConfig(level=logging.INFO, format=LOGGER_FORMAT, datefmt="%d-%b-%y %H:%M:%S") + + +def logger_init() -> logging.Logger: + """ Returns the Root Loggin Object for Mealie """ + logger = 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 + + +def get_logger(module=None) -> logging.Logger: + """ Returns a child logger for mealie """ + global root_logger + + if module is None: + return root_logger + + return root_logger.getChild(module) + + +root_logger = logger_init() diff --git a/mealie/db/init_db.py b/mealie/db/init_db.py index 2dacbf438..f63d20ed7 100644 --- a/mealie/db/init_db.py +++ b/mealie/db/init_db.py @@ -1,4 +1,4 @@ -from fastapi.logger import logger +from mealie.core import root_logger from mealie.core.config import settings from mealie.core.security import get_password_hash from mealie.db.database import db @@ -7,6 +7,8 @@ from mealie.schema.settings import SiteSettings from mealie.schema.theme import SiteTheme from sqlalchemy.orm import Session +logger = root_logger.get_logger("init_db") + def init_db(db: Session = None) -> None: if not db: @@ -47,6 +49,7 @@ def default_user_init(session: Session): logger.info("Generating Default User") db.users.create(session, default_user) + def main(): if sql_exists: print("Database Exists") @@ -54,5 +57,6 @@ def main(): print("Database Doesn't Exists, Initializing...") init_db() + if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/mealie/db/models/recipe/category.py b/mealie/db/models/recipe/category.py index 4e68baa54..732e0f1de 100644 --- a/mealie/db/models/recipe/category.py +++ b/mealie/db/models/recipe/category.py @@ -1,10 +1,12 @@ import sqlalchemy as sa import sqlalchemy.orm as orm -from fastapi.logger import logger +from mealie.core import root_logger from mealie.db.models.model_base import SqlAlchemyBase from slugify import slugify from sqlalchemy.orm import validates +logger = root_logger.get_logger() + site_settings2categories = sa.Table( "site_settings2categoories", SqlAlchemyBase.metadata, diff --git a/mealie/db/models/recipe/tag.py b/mealie/db/models/recipe/tag.py index 8c7e5ad46..bc889d1e0 100644 --- a/mealie/db/models/recipe/tag.py +++ b/mealie/db/models/recipe/tag.py @@ -1,10 +1,12 @@ import sqlalchemy as sa import sqlalchemy.orm as orm -from fastapi.logger import logger +from mealie.core import root_logger from mealie.db.models.model_base import SqlAlchemyBase from slugify import slugify from sqlalchemy.orm import validates +logger = root_logger.get_logger() + recipes2tags = sa.Table( "recipes2tags", SqlAlchemyBase.metadata, diff --git a/mealie/routes/debug_routes.py b/mealie/routes/debug_routes.py index 933e781c8..ab062026d 100644 --- a/mealie/routes/debug_routes.py +++ b/mealie/routes/debug_routes.py @@ -1,7 +1,8 @@ import json from fastapi import APIRouter, Depends -from mealie.core.config import APP_VERSION, LOGGER_FILE, app_dirs, settings +from mealie.core.config import APP_VERSION, app_dirs, settings +from mealie.core.root_logger import LOGGER_FILE from mealie.routes.deps import get_current_user from mealie.schema.debug import AppInfo, DebugInfo diff --git a/mealie/routes/recipe/tag_routes.py b/mealie/routes/recipe/tag_routes.py index 65dfbdc19..205c60679 100644 --- a/mealie/routes/recipe/tag_routes.py +++ b/mealie/routes/recipe/tag_routes.py @@ -19,6 +19,7 @@ async def get_all_recipe_tags(session: Session = Depends(generate_session)): """ Returns a list of available tags in the database """ return db.tags.get_all_limit_columns(session, ["slug", "name"]) + @router.post("") async def create_recipe_tag( tag: TagIn, session: Session = Depends(generate_session), current_user=Depends(get_current_user) diff --git a/mealie/schema/debug.py b/mealie/schema/debug.py index 4cb94396d..0348af14b 100644 --- a/mealie/schema/debug.py +++ b/mealie/schema/debug.py @@ -7,9 +7,10 @@ class AppInfo(CamelModel): version: str demo_status: bool + class DebugInfo(AppInfo): api_port: int api_docs: bool db_type: str sqlite_file: Path - default_group: str \ No newline at end of file + default_group: str diff --git a/mealie/services/backups/exports.py b/mealie/services/backups/exports.py index 86220ae85..5133bd664 100644 --- a/mealie/services/backups/exports.py +++ b/mealie/services/backups/exports.py @@ -4,13 +4,15 @@ from datetime import datetime from pathlib import Path from typing import Union -from fastapi.logger import logger +from mealie.core import root_logger from jinja2 import Template from mealie.core.config import app_dirs from mealie.db.database import db from mealie.db.db_setup import create_session from pydantic.main import BaseModel +logger = root_logger.get_logger() + class ExportDatabase: def __init__(self, tag=None, templates=None) -> None: diff --git a/mealie/services/image/image.py b/mealie/services/image/image.py index 51e4c82e9..049fe8c06 100644 --- a/mealie/services/image/image.py +++ b/mealie/services/image/image.py @@ -1,13 +1,14 @@ import shutil from dataclasses import dataclass from pathlib import Path -from typing import Union import requests -from fastapi.logger import logger +from mealie.core import root_logger from mealie.core.config import app_dirs from mealie.services.image import minify +logger = root_logger.get_logger() + @dataclass class ImageOptions: diff --git a/mealie/services/image/minify.py b/mealie/services/image/minify.py index c6f781e3a..de71f34a2 100644 --- a/mealie/services/image/minify.py +++ b/mealie/services/image/minify.py @@ -1,13 +1,15 @@ import shutil from pathlib import Path -from fastapi.logger import logger +from mealie.core import root_logger from mealie.core.config import app_dirs from mealie.db.database import db from mealie.db.db_setup import create_session from PIL import Image from sqlalchemy.orm.session import Session +logger = root_logger.get_logger() + def minify_image(image_file: Path, min_dest: Path, tiny_dest: Path): """Minifies an image in it's original file format. Quality is lost diff --git a/mealie/services/migrations/_migration_base.py b/mealie/services/migrations/_migration_base.py index 2eb4bc8a2..c3331a90c 100644 --- a/mealie/services/migrations/_migration_base.py +++ b/mealie/services/migrations/_migration_base.py @@ -4,7 +4,7 @@ from tempfile import TemporaryDirectory from typing import Any, Callable, Optional import yaml -from fastapi.logger import logger +from mealie.core import root_logger from mealie.db.database import db from mealie.schema.migration import MigrationImport from mealie.schema.recipe import Recipe @@ -13,6 +13,8 @@ from mealie.services.scraper.cleaner import Cleaner from mealie.utils.unzip import unpack_zip from pydantic import BaseModel +logger = root_logger.get_logger() + class MigrationAlias(BaseModel): """A datatype used by MigrationBase to pre-process a recipe dictionary to rewrite @@ -110,7 +112,6 @@ class MigrationBase(BaseModel): image.write_image(dest_slug, src, extension=src.suffix) minify.migrate_images() # TODO: Refactor to support single file minification that doesn't suck - def rewrite_alias(self, recipe_dict: dict) -> dict: """A helper function to reassign attributes by an alias using a list of MigrationAlias objects to rewrite the alias attribute found in the recipe_dict diff --git a/mealie/services/migrations/migration.py b/mealie/services/migrations/migration.py index 52069a6c2..0bc96f15c 100644 --- a/mealie/services/migrations/migration.py +++ b/mealie/services/migrations/migration.py @@ -1,11 +1,13 @@ from enum import Enum from pathlib import Path -from fastapi.logger import logger +from mealie.core import root_logger from mealie.schema.migration import MigrationImport -from mealie.services.migrations import chowdown, chowdown, nextcloud +from mealie.services.migrations import chowdown, nextcloud from sqlalchemy.orm.session import Session +logger = root_logger.get_logger() + class Migration(str, Enum): """The class defining the supported types of migrations for Mealie. Pass the diff --git a/mealie/services/migrations/nextcloud.py b/mealie/services/migrations/nextcloud.py index 7bf018cf4..48461e618 100644 --- a/mealie/services/migrations/nextcloud.py +++ b/mealie/services/migrations/nextcloud.py @@ -4,8 +4,7 @@ from typing import Optional from mealie.schema.migration import MigrationImport from mealie.services.migrations import helpers -from mealie.services.migrations._migration_base import (MigrationAlias, - MigrationBase) +from mealie.services.migrations._migration_base import MigrationAlias, MigrationBase from slugify import slugify from sqlalchemy.orm.session import Session diff --git a/mealie/services/scheduler/scheduled_jobs.py b/mealie/services/scheduler/scheduled_jobs.py index fdfa602e2..4a8446b96 100644 --- a/mealie/services/scheduler/scheduled_jobs.py +++ b/mealie/services/scheduler/scheduled_jobs.py @@ -1,15 +1,18 @@ from apscheduler.schedulers.background import BackgroundScheduler +from mealie.core import root_logger from mealie.db.database import db from mealie.db.db_setup import create_session -from fastapi.logger import logger from mealie.schema.user import GroupInDB from mealie.services.backups.exports import auto_backup_job from mealie.services.scheduler.global_scheduler import scheduler from mealie.services.scheduler.scheduler_utils import Cron, cron_parser from mealie.utils.post_webhooks import post_webhooks +logger = root_logger.get_logger() # TODO Fix Scheduler + + @scheduler.scheduled_job(trigger="interval", minutes=30) def update_webhook_schedule(): """ diff --git a/mealie/services/scraper/scraper.py b/mealie/services/scraper/scraper.py index 451827052..6dfb39653 100644 --- a/mealie/services/scraper/scraper.py +++ b/mealie/services/scraper/scraper.py @@ -3,15 +3,17 @@ from typing import List import requests import scrape_schema_recipe +from mealie.core import root_logger from mealie.core.config import app_dirs -from fastapi.logger import logger -from mealie.services.image.image import scrape_image from mealie.schema.recipe import Recipe +from mealie.services.image.image import scrape_image from mealie.services.scraper import open_graph from mealie.services.scraper.cleaner import Cleaner LAST_JSON = app_dirs.DEBUG_DIR.joinpath("last_recipe.json") +logger = root_logger.get_logger() + def create_from_url(url: str) -> Recipe: """Main entry point for generating a recipe from a URL. Pass in a URL and diff --git a/tests/unit_tests/test_cleaner.py b/tests/unit_tests/test_cleaner.py index dbe597281..ed1ea0d11 100644 --- a/tests/unit_tests/test_cleaner.py +++ b/tests/unit_tests/test_cleaner.py @@ -80,7 +80,7 @@ def test_cleaner_instructions(instructions): def test_html_with_recipe_data(): path = TEST_RAW_HTML.joinpath("healthy_pasta_bake_60759.html") url = "https://www.bbc.co.uk/food/recipes/healthy_pasta_bake_60759" - recipe_data = extract_recipe_from_html(open(path,encoding="utf8").read(), url) + recipe_data = extract_recipe_from_html(open(path, encoding="utf8").read(), url) assert len(recipe_data["name"]) > 10 assert len(recipe_data["slug"]) > 10 diff --git a/tests/unit_tests/test_config.py b/tests/unit_tests/test_config.py index c2641b428..895420a34 100644 --- a/tests/unit_tests/test_config.py +++ b/tests/unit_tests/test_config.py @@ -29,7 +29,7 @@ def test_non_default_settings(monkeypatch): monkeypatch.setenv("DEFAULT_GROUP", "Test Group") monkeypatch.setenv("DEFAULT_PASSWORD", "Test Password") monkeypatch.setenv("API_PORT", "8000") - monkeypatch.setenv("API_DOCS", 'False') + monkeypatch.setenv("API_DOCS", "False") app_settings = AppSettings()