feat(HEL-382): 搭建 datahub 底座和盘后正式数据链路
新增独立 xiaobai-datahub 服务(SQLite WAL、Tushare 盘后发布、/v1 契约和管理后台),不改现站页面与数据链路。 Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
co-authored by
Cursor
multica-agent
parent
c2ebc0ab91
commit
3498dd7a4b
@@ -0,0 +1,56 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
import sys
|
||||
from typing import Any
|
||||
|
||||
from datahub.timeutil import isoformat
|
||||
|
||||
_SECRET_KEYS = (
|
||||
"token", "password", "secret", "key", "authorization", "credential",
|
||||
"tushare_token", "datahub_token", "encryption_key", "cookie",
|
||||
)
|
||||
|
||||
|
||||
def _redact(value: Any, key: str = "") -> Any:
|
||||
lowered = key.lower()
|
||||
if any(part in lowered for part in _SECRET_KEYS):
|
||||
return "***"
|
||||
if isinstance(value, dict):
|
||||
return {str(item_key): _redact(item_value, str(item_key)) for item_key, item_value in value.items()}
|
||||
if isinstance(value, list):
|
||||
return [_redact(item) for item in value]
|
||||
return value
|
||||
|
||||
|
||||
class JsonFormatter(logging.Formatter):
|
||||
def format(self, record: logging.LogRecord) -> str:
|
||||
payload: dict[str, Any] = {
|
||||
"ts": isoformat(),
|
||||
"level": record.levelname,
|
||||
"logger": record.name,
|
||||
"message": record.getMessage(),
|
||||
}
|
||||
extra = getattr(record, "hub", None)
|
||||
if isinstance(extra, dict):
|
||||
payload.update(_redact(extra))
|
||||
if record.exc_info:
|
||||
payload["exc"] = self.formatException(record.exc_info)
|
||||
return json.dumps(payload, ensure_ascii=False, default=str)
|
||||
|
||||
|
||||
def configure_logging(level: str = "INFO") -> logging.Logger:
|
||||
logger = logging.getLogger("datahub")
|
||||
if logger.handlers:
|
||||
return logger
|
||||
handler = logging.StreamHandler(sys.stdout)
|
||||
handler.setFormatter(JsonFormatter())
|
||||
logger.addHandler(handler)
|
||||
logger.setLevel(getattr(logging, level.upper(), logging.INFO))
|
||||
logger.propagate = False
|
||||
return logger
|
||||
|
||||
|
||||
def get_logger() -> logging.Logger:
|
||||
return logging.getLogger("datahub")
|
||||
Reference in New Issue
Block a user