87 lines
2.2 KiB
Python
87 lines
2.2 KiB
Python
|
|
from dataclasses import dataclass, field
|
||
|
|
from datetime import datetime
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
|
||
|
|
MODULES = {"api", "bot", "ocr", "ai", "db", "capture", "audit", "error"}
|
||
|
|
DOMAIN_MODULES = {"api", "bot", "ocr", "ai", "db", "capture"}
|
||
|
|
|
||
|
|
ALLOWED_EVENTS = {
|
||
|
|
"api.bot.status",
|
||
|
|
"api.bot.start",
|
||
|
|
"api.bot.stop",
|
||
|
|
"api.messages.receive",
|
||
|
|
"audit.decision",
|
||
|
|
"bot.chat_analyze",
|
||
|
|
"bot.chat_snapshot",
|
||
|
|
"bot.loop",
|
||
|
|
"bot.session_scan",
|
||
|
|
"bot.session_service.init",
|
||
|
|
"bot.session_title",
|
||
|
|
"bot.submit",
|
||
|
|
"bot.unread.detect",
|
||
|
|
"bot.unread.scan",
|
||
|
|
"ocr.baidu.token",
|
||
|
|
"ocr.baidu.recognize",
|
||
|
|
"ocr.rapid.init",
|
||
|
|
"ocr.rapid.recognize",
|
||
|
|
"ocr.fallback",
|
||
|
|
"ocr.session_name",
|
||
|
|
"ocr.session_title",
|
||
|
|
"ocr.generic",
|
||
|
|
"capture.contact_list",
|
||
|
|
"capture.session_title",
|
||
|
|
"capture.chat_area",
|
||
|
|
"ai.request",
|
||
|
|
"ai.response",
|
||
|
|
"db.init",
|
||
|
|
"db.error",
|
||
|
|
"db.rule.query",
|
||
|
|
"db.rule.match",
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def normalize_event(module: str, event: str) -> str:
|
||
|
|
e = str(event or "").strip().lower()
|
||
|
|
m = str(module or "").strip().lower()
|
||
|
|
if e in ALLOWED_EVENTS:
|
||
|
|
return e
|
||
|
|
if "." in e:
|
||
|
|
prefix = e.split(".", 1)[0]
|
||
|
|
if prefix in DOMAIN_MODULES:
|
||
|
|
return e
|
||
|
|
if m in DOMAIN_MODULES:
|
||
|
|
return f"{m}.unknown"
|
||
|
|
return "api.unknown"
|
||
|
|
|
||
|
|
|
||
|
|
@dataclass
|
||
|
|
class LogEvent:
|
||
|
|
level: str
|
||
|
|
module: str
|
||
|
|
event: str
|
||
|
|
trace_id: str
|
||
|
|
stage: str
|
||
|
|
status: str
|
||
|
|
message: str
|
||
|
|
reason: str = ""
|
||
|
|
extra: dict[str, Any] = field(default_factory=dict)
|
||
|
|
ts: str = ""
|
||
|
|
|
||
|
|
def to_dict(self) -> dict[str, Any]:
|
||
|
|
ts = self.ts or datetime.now().astimezone().isoformat(timespec="milliseconds")
|
||
|
|
module = self.module if self.module in MODULES else "api"
|
||
|
|
event = normalize_event(module, self.event)
|
||
|
|
return {
|
||
|
|
"ts": ts,
|
||
|
|
"level": (self.level or "INFO").upper(),
|
||
|
|
"module": module,
|
||
|
|
"event": event,
|
||
|
|
"trace_id": self.trace_id or "-",
|
||
|
|
"stage": self.stage or "-",
|
||
|
|
"status": self.status or "ok",
|
||
|
|
"reason": self.reason or "",
|
||
|
|
"message": self.message or "",
|
||
|
|
"extra": self.extra or {},
|
||
|
|
}
|