br-logging-and-profiling 0.1.0__tar.gz
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.
- br_logging_and_profiling-0.1.0/PKG-INFO +57 -0
- br_logging_and_profiling-0.1.0/README.md +29 -0
- br_logging_and_profiling-0.1.0/br_logging_and_profiling.egg-info/PKG-INFO +57 -0
- br_logging_and_profiling-0.1.0/br_logging_and_profiling.egg-info/SOURCES.txt +13 -0
- br_logging_and_profiling-0.1.0/br_logging_and_profiling.egg-info/dependency_links.txt +1 -0
- br_logging_and_profiling-0.1.0/br_logging_and_profiling.egg-info/requires.txt +11 -0
- br_logging_and_profiling-0.1.0/br_logging_and_profiling.egg-info/top_level.txt +1 -0
- br_logging_and_profiling-0.1.0/br_py_log_n_profile/__init__.py +15 -0
- br_logging_and_profiling-0.1.0/br_py_log_n_profile/do_log/__init__.py +4 -0
- br_logging_and_profiling-0.1.0/br_py_log_n_profile/do_log/log_it.py +145 -0
- br_logging_and_profiling-0.1.0/br_py_log_n_profile/do_log/ray_id.py +23 -0
- br_logging_and_profiling-0.1.0/br_py_log_n_profile/profiling/__init__.py +1 -0
- br_logging_and_profiling-0.1.0/br_py_log_n_profile/profiling/base.py +80 -0
- br_logging_and_profiling-0.1.0/pyproject.toml +78 -0
- br_logging_and_profiling-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: br-logging-and-profiling
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Loguru-based logging facade, correlation IDs, and profiling decorator extracted from Forecasting-sidecar3.
|
|
5
|
+
Author: Brais Diaz
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/brais/br-logging-and-profiling
|
|
8
|
+
Project-URL: Repository, https://github.com/brais/br-logging-and-profiling
|
|
9
|
+
Keywords: logging,profiling,loguru,colorama,ray-id
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Requires-Python: >=3.12
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: loguru>=0.7.0
|
|
19
|
+
Requires-Dist: colorama>=0.4.6
|
|
20
|
+
Requires-Dist: pandas>=2.0
|
|
21
|
+
Requires-Dist: numpy<2.2,>=1.24
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
24
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
25
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
26
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
27
|
+
Requires-Dist: gitpython; extra == "dev"
|
|
28
|
+
|
|
29
|
+
# br_logging_and_profiling
|
|
30
|
+
|
|
31
|
+
Reusable logging/profiling/tracing package extracted from Forecasting-sidecar3.
|
|
32
|
+
|
|
33
|
+
## Current state
|
|
34
|
+
|
|
35
|
+
- Logging: Loguru + colorama via `br_py_log_n_profile.do_log.log_it`
|
|
36
|
+
- Profiling: `profile_it` decorator (wall-clock timing, colored console output)
|
|
37
|
+
- Correlation IDs: `ray_id` via `contextvars.ContextVar`
|
|
38
|
+
|
|
39
|
+
## Planned
|
|
40
|
+
|
|
41
|
+
- `tracing/` module: `init_tracing()`, `traced` decorator (OTel span replacement for `profile_it`), `@counted`/`@timed_metric` for hot-loop metrics
|
|
42
|
+
- Backend: Prometheus + Jaeger + Grafana + OTel Collector
|
|
43
|
+
- Migration phases: Phase 0 (deps/config) → Phase 1 (core tracing) → Phase 2 (migrate by layer) → Phase 3 (metrics) → Phase 4 (backend stack)
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install br-logging-and-profiling
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Development
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install -r requirements-dev.txt
|
|
55
|
+
pre-commit install
|
|
56
|
+
pytest -m unit
|
|
57
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# br_logging_and_profiling
|
|
2
|
+
|
|
3
|
+
Reusable logging/profiling/tracing package extracted from Forecasting-sidecar3.
|
|
4
|
+
|
|
5
|
+
## Current state
|
|
6
|
+
|
|
7
|
+
- Logging: Loguru + colorama via `br_py_log_n_profile.do_log.log_it`
|
|
8
|
+
- Profiling: `profile_it` decorator (wall-clock timing, colored console output)
|
|
9
|
+
- Correlation IDs: `ray_id` via `contextvars.ContextVar`
|
|
10
|
+
|
|
11
|
+
## Planned
|
|
12
|
+
|
|
13
|
+
- `tracing/` module: `init_tracing()`, `traced` decorator (OTel span replacement for `profile_it`), `@counted`/`@timed_metric` for hot-loop metrics
|
|
14
|
+
- Backend: Prometheus + Jaeger + Grafana + OTel Collector
|
|
15
|
+
- Migration phases: Phase 0 (deps/config) → Phase 1 (core tracing) → Phase 2 (migrate by layer) → Phase 3 (metrics) → Phase 4 (backend stack)
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install br-logging-and-profiling
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Development
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install -r requirements-dev.txt
|
|
27
|
+
pre-commit install
|
|
28
|
+
pytest -m unit
|
|
29
|
+
```
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: br-logging-and-profiling
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Loguru-based logging facade, correlation IDs, and profiling decorator extracted from Forecasting-sidecar3.
|
|
5
|
+
Author: Brais Diaz
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/brais/br-logging-and-profiling
|
|
8
|
+
Project-URL: Repository, https://github.com/brais/br-logging-and-profiling
|
|
9
|
+
Keywords: logging,profiling,loguru,colorama,ray-id
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
+
Requires-Python: >=3.12
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
Requires-Dist: loguru>=0.7.0
|
|
19
|
+
Requires-Dist: colorama>=0.4.6
|
|
20
|
+
Requires-Dist: pandas>=2.0
|
|
21
|
+
Requires-Dist: numpy<2.2,>=1.24
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
24
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
25
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
26
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
27
|
+
Requires-Dist: gitpython; extra == "dev"
|
|
28
|
+
|
|
29
|
+
# br_logging_and_profiling
|
|
30
|
+
|
|
31
|
+
Reusable logging/profiling/tracing package extracted from Forecasting-sidecar3.
|
|
32
|
+
|
|
33
|
+
## Current state
|
|
34
|
+
|
|
35
|
+
- Logging: Loguru + colorama via `br_py_log_n_profile.do_log.log_it`
|
|
36
|
+
- Profiling: `profile_it` decorator (wall-clock timing, colored console output)
|
|
37
|
+
- Correlation IDs: `ray_id` via `contextvars.ContextVar`
|
|
38
|
+
|
|
39
|
+
## Planned
|
|
40
|
+
|
|
41
|
+
- `tracing/` module: `init_tracing()`, `traced` decorator (OTel span replacement for `profile_it`), `@counted`/`@timed_metric` for hot-loop metrics
|
|
42
|
+
- Backend: Prometheus + Jaeger + Grafana + OTel Collector
|
|
43
|
+
- Migration phases: Phase 0 (deps/config) → Phase 1 (core tracing) → Phase 2 (migrate by layer) → Phase 3 (metrics) → Phase 4 (backend stack)
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install br-logging-and-profiling
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Development
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install -r requirements-dev.txt
|
|
55
|
+
pre-commit install
|
|
56
|
+
pytest -m unit
|
|
57
|
+
```
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
br_logging_and_profiling.egg-info/PKG-INFO
|
|
4
|
+
br_logging_and_profiling.egg-info/SOURCES.txt
|
|
5
|
+
br_logging_and_profiling.egg-info/dependency_links.txt
|
|
6
|
+
br_logging_and_profiling.egg-info/requires.txt
|
|
7
|
+
br_logging_and_profiling.egg-info/top_level.txt
|
|
8
|
+
br_py_log_n_profile/__init__.py
|
|
9
|
+
br_py_log_n_profile/do_log/__init__.py
|
|
10
|
+
br_py_log_n_profile/do_log/log_it.py
|
|
11
|
+
br_py_log_n_profile/do_log/ray_id.py
|
|
12
|
+
br_py_log_n_profile/profiling/__init__.py
|
|
13
|
+
br_py_log_n_profile/profiling/base.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
br_py_log_n_profile
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Reusable logging/profiling/tracing package extracted from Forecasting-sidecar3."""
|
|
2
|
+
|
|
3
|
+
from br_py_log_n_profile.do_log import get_ray_id, log, log_d, log_e, log_i, log_w, set_ray_id
|
|
4
|
+
from br_py_log_n_profile.profiling import profile_it
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"get_ray_id",
|
|
8
|
+
"log",
|
|
9
|
+
"log_d",
|
|
10
|
+
"log_e",
|
|
11
|
+
"log_i",
|
|
12
|
+
"log_w",
|
|
13
|
+
"profile_it",
|
|
14
|
+
"set_ray_id",
|
|
15
|
+
]
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import sys
|
|
3
|
+
import traceback
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from types import FrameType
|
|
6
|
+
|
|
7
|
+
from colorama import Fore, Style
|
|
8
|
+
from loguru import logger
|
|
9
|
+
|
|
10
|
+
from .ray_id import get_ray_id
|
|
11
|
+
|
|
12
|
+
__severity_color_map = {
|
|
13
|
+
logging.INFO: Fore.GREEN,
|
|
14
|
+
logging.WARNING: Fore.YELLOW,
|
|
15
|
+
logging.ERROR: Fore.RED,
|
|
16
|
+
logging.DEBUG: Fore.CYAN,
|
|
17
|
+
}
|
|
18
|
+
__root_path: Path | None = None
|
|
19
|
+
__log_format = "{time:YYYY-MM-DD HH:mm:ss.SS} | {level} | {name}:{function}:{line} - {message}"
|
|
20
|
+
__log_to_std_out_level = logging.DEBUG
|
|
21
|
+
__log_to_file_level = 0
|
|
22
|
+
__min_log_level = __log_to_std_out_level
|
|
23
|
+
|
|
24
|
+
__all__ = ["log_d", "log_e", "log_i", "log_w"]
|
|
25
|
+
|
|
26
|
+
_NAMED_LEVEL_THRESHOLDS = (
|
|
27
|
+
(logging.CRITICAL, "CRITICAL"),
|
|
28
|
+
(logging.ERROR, "ERROR"),
|
|
29
|
+
(logging.WARNING, "WARNING"),
|
|
30
|
+
(logging.INFO, "INFO"),
|
|
31
|
+
(logging.DEBUG, "DEBUG"),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
_STANDARD_LEVEL_NAMES = {
|
|
35
|
+
logging.CRITICAL: "CRITICAL",
|
|
36
|
+
logging.ERROR: "ERROR",
|
|
37
|
+
logging.WARNING: "WARNING",
|
|
38
|
+
logging.INFO: "INFO",
|
|
39
|
+
logging.DEBUG: "DEBUG",
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _nearest_level_name(severity: int) -> str:
|
|
44
|
+
name = _STANDARD_LEVEL_NAMES.get(severity)
|
|
45
|
+
if name is not None:
|
|
46
|
+
return name
|
|
47
|
+
for threshold, name in _NAMED_LEVEL_THRESHOLDS:
|
|
48
|
+
if severity >= threshold:
|
|
49
|
+
return name
|
|
50
|
+
return "DEBUG"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class InterceptHandler(logging.Handler):
|
|
54
|
+
def emit(self, record: logging.LogRecord) -> None:
|
|
55
|
+
try:
|
|
56
|
+
level = logger.level(record.levelname).name
|
|
57
|
+
except ValueError:
|
|
58
|
+
level = _nearest_level_name(record.levelno)
|
|
59
|
+
|
|
60
|
+
frame: FrameType | None
|
|
61
|
+
frame, depth = sys._getframe(6), 6
|
|
62
|
+
while frame and frame.f_code.co_filename == logging.__file__:
|
|
63
|
+
frame = frame.f_back
|
|
64
|
+
depth += 1
|
|
65
|
+
|
|
66
|
+
logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _intercept_stdlib_logging() -> None:
|
|
70
|
+
logging.basicConfig(handlers=[InterceptHandler()], force=True)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def root_path(root_distance: int = 5) -> Path:
|
|
74
|
+
global __root_path
|
|
75
|
+
if __root_path is None:
|
|
76
|
+
__root_path = Path(__file__)
|
|
77
|
+
try:
|
|
78
|
+
for _i in range(root_distance):
|
|
79
|
+
__root_path = __root_path.parent
|
|
80
|
+
except (NameError, FileNotFoundError):
|
|
81
|
+
logger.warning(
|
|
82
|
+
f"Unable to find parent for {__root_path}. "
|
|
83
|
+
f"Calling init_logger will enable extended "
|
|
84
|
+
f"features and resolve this warning."
|
|
85
|
+
)
|
|
86
|
+
return __root_path
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _init_default_logger() -> None:
|
|
90
|
+
log_dir = root_path() / "logs"
|
|
91
|
+
log_dir.mkdir(parents=True, exist_ok=True)
|
|
92
|
+
runtime_log_dir = log_dir / "runtime"
|
|
93
|
+
runtime_log_dir.mkdir(parents=True, exist_ok=True)
|
|
94
|
+
logger.remove()
|
|
95
|
+
logger.add(
|
|
96
|
+
sys.stdout,
|
|
97
|
+
format=__log_format,
|
|
98
|
+
colorize=True,
|
|
99
|
+
level=__log_to_std_out_level,
|
|
100
|
+
)
|
|
101
|
+
logger.add(
|
|
102
|
+
runtime_log_dir / "runtime.log",
|
|
103
|
+
format=__log_format,
|
|
104
|
+
level=__log_to_file_level,
|
|
105
|
+
rotation="00:00",
|
|
106
|
+
retention="30 days",
|
|
107
|
+
enqueue=True,
|
|
108
|
+
)
|
|
109
|
+
_intercept_stdlib_logging()
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
_init_default_logger()
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def log_d(message: str, stack_limit: int = 0, stack_offset: int = 0) -> None:
|
|
116
|
+
log(message, logging.DEBUG, stack_limit, stack_offset + 1)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def log_w(message: str, stack_limit: int = 0, stack_offset: int = 0) -> None:
|
|
120
|
+
log(message, logging.WARNING, stack_limit, stack_offset + 1)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def log_i(message: str, stack_limit: int = 0, stack_offset: int = 0) -> None:
|
|
124
|
+
log(message, logging.INFO, stack_limit, stack_offset + 1)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def log_e(message: str, stack_limit: int = 0, stack_offset: int = 0) -> None:
|
|
128
|
+
log(message, logging.ERROR, stack_limit, stack_offset + 1)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def log(message: str, severity: int, stack_limit: int = 0, stack_offset: int = 0) -> None:
|
|
132
|
+
if __min_log_level > severity:
|
|
133
|
+
return
|
|
134
|
+
try:
|
|
135
|
+
stack_trace = ""
|
|
136
|
+
if stack_limit > 0:
|
|
137
|
+
stack = traceback.format_stack(limit=stack_offset + stack_limit + 1)[: -(stack_offset + 1)][-(stack_limit):]
|
|
138
|
+
stack_trace = "\n" + "".join(stack)
|
|
139
|
+
color = __severity_color_map.get(severity, Fore.WHITE)
|
|
140
|
+
id_of_ray = get_ray_id()
|
|
141
|
+
logger.opt(depth=stack_offset + 1).log(
|
|
142
|
+
_nearest_level_name(severity), f"{color}{message}{stack_trace} (ray:{id_of_ray}){Style.RESET_ALL}"
|
|
143
|
+
)
|
|
144
|
+
except Exception as e:
|
|
145
|
+
logger.exception(f"Failed to log message: {message} | Error: {e!s}")
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
from contextvars import ContextVar
|
|
3
|
+
|
|
4
|
+
ray_id_var: ContextVar[uuid.UUID | None] = ContextVar("ray_id")
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def set_ray_id(id: uuid.UUID) -> None:
|
|
8
|
+
ray_id_var.set(id)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_ray_id(generate: bool = True) -> uuid.UUID | None:
|
|
12
|
+
id_of_ray = ray_id_var.get(None)
|
|
13
|
+
if generate and id_of_ray is None:
|
|
14
|
+
id_of_ray = ray_id(source_type=0)
|
|
15
|
+
set_ray_id(id_of_ray)
|
|
16
|
+
return id_of_ray
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def ray_id(source_type: int, id_of_ray: uuid.UUID | None = None) -> uuid.UUID:
|
|
20
|
+
if id_of_ray is not None:
|
|
21
|
+
return id_of_ray
|
|
22
|
+
id_of_ray = uuid.uuid1(node=source_type)
|
|
23
|
+
return id_of_ray
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .base import profile_it as profile_it
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
from functools import wraps
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
from colorama import Fore
|
|
8
|
+
|
|
9
|
+
from ..do_log.log_it import log_d
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def profile_it[**P, R](func: Callable[P, R]) -> Callable[P, R]:
|
|
13
|
+
@wraps(func)
|
|
14
|
+
def _measure_time(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
15
|
+
start_time = time.time()
|
|
16
|
+
function_parameters = parameters_to_str(args, kwargs)
|
|
17
|
+
log_d(f"{func.__name__}({function_parameters}) started", stack_offset=1)
|
|
18
|
+
result = func(*args, **kwargs)
|
|
19
|
+
end_time = time.time()
|
|
20
|
+
execution_time = end_time - start_time
|
|
21
|
+
execution_time_color = (
|
|
22
|
+
Fore.BLUE
|
|
23
|
+
if execution_time < 0.01
|
|
24
|
+
else Fore.GREEN
|
|
25
|
+
if execution_time < 0.1
|
|
26
|
+
else Fore.YELLOW
|
|
27
|
+
if execution_time < 1
|
|
28
|
+
else Fore.RED
|
|
29
|
+
)
|
|
30
|
+
log_d(
|
|
31
|
+
f"{func.__name__}({function_parameters}) executed in {execution_time_color}{execution_time:.3f} seconds",
|
|
32
|
+
stack_offset=1,
|
|
33
|
+
)
|
|
34
|
+
return result
|
|
35
|
+
|
|
36
|
+
return _measure_time
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def parameters_to_str(args: tuple[object, ...], kwargs: dict[str, object]) -> str:
|
|
40
|
+
def process_item(item: object) -> str:
|
|
41
|
+
if isinstance(item, pd.DataFrame):
|
|
42
|
+
return f"{len(item)}*{item.columns}"
|
|
43
|
+
elif isinstance(item, list):
|
|
44
|
+
try:
|
|
45
|
+
return f"list{np.array(item).shape}"
|
|
46
|
+
except ValueError as e:
|
|
47
|
+
raise e
|
|
48
|
+
except Exception as e:
|
|
49
|
+
raise e
|
|
50
|
+
elif isinstance(item, np.ndarray):
|
|
51
|
+
return f"ndarray{item.shape}"
|
|
52
|
+
elif isinstance(item, dict):
|
|
53
|
+
return process_dict(item)
|
|
54
|
+
else:
|
|
55
|
+
return str(item)
|
|
56
|
+
|
|
57
|
+
def process_dict(d: dict[object, object]) -> str:
|
|
58
|
+
t_parameters: list[str] = []
|
|
59
|
+
for key, value in d.items():
|
|
60
|
+
if isinstance(value, list):
|
|
61
|
+
try:
|
|
62
|
+
t_parameters.append(f"{key}: list{np.array(value).shape}")
|
|
63
|
+
except ValueError as e:
|
|
64
|
+
raise e
|
|
65
|
+
except Exception as e:
|
|
66
|
+
raise e
|
|
67
|
+
elif isinstance(value, pd.DataFrame):
|
|
68
|
+
t_parameters.append(f"{key}: {len(value)}*{value.columns}")
|
|
69
|
+
elif isinstance(value, np.ndarray):
|
|
70
|
+
t_parameters.append(f"{key}: ndarray{value.shape}")
|
|
71
|
+
elif isinstance(value, dict):
|
|
72
|
+
t_parameters.append(f"{key}: {{ {process_dict(value)} }}")
|
|
73
|
+
else:
|
|
74
|
+
t_parameters.append(f"{key}: {value}")
|
|
75
|
+
return ", ".join(t_parameters)
|
|
76
|
+
|
|
77
|
+
parameters = [process_item(arg) for arg in args]
|
|
78
|
+
parameters += [f"{k}: {process_item(kwargs[k])}" for k in kwargs]
|
|
79
|
+
|
|
80
|
+
return ", ".join(parameters)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "br-logging-and-profiling"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Loguru-based logging facade, correlation IDs, and profiling decorator extracted from Forecasting-sidecar3."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.12"
|
|
12
|
+
authors = [{ name = "Brais Diaz" }]
|
|
13
|
+
keywords = ["logging", "profiling", "loguru", "colorama", "ray-id"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
21
|
+
]
|
|
22
|
+
dependencies = [
|
|
23
|
+
"loguru>=0.7.0",
|
|
24
|
+
"colorama>=0.4.6",
|
|
25
|
+
"pandas>=2.0",
|
|
26
|
+
"numpy>=1.24,<2.2",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
dev = [
|
|
31
|
+
"pre-commit",
|
|
32
|
+
"pytest>=7.0",
|
|
33
|
+
"mypy>=1.0",
|
|
34
|
+
"ruff>=0.6",
|
|
35
|
+
"gitpython",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[project.urls]
|
|
39
|
+
Homepage = "https://github.com/brais/br-logging-and-profiling"
|
|
40
|
+
Repository = "https://github.com/brais/br-logging-and-profiling"
|
|
41
|
+
|
|
42
|
+
[tool.setuptools.packages.find]
|
|
43
|
+
where = ["."]
|
|
44
|
+
include = ["br_py_log_n_profile*"]
|
|
45
|
+
|
|
46
|
+
[tool.setuptools.package-data]
|
|
47
|
+
br_py_log_n_profile = ["py.typed"]
|
|
48
|
+
|
|
49
|
+
[tool.ruff]
|
|
50
|
+
target-version = "py312"
|
|
51
|
+
line-length = 120
|
|
52
|
+
extend-exclude = ["*.ipynb", ".testvenv"]
|
|
53
|
+
|
|
54
|
+
[tool.ruff.lint]
|
|
55
|
+
select = ["E", "F", "I", "UP", "B", "C4", "SIM", "W"]
|
|
56
|
+
|
|
57
|
+
[tool.mypy]
|
|
58
|
+
python_version = "3.12"
|
|
59
|
+
explicit_package_bases = true
|
|
60
|
+
strict = true
|
|
61
|
+
disallow_any_explicit = true
|
|
62
|
+
no_implicit_optional = true
|
|
63
|
+
warn_return_any = true
|
|
64
|
+
ignore_missing_imports = true
|
|
65
|
+
follow_imports = "silent"
|
|
66
|
+
|
|
67
|
+
[tool.pytest.ini_options]
|
|
68
|
+
minversion = "7.0"
|
|
69
|
+
testpaths = ["tests"]
|
|
70
|
+
pythonpath = ["."]
|
|
71
|
+
python_files = ["test_*.py"]
|
|
72
|
+
python_functions = ["test_*"]
|
|
73
|
+
addopts = "-ra --strict-markers --import-mode=importlib"
|
|
74
|
+
markers = [
|
|
75
|
+
"unit: fast, isolated, no I/O",
|
|
76
|
+
"integration: multiple modules/stages wired together",
|
|
77
|
+
"contract: validates public API contract against installed package",
|
|
78
|
+
]
|