This commit is contained in:
Your Name
2026-07-28 15:04:17 +08:00
parent ac406a5f99
commit 8f68af1c2c
27 changed files with 3442 additions and 296 deletions
+101
View File
@@ -0,0 +1,101 @@
"""Bound diagnostic payloads without changing live message processing."""
from __future__ import annotations
import json
import os
from typing import Any
TRUNCATION_MARKER = "\n...[日志内容过长,已截断]"
_MESSAGE_FIELDS = (
"type",
"url",
"uri",
"text",
"name",
"width",
"height",
"duration",
"sticker_id",
"mime_type",
)
def _env_limit(name: str, default: int, minimum: int, maximum: int) -> int:
try:
value = int(os.getenv(name, str(default)) or default)
except (TypeError, ValueError):
value = default
return max(minimum, min(maximum, value))
def truncate_text(value: Any, limit: int) -> str:
text = "" if value is None else str(value)
if len(text) <= limit:
return text
keep = max(0, limit - len(TRUNCATION_MARKER))
return text[:keep] + TRUNCATION_MARKER
def bound_system_log_detail(value: Any) -> str:
return truncate_text(
value,
_env_limit("KEFU_SYSTEM_LOG_MAX_CHARS", 4096, 512, 65536),
)
def _compact_media_message(value: Any) -> Any:
if not isinstance(value, dict):
return truncate_text(value, 2048)
compact: dict[str, Any] = {}
for key in _MESSAGE_FIELDS:
if key not in value:
continue
item = value[key]
compact[key] = truncate_text(item, 2048) if isinstance(item, str) else item
compact["_log_truncated"] = True
return compact
def bound_message_log_content(value: Any) -> str:
"""Keep a valid compact media JSON payload when a log entry is oversized."""
limit = _env_limit("KEFU_MESSAGE_LOG_MAX_CHARS", 16384, 2048, 262144)
text = "" if value is None else str(value)
if len(text) <= limit:
return text
try:
parsed = json.loads(text)
except (TypeError, ValueError, json.JSONDecodeError):
return truncate_text(text, limit)
if isinstance(parsed, dict) and parsed.get("type"):
compact = _compact_media_message(parsed)
elif isinstance(parsed, dict) and isinstance(parsed.get("messages"), list):
compact = {
"messages": [
_compact_media_message(item)
for item in parsed["messages"][:20]
],
"_log_truncated": True,
}
else:
return truncate_text(text, limit)
encoded = json.dumps(compact, ensure_ascii=False, separators=(",", ":"))
return encoded if len(encoded) <= limit else truncate_text(encoded, limit)
def bound_raw_message_log_content(value: Any) -> str:
return truncate_text(
value,
_env_limit("KEFU_RAW_MESSAGE_LOG_MAX_CHARS", 32768, 4096, 262144),
)
def bound_error_log_content(value: Any) -> str:
return truncate_text(
value,
_env_limit("KEFU_ERROR_LOG_MAX_CHARS", 4096, 512, 65536),
)
+4 -2
View File
@@ -8,6 +8,7 @@ from typing import Optional
from models.database import AsyncSessionLocal
from models.models import ReceivedMessageLog
from utils.log_limits import bound_raw_message_log_content
logger = logging.getLogger("received_message_log")
@@ -23,8 +24,9 @@ async def record_received_message(
message_type: Optional[int] = None,
server_message_id: Optional[str] = None,
) -> None:
# 原样落库:不做 strip / parse / serialize,空字符串也记录
store_content = raw_content if raw_content is not None else ""
# The live message object remains untouched for matching/replying. Only
# this diagnostic copy is bounded before persistence.
store_content = bound_raw_message_log_content(raw_content)
async with AsyncSessionLocal() as db:
try:
+7 -3
View File
@@ -15,6 +15,8 @@ from collections import deque
from datetime import datetime
from typing import Optional
from .log_limits import bound_system_log_detail, truncate_text
logger = logging.getLogger("douyin_im.system")
_VALID_LEVELS = ("info", "success", "warning", "error")
@@ -43,14 +45,16 @@ def record(
"account_id": account_id,
"level": level,
"category": category,
"event": str(event or ""),
"detail": str(detail or ""),
"event": truncate_text(event, 255),
"detail": bound_system_log_detail(detail),
"created_at": datetime.utcnow().isoformat(),
}
_buffer.appendleft(entry)
_pending.append(entry)
msg = f"[{category}] {event}" + (f" | {detail}" if detail else "")
msg = f"[{category}] {entry['event']}" + (
f" | {entry['detail']}" if entry["detail"] else ""
)
if level == "error":
logger.error(msg)
elif level == "warning":