Skip to content

Commit f609dc2

Browse files
committed
refactor: update log management
1 parent cdc086c commit f609dc2

File tree

8 files changed

+119
-55
lines changed

8 files changed

+119
-55
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""empty message
2+
3+
Revision ID: db1a95567cbb
4+
Revises: fb2e8dd19158
5+
Create Date: 2025-12-30 12:29:14.290394
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
import sqlmodel.sql.sqltypes
11+
from sqlalchemy.dialects import postgresql
12+
13+
# revision identifiers, used by Alembic.
14+
revision = 'db1a95567cbb'
15+
down_revision = 'fb2e8dd19158'
16+
branch_labels = None
17+
depends_on = None
18+
19+
20+
def upgrade():
21+
op.create_table('sys_logs_resource',
22+
sa.Column('id', sa.BIGINT(),
23+
sa.Identity(always=True, start=1, increment=1, minvalue=1, maxvalue=999999999999999,
24+
cycle=False, cache=1), autoincrement=True, nullable=False),
25+
sa.Column('resource_id', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
26+
sa.Column('module', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
27+
sa.Column('resource_name', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
28+
sa.Column('log_id', sa.BIGINT(), autoincrement=False, nullable=True),
29+
sa.PrimaryKeyConstraint('id', name=op.f('sys_logs_resource_pkey'))
30+
)
31+
# ### end Alembic commands ###
32+
def downgrade():
33+
# ### commands auto generated by Alembic - please adjust! ###
34+
op.drop_table('sys_logs_resource')
35+
# ### end Alembic commands ###

backend/common/audit/models/log_model.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ class OperationType(str, Enum):
4444
ANALYSIS = "analysis"
4545
PREDICTION = "prediction"
4646

47+
class SystemLogsResource(SQLModel, table=True):
48+
__tablename__ = "sys_logs_resource"
49+
id: Optional[int] = Field(default=None, primary_key=True)
50+
log_id: Optional[int] = Field(default=None,sa_type=BigInteger())
51+
resource_id: Optional[str] = Field(default=None)
52+
resource_name: Optional[str] = Field(default=None)
53+
module: Optional[str] = Field(default=None)
54+
4755

4856
class SystemLog(SQLModel, table=True):
4957
__tablename__ = "sys_logs"

backend/common/audit/schemas/logger_decorator.py

Lines changed: 65 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
import functools
33
import json
44
import inspect
5-
from typing import Callable, Any, Optional, Dict, Union
5+
from typing import Callable, Any, Optional, Dict, Union, List
66
from fastapi import Request, HTTPException
77
from datetime import datetime
88
from pydantic import BaseModel
99
from sqlmodel import Session, select
1010
import traceback
1111
from sqlbot_xpack.audit.curd.audit import build_resource_union_query
12-
from common.audit.models.log_model import OperationType, OperationStatus, SystemLog
12+
from common.audit.models.log_model import OperationType, OperationStatus, SystemLog, SystemLogsResource
1313
from common.audit.schemas.request_context import RequestContext
1414
from apps.system.crud.user import get_user_by_account
1515
from apps.system.schemas.system_schema import UserInfoDTO, BaseUserDTO
@@ -18,42 +18,36 @@
1818
from common.core.db import engine
1919

2020

21-
22-
def get_resource_name_by_id_and_module(session, resource_id: Any, module: str) -> Optional[str]:
21+
def get_resource_name_by_id_and_module(session, resource_id: Any, module: str) -> List[Dict[str, str]]:
2322
resource_union_query = build_resource_union_query()
2423
resource_alias = resource_union_query.alias("resource")
2524

26-
if isinstance(resource_id, list):
27-
# 处理列表情况
28-
if not resource_id:
29-
return None
30-
31-
# 构建查询,使用 IN 条件
32-
query = select(
33-
resource_alias.c.name
34-
).where(
35-
and_(
36-
resource_alias.c.id.in_([str(id_) for id_ in resource_id]),
37-
resource_alias.c.module == module
38-
)
25+
# 统一处理为列表
26+
if not isinstance(resource_id, list):
27+
resource_id = [resource_id]
28+
29+
if not resource_id:
30+
return []
31+
32+
# 构建查询,使用 IN 条件
33+
query = select(
34+
resource_alias.c.id,
35+
resource_alias.c.name,
36+
resource_alias.c.module
37+
).where(
38+
and_(
39+
resource_alias.c.id.in_([str(id_) for id_ in resource_id]),
40+
resource_alias.c.module == module
3941
)
40-
# 执行查询并获取所有结果
41-
results = session.execute(query).scalars().all()
42-
43-
# 用逗号连接所有名称
44-
return ",".join(results) if results else None
45-
else:
46-
# 处理单个字符串情况
47-
query = select(
48-
resource_alias.c.name
49-
).where(
50-
and_(
51-
resource_alias.c.id == str(resource_id),
52-
resource_alias.c.module == module
53-
)
54-
)
55-
return session.execute(query).scalar()
42+
)
5643

44+
results = session.execute(query).fetchall()
45+
46+
return [{
47+
'resource_id': str(row.id),
48+
'resource_name': row.name or '',
49+
'module': row.module or ''
50+
} for row in results]
5751

5852
class LogConfig(BaseModel):
5953
operation_type: OperationType
@@ -390,6 +384,7 @@ async def create_log_record(
390384
remark: Optional[str] = None,
391385
oid: int = -1,
392386
opt_type_ref : OperationType = None,
387+
resource_info_list : Optional[List] = None,
393388
) -> Optional[SystemLog]:
394389
"""Create log records"""
395390
try:
@@ -422,21 +417,46 @@ async def create_log_record(
422417
error_message=error_message,
423418
module=config.module,
424419
resource_id=str(resource_id),
425-
resource_name=str(resource_name),
426420
request_method=request.method if request else None,
427421
request_path=request.url.path if request else None,
428422
request_params=request_params,
429423
create_time=datetime.now(),
430424
remark=remark
431425
)
432426

427+
433428
with Session(engine) as session:
434429
session.add(log)
435-
session.query(SystemLog).filter(SystemLog.resource_id == str(resource_id)).update({
436-
SystemLog.resource_name: str(resource_name)
437-
}, synchronize_session='fetch')
438430
session.commit()
439431
session.refresh(log)
432+
# 统一处理不同类型的 resource_id_info
433+
if isinstance(resource_id, list):
434+
resource_ids = [str(rid) for rid in resource_id]
435+
else:
436+
resource_ids = [str(resource_id)]
437+
# 批量添加 SystemLogsResource
438+
resource_entries = []
439+
for resource_id_details in resource_ids:
440+
resource_entry = SystemLogsResource(
441+
resource_id=resource_id_details,
442+
log_id=log.id,
443+
module=config.module
444+
)
445+
resource_entries.append(resource_entry)
446+
if resource_entries:
447+
session.bulk_save_objects(resource_entries)
448+
session.commit()
449+
450+
if config.operation_type == OperationType.DELETE and resource_info_list is not None:
451+
# 批量更新 SystemLogsResource 表的 resource_name
452+
for resource_info in resource_info_list:
453+
session.query(SystemLogsResource).filter(
454+
SystemLogsResource.resource_id == resource_info['resource_id'],
455+
SystemLogsResource.module == resource_info['module'],
456+
).update({
457+
SystemLogsResource.resource_name: resource_info['resource_name']
458+
}, synchronize_session='fetch')
459+
session.commit()
440460
return log
441461

442462
except Exception as e:
@@ -472,6 +492,7 @@ async def async_wrapper(*args, **kwargs):
472492
remark = None
473493
oid = -1
474494
opt_type_ref = None
495+
resource_info_list = None
475496

476497
try:
477498
# Get current request
@@ -515,7 +536,7 @@ async def async_wrapper(*args, **kwargs):
515536
resource_name = input_account
516537
if config.operation_type == OperationType.DELETE:
517538
with Session(engine) as session:
518-
resource_name = get_resource_name_by_id_and_module(session, resource_id, config.module)
539+
resource_info_list = get_resource_name_by_id_and_module(session, resource_id, config.module)
519540

520541
if config.operation_type == OperationType.CREATE_OR_UPDATE:
521542
opt_type_ref = OperationType.UPDATE if resource_id is not None else OperationType.CREATE
@@ -530,10 +551,6 @@ async def async_wrapper(*args, **kwargs):
530551
result,
531552
"result"
532553
)
533-
if config.operation_type != OperationType.DELETE:
534-
with Session(engine) as session:
535-
resource_name = get_resource_name_by_id_and_module(session, resource_id, config.module)
536-
return result
537554

538555
except Exception as e:
539556
status = OperationStatus.FAILED
@@ -568,7 +585,8 @@ async def async_wrapper(*args, **kwargs):
568585
remark=remark,
569586
request=request,
570587
oid=oid,
571-
opt_type_ref=opt_type_ref
588+
opt_type_ref=opt_type_ref,
589+
resource_info_list=resource_info_list
572590
)
573591
except Exception as log_error:
574592
print(f"[SystemLogger] Log creation failed: {log_error}")
@@ -581,6 +599,7 @@ def sync_wrapper(*args, **kwargs):
581599
request = None
582600
resource_id = None
583601
resource_name = None
602+
resource_info_list = None
584603
result = None
585604

586605
try:
@@ -602,7 +621,7 @@ def sync_wrapper(*args, **kwargs):
602621
# Obtain client information
603622
if config.operation_type == OperationType.DELETE:
604623
with Session(engine) as session:
605-
resource_name = get_resource_name_by_id_and_module(session, resource_id, config.module)
624+
resource_info_list = get_resource_name_by_id_and_module(session, resource_id, config.module)
606625

607626
# Execute the original function
608627
result = func(*args, **kwargs)
@@ -615,10 +634,6 @@ def sync_wrapper(*args, **kwargs):
615634
"result"
616635
)
617636

618-
if config.operation_type != OperationType.DELETE:
619-
with Session(engine) as session:
620-
resource_name = get_resource_name_by_id_and_module(session, resource_id, config.module)
621-
622637
return result
623638

624639
except Exception as e:
@@ -652,7 +667,8 @@ def sync_wrapper(*args, **kwargs):
652667
error_message=error_message,
653668
resource_id=resource_id,
654669
resource_name=resource_name,
655-
request=request
670+
request=request,
671+
resource_info_list=resource_info_list
656672
)
657673
)
658674
else:

backend/locales/en.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,9 @@
176176
"log_setting": "Login Authentication",
177177
"setting": "Settings",
178178
"system_management": "System Management",
179-
"opt_log": "Operation Log"
179+
"opt_log": "Operation Log",
180+
"prediction": "Data prediction",
181+
"analysis": "Data analysis"
180182
},
181183
"i18n_table_not_exist": "Table not exist"
182184
}

backend/locales/ko-KR.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,9 @@
176176
"log_setting": "로그인 인증",
177177
"setting": "설정",
178178
"system_management": "시스템 관리",
179-
"opt_log": "작업 로그"
179+
"opt_log": "작업 로그",
180+
"prediction": "데이터 예측",
181+
"analysis": "데이터 분석"
180182
},
181183
"i18n_table_not_exist": "현재 테이블이 존재하지 않습니다"
182184
}

backend/locales/zh-CN.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,9 @@
176176
"log_setting": "登录认证",
177177
"setting": "设置",
178178
"system_management": "系统管理",
179-
"opt_log": "操作日志"
179+
"opt_log": "操作日志",
180+
"prediction": "数据预测",
181+
"analysis": "数据分析"
180182

181183
},
182184
"i18n_table_not_exist": "当前表不存在"

backend/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,11 @@ url = "https://test.pypi.org/simple"
8383
explicit = true
8484

8585
[tool.uv.sources]
86-
sqlbot-xpack = { index = "testpypi" }
8786
torch = [
8887
{ index = "pytorch-cpu", extra = "cpu" },
8988
{ index = "pytorch-cu128", extra = "cu128" },
9089
]
90+
sqlbot-xpack = { path = "../../sqlbot-xpack" }
9191

9292
[tool.uv]
9393
conflicts = [

frontend/src/api/audit.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ export const audit = {
55
request.get(`/system/audit/page/${pageNum}/${pageSize}${params}`),
66
getOptions: () => request.get(`/system/audit/get_options`),
77
export2Excel: (params: any) =>
8-
request.get(`/system/audit/export`, {
9-
params,
8+
request.get(`/system/audit/export${params}`, {
109
responseType: 'blob',
1110
requestOptions: { customError: true },
1211
}),

0 commit comments

Comments
 (0)