beans-logging 7.0.0__py3-none-any.whl → 8.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- beans_logging/__init__.py +5 -1
- beans_logging/__version__.py +1 -1
- beans_logging/_builder.py +69 -91
- beans_logging/_core.py +8 -7
- beans_logging/config.py +86 -80
- beans_logging/constants.py +46 -0
- beans_logging/{_intercept.py → intercepters.py} +2 -2
- beans_logging/schemas.py +2 -6
- {beans_logging-7.0.0.dist-info → beans_logging-8.0.0.dist-info}/METADATA +23 -56
- beans_logging-8.0.0.dist-info/RECORD +18 -0
- {beans_logging-7.0.0.dist-info → beans_logging-8.0.0.dist-info}/WHEEL +1 -1
- beans_logging/_constants.py +0 -30
- beans_logging-7.0.0.dist-info/RECORD +0 -18
- {beans_logging-7.0.0.dist-info → beans_logging-8.0.0.dist-info}/licenses/LICENSE.txt +0 -0
- {beans_logging-7.0.0.dist-info → beans_logging-8.0.0.dist-info}/top_level.txt +0 -0
beans_logging/__init__.py
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from .__version__ import __version__
|
|
4
|
-
from .
|
|
4
|
+
from .schemas import LoguruHandlerPM, LogHandlerPM
|
|
5
|
+
from .config import get_default_handlers, LoggerConfigPM
|
|
5
6
|
from ._core import Logger, logger, LoggerLoader
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
__all__ = [
|
|
9
10
|
"__version__",
|
|
11
|
+
"LoguruHandlerPM",
|
|
12
|
+
"LogHandlerPM",
|
|
13
|
+
"get_default_handlers",
|
|
10
14
|
"LoggerConfigPM",
|
|
11
15
|
"Logger",
|
|
12
16
|
"logger",
|
beans_logging/__version__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "
|
|
1
|
+
__version__ = "8.0.0"
|
beans_logging/_builder.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from typing import Any
|
|
3
|
+
from pathlib import Path
|
|
3
4
|
|
|
4
5
|
from pydantic import validate_call
|
|
5
6
|
|
|
6
|
-
from .
|
|
7
|
+
from .constants import LogHandlerTypeEnum, LogLevelEnum
|
|
7
8
|
from .schemas import LogHandlerPM
|
|
8
9
|
from .config import LoggerConfigPM
|
|
9
10
|
from .sinks import std_sink
|
|
@@ -34,117 +35,94 @@ def build_handler(handler: LogHandlerPM, config: LoggerConfigPM) -> dict[str, An
|
|
|
34
35
|
dict[str, Any]: Loguru handler config as dictionary.
|
|
35
36
|
"""
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if _handler_dict.get("type") == LogHandlerTypeEnum.STD:
|
|
41
|
-
_handler_dict["sink"] = std_sink
|
|
42
|
-
elif _handler_dict.get("type") == LogHandlerTypeEnum.FILE:
|
|
43
|
-
_logs_path: str = ""
|
|
44
|
-
if _handler_dict.get("serialize") or _handler_dict.get("custom_serialize"):
|
|
45
|
-
if _handler_dict.get("error"):
|
|
46
|
-
_logs_path = os.path.join(
|
|
47
|
-
config.default.file.logs_dir,
|
|
48
|
-
config.default.file.json_.err_path,
|
|
49
|
-
)
|
|
50
|
-
else:
|
|
51
|
-
_logs_path = os.path.join(
|
|
52
|
-
config.default.file.logs_dir,
|
|
53
|
-
config.default.file.json_.log_path,
|
|
54
|
-
)
|
|
55
|
-
else:
|
|
56
|
-
if _handler_dict.get("error"):
|
|
57
|
-
_logs_path = os.path.join(
|
|
58
|
-
config.default.file.logs_dir,
|
|
59
|
-
config.default.file.plain.err_path,
|
|
60
|
-
)
|
|
61
|
-
else:
|
|
62
|
-
_logs_path = os.path.join(
|
|
63
|
-
config.default.file.logs_dir,
|
|
64
|
-
config.default.file.plain.log_path,
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
if "{app_name}" in _logs_path:
|
|
68
|
-
_logs_path = _logs_path.format(app_name=config.app_name)
|
|
69
|
-
|
|
70
|
-
_handler_dict["sink"] = _logs_path
|
|
38
|
+
if handler.sink is None:
|
|
39
|
+
if handler.h_type == LogHandlerTypeEnum.STD:
|
|
40
|
+
handler.sink = std_sink
|
|
71
41
|
else:
|
|
72
42
|
raise ValueError(
|
|
73
|
-
"'sink' attribute is empty, required for any log handler except std
|
|
43
|
+
"'sink' attribute is empty, required for any log handler except std handler!"
|
|
74
44
|
)
|
|
75
45
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
_handler_dict["level"] = config.default.level.base
|
|
46
|
+
_sink = handler.sink
|
|
47
|
+
if isinstance(_sink, (str, Path)):
|
|
48
|
+
if not os.path.isabs(_sink):
|
|
49
|
+
_sink = os.path.join(config.default.file.logs_dir, _sink)
|
|
81
50
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
51
|
+
if isinstance(_sink, Path):
|
|
52
|
+
_sink = str(_sink)
|
|
53
|
+
|
|
54
|
+
if "{app_name}" in _sink:
|
|
55
|
+
_sink = _sink.format(app_name=config.app_name)
|
|
86
56
|
|
|
87
|
-
|
|
88
|
-
_handler_dict["serialize"] = False
|
|
89
|
-
_handler_dict["format"] = json_formatter
|
|
57
|
+
handler.sink = _sink
|
|
90
58
|
|
|
91
|
-
if
|
|
92
|
-
if
|
|
93
|
-
|
|
59
|
+
if handler.level is None:
|
|
60
|
+
if handler.error:
|
|
61
|
+
handler.level = config.default.level.err
|
|
94
62
|
else:
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
63
|
+
handler.level = config.default.level.base
|
|
64
|
+
|
|
65
|
+
if (handler.custom_serialize is None) and handler.serialize:
|
|
66
|
+
handler.custom_serialize = config.default.custom_serialize
|
|
67
|
+
|
|
68
|
+
if handler.custom_serialize:
|
|
69
|
+
handler.serialize = False
|
|
70
|
+
handler.format_ = json_formatter
|
|
71
|
+
|
|
72
|
+
if (handler.format_ is None) and (not handler.serialize):
|
|
73
|
+
handler.format_ = config.default.format_str
|
|
74
|
+
|
|
75
|
+
if handler.filter_ is None:
|
|
76
|
+
if handler.h_type == LogHandlerTypeEnum.STD:
|
|
77
|
+
handler.filter_ = use_std_filter
|
|
78
|
+
elif handler.h_type == LogHandlerTypeEnum.FILE:
|
|
79
|
+
if handler.serialize or handler.custom_serialize:
|
|
80
|
+
if handler.error:
|
|
81
|
+
handler.filter_ = use_file_json_err_filter
|
|
104
82
|
else:
|
|
105
|
-
|
|
83
|
+
handler.filter_ = use_file_json_filter
|
|
106
84
|
else:
|
|
107
|
-
if
|
|
108
|
-
|
|
85
|
+
if handler.error:
|
|
86
|
+
handler.filter_ = use_file_err_filter
|
|
109
87
|
else:
|
|
110
|
-
|
|
88
|
+
handler.filter_ = use_file_filter
|
|
111
89
|
else:
|
|
112
|
-
|
|
90
|
+
handler.filter_ = use_all_filter
|
|
113
91
|
|
|
114
|
-
if
|
|
115
|
-
|
|
92
|
+
if handler.backtrace is None:
|
|
93
|
+
handler.backtrace = True
|
|
116
94
|
|
|
117
|
-
if (
|
|
118
|
-
(
|
|
119
|
-
or (_handler_dict.get("level") == 5)
|
|
95
|
+
if (handler.diagnose is None) and (
|
|
96
|
+
(handler.level == LogLevelEnum.TRACE) or (handler.level == 5)
|
|
120
97
|
):
|
|
121
|
-
|
|
98
|
+
handler.diagnose = True
|
|
122
99
|
|
|
123
|
-
if
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
_handler_dict["colorize"] = config.default.std.colorize
|
|
127
|
-
|
|
128
|
-
if _handler_dict.get("type") == LogHandlerTypeEnum.FILE:
|
|
129
|
-
if _handler_dict.get("enqueue") is None:
|
|
130
|
-
_handler_dict["enqueue"] = True
|
|
100
|
+
if handler.h_type == LogHandlerTypeEnum.FILE:
|
|
101
|
+
if handler.enqueue is None:
|
|
102
|
+
handler.enqueue = True
|
|
131
103
|
|
|
132
|
-
if
|
|
133
|
-
|
|
104
|
+
if handler.rotation is None:
|
|
105
|
+
handler.rotation = Rotator(
|
|
134
106
|
rotate_size=config.default.file.rotate_size,
|
|
135
107
|
rotate_time=config.default.file.rotate_time,
|
|
136
108
|
).should_rotate
|
|
137
109
|
|
|
138
|
-
if
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
_handler_dict.
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
110
|
+
if handler.retention is None:
|
|
111
|
+
handler.retention = config.default.file.retention
|
|
112
|
+
|
|
113
|
+
if handler.encoding is None:
|
|
114
|
+
handler.encoding = config.default.file.encoding
|
|
115
|
+
|
|
116
|
+
_handler_dict = handler.model_dump(
|
|
117
|
+
by_alias=True,
|
|
118
|
+
exclude_none=True,
|
|
119
|
+
exclude={
|
|
120
|
+
"enabled",
|
|
121
|
+
"h_type",
|
|
122
|
+
"error",
|
|
123
|
+
"custom_serialize",
|
|
124
|
+
},
|
|
125
|
+
)
|
|
148
126
|
|
|
149
127
|
return _handler_dict
|
|
150
128
|
|
beans_logging/_core.py
CHANGED
|
@@ -17,10 +17,11 @@ from pydantic import validate_call
|
|
|
17
17
|
from potato_util import io as io_utils
|
|
18
18
|
|
|
19
19
|
# Internal modules
|
|
20
|
+
from .constants import DEFAULT_LOGURU_HANDLER_NAME, DEFAULT_NO_HANDLER_NAME_PREFIX
|
|
20
21
|
from .schemas import LogHandlerPM, LoguruHandlerPM
|
|
21
22
|
from .config import LoggerConfigPM
|
|
22
23
|
from ._builder import build_handler
|
|
23
|
-
from .
|
|
24
|
+
from .intercepters import add_intercepter
|
|
24
25
|
|
|
25
26
|
|
|
26
27
|
class LoggerLoader:
|
|
@@ -52,7 +53,7 @@ class LoggerLoader:
|
|
|
52
53
|
**kwargs,
|
|
53
54
|
) -> None:
|
|
54
55
|
|
|
55
|
-
self.handlers_map = {
|
|
56
|
+
self.handlers_map = {DEFAULT_LOGURU_HANDLER_NAME: 0}
|
|
56
57
|
if not config:
|
|
57
58
|
config = LoggerConfigPM()
|
|
58
59
|
|
|
@@ -63,15 +64,15 @@ class LoggerLoader:
|
|
|
63
64
|
self.config_path = config_path
|
|
64
65
|
|
|
65
66
|
if auto_load:
|
|
66
|
-
self.load()
|
|
67
|
+
self.load(load_config_file=True)
|
|
67
68
|
|
|
68
69
|
@validate_call
|
|
69
|
-
def load(self, load_config_file: bool =
|
|
70
|
+
def load(self, load_config_file: bool = False) -> "Logger":
|
|
70
71
|
"""Load logger handlers based on logger config.
|
|
71
72
|
|
|
72
73
|
Args:
|
|
73
74
|
load_config_file (bool, optional): Whether to load config from file before loading handlers.
|
|
74
|
-
Default is
|
|
75
|
+
Default is False.
|
|
75
76
|
|
|
76
77
|
Returns:
|
|
77
78
|
Logger: Main loguru logger instance.
|
|
@@ -84,7 +85,7 @@ class LoggerLoader:
|
|
|
84
85
|
for _key, _handler in self.config.handlers.items():
|
|
85
86
|
self.add_handler(name=_key, handler=_handler)
|
|
86
87
|
|
|
87
|
-
|
|
88
|
+
add_intercepter(config=self.config)
|
|
88
89
|
return logger
|
|
89
90
|
|
|
90
91
|
def _load_config_file(self) -> None:
|
|
@@ -195,7 +196,7 @@ class LoggerLoader:
|
|
|
195
196
|
|
|
196
197
|
_handler_id = logger.add(**_handler_dict)
|
|
197
198
|
if not name:
|
|
198
|
-
name = f"
|
|
199
|
+
name = f"{DEFAULT_NO_HANDLER_NAME_PREFIX}{uuid.uuid4().hex}"
|
|
199
200
|
|
|
200
201
|
self.handlers_map[name] = _handler_id
|
|
201
202
|
|
beans_logging/config.py
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
import
|
|
1
|
+
import os
|
|
2
2
|
import datetime
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
|
-
if sys.version_info >= (3, 11):
|
|
6
|
-
from typing import Self
|
|
7
|
-
else:
|
|
8
|
-
from typing_extensions import Self
|
|
9
|
-
|
|
10
5
|
import potato_util as utils
|
|
11
|
-
from pydantic import Field,
|
|
6
|
+
from pydantic import Field, field_validator
|
|
12
7
|
|
|
13
|
-
from .
|
|
14
|
-
|
|
8
|
+
from .constants import (
|
|
9
|
+
LogLevelEnum,
|
|
10
|
+
LogHandlerTypeEnum,
|
|
11
|
+
DEFAULT_ALL_STD_HANDLER_NAME,
|
|
12
|
+
DEFAULT_ALL_FILE_HANDLER_NAME,
|
|
13
|
+
DEFAULT_ERR_FILE_HANDLER_NAME,
|
|
14
|
+
DEFAULT_ALL_JSON_HANDLER_NAME,
|
|
15
|
+
DEFAULT_ERR_JSON_HANDLER_NAME,
|
|
16
|
+
)
|
|
17
|
+
from .schemas import ExtraBaseModel, LogHandlerPM
|
|
15
18
|
|
|
16
19
|
|
|
17
|
-
def
|
|
20
|
+
def get_default_handlers() -> dict[str, LogHandlerPM]:
|
|
18
21
|
"""Get default log handlers.
|
|
19
22
|
|
|
20
23
|
Returns:
|
|
@@ -22,53 +25,46 @@ def _get_handlers() -> dict[str, LogHandlerPM]:
|
|
|
22
25
|
"""
|
|
23
26
|
|
|
24
27
|
_log_handlers: dict[str, LogHandlerPM] = {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
DEFAULT_ALL_STD_HANDLER_NAME: LogHandlerPM(
|
|
29
|
+
h_type=LogHandlerTypeEnum.STD,
|
|
30
|
+
format_=(
|
|
31
|
+
"[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | "
|
|
32
|
+
"<w>{name}:{line}</w>]: <level>{message}</level>"
|
|
33
|
+
),
|
|
34
|
+
colorize=True,
|
|
35
|
+
),
|
|
36
|
+
DEFAULT_ALL_FILE_HANDLER_NAME: LogHandlerPM(
|
|
37
|
+
enabled=False,
|
|
38
|
+
h_type=LogHandlerTypeEnum.FILE,
|
|
39
|
+
sink="{app_name}.all.log",
|
|
28
40
|
),
|
|
29
|
-
|
|
30
|
-
|
|
41
|
+
DEFAULT_ERR_FILE_HANDLER_NAME: LogHandlerPM(
|
|
42
|
+
enabled=False,
|
|
43
|
+
h_type=LogHandlerTypeEnum.FILE,
|
|
44
|
+
sink="{app_name}.err.log",
|
|
45
|
+
error=True,
|
|
31
46
|
),
|
|
32
|
-
|
|
33
|
-
|
|
47
|
+
DEFAULT_ALL_JSON_HANDLER_NAME: LogHandlerPM(
|
|
48
|
+
enabled=False,
|
|
49
|
+
h_type=LogHandlerTypeEnum.FILE,
|
|
50
|
+
sink="json/{app_name}.all.json.log",
|
|
51
|
+
serialize=True,
|
|
34
52
|
),
|
|
35
|
-
|
|
36
|
-
|
|
53
|
+
DEFAULT_ERR_JSON_HANDLER_NAME: LogHandlerPM(
|
|
54
|
+
enabled=False,
|
|
55
|
+
h_type=LogHandlerTypeEnum.FILE,
|
|
56
|
+
sink="json/{app_name}.err.json.log",
|
|
57
|
+
serialize=True,
|
|
58
|
+
error=True,
|
|
37
59
|
),
|
|
38
60
|
}
|
|
39
61
|
|
|
40
62
|
return _log_handlers
|
|
41
63
|
|
|
42
64
|
|
|
43
|
-
class StdConfigPM(ExtraBaseModel):
|
|
44
|
-
format_str: str = Field(
|
|
45
|
-
default=(
|
|
46
|
-
"[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{name}:{line}</w>]:"
|
|
47
|
-
" <level>{message}</level>"
|
|
48
|
-
),
|
|
49
|
-
min_length=8,
|
|
50
|
-
max_length=512,
|
|
51
|
-
)
|
|
52
|
-
colorize: bool = Field(default=True)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
class PathsConfigPM(ExtraBaseModel):
|
|
56
|
-
log_path: str = Field(..., min_length=4, max_length=1024)
|
|
57
|
-
err_path: str = Field(..., min_length=4, max_length=1024)
|
|
58
|
-
|
|
59
|
-
@model_validator(mode="after")
|
|
60
|
-
def _check_log_path(self) -> Self:
|
|
61
|
-
if self.log_path == self.err_path:
|
|
62
|
-
raise ValueError(
|
|
63
|
-
f"`log_path` and `err_path` attributes have same value: '{self.log_path}', must be different!"
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
return self
|
|
67
|
-
|
|
68
|
-
|
|
69
65
|
class FileConfigPM(ExtraBaseModel):
|
|
70
66
|
logs_dir: str = Field(
|
|
71
|
-
|
|
67
|
+
default_factory=lambda: os.path.join(os.getcwd(), "logs"),
|
|
72
68
|
min_length=2,
|
|
73
69
|
max_length=1024,
|
|
74
70
|
)
|
|
@@ -79,21 +75,6 @@ class FileConfigPM(ExtraBaseModel):
|
|
|
79
75
|
retention: int = Field(default=90, ge=1)
|
|
80
76
|
encoding: str = Field(default="utf8", min_length=2, max_length=31)
|
|
81
77
|
|
|
82
|
-
plain: PathsConfigPM = Field(
|
|
83
|
-
default_factory=lambda: PathsConfigPM(
|
|
84
|
-
log_path="{app_name}.all.log",
|
|
85
|
-
err_path="{app_name}.err.log",
|
|
86
|
-
)
|
|
87
|
-
)
|
|
88
|
-
json_: PathsConfigPM = Field(
|
|
89
|
-
default_factory=lambda: PathsConfigPM(
|
|
90
|
-
log_path="json/{app_name}.json.all.log",
|
|
91
|
-
err_path="json/{app_name}.json.err.log",
|
|
92
|
-
),
|
|
93
|
-
validation_alias="json",
|
|
94
|
-
serialization_alias="json",
|
|
95
|
-
)
|
|
96
|
-
|
|
97
78
|
@field_validator("rotate_time", mode="before")
|
|
98
79
|
@classmethod
|
|
99
80
|
def _check_rotate_time(cls, val: Any) -> Any:
|
|
@@ -102,6 +83,14 @@ class FileConfigPM(ExtraBaseModel):
|
|
|
102
83
|
|
|
103
84
|
return val
|
|
104
85
|
|
|
86
|
+
@field_validator("logs_dir", mode="before")
|
|
87
|
+
@classmethod
|
|
88
|
+
def _check_logs_dir(cls, val: Any) -> Any:
|
|
89
|
+
if isinstance(val, str) and (not os.path.isabs(val)):
|
|
90
|
+
val = os.path.abspath(val)
|
|
91
|
+
|
|
92
|
+
return val
|
|
93
|
+
|
|
105
94
|
|
|
106
95
|
class LevelConfigPM(ExtraBaseModel):
|
|
107
96
|
base: str | int | LogLevelEnum = Field(default=LogLevelEnum.INFO)
|
|
@@ -123,7 +112,6 @@ class LevelConfigPM(ExtraBaseModel):
|
|
|
123
112
|
|
|
124
113
|
class DefaultConfigPM(ExtraBaseModel):
|
|
125
114
|
level: LevelConfigPM = Field(default_factory=LevelConfigPM)
|
|
126
|
-
std: StdConfigPM = Field(default_factory=StdConfigPM)
|
|
127
115
|
format_str: str = Field(
|
|
128
116
|
default="[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line}]: {message}",
|
|
129
117
|
min_length=8,
|
|
@@ -151,36 +139,54 @@ class LoggerConfigPM(ExtraBaseModel):
|
|
|
151
139
|
)
|
|
152
140
|
default: DefaultConfigPM = Field(default_factory=DefaultConfigPM)
|
|
153
141
|
intercept: InterceptConfigPM = Field(default_factory=InterceptConfigPM)
|
|
154
|
-
handlers: dict[str, LogHandlerPM] = Field(default_factory=
|
|
142
|
+
handlers: dict[str, LogHandlerPM] = Field(default_factory=get_default_handlers)
|
|
155
143
|
extra: ExtraConfigPM | None = Field(default_factory=ExtraConfigPM)
|
|
156
144
|
|
|
157
145
|
@field_validator("handlers", mode="before")
|
|
158
146
|
@classmethod
|
|
159
|
-
def _check_handlers(cls, val: Any) ->
|
|
160
|
-
|
|
161
|
-
|
|
147
|
+
def _check_handlers(cls, val: Any) -> dict[str, LogHandlerPM]:
|
|
148
|
+
|
|
149
|
+
_default_handlers = get_default_handlers()
|
|
150
|
+
|
|
151
|
+
if not val:
|
|
152
|
+
val = _default_handlers
|
|
153
|
+
return val
|
|
154
|
+
|
|
155
|
+
if not isinstance(val, dict):
|
|
156
|
+
raise TypeError(
|
|
157
|
+
f"'handlers' attribute type {type(val).__name__} is invalid, must be a dict of <LogHandlerPM> or dict!"
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
for _key, _handler in val.items():
|
|
161
|
+
if not isinstance(_handler, (LogHandlerPM, dict)):
|
|
162
162
|
raise TypeError(
|
|
163
|
-
f"'handlers' attribute type {type(
|
|
164
|
-
f"<
|
|
163
|
+
f"'handlers' attribute's '{_key}' key -> value type {type(_handler).__name__} is invalid, must be "
|
|
164
|
+
f"<LogHandlerPM> or dict!"
|
|
165
165
|
)
|
|
166
166
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
167
|
+
if isinstance(_handler, LogHandlerPM):
|
|
168
|
+
val[_key] = _handler.model_dump(
|
|
169
|
+
by_alias=True, exclude_unset=True, exclude_none=True
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
_default_dict = {
|
|
173
|
+
_key: _handler.model_dump(
|
|
174
|
+
by_alias=True, exclude_unset=True, exclude_none=True
|
|
175
|
+
)
|
|
176
|
+
for _key, _handler in _default_handlers.items()
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if _default_dict != val:
|
|
180
|
+
val = utils.deep_merge(_default_dict, val)
|
|
173
181
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
**_handler.model_dump(exclude_none=True, exclude_unset=True)
|
|
177
|
-
)
|
|
178
|
-
elif isinstance(_handler, dict):
|
|
179
|
-
val[_i] = LogHandlerPM(**_handler)
|
|
182
|
+
for _key, _handler in val.items():
|
|
183
|
+
val[_key] = LogHandlerPM(**_handler)
|
|
180
184
|
|
|
181
185
|
return val
|
|
182
186
|
|
|
183
187
|
|
|
184
188
|
__all__ = [
|
|
185
189
|
"LoggerConfigPM",
|
|
190
|
+
"InterceptConfigPM",
|
|
191
|
+
"get_default_handlers",
|
|
186
192
|
]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class LogHandlerTypeEnum(str, Enum):
|
|
5
|
+
STD = "STD"
|
|
6
|
+
FILE = "FILE"
|
|
7
|
+
SOCKET = "SOCKET"
|
|
8
|
+
HTTP = "HTTP"
|
|
9
|
+
SYSLOG = "SYSLOG"
|
|
10
|
+
QUEUE = "QUEUE"
|
|
11
|
+
MEMORY = "MEMORY"
|
|
12
|
+
NULL = "NULL"
|
|
13
|
+
CUSTOM = "CUSTOM"
|
|
14
|
+
UNKNOWN = "UNKNOWN"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class LogLevelEnum(str, Enum):
|
|
18
|
+
TRACE = "TRACE"
|
|
19
|
+
DEBUG = "DEBUG"
|
|
20
|
+
INFO = "INFO"
|
|
21
|
+
SUCCESS = "SUCCESS"
|
|
22
|
+
WARNING = "WARNING"
|
|
23
|
+
ERROR = "ERROR"
|
|
24
|
+
CRITICAL = "CRITICAL"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
DEFAULT_LOGURU_HANDLER_NAME = "default.loguru.std_handler"
|
|
28
|
+
DEFAULT_ALL_STD_HANDLER_NAME = "default.all.std_handler"
|
|
29
|
+
DEFAULT_ALL_FILE_HANDLER_NAME = "default.all.file_handler"
|
|
30
|
+
DEFAULT_ERR_FILE_HANDLER_NAME = "default.err.file_handler"
|
|
31
|
+
DEFAULT_ALL_JSON_HANDLER_NAME = "default.all.json_handler"
|
|
32
|
+
DEFAULT_ERR_JSON_HANDLER_NAME = "default.err.json_handler"
|
|
33
|
+
DEFAULT_NO_HANDLER_NAME_PREFIX = "log_handler."
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
__all__ = [
|
|
37
|
+
"LogHandlerTypeEnum",
|
|
38
|
+
"LogLevelEnum",
|
|
39
|
+
"DEFAULT_LOGURU_HANDLER_NAME",
|
|
40
|
+
"DEFAULT_ALL_STD_HANDLER_NAME",
|
|
41
|
+
"DEFAULT_ALL_FILE_HANDLER_NAME",
|
|
42
|
+
"DEFAULT_ERR_FILE_HANDLER_NAME",
|
|
43
|
+
"DEFAULT_ALL_JSON_HANDLER_NAME",
|
|
44
|
+
"DEFAULT_ERR_JSON_HANDLER_NAME",
|
|
45
|
+
"DEFAULT_NO_HANDLER_NAME_PREFIX",
|
|
46
|
+
]
|
|
@@ -45,7 +45,7 @@ class InterceptHandler(Handler):
|
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
@validate_call
|
|
48
|
-
def
|
|
48
|
+
def add_intercepter(config: LoggerConfigPM) -> None:
|
|
49
49
|
"""Initialize log interceptor based on provided config.
|
|
50
50
|
|
|
51
51
|
Args:
|
|
@@ -102,5 +102,5 @@ def init_intercepter(config: LoggerConfigPM) -> None:
|
|
|
102
102
|
|
|
103
103
|
__all__ = [
|
|
104
104
|
"InterceptHandler",
|
|
105
|
-
"
|
|
105
|
+
"add_intercepter",
|
|
106
106
|
]
|
beans_logging/schemas.py
CHANGED
|
@@ -19,7 +19,7 @@ if TYPE_CHECKING:
|
|
|
19
19
|
from loguru import Record, Message
|
|
20
20
|
from pydantic import BaseModel, Field, ConfigDict, model_validator
|
|
21
21
|
|
|
22
|
-
from .
|
|
22
|
+
from .constants import LogHandlerTypeEnum, LogLevelEnum
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class ExtraBaseModel(BaseModel):
|
|
@@ -94,11 +94,7 @@ class LoguruHandlerPM(ExtraBaseModel):
|
|
|
94
94
|
|
|
95
95
|
|
|
96
96
|
class LogHandlerPM(LoguruHandlerPM):
|
|
97
|
-
|
|
98
|
-
default=LogHandlerTypeEnum.UNKNOWN,
|
|
99
|
-
validation_alias="type",
|
|
100
|
-
serialization_alias="type",
|
|
101
|
-
)
|
|
97
|
+
h_type: LogHandlerTypeEnum = Field(default=LogHandlerTypeEnum.UNKNOWN)
|
|
102
98
|
sink: _SinkType | None = Field(default=None)
|
|
103
99
|
level: str | int | LogLevelEnum | None = Field(default=None)
|
|
104
100
|
custom_serialize: bool | None = Field(default=None)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: beans_logging
|
|
3
|
-
Version:
|
|
3
|
+
Version: 8.0.0
|
|
4
4
|
Summary: 'beans-logging' is a python package for simple logger and easily managing logs.
|
|
5
5
|
Author-email: Batkhuu Byambajav <batkhuu10@gmail.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/bybatkhuu/module-python-logging
|
|
@@ -25,7 +25,7 @@ Requires-Dist: pydantic[timezone]<3.0.0,>=2.5.3
|
|
|
25
25
|
Requires-Dist: loguru<1.0.0,>=0.7.3
|
|
26
26
|
Requires-Dist: potato_util<1.0.0,>=0.2.0
|
|
27
27
|
Provides-Extra: fastapi
|
|
28
|
-
Requires-Dist: beans-logging-fastapi<
|
|
28
|
+
Requires-Dist: beans-logging-fastapi<3.0.0,>=1.0.0; extra == "fastapi"
|
|
29
29
|
Provides-Extra: test
|
|
30
30
|
Requires-Dist: pytest<10.0.0,>=8.0.2; extra == "test"
|
|
31
31
|
Requires-Dist: pytest-cov<8.0.0,>=5.0.0; extra == "test"
|
|
@@ -38,6 +38,7 @@ Requires-Dist: build<2.0.0,>=1.1.1; extra == "build"
|
|
|
38
38
|
Requires-Dist: twine<7.0.0,>=6.0.1; extra == "build"
|
|
39
39
|
Provides-Extra: docs
|
|
40
40
|
Requires-Dist: pylint<5.0.0,>=3.0.4; extra == "docs"
|
|
41
|
+
Requires-Dist: click<8.2.2,>=8.0.0; extra == "docs"
|
|
41
42
|
Requires-Dist: mkdocs-material<10.0.0,>=9.5.50; extra == "docs"
|
|
42
43
|
Requires-Dist: mkdocs-awesome-nav<4.0.0,>=3.0.0; extra == "docs"
|
|
43
44
|
Requires-Dist: mkdocstrings[python]<2.0.0,>=0.24.3; extra == "docs"
|
|
@@ -52,6 +53,7 @@ Requires-Dist: wheel<1.0.0,>=0.43.0; extra == "dev"
|
|
|
52
53
|
Requires-Dist: build<2.0.0,>=1.1.1; extra == "dev"
|
|
53
54
|
Requires-Dist: twine<7.0.0,>=6.0.1; extra == "dev"
|
|
54
55
|
Requires-Dist: pylint<5.0.0,>=3.0.4; extra == "dev"
|
|
56
|
+
Requires-Dist: click<8.2.2,>=8.0.0; extra == "dev"
|
|
55
57
|
Requires-Dist: mkdocs-material<10.0.0,>=9.5.50; extra == "dev"
|
|
56
58
|
Requires-Dist: mkdocs-awesome-nav<4.0.0,>=3.0.0; extra == "dev"
|
|
57
59
|
Requires-Dist: mkdocstrings[python]<2.0.0,>=0.24.3; extra == "dev"
|
|
@@ -102,42 +104,7 @@ It is a `Loguru` based custom logging package for python projects.
|
|
|
102
104
|
- Install [**git**](https://git-scm.com/downloads)
|
|
103
105
|
- Setup an [**SSH key**](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh)
|
|
104
106
|
|
|
105
|
-
### 2.
|
|
106
|
-
|
|
107
|
-
[TIP] Skip this step, if you're going to install the package directly from **PyPi** or **GitHub** repository.
|
|
108
|
-
|
|
109
|
-
**2.1.** Prepare projects directory (if not exists):
|
|
110
|
-
|
|
111
|
-
```sh
|
|
112
|
-
# Create projects directory:
|
|
113
|
-
mkdir -pv ~/workspaces/projects
|
|
114
|
-
|
|
115
|
-
# Enter into projects directory:
|
|
116
|
-
cd ~/workspaces/projects
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
**2.2.** Follow one of the below options **[A]**, **[B]** or **[C]**:
|
|
120
|
-
|
|
121
|
-
**OPTION A.** Clone the repository:
|
|
122
|
-
|
|
123
|
-
```sh
|
|
124
|
-
git clone https://github.com/bybatkhuu/module-python-logging.git && \
|
|
125
|
-
cd module-python-logging
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
**OPTION B.** Clone the repository (for **DEVELOPMENT**: git + ssh key):
|
|
129
|
-
|
|
130
|
-
```sh
|
|
131
|
-
git clone git@github.com:bybatkhuu/module-python-logging.git && \
|
|
132
|
-
cd module-python-logging
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
**OPTION C.** Download source code:
|
|
136
|
-
|
|
137
|
-
1. Download archived **zip** file from [**releases**](https://github.com/bybatkhuu/module-python-logging/releases).
|
|
138
|
-
2. Extract it into the projects directory.
|
|
139
|
-
|
|
140
|
-
### 3. 📦 Install the package
|
|
107
|
+
### 2. 📦 Install the package
|
|
141
108
|
|
|
142
109
|
[NOTE] Choose one of the following methods to install the package **[A ~ F]**:
|
|
143
110
|
|
|
@@ -156,6 +123,9 @@ pip install git+https://github.com/bybatkhuu/module-python-logging.git
|
|
|
156
123
|
**OPTION C.** Install from the downloaded **source code**:
|
|
157
124
|
|
|
158
125
|
```sh
|
|
126
|
+
git clone https://github.com/bybatkhuu/module-python-logging.git && \
|
|
127
|
+
cd ./module-python-logging
|
|
128
|
+
|
|
159
129
|
# Install directly from the source code:
|
|
160
130
|
pip install .
|
|
161
131
|
|
|
@@ -323,9 +293,6 @@ logger:
|
|
|
323
293
|
level:
|
|
324
294
|
base: INFO
|
|
325
295
|
err: WARNING
|
|
326
|
-
std:
|
|
327
|
-
format_str: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{name}:{line}</w>]: <level>{message}</level>"
|
|
328
|
-
colorize: true
|
|
329
296
|
format_str: "[{time:YYYY-MM-DD HH:mm:ss.SSS Z} | {extra[level_short]:<5} | {name}:{line}]: {message}"
|
|
330
297
|
file:
|
|
331
298
|
logs_dir: "./logs"
|
|
@@ -333,12 +300,6 @@ logger:
|
|
|
333
300
|
rotate_time: "00:00:00"
|
|
334
301
|
retention: 90
|
|
335
302
|
encoding: utf8
|
|
336
|
-
plain:
|
|
337
|
-
log_path: "{app_name}.all.log"
|
|
338
|
-
err_path: "{app_name}.err.log"
|
|
339
|
-
json:
|
|
340
|
-
log_path: "json/{app_name}.json.all.log"
|
|
341
|
-
err_path: "json/{app_name}.json.err.log"
|
|
342
303
|
custom_serialize: false
|
|
343
304
|
intercept:
|
|
344
305
|
enabled: true
|
|
@@ -348,24 +309,30 @@ logger:
|
|
|
348
309
|
mute_modules: []
|
|
349
310
|
handlers:
|
|
350
311
|
default.all.std_handler:
|
|
351
|
-
type: STD
|
|
352
312
|
enabled: true
|
|
313
|
+
h_type: STD
|
|
314
|
+
format: "[<c>{time:YYYY-MM-DD HH:mm:ss.SSS Z}</c> | <level>{extra[level_short]:<5}</level> | <w>{name}:{line}</w>]: <level>{message}</level>"
|
|
315
|
+
colorize: true
|
|
353
316
|
default.all.file_handler:
|
|
354
|
-
type: FILE
|
|
355
317
|
enabled: false
|
|
318
|
+
h_type: FILE
|
|
319
|
+
sink: "{app_name}.all.log"
|
|
356
320
|
default.err.file_handler:
|
|
357
|
-
type: FILE
|
|
358
|
-
error: true
|
|
359
321
|
enabled: false
|
|
322
|
+
h_type: FILE
|
|
323
|
+
sink: "{app_name}.err.log"
|
|
324
|
+
error: true
|
|
360
325
|
default.all.json_handler:
|
|
361
|
-
type: FILE
|
|
362
|
-
serialize: true
|
|
363
326
|
enabled: false
|
|
327
|
+
h_type: FILE
|
|
328
|
+
sink: "json/{app_name}.all.json.log"
|
|
329
|
+
serialize: true
|
|
364
330
|
default.err.json_handler:
|
|
365
|
-
|
|
331
|
+
enabled: false
|
|
332
|
+
h_type: FILE
|
|
333
|
+
sink: "json/{app_name}.err.json.log"
|
|
366
334
|
serialize: true
|
|
367
335
|
error: true
|
|
368
|
-
enabled: false
|
|
369
336
|
extra:
|
|
370
337
|
```
|
|
371
338
|
|
|
@@ -418,7 +385,7 @@ To build the documentation, run the following command:
|
|
|
418
385
|
pip install -r ./requirements/requirements.docs.txt
|
|
419
386
|
|
|
420
387
|
# Serve documentation locally (for development):
|
|
421
|
-
mkdocs serve -a 0.0.0.0:8000
|
|
388
|
+
mkdocs serve -a 0.0.0.0:8000 --livereload
|
|
422
389
|
# Or use the docs script:
|
|
423
390
|
./scripts/docs.sh
|
|
424
391
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
beans_logging/__init__.py,sha256=evD0GgFDj9LjQPuJLP_9uEYBPAlU04-nD5Rq1n76Utg,405
|
|
2
|
+
beans_logging/__version__.py,sha256=SWqJTEDnx2fOon29wQowBCNjEkhyhMbbqVsSu4EpdWI,22
|
|
3
|
+
beans_logging/_builder.py,sha256=Pg9fXFPMCe4o-hl1xJPajSTmdglJ0Emofxdzuod_9xM,3935
|
|
4
|
+
beans_logging/_core.py,sha256=lG-wRvQ6vz4rS2Je74MAg80xmdHx2Iue9LHOh2S7zYc,9746
|
|
5
|
+
beans_logging/auto.py,sha256=MoNuQomiIFWQVpNTkOmFFVMo00HBlErfHC728GFOyqc,218
|
|
6
|
+
beans_logging/config.py,sha256=NpZo0wiwsYe25OyPMoHRtkbVG6UxuEHEfO3w7O1kbWM,6102
|
|
7
|
+
beans_logging/constants.py,sha256=Ztt08flQ-378TMYiasAI5pUvLxKJ3p0WEb0w71wXKsE,1169
|
|
8
|
+
beans_logging/filters.py,sha256=-Rys2rwuT7EUvuEA19jnhW6enIEkDuPzeGbAAz6RJSc,3720
|
|
9
|
+
beans_logging/formats.py,sha256=Vrr4RkCfiJl-oi6BLVxeR-k0WhTR0oBI4mpsWgBJBNE,1624
|
|
10
|
+
beans_logging/intercepters.py,sha256=9tgyNXE7d_OlHUl9IJ2yEeDmUWZBYGYCWXMT3r58_RM,3247
|
|
11
|
+
beans_logging/rotators.py,sha256=lzR31sdEPTZVDkyhC81FL4OnezIVKlElGJDRA2Svn2I,2121
|
|
12
|
+
beans_logging/schemas.py,sha256=7C8PKwWVnayX4NmPA-mKajB4Lrksgr0QUJGjbEU5mro,4360
|
|
13
|
+
beans_logging/sinks.py,sha256=7Guusg3N1S-28hLnRzuunP8lXnhexzny3aj-AR0HhuQ,482
|
|
14
|
+
beans_logging-8.0.0.dist-info/licenses/LICENSE.txt,sha256=CUTK-r0BWIg1r0bBiemAcMhakgV0N7HuRhw6rQ-A9A4,1074
|
|
15
|
+
beans_logging-8.0.0.dist-info/METADATA,sha256=P06jptdg47p2ea3XmKb-esErDJ17MZY-Xn0oVpNHYmI,12384
|
|
16
|
+
beans_logging-8.0.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
17
|
+
beans_logging-8.0.0.dist-info/top_level.txt,sha256=lx8JEqYGNha1sYbVrTtMo2Z01A7Shq8hX6bfsuKLTG8,14
|
|
18
|
+
beans_logging-8.0.0.dist-info/RECORD,,
|
beans_logging/_constants.py
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
from enum import Enum
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class LogHandlerTypeEnum(str, Enum):
|
|
5
|
-
STD = "STD"
|
|
6
|
-
FILE = "FILE"
|
|
7
|
-
SOCKET = "SOCKET"
|
|
8
|
-
HTTP = "HTTP"
|
|
9
|
-
SYSLOG = "SYSLOG"
|
|
10
|
-
QUEUE = "QUEUE"
|
|
11
|
-
MEMORY = "MEMORY"
|
|
12
|
-
NULL = "NULL"
|
|
13
|
-
CUSTOM = "CUSTOM"
|
|
14
|
-
UNKNOWN = "UNKNOWN"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class LogLevelEnum(str, Enum):
|
|
18
|
-
TRACE = "TRACE"
|
|
19
|
-
DEBUG = "DEBUG"
|
|
20
|
-
INFO = "INFO"
|
|
21
|
-
SUCCESS = "SUCCESS"
|
|
22
|
-
WARNING = "WARNING"
|
|
23
|
-
ERROR = "ERROR"
|
|
24
|
-
CRITICAL = "CRITICAL"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
__all__ = [
|
|
28
|
-
"LogHandlerTypeEnum",
|
|
29
|
-
"LogLevelEnum",
|
|
30
|
-
]
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
beans_logging/__init__.py,sha256=KOXpuCNTMsdlY9MF6ONwRjM5O1_JCkIzt_qetb2BFTw,261
|
|
2
|
-
beans_logging/__version__.py,sha256=VgMOOqsYbyb60I1RmlZpqwqQ0C0IyT3R0c8_xX4pRGM,22
|
|
3
|
-
beans_logging/_builder.py,sha256=KUHZLMj6AqyDQGpVVB4XGEP3xI_kkjNMG-pbV_PvtLE,5644
|
|
4
|
-
beans_logging/_constants.py,sha256=rH9ZN-b7GXNXjbpOZUJfsft54Eiy8jnXm82jsFcMo3k,510
|
|
5
|
-
beans_logging/_core.py,sha256=qkGl5NRKY7lKuVatwFmddwxeYS5viU5DDnfKucWK3Mo,9617
|
|
6
|
-
beans_logging/_intercept.py,sha256=TeYze0eXRMVkOoC9Bl2qmaC7fSwExfQAmmGHz5KiuCU,3249
|
|
7
|
-
beans_logging/auto.py,sha256=MoNuQomiIFWQVpNTkOmFFVMo00HBlErfHC728GFOyqc,218
|
|
8
|
-
beans_logging/config.py,sha256=yDA-IbjhMIgP1DrFKa0ZDibNWAH_Ov8R7Hnqfggl71E,6172
|
|
9
|
-
beans_logging/filters.py,sha256=-Rys2rwuT7EUvuEA19jnhW6enIEkDuPzeGbAAz6RJSc,3720
|
|
10
|
-
beans_logging/formats.py,sha256=Vrr4RkCfiJl-oi6BLVxeR-k0WhTR0oBI4mpsWgBJBNE,1624
|
|
11
|
-
beans_logging/rotators.py,sha256=lzR31sdEPTZVDkyhC81FL4OnezIVKlElGJDRA2Svn2I,2121
|
|
12
|
-
beans_logging/schemas.py,sha256=b4igq8CkAzn7CGOBDc09hW0YTvWyuWRe97fpv_OaNdk,4444
|
|
13
|
-
beans_logging/sinks.py,sha256=7Guusg3N1S-28hLnRzuunP8lXnhexzny3aj-AR0HhuQ,482
|
|
14
|
-
beans_logging-7.0.0.dist-info/licenses/LICENSE.txt,sha256=CUTK-r0BWIg1r0bBiemAcMhakgV0N7HuRhw6rQ-A9A4,1074
|
|
15
|
-
beans_logging-7.0.0.dist-info/METADATA,sha256=v6LwlP4Gc4ZnyvYnVHka9okW38UV9e2f2A_23-5Q9qs,13155
|
|
16
|
-
beans_logging-7.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
17
|
-
beans_logging-7.0.0.dist-info/top_level.txt,sha256=lx8JEqYGNha1sYbVrTtMo2Z01A7Shq8hX6bfsuKLTG8,14
|
|
18
|
-
beans_logging-7.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|