Skip to content

Commit 0a28ea5

Browse files
committed
add logging config, setup and formatter
1 parent 7f04bef commit 0a28ea5

File tree

6 files changed

+118
-65
lines changed

6 files changed

+118
-65
lines changed

autointent/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""This is AutoIntent API reference."""
22

3+
from ._logging import setup_logging
34
from ._ranker import Ranker
45
from ._embedder import Embedder
56
from ._vector_index import VectorIndex
@@ -8,5 +9,4 @@
89
from .context import Context
910
from ._pipeline import Pipeline
1011

11-
12-
__all__ = ["Context", "Dataset", "Embedder", "Hasher", "Pipeline", "Ranker", "VectorIndex"]
12+
__all__ = ["Context", "Dataset", "Embedder", "Hasher", "Pipeline", "Ranker", "VectorIndex", "setup_logging"]

autointent/_logging/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .setup import setup_logging
2+
3+
__all__ = ["setup_logging"]

autointent/_logging/config.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
version: 1
2+
disable_existing_loggers: false
3+
formatters:
4+
simple:
5+
format: '%(levelname)s: %(message)s'
6+
datefmt: '%Y-%m-%dT%H:%M:%S%z'
7+
json:
8+
(): autointent._logging.formatter.JSONFormatter
9+
fmt_keys:
10+
level: levelname
11+
message: message
12+
timestamp: timestamp
13+
logger: name
14+
module: module
15+
function: funcName
16+
line: lineno
17+
thread_name: threadName
18+
handlers:
19+
stderr:
20+
class: logging.StreamHandler
21+
level: INFO
22+
formatter: json
23+
stream: ext://sys.stdout
24+
loggers:
25+
root:
26+
level: DEBUG
27+
handlers:
28+
- stderr
29+
- file

autointent/_logging/formatter.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import datetime as dt
2+
import json
3+
import logging
4+
from typing import Any, override
5+
6+
LOG_RECORD_BUILTIN_ATTRS = {
7+
"args",
8+
"asctime",
9+
"created",
10+
"exc_info",
11+
"exc_text",
12+
"filename",
13+
"funcName",
14+
"levelname",
15+
"levelno",
16+
"lineno",
17+
"module",
18+
"msecs",
19+
"message",
20+
"msg",
21+
"name",
22+
"pathname",
23+
"process",
24+
"processName",
25+
"relativeCreated",
26+
"stack_info",
27+
"thread",
28+
"threadName",
29+
"taskName",
30+
}
31+
32+
33+
class JSONFormatter(logging.Formatter):
34+
"""This is a custom formatter for saving logging records as a json."""
35+
36+
def __init__(
37+
self,
38+
*,
39+
fmt_keys: dict[str, str] | None = None,
40+
) -> None:
41+
super().__init__()
42+
self.fmt_keys = fmt_keys if fmt_keys is not None else {}
43+
44+
@override
45+
def format(self, record: logging.LogRecord) -> str:
46+
message = self._prepare_log_dict(record)
47+
return json.dumps(message, default=str)
48+
49+
def _prepare_log_dict(self, record: logging.LogRecord) -> dict[str, Any]:
50+
always_fields = {
51+
"message": record.getMessage(),
52+
"timestamp": dt.datetime.fromtimestamp(record.created, tz=dt.timezone.utc).isoformat(),
53+
}
54+
if record.exc_info is not None:
55+
always_fields["exc_info"] = self.formatException(record.exc_info)
56+
57+
if record.stack_info is not None:
58+
always_fields["stack_info"] = self.formatStack(record.stack_info)
59+
60+
message = {
61+
key: msg_val if (msg_val := always_fields.pop(val, None)) is not None else getattr(record, val)
62+
for key, val in self.fmt_keys.items()
63+
}
64+
message.update(always_fields)
65+
66+
extra_fields = {key: val for key, val in record.__dict__.items() if key not in LOG_RECORD_BUILTIN_ATTRS}
67+
message.update(extra_fields)
68+
69+
return message

autointent/_logging/setup.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import importlib.resources as ires
2+
import json
3+
import logging.config
4+
import logging.handlers
5+
6+
from autointent.custom_types import LogLevel
7+
8+
9+
def setup_logging(level: LogLevel) -> None:
10+
config_file = ires.files("autointent._logging").joinpath("config.json")
11+
with config_file.open() as f_in:
12+
config = json.load(f_in)
13+
14+
logging.config.dictConfig(config)
15+
logging.basicConfig(level=level.value)

testbed.py

Lines changed: 0 additions & 63 deletions
This file was deleted.

0 commit comments

Comments
 (0)