Repository URL to install this package:
|
Version:
1.0.2 ▾
|
import logging
from itertools import chain
from pathlib import Path
from typing import Dict, Iterable, Iterator, Tuple
from pythonjsonlogger.jsonlogger import RESERVED_ATTRS, JsonFormatter
ELASTIC_APM_FILTERS = (
"elasticapm_labels",
"elasticapm_service_name",
"elasticapm_span_id",
"elasticapm_trace_id",
"elasticapm_transaction_id",
"elasticapm_event_dataset",
)
DEFAULT_LOGGING_FORMAT = "asctime=%(asctime)s levelname=%(levelname)s name=%(name)s pathname=%(pathname)s lineno=%(lineno)d message=%(message)s"
DEFAULT_JSON_LOGGING_FORMAT = "%(asctime)s %(levelname)s %(name)s %(pathname)s %(lineno)d %(message)s"
HOME_PATH = str(Path.home())
def parse_loggers(loggers: Iterable[str]) -> Iterator[Tuple[str, str]]:
for logger in loggers:
log_parts = logger.split("=")
if len(log_parts) == 1:
yield log_parts[0], "INFO"
elif len(log_parts) == 2:
yield log_parts[0], log_parts[1]
class CustomFormatter(logging.Formatter):
def __init__(self, *args, **kwargs):
self.reserved = kwargs.pop("reserved_attrs", RESERVED_ATTRS)
super().__init__(*args, **kwargs)
def get_extra(self, record: logging.LogRecord) -> Iterator[str]:
for key, value in record.__dict__.items():
if key not in self.reserved and not (hasattr(key, "startswith") and key.startswith("_")):
yield f"{key}={value!r}"
def format(self, record: logging.LogRecord) -> str:
base = super().format(record)
return ", ".join(chain([base], self.get_extra(record)))
def get_logging_formatter(
loggers: Iterable[str],
log_stream_handler=None,
extra_config: Iterable[any] = [],
) -> Dict:
logging_config = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"default": {
"()": CustomFormatter,
"reserved_attrs": RESERVED_ATTRS + ELASTIC_APM_FILTERS,
"format": DEFAULT_LOGGING_FORMAT,
},
"json": {
"()": JsonFormatter,
"reserved_attrs": RESERVED_ATTRS + ELASTIC_APM_FILTERS,
"format": DEFAULT_JSON_LOGGING_FORMAT,
},
},
"handlers": {
"default": {
"class": "logging.StreamHandler",
"formatter": log_stream_handler or "default",
},
"log_file": {
"class": "logging.handlers.RotatingFileHandler",
"filename": f"{HOME_PATH}/logs/output_drf.log",
"maxBytes": 1024 * 1024 * 15, # 15MB
"backupCount": 10,
"formatter": log_stream_handler or "default",
},
},
"root": {
"handlers": ["default", "log_file"],
},
"loggers": {name: {"level": level} for name, level in parse_loggers(loggers)},
}
for configurer in extra_config:
configurer.configure(logging_config)
return logging_config