forked from iti-framework/iTi-Flask
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
2.9 KiB
Python
98 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
from flask import has_request_context, request, current_app
|
|
from typing import Optional
|
|
import json
|
|
|
|
from flask_jwt_extended import current_user
|
|
|
|
from iti.applications.models import SysLog
|
|
from iti.applications.extensions.db import db
|
|
from iti.applications.common.enums import LogType
|
|
from iti.applications.common.utils.sys_log_helper import (
|
|
summarize_response_json,
|
|
safe_json_dumps,
|
|
truncate_text,
|
|
)
|
|
|
|
|
|
def add_sys_log(
|
|
name: str,
|
|
*,
|
|
type: "LogType | str" = LogType.OPERATION,
|
|
desc: Optional[str] = None,
|
|
success: Optional[bool] = None,
|
|
response: Optional[dict | str] = None,
|
|
exception: Optional[Exception | str] = None,
|
|
extra: Optional[dict] = None,
|
|
) -> None:
|
|
"""
|
|
手动新增系统日志(请求内/外均可调用)。
|
|
- 共用 after_request 的摘要策略与配置项
|
|
- 参数尽量少,自动采集请求上下文信息(如有)
|
|
"""
|
|
|
|
max_body_chars = (
|
|
int(current_app.config.get("SYSLOG_MAX_BODY_CHARS", 2048))
|
|
if current_app
|
|
else 2048
|
|
)
|
|
items_sample_size = (
|
|
int(current_app.config.get("SYSLOG_ITEMS_SAMPLE", 5)) if current_app else 5
|
|
)
|
|
|
|
method = path = user_agent = ip = None
|
|
headers = query = body = None
|
|
user_id = None
|
|
|
|
if has_request_context():
|
|
method = request.method
|
|
path = request.path
|
|
headers = {k: request.headers.getlist(k) for k in request.headers.keys()}
|
|
query = request.args.to_dict()
|
|
body = request.get_json(silent=True) or {}
|
|
user_id = current_user.id if current_user else None
|
|
user_agent = request.headers.get("User-Agent", "None")
|
|
ip = request.remote_addr or request.headers.get("X-Forwarded-For")
|
|
|
|
resp_text: Optional[str] = None
|
|
if isinstance(response, dict):
|
|
summarized = summarize_response_json(response, items_sample_size)
|
|
resp_text = safe_json_dumps(
|
|
summarized, ensure_ascii=False, max_chars=max_body_chars
|
|
)
|
|
elif isinstance(response, str):
|
|
resp_text = truncate_text(response, max_body_chars)
|
|
|
|
if success is None:
|
|
success = False if exception else None
|
|
|
|
log = SysLog(
|
|
name=name,
|
|
desc=desc or "",
|
|
type=(
|
|
type.value
|
|
if isinstance(type, LogType)
|
|
else (type or LogType.OPERATION.value)
|
|
),
|
|
method=method,
|
|
user_id=user_id,
|
|
path=path,
|
|
ip=ip,
|
|
user_agent=user_agent,
|
|
headers=json.dumps(headers, ensure_ascii=False)
|
|
if headers is not None
|
|
else None,
|
|
query_params=json.dumps(query, ensure_ascii=False)
|
|
if query is not None
|
|
else None,
|
|
body_params=json.dumps(body, ensure_ascii=False) if body is not None else None,
|
|
execution_time=None,
|
|
response=resp_text,
|
|
success=success,
|
|
exception=str(exception) if exception else None,
|
|
)
|
|
|
|
db.session.add(log)
|
|
db.session.commit()
|