Initial project import
This commit is contained in:
+110
@@ -0,0 +1,110 @@
|
||||
import base64
|
||||
import binascii
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
from typing import Any
|
||||
|
||||
|
||||
class Logger:
|
||||
_DATA_URL_RE = re.compile(r"data:image/[^;]+;base64,[A-Za-z0-9+/=]+")
|
||||
_JSON_B64_RE = re.compile(r'("b64_json"\s*:\s*")([A-Za-z0-9+/=]+)(")')
|
||||
|
||||
def __init__(self, name: str = "chatgpt2api") -> None:
|
||||
self._logger = logging.getLogger(name)
|
||||
if not self._logger.handlers:
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(logging.Formatter("[%(levelname)s] %(message)s"))
|
||||
self._logger.addHandler(handler)
|
||||
self._logger.setLevel(logging.DEBUG)
|
||||
self._logger.propagate = False
|
||||
|
||||
def _enabled(self, level: str) -> bool:
|
||||
try:
|
||||
from services.config import config
|
||||
levels = set(config.log_levels)
|
||||
except Exception:
|
||||
levels = set()
|
||||
return level in (levels or {"info", "warning", "error"})
|
||||
|
||||
def _mask_string(self, value: str, keep: int = 10) -> str:
|
||||
if len(value) <= keep:
|
||||
return value
|
||||
return value[:keep] + "..."
|
||||
|
||||
def _mask_base64(self, value: str) -> str:
|
||||
if value.startswith("data:") and ";base64," in value:
|
||||
header, _, data = value.partition(",")
|
||||
return f"{header},{self._mask_string(data, 24)} (base64 len={len(data)})"
|
||||
return f"{self._mask_string(value, 24)} (base64 len={len(value)})"
|
||||
|
||||
def _is_base64_string(self, value: str) -> bool:
|
||||
if len(value) < 64 or len(value) % 4 != 0:
|
||||
return False
|
||||
if not any(char in value for char in "+/="):
|
||||
return False
|
||||
try:
|
||||
base64.b64decode(value, validate=True)
|
||||
return True
|
||||
except (binascii.Error, ValueError):
|
||||
return False
|
||||
|
||||
def _sanitize_string(self, value: str) -> str:
|
||||
stripped = value.strip()
|
||||
if stripped.startswith("data:") and ";base64," in stripped:
|
||||
return self._mask_base64(stripped)
|
||||
if self._is_base64_string(stripped):
|
||||
return self._mask_base64(stripped)
|
||||
sanitized = self._DATA_URL_RE.sub(lambda match: self._mask_base64(match.group(0)), value)
|
||||
sanitized = self._JSON_B64_RE.sub(
|
||||
lambda match: f'{match.group(1)}{self._mask_base64(match.group(2))}{match.group(3)}',
|
||||
sanitized,
|
||||
)
|
||||
if sanitized != value:
|
||||
return sanitized
|
||||
return value
|
||||
|
||||
def _sanitize(self, value: Any) -> Any:
|
||||
if isinstance(value, dict):
|
||||
sanitized = {}
|
||||
for key, item in value.items():
|
||||
lowered_key = key.lower()
|
||||
if isinstance(item, str) and ("token" in lowered_key or lowered_key == "dx"):
|
||||
sanitized[key] = self._mask_string(item)
|
||||
elif isinstance(item, str) and ("base64" in lowered_key or lowered_key == "b64_json"):
|
||||
sanitized[key] = self._mask_base64(item)
|
||||
else:
|
||||
sanitized[key] = self._sanitize(item)
|
||||
return sanitized
|
||||
if isinstance(value, list):
|
||||
return [self._sanitize(item) for item in value]
|
||||
if isinstance(value, tuple):
|
||||
return tuple(self._sanitize(item) for item in value)
|
||||
if isinstance(value, str):
|
||||
return self._sanitize_string(value)
|
||||
return value
|
||||
|
||||
def _message(self, value: Any) -> str:
|
||||
sanitized = self._sanitize(value)
|
||||
if isinstance(sanitized, str):
|
||||
return sanitized
|
||||
return json.dumps(sanitized, ensure_ascii=False, default=str)
|
||||
|
||||
def debug(self, message: Any) -> None:
|
||||
if self._enabled("debug"):
|
||||
self._logger.debug(self._message(message))
|
||||
|
||||
def info(self, message: Any) -> None:
|
||||
if self._enabled("info"):
|
||||
self._logger.info(self._message(message))
|
||||
|
||||
def warning(self, message: Any) -> None:
|
||||
if self._enabled("warning"):
|
||||
self._logger.warning(self._message(message))
|
||||
|
||||
def error(self, message: Any) -> None:
|
||||
if self._enabled("error"):
|
||||
self._logger.error(self._message(message))
|
||||
|
||||
|
||||
logger = Logger()
|
||||
Reference in New Issue
Block a user