refactor: update log management

This commit is contained in:
wangjiahao
2025-12-30 14:26:31 +08:00
parent cdc086c2b4
commit f609dc2856
8 changed files with 117 additions and 53 deletions
@@ -0,0 +1,35 @@
"""empty message
Revision ID: db1a95567cbb
Revises: fb2e8dd19158
Create Date: 2025-12-30 12:29:14.290394
"""
from alembic import op
import sqlalchemy as sa
import sqlmodel.sql.sqltypes
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = 'db1a95567cbb'
down_revision = 'fb2e8dd19158'
branch_labels = None
depends_on = None
def upgrade():
op.create_table('sys_logs_resource',
sa.Column('id', sa.BIGINT(),
sa.Identity(always=True, start=1, increment=1, minvalue=1, maxvalue=999999999999999,
cycle=False, cache=1), autoincrement=True, nullable=False),
sa.Column('resource_id', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('module', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('resource_name', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('log_id', sa.BIGINT(), autoincrement=False, nullable=True),
sa.PrimaryKeyConstraint('id', name=op.f('sys_logs_resource_pkey'))
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('sys_logs_resource')
# ### end Alembic commands ###
+8
View File
@@ -44,6 +44,14 @@ class OperationType(str, Enum):
ANALYSIS = "analysis"
PREDICTION = "prediction"
class SystemLogsResource(SQLModel, table=True):
__tablename__ = "sys_logs_resource"
id: Optional[int] = Field(default=None, primary_key=True)
log_id: Optional[int] = Field(default=None,sa_type=BigInteger())
resource_id: Optional[str] = Field(default=None)
resource_name: Optional[str] = Field(default=None)
module: Optional[str] = Field(default=None)
class SystemLog(SQLModel, table=True):
__tablename__ = "sys_logs"
@@ -2,14 +2,14 @@ import time
import functools
import json
import inspect
from typing import Callable, Any, Optional, Dict, Union
from typing import Callable, Any, Optional, Dict, Union, List
from fastapi import Request, HTTPException
from datetime import datetime
from pydantic import BaseModel
from sqlmodel import Session, select
import traceback
from sqlbot_xpack.audit.curd.audit import build_resource_union_query
from common.audit.models.log_model import OperationType, OperationStatus, SystemLog
from common.audit.models.log_model import OperationType, OperationStatus, SystemLog, SystemLogsResource
from common.audit.schemas.request_context import RequestContext
from apps.system.crud.user import get_user_by_account
from apps.system.schemas.system_schema import UserInfoDTO, BaseUserDTO
@@ -18,42 +18,36 @@ from sqlalchemy import and_, select
from common.core.db import engine
def get_resource_name_by_id_and_module(session, resource_id: Any, module: str) -> Optional[str]:
def get_resource_name_by_id_and_module(session, resource_id: Any, module: str) -> List[Dict[str, str]]:
resource_union_query = build_resource_union_query()
resource_alias = resource_union_query.alias("resource")
if isinstance(resource_id, list):
# 处理列表情况
if not resource_id:
return None
# 统一处理为列表
if not isinstance(resource_id, list):
resource_id = [resource_id]
# 构建查询,使用 IN 条件
query = select(
resource_alias.c.name
).where(
and_(
resource_alias.c.id.in_([str(id_) for id_ in resource_id]),
resource_alias.c.module == module
)
if not resource_id:
return []
# 构建查询,使用 IN 条件
query = select(
resource_alias.c.id,
resource_alias.c.name,
resource_alias.c.module
).where(
and_(
resource_alias.c.id.in_([str(id_) for id_ in resource_id]),
resource_alias.c.module == module
)
# 执行查询并获取所有结果
results = session.execute(query).scalars().all()
)
# 用逗号连接所有名称
return ",".join(results) if results else None
else:
# 处理单个字符串情况
query = select(
resource_alias.c.name
).where(
and_(
resource_alias.c.id == str(resource_id),
resource_alias.c.module == module
)
)
return session.execute(query).scalar()
results = session.execute(query).fetchall()
return [{
'resource_id': str(row.id),
'resource_name': row.name or '',
'module': row.module or ''
} for row in results]
class LogConfig(BaseModel):
operation_type: OperationType
@@ -390,6 +384,7 @@ class SystemLogger:
remark: Optional[str] = None,
oid: int = -1,
opt_type_ref : OperationType = None,
resource_info_list : Optional[List] = None,
) -> Optional[SystemLog]:
"""Create log records"""
try:
@@ -422,7 +417,6 @@ class SystemLogger:
error_message=error_message,
module=config.module,
resource_id=str(resource_id),
resource_name=str(resource_name),
request_method=request.method if request else None,
request_path=request.url.path if request else None,
request_params=request_params,
@@ -430,13 +424,39 @@ class SystemLogger:
remark=remark
)
with Session(engine) as session:
session.add(log)
session.query(SystemLog).filter(SystemLog.resource_id == str(resource_id)).update({
SystemLog.resource_name: str(resource_name)
}, synchronize_session='fetch')
session.commit()
session.refresh(log)
# 统一处理不同类型的 resource_id_info
if isinstance(resource_id, list):
resource_ids = [str(rid) for rid in resource_id]
else:
resource_ids = [str(resource_id)]
# 批量添加 SystemLogsResource
resource_entries = []
for resource_id_details in resource_ids:
resource_entry = SystemLogsResource(
resource_id=resource_id_details,
log_id=log.id,
module=config.module
)
resource_entries.append(resource_entry)
if resource_entries:
session.bulk_save_objects(resource_entries)
session.commit()
if config.operation_type == OperationType.DELETE and resource_info_list is not None:
# 批量更新 SystemLogsResource 表的 resource_name
for resource_info in resource_info_list:
session.query(SystemLogsResource).filter(
SystemLogsResource.resource_id == resource_info['resource_id'],
SystemLogsResource.module == resource_info['module'],
).update({
SystemLogsResource.resource_name: resource_info['resource_name']
}, synchronize_session='fetch')
session.commit()
return log
except Exception as e:
@@ -472,6 +492,7 @@ def system_log(config: Union[LogConfig, Dict]):
remark = None
oid = -1
opt_type_ref = None
resource_info_list = None
try:
# Get current request
@@ -515,7 +536,7 @@ def system_log(config: Union[LogConfig, Dict]):
resource_name = input_account
if config.operation_type == OperationType.DELETE:
with Session(engine) as session:
resource_name = get_resource_name_by_id_and_module(session, resource_id, config.module)
resource_info_list = get_resource_name_by_id_and_module(session, resource_id, config.module)
if config.operation_type == OperationType.CREATE_OR_UPDATE:
opt_type_ref = OperationType.UPDATE if resource_id is not None else OperationType.CREATE
@@ -530,10 +551,6 @@ def system_log(config: Union[LogConfig, Dict]):
result,
"result"
)
if config.operation_type != OperationType.DELETE:
with Session(engine) as session:
resource_name = get_resource_name_by_id_and_module(session, resource_id, config.module)
return result
except Exception as e:
status = OperationStatus.FAILED
@@ -568,7 +585,8 @@ def system_log(config: Union[LogConfig, Dict]):
remark=remark,
request=request,
oid=oid,
opt_type_ref=opt_type_ref
opt_type_ref=opt_type_ref,
resource_info_list=resource_info_list
)
except Exception as log_error:
print(f"[SystemLogger] Log creation failed: {log_error}")
@@ -581,6 +599,7 @@ def system_log(config: Union[LogConfig, Dict]):
request = None
resource_id = None
resource_name = None
resource_info_list = None
result = None
try:
@@ -602,7 +621,7 @@ def system_log(config: Union[LogConfig, Dict]):
# Obtain client information
if config.operation_type == OperationType.DELETE:
with Session(engine) as session:
resource_name = get_resource_name_by_id_and_module(session, resource_id, config.module)
resource_info_list = get_resource_name_by_id_and_module(session, resource_id, config.module)
# Execute the original function
result = func(*args, **kwargs)
@@ -615,10 +634,6 @@ def system_log(config: Union[LogConfig, Dict]):
"result"
)
if config.operation_type != OperationType.DELETE:
with Session(engine) as session:
resource_name = get_resource_name_by_id_and_module(session, resource_id, config.module)
return result
except Exception as e:
@@ -652,7 +667,8 @@ def system_log(config: Union[LogConfig, Dict]):
error_message=error_message,
resource_id=resource_id,
resource_name=resource_name,
request=request
request=request,
resource_info_list=resource_info_list
)
)
else:
+3 -1
View File
@@ -176,7 +176,9 @@
"log_setting": "Login Authentication",
"setting": "Settings",
"system_management": "System Management",
"opt_log": "Operation Log"
"opt_log": "Operation Log",
"prediction": "Data prediction",
"analysis": "Data analysis"
},
"i18n_table_not_exist": "Table not exist"
}
+3 -1
View File
@@ -176,7 +176,9 @@
"log_setting": "로그인 인증",
"setting": "설정",
"system_management": "시스템 관리",
"opt_log": "작업 로그"
"opt_log": "작업 로그",
"prediction": "데이터 예측",
"analysis": "데이터 분석"
},
"i18n_table_not_exist": "현재 테이블이 존재하지 않습니다"
}
+3 -1
View File
@@ -176,7 +176,9 @@
"log_setting": "登录认证",
"setting": "设置",
"system_management": "系统管理",
"opt_log": "操作日志"
"opt_log": "操作日志",
"prediction": "数据预测",
"analysis": "数据分析"
},
"i18n_table_not_exist": "当前表不存在"
+1 -1
View File
@@ -83,11 +83,11 @@ url = "https://test.pypi.org/simple"
explicit = true
[tool.uv.sources]
sqlbot-xpack = { index = "testpypi" }
torch = [
{ index = "pytorch-cpu", extra = "cpu" },
{ index = "pytorch-cu128", extra = "cu128" },
]
sqlbot-xpack = { path = "../../sqlbot-xpack" }
[tool.uv]
conflicts = [
+1 -2
View File
@@ -5,8 +5,7 @@ export const audit = {
request.get(`/system/audit/page/${pageNum}/${pageSize}${params}`),
getOptions: () => request.get(`/system/audit/get_options`),
export2Excel: (params: any) =>
request.get(`/system/audit/export`, {
params,
request.get(`/system/audit/export${params}`, {
responseType: 'blob',
requestOptions: { customError: true },
}),