Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ if logger_loader.config.extra.http_json_enabled:
)
```

[**`app.py`**](https://github.com/bybatkhuu/module.python-logging/blob/main/examples/advanced/app.py):
[**`main.py`**](https://github.com/bybatkhuu/module.python-logging/blob/main/examples/advanced/main.py):

```python
from typing import Union
Expand Down Expand Up @@ -338,28 +338,28 @@ cd ./examples/advanced
# Install python dependencies for examples:
pip install -r ./requirements.txt

uvicorn app:app --host=0.0.0.0 --port=8000
uvicorn main:app --host=0.0.0.0 --port=8000
```

**Output**:

```txt
[2023-09-01 12:37:38.569 +09:00 | TRACE | beans_logging._base:499]: Intercepted modules: ['watchfiles.watcher', 'asyncio', 'watchfiles', 'concurrent', 'dotenv', 'concurrent.futures', 'fastapi', 'dotenv.main', 'uvicorn', 'watchfiles.main']; Muted modules: ['uvicorn.error', 'uvicorn.access'];
[2023-09-01 12:37:38.579 +09:00 | INFO | uvicorn.server:76]: Started server process [22599]
[2023-09-01 12:37:38.579 +09:00 | INFO | uvicorn.lifespan.on:46]: Waiting for application startup.
[2023-09-01 12:37:38.579 +09:00 | INFO | app:21]: Preparing to startup...
[2023-09-01 12:37:38.580 +09:00 | OK | app:22]: Finished preparation to startup.
[2023-09-01 12:37:38.580 +09:00 | INFO | app:23]: API version: 0.0.1-000000
[2023-09-01 12:37:38.580 +09:00 | INFO | uvicorn.lifespan.on:60]: Application startup complete.
[2023-09-01 12:37:38.582 +09:00 | INFO | uvicorn.server:218]: Uvicorn running on http://0.0.0.0:9000 (Press CTRL+C to quit)
[2023-09-01 12:37:48.487 +09:00 | DEBUG | anyio._backends._asyncio:807]: [0b9f972939054a58ba10e7a39a12bd21] 127.0.0.1 - "GET / HTTP/1.1"
[2023-09-01 12:37:48.488 +09:00 | OK | anyio._backends._asyncio:807]: [0b9f972939054a58ba10e7a39a12bd21] 127.0.0.1 - "GET / HTTP/1.1" 200 17B 0.5ms
^C[2023-09-01 12:37:51.845 +09:00 | INFO | uvicorn.server:264]: Shutting down
[2023-09-01 12:37:51.949 +09:00 | INFO | uvicorn.lifespan.on:65]: Waiting for application shutdown.
[2023-09-01 12:37:51.951 +09:00 | INFO | app:26]: Praparing to shutdown...
[2023-09-01 12:37:51.952 +09:00 | OK | app:27]: Finished preparation to shutdown.
[2023-09-01 12:37:51.952 +09:00 | INFO | uvicorn.lifespan.on:76]: Application shutdown complete.
[2023-09-01 12:37:51.953 +09:00 | INFO | uvicorn.server:86]: Finished server process [22599]
[2023-09-01 14:55:11.724 +09:00 | TRACE | beans_logging._base:576]: Intercepted modules: ['watchfiles.watcher', 'dotenv', 'asyncio', 'dotenv.main', 'watchfiles.main', 'concurrent.futures', 'uvicorn', 'fastapi', 'concurrent', 'watchfiles']; Muted modules: ['uvicorn.access', 'uvicorn.error'];
[2023-09-01 14:55:11.740 +09:00 | INFO | uvicorn.server:76]: Started server process [17146]
[2023-09-01 14:55:11.740 +09:00 | INFO | uvicorn.lifespan.on:46]: Waiting for application startup.
[2023-09-01 14:55:11.741 +09:00 | INFO | main:21]: Preparing to startup...
[2023-09-01 14:55:11.741 +09:00 | OK | main:22]: Finished preparation to startup.
[2023-09-01 14:55:11.741 +09:00 | INFO | main:23]: API version: 0.0.1-000000
[2023-09-01 14:55:11.741 +09:00 | INFO | uvicorn.lifespan.on:60]: Application startup complete.
[2023-09-01 14:55:11.745 +09:00 | INFO | uvicorn.server:218]: Uvicorn running on http://0.0.0.0:9000 (Press CTRL+C to quit)
[2023-09-01 14:55:17.417 +09:00 | DEBUG | anyio._backends._asyncio:833]: [f635ebbc3f2348db9dcff681be1bd52a] 127.0.0.1 - "GET / HTTP/1.1"
[2023-09-01 14:55:17.418 +09:00 | OK | anyio._backends._asyncio:833]: [f635ebbc3f2348db9dcff681be1bd52a] 127.0.0.1 - "GET / HTTP/1.1" 200 17B 0.7ms
^C[2023-09-01 14:55:18.729 +09:00 | INFO | uvicorn.server:264]: Shutting down
[2023-09-01 14:55:18.831 +09:00 | INFO | uvicorn.lifespan.on:65]: Waiting for application shutdown.
[2023-09-01 14:55:18.834 +09:00 | INFO | main:26]: Praparing to shutdown...
[2023-09-01 14:55:18.835 +09:00 | OK | main:27]: Finished preparation to shutdown.
[2023-09-01 14:55:18.837 +09:00 | INFO | uvicorn.lifespan.on:76]: Application shutdown complete.
[2023-09-01 14:55:18.837 +09:00 | INFO | uvicorn.server:86]: Finished server process [17146]
```

---
Expand Down
2 changes: 1 addition & 1 deletion beans_logging/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

from ._base import Logger, logger, LoggerLoader
from .schemas import LoggerConfigPM
from ._const import WarnEnum
from ._consts import WarnEnum
from .__version__ import __version__
35 changes: 29 additions & 6 deletions beans_logging/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@
import yaml
from loguru import logger
from loguru._logger import Logger
from pydantic import validate_call
import pydantic

if "2.0.0" <= pydantic.__version__:
from pydantic import validate_call
else:
from pydantic import validate_arguments as validate_call

## Internal modules
from ._utils import create_dir, deep_merge
Expand Down Expand Up @@ -168,7 +173,11 @@ def update_config(self, config: Union[LoggerConfigPM, Dict[str, Any]]):
"""

if isinstance(config, dict):
_config_dict = self.config.model_dump()
if "2.0.0" <= pydantic.__version__:
_config_dict = self.config.model_dump()
else:
_config_dict = self.config.dict()

_merged_dict = deep_merge(_config_dict, config)
try:
self.config = LoggerConfigPM(**_merged_dict)
Expand Down Expand Up @@ -219,7 +228,11 @@ def _load_config_file(self):
return

_new_config_dict = _new_config_dict["logger"]
_config_dict = self.config.model_dump()
if "2.0.0" <= pydantic.__version__:
_config_dict = self.config.model_dump()
else:
_config_dict = self.config.dict()

_merged_dict = deep_merge(_config_dict, _new_config_dict)
self.config = LoggerConfigPM(**_merged_dict)
except Exception:
Expand All @@ -240,7 +253,11 @@ def _load_config_file(self):
return

_new_config_dict = _new_config_dict["logger"]
_config_dict = self.config.model_dump()
if "2.0.0" <= pydantic.__version__:
_config_dict = self.config.model_dump()
else:
_config_dict = self.config.dict()

_merged_dict = deep_merge(_config_dict, _new_config_dict)
self.config = LoggerConfigPM(**_merged_dict)
except Exception:
Expand All @@ -252,7 +269,9 @@ def _load_config_file(self):
# try:
# import toml

# with open(self.config_file_path, "r", encoding="utf-8") as _config_file:
# with open(
# self.config_file_path, "r", encoding="utf-8"
# ) as _config_file:
# _new_config_dict = toml.load(_config_file) or {}
# if "logger" not in _new_config_dict:
# logger.warning(
Expand All @@ -261,7 +280,11 @@ def _load_config_file(self):
# return

# _new_config_dict = _new_config_dict["logger"]
# _config_dict = self.config.model_dump()
# if "2.0.0" <= pydantic.__version__:
# _config_dict = self.config.model_dump()
# else:
# _config_dict = self.config.dict()

# _merged_dict = deep_merge(_config_dict, _new_config_dict)
# self.config = LoggerConfigPM(**_merged_dict)
# except Exception:
Expand Down
10 changes: 0 additions & 10 deletions beans_logging/_const.py

This file was deleted.

20 changes: 20 additions & 0 deletions beans_logging/_consts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-

from enum import Enum


class WarnEnum(str, Enum):
ERROR = "ERROR"
ALWAYS = "ALWAYS"
DEBUG = "DEBUG"
IGNORE = "IGNORE"


class LogLevelEnum(str, Enum):
TRACE = "TRACE"
DEBUG = "DEBUG"
INFO = "INFO"
SUCCESS = "SUCCESS"
WARNING = "WARNING"
ERROR = "ERROR"
CRITICAL = "CRITICAL"
41 changes: 36 additions & 5 deletions beans_logging/_utils.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
# -*- coding: utf-8 -*-

import os
import sys
import copy
import errno

from loguru import logger
from pydantic import validate_call
import pydantic

from ._const import WarnEnum
if "2.0.0" <= pydantic.__version__:
from pydantic import validate_call
else:
from pydantic import validate_arguments as validate_call

from ._consts import WarnEnum


@validate_call
Expand All @@ -16,13 +22,13 @@ def create_dir(create_dir: str, warn_mode: WarnEnum = WarnEnum.DEBUG):

Args:
create_dir (str, required): Create directory path.
warn_mode (str, optional): Warning message mode, for example: 'LOG', 'DEBUG', 'QUIET'. Defaults to "QUIET".
warn_mode (str, optional): Warning message mode, for example: 'ERROR', 'ALWAYS', 'DEBUG', 'IGNORE'. Defaults to "DEBUG".
"""

if not os.path.isdir(create_dir):
try:
_message = f"Creaing '{create_dir}' directory..."
if warn_mode == WarnEnum.LOG:
if warn_mode == WarnEnum.ALWAYS:
logger.info(_message)
elif warn_mode == WarnEnum.DEBUG:
logger.debug(_message)
Expand All @@ -36,7 +42,7 @@ def create_dir(create_dir: str, warn_mode: WarnEnum = WarnEnum.DEBUG):
raise

_message = f"Successfully created '{create_dir}' directory."
if warn_mode == WarnEnum.LOG:
if warn_mode == WarnEnum.ALWAYS:
logger.success(_message)
elif warn_mode == WarnEnum.DEBUG:
logger.debug(_message)
Expand Down Expand Up @@ -67,3 +73,28 @@ def deep_merge(dict1: dict, dict2: dict) -> dict:
_merged[_key] = copy.deepcopy(_val)

return _merged


def get_default_logs_dir() -> str:
"""Return default logs directory path (current working directory + 'logs').

Returns:
str: Default logs directory path.
"""

return os.path.join(os.getcwd(), "logs")


def get_app_name() -> str:
"""Return application name (sys.argv[0]).

Returns:
str: Application name.
"""

return (
os.path.splitext(os.path.basename(sys.argv[0]))[0]
.strip()
.replace(" ", "-")
.lower()
)
7 changes: 6 additions & 1 deletion beans_logging/fastapi/_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

from typing import Union, Callable

from pydantic import validate_call
import pydantic

if "2.0.0" <= pydantic.__version__:
from pydantic import validate_call
else:
from pydantic import validate_arguments as validate_call

from beans_logging import LoggerLoader

Expand Down
8 changes: 8 additions & 0 deletions beans_logging/schemas/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-

import pydantic

if "2.0.0" <= pydantic.__version__:
from .config import LoggerConfigPM
else:
from .config_v1 import LoggerConfigPM
33 changes: 5 additions & 28 deletions beans_logging/schemas.py → beans_logging/schemas/config.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# -*- coding: utf-8 -*-

import os
import sys
import datetime
from enum import Enum
from typing import List

from pydantic import (
Expand All @@ -15,34 +12,14 @@
ConfigDict,
)


def _get_logs_dir() -> str:
return os.path.join(os.getcwd(), "logs")


def _get_app_name() -> str:
return (
os.path.splitext(os.path.basename(sys.argv[0]))[0]
.strip()
.replace(" ", "-")
.lower()
)
from .._consts import LogLevelEnum
from .._utils import get_default_logs_dir, get_app_name


class ExtraBaseModel(BaseModel):
model_config = ConfigDict(extra="allow")


class LevelEnum(str, Enum):
TRACE = "TRACE"
DEBUG = "DEBUG"
INFO = "INFO"
SUCCESS = "SUCCESS"
WARNING = "WARNING"
ERROR = "ERROR"
CRITICAL = "CRITICAL"


class StdHandlerPM(ExtraBaseModel):
enabled: bool = Field(default=True)

Expand Down Expand Up @@ -104,7 +81,7 @@ def _check_log_path(self) -> "JsonHandlersPM":

class FilePM(ExtraBaseModel):
logs_dir: constr(strip_whitespace=True) = Field(
default_factory=_get_logs_dir, min_length=2, max_length=1023
default_factory=get_default_logs_dir, min_length=2, max_length=1023
)
rotate_size: int = Field(
default=10_000_000, ge=1_000, lt=1_000_000_000 # 10MB = 10 * 1000 * 1000
Expand Down Expand Up @@ -143,11 +120,11 @@ class ExtraPM(ExtraBaseModel):

class LoggerConfigPM(ExtraBaseModel):
app_name: constr(strip_whitespace=True) = Field(
default_factory=_get_app_name,
default_factory=get_app_name,
min_length=1,
max_length=127,
)
level: LevelEnum = Field(default=LevelEnum.INFO)
level: LogLevelEnum = Field(default=LogLevelEnum.INFO)
use_backtrace: bool = Field(default=True)
use_diagnose: bool = Field(default=False)
stream: StreamPM = Field(default_factory=StreamPM)
Expand Down
Loading