From b3f52a8730833539f5bbc6f55e1b60764144da3b Mon Sep 17 00:00:00 2001 From: Denis Anikin Date: Mon, 9 Oct 2023 21:50:07 +0300 Subject: [PATCH] Structlog and more fixes --- poetry.lock | 51 +++++++++++------------------- pyproject.toml | 2 +- whole_app/dictionaries/__init__.py | 9 +++--- whole_app/misc_helpers.py | 22 ++++++++++--- whole_app/settings.py | 9 +++--- 5 files changed, 46 insertions(+), 47 deletions(-) diff --git a/poetry.lock b/poetry.lock index ca4384e..76b6d45 100644 --- a/poetry.lock +++ b/poetry.lock @@ -484,24 +484,6 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] -[[package]] -name = "loguru" -version = "0.7.2" -description = "Python logging made (stupidly) simple" -optional = false -python-versions = ">=3.5" -files = [ - {file = "loguru-0.7.2-py3-none-any.whl", hash = "sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb"}, - {file = "loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"}, -] - -[package.dependencies] -colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} -win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} - -[package.extras] -dev = ["Sphinx (==7.2.5)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.2.2)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.4.1)", "mypy (==v1.5.1)", "pre-commit (==3.4.0)", "pytest (==6.1.2)", "pytest (==7.4.0)", "pytest-cov (==2.12.1)", "pytest-cov (==4.1.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.0.0)", "sphinx-autobuild (==2021.3.14)", "sphinx-rtd-theme (==1.3.0)", "tox (==3.27.1)", "tox (==4.11.0)"] - [[package]] name = "mypy" version = "1.5.1" @@ -1020,6 +1002,23 @@ anyio = ">=3.4.0,<5" [package.extras] full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] +[[package]] +name = "structlog" +version = "23.2.0" +description = "Structured Logging for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "structlog-23.2.0-py3-none-any.whl", hash = "sha256:16a167e87b9fa7fae9a972d5d12805ef90e04857a93eba479d4be3801a6a1482"}, + {file = "structlog-23.2.0.tar.gz", hash = "sha256:334666b94707f89dbc4c81a22a8ccd34449f0201d5b1ee097a030b577fa8c858"}, +] + +[package.extras] +dev = ["structlog[tests,typing]"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-mermaid", "twisted"] +tests = ["freezegun (>=0.2.8)", "pretend", "pytest (>=6.0)", "pytest-asyncio (>=0.17)", "simplejson"] +typing = ["mypy (>=1.4)", "rich", "twisted"] + [[package]] name = "toml" version = "0.10.2" @@ -1139,21 +1138,7 @@ files = [ [package.dependencies] toml = "*" -[[package]] -name = "win32-setctime" -version = "1.1.0" -description = "A small Python utility to set file creation time on Windows" -optional = false -python-versions = ">=3.5" -files = [ - {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, - {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, -] - -[package.extras] -dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] - [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "415c822b72ce164f2d0d90319d94160b599444eb8f5a94e480bbe015259e226a" +content-hash = "286196a5c33f2f4cd5c8170a97d3281c733088115c490132d007c38966f168a3" diff --git a/pyproject.toml b/pyproject.toml index 5b87b3f..498596a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,6 @@ license = "MIT" python = "^3.10" gunicorn = "*" uvicorn = "*" -loguru = "*" pyenchant = "*" toml = "*" pylru = "*" @@ -18,6 +17,7 @@ anyio = "*" sentry-sdk = "*" pydantic-settings = "*" fastapi = "*" +structlog = "^23.2.0" [tool.poetry.group.dev.dependencies] httpx = "*" diff --git a/whole_app/dictionaries/__init__.py b/whole_app/dictionaries/__init__.py index 05f4a7d..95ae1f6 100644 --- a/whole_app/dictionaries/__init__.py +++ b/whole_app/dictionaries/__init__.py @@ -1,20 +1,21 @@ -from loguru import logger +import typing + +import structlog from . import dummy as dummy_storage from . import file as file_storage from . import protocol -from whole_app import misc_helpers from whole_app.settings import SETTINGS, StorageProviders -misc_helpers.init_logger() +LOGGER_OBJ: typing.Final = structlog.get_logger() def init_storage() -> None: if SETTINGS.dictionaries_storage_provider == StorageProviders.FILE: file_storage.init_storage() elif SETTINGS.dictionaries_storage_provider == StorageProviders.DUMMY: - logger.warning( + LOGGER_OBJ.warning( "Storage provider set to dummy mode. " "Currently all user dictionary requests will be thrown away. We worn you.", ) diff --git a/whole_app/misc_helpers.py b/whole_app/misc_helpers.py index e995000..83c9a91 100644 --- a/whole_app/misc_helpers.py +++ b/whole_app/misc_helpers.py @@ -1,10 +1,22 @@ -import sys +import logging +import typing -from loguru import logger +import structlog -from .settings import SETTINGS +from whole_app.settings import SETTINGS def init_logger() -> None: - logger.remove() - logger.add(sys.stdout, serialize=SETTINGS.structured_logging) + our_processors: typing.Final[typing.Any] = [ + structlog.contextvars.merge_contextvars, + structlog.processors.add_log_level, + structlog.processors.format_exc_info, + structlog.processors.TimeStamper(fmt="iso", utc=True), + ] + if SETTINGS.structured_logging: + our_processors.append(structlog.processors.JSONRenderer()) + structlog.configure( + cache_logger_on_first_use=True, + wrapper_class=structlog.make_filtering_bound_logger(logging.INFO), + processors=our_processors, + ) diff --git a/whole_app/settings.py b/whole_app/settings.py index 3499f49..53815b8 100644 --- a/whole_app/settings.py +++ b/whole_app/settings.py @@ -3,11 +3,12 @@ import typing import pydantic +import structlog import toml -from loguru import logger from pydantic_settings import BaseSettings +LOGGER_OBJ: typing.Final = structlog.get_logger() PATH_TO_PYPROJECT: typing.Final = pathlib.Path(__file__).parent.parent / "pyproject.toml" AvailableLanguagesType = typing.Literal[ "ru_RU", @@ -24,7 +25,7 @@ def _warn_about_poor_lru_cache_size( possible_value: int, ) -> int: if int(possible_value) < 1: - logger.warning( + LOGGER_OBJ.warning( ( "You set cache size less then 1. In this case, " "the cache size will be unlimited and polute your memory." @@ -38,7 +39,7 @@ def _warn_about_empty_api_key( possible_value: str, ) -> str: if not possible_value: - logger.warning("You set empty API key. This is not recommended.") + LOGGER_OBJ.warning("You set empty API key. This is not recommended.") return possible_value @@ -51,7 +52,7 @@ def _parse_version_from_local_file( ) return pyproject_obj["tool"]["poetry"]["version"] except (toml.TomlDecodeError, KeyError, FileNotFoundError) as exc: - logger.warning(f"Cant parse version from pyproject. Trouble {exc}") + LOGGER_OBJ.warning("Cant parse version from pyproject. Trouble %s", exc) return default_value