Compare commits

..

No commits in common. 'ec16a62ee12f9c92a78833cdb373e6d1400d3f71' and '9a211f9484c0f325dfa44597acd70b7e9444df2d' have entirely different histories.

@ -1,15 +1,10 @@
from collections import namedtuple
from typing import TypeVar, Generic, Optional
from beartype.claw import beartype_this_package
from pydantic import BaseModel
beartype_this_package()
HttpCode = namedtuple('HttpResp', ['code', 'msg'])
T = TypeVar("T")
class HttpResp:
"""HTTP响应结果
"""
@ -29,10 +24,4 @@ class HttpResp:
REQUEST_404_ERROR = HttpCode(404, '请求接口不存在')
DATA_ALREADY_EXISTS = HttpCode(409, '数据已存在')
SYSTEM_ERROR = HttpCode(500, '系统错误')
SYSTEM_TIMEOUT_ERROR = HttpCode(504, '请求超时')
class ApiResponse(BaseModel, Generic[T]):
code: int = HttpResp.SUCCESS.code
message: str = HttpResp.SUCCESS.msg
data: Optional[T] = None
SYSTEM_TIMEOUT_ERROR = HttpCode(504, '请求超时')

@ -1,9 +1,8 @@
from typing import Optional, List, Any, Generic, TypeVar
from typing import Optional, List, Any
from typing import Union
from pydantic import BaseModel, Field
T = TypeVar('T')
class BaseTabelDto(BaseModel):
id: Optional[str] = None
@ -28,14 +27,14 @@ class BaseRenameReq(BaseModel):
name: str
class BasePageResp(BaseModel, Generic[T]):
class BasePageResp(BaseModel):
page_number: Optional[int]
page_size: Optional[int]
page_count: Optional[int]
sort: Optional[str]
orderby: Optional[str]
count: Optional[int]
data: Optional[List[T]]
data: Optional[List[Any]]
class Config:
arbitrary_types_allowed = True

@ -1,58 +0,0 @@
from typing import List
from pydantic import BaseModel
class CpuInfo(BaseModel):
cpu_num: int
total: float
sys: float
used: float
wait: float
free: float
class SystemInfo(BaseModel):
computerName: str
computerIp: str
userDir: str
osName: str
osArch: str
class DiskInfo(BaseModel):
dirName: str
sysTypeName: str
typeName: str
total: str # 格式化大小,如 "1.20GB"
free: str # 格式化大小
used: str # 格式化大小
usage: float # 百分比
class MemoryInfo(BaseModel):
total: float # GB
used: float # GB
free: float # GB
usage: float # 百分比
class PythonEnvInfo(BaseModel):
name: str
version: str
home: str
inputArgs: str
total: float # MB
max: float # MB
free: float # MB
usage: float # MB
runTime: str # 格式化时间,如 "1天2小时30分钟"
startTime: str # 格式化时间
class ServerInfo(BaseModel):
cpu: CpuInfo
memory: MemoryInfo
system: SystemInfo
disks: List[DiskInfo]
python: PythonEnvInfo

@ -1,8 +1,8 @@
import inspect
import logging
from datetime import datetime
from functools import wraps
from typing import Union, Type, Callable, TypeVar, get_type_hints
from typing import Union, Type, Callable, TypeVar
from datetime import datetime
import pytz
from fastapi.encoders import jsonable_encoder
@ -10,24 +10,15 @@ from pydantic import BaseModel
from starlette.responses import JSONResponse
from config import get_settings
from entity.dto import HttpResp, ApiResponse
from entity.dto import HttpResp
from exceptions.base import AppException
from utils import get_uuid
RT = TypeVar('RT') # 返回类型
def unified_resp(func: Callable[..., RT]) -> Callable[..., RT]:
"""统一响应格式
接口正常返回时,统一响应结果格式
"""
# 获取原始函数的返回类型注解
hints = get_type_hints(func)
return_type = hints.get('return', None)
# 修改函数的返回类型注解
if return_type:
func.__annotations__['return'] = ApiResponse[return_type]
@wraps(func)
async def wrapper(*args, **kwargs) -> RT:

@ -2,7 +2,6 @@ import logging
from fastapi import APIRouter
from entity.dto.monitor_dto import ServerInfo
from router import unified_resp
from utils.server_info_utils import ServerInfoUtils
@ -11,14 +10,14 @@ logger = logging.getLogger(__name__)
router = APIRouter(prefix='/monitor', tags=["缓存监控服务"])
@router.get('/server', summary='服务监控')
@router.get('/server',summary='服务监控')
@unified_resp
def monitor_server() -> ServerInfo:
def monitor_server():
"""服务器信息监控"""
return ServerInfo(
cpu=ServerInfoUtils.get_cpu_info(),
memory=ServerInfoUtils.get_mem_info(),
system=ServerInfoUtils.get_sys_info(),
disks=ServerInfoUtils.get_disk_info(),
python=ServerInfoUtils.get_py_info()
)
return {
'cpu': ServerInfoUtils.get_cpu_info(),
'mem': ServerInfoUtils.get_mem_info(),
'sys': ServerInfoUtils.get_sys_info(),
'disk': ServerInfoUtils.get_disk_info(),
'py': ServerInfoUtils.get_py_info(),
}

@ -1,9 +1,5 @@
from typing import List
from fastapi import APIRouter, Query
from entity.db_models import User
from entity.dto.base import BasePageResp
from entity.dto.user_dto import UserQueryPageReq, UserQueryReq
from router import BaseController, unified_resp
from service.user_service import UserService
@ -14,10 +10,10 @@ base_app = BaseController(base_service)
@router.get("/page")
@unified_resp
async def get_page(req:UserQueryPageReq=Query(...)) -> BasePageResp[User]:
async def get_page(req:UserQueryPageReq=Query(...)):
return await base_service.get_by_page(req)
@router.get("/list")
@unified_resp
async def get_list(req:UserQueryReq=Query(...))->List[User]:
async def get_list(req:UserQueryReq=Query(...)):
return await base_service.get_list(req)

@ -1,10 +1,11 @@
from typing import Union, Type, List, Any, TypeVar, Generic
from typing import Union, Type, List, Any, TypeVar, Generic, Callable, Coroutine, Optional
from fastapi_pagination import Params
from fastapi_pagination.ext.sqlalchemy import paginate
from pydantic import BaseModel
from sqlalchemy import func
from sqlalchemy.ext.asyncio import AsyncSession
from sqlmodel import SQLModel
from core.global_context import current_session
from entity import DbBaseModel
@ -21,7 +22,6 @@ session.scalar: 直接明确获取一条数据,可以直接返回,无需额
"""
T = TypeVar('T', bound=DbBaseModel)
class BaseService(Generic[T]):
model: Type[T] # 子类必须指定模型
@ -66,7 +66,7 @@ class BaseService(Generic[T]):
pass
@classmethod
async def get_by_page(cls, query_params: Union[dict, BasePageQueryReq]) -> BasePageResp[T]:
async def get_by_page(cls, query_params: Union[dict, BasePageQueryReq])->BasePageResp:
if not isinstance(query_params, dict):
query_params = query_params.model_dump()
query_params = {k: v for k, v in query_params.items() if v is not None}
@ -75,7 +75,7 @@ class BaseService(Generic[T]):
@classmethod
async def auto_page(cls, query_stmt, query_params: Union[dict, BasePageQueryReq] = None,
dto_model_class: Type[BaseModel] = None) -> BasePageResp[T]:
dto_model_class: Type[BaseModel] = None)->BasePageResp:
if not query_params:
query_params = {}
if not isinstance(query_params, dict):
@ -116,7 +116,7 @@ class BaseService(Generic[T]):
})
@classmethod
async def get_list(cls, query_params: Union[dict, BaseQueryReq]) -> List[T]:
async def get_list(cls, query_params: Union[dict, BaseQueryReq])->List[T]:
if not isinstance(query_params, dict):
query_params = query_params.model_dump()
query_params = {k: v for k, v in query_params.items() if v is not None}
@ -150,7 +150,7 @@ class BaseService(Generic[T]):
return [item["id"] for item in exec_result.scalars().all()]
@classmethod
async def save(cls, **kwargs) -> T:
async def save(cls, **kwargs)->T:
sample_obj = cls.model(**kwargs)
session = cls.get_db()
session.add(sample_obj)
@ -158,7 +158,7 @@ class BaseService(Generic[T]):
return sample_obj
@classmethod
async def insert_many(cls, data_list, batch_size=100) -> None:
async def insert_many(cls, data_list, batch_size=100)->None:
async with cls.get_db() as session:
for d in data_list:
if not d.get("id", None):
@ -168,27 +168,27 @@ class BaseService(Generic[T]):
session.add_all(data_list[i: i + batch_size])
@classmethod
async def update_by_id(cls, pid, data) -> int:
async def update_by_id(cls, pid, data)-> int:
update_stmt = cls.model.update().where(cls.model.id == pid).values(**data)
session = cls.get_db()
result = await session.execute(update_stmt)
return result.rowcount
@classmethod
async def update_many_by_id(cls, data_list) -> None:
async def update_many_by_id(cls, data_list)->None:
async with cls.get_db() as session:
for data in data_list:
stmt = cls.model.update().where(cls.model.id == data["id"]).values(**data)
await session.execute(stmt)
@classmethod
async def get_by_id(cls, pid) -> T:
async def get_by_id(cls, pid)->T:
stmt = cls.model.select().where(cls.model.id == pid)
session = cls.get_db()
return await session.scalar(stmt)
@classmethod
async def get_by_ids(cls, pids, cols=None) -> List[T]:
async def get_by_ids(cls, pids, cols=None)->List[T]:
if cols:
objs = cls.model.select(*cols)
else:
@ -199,14 +199,14 @@ class BaseService(Generic[T]):
return list(result.all())
@classmethod
async def delete_by_id(cls, pid) -> int:
async def delete_by_id(cls, pid)-> int:
del_stmt = cls.model.delete().where(cls.model.id == pid)
session = cls.get_db()
exec_result = await session.execute(del_stmt)
return exec_result.rowcount
@classmethod
async def delete_by_ids(cls, pids) -> int:
async def delete_by_ids(cls, pids)-> int:
session = cls.get_db()
del_stmt = cls.model.delete().where(cls.model.id.in_(pids))
result = await session.execute(del_stmt)

@ -7,7 +7,6 @@ from typing import List, Any
import psutil
from config import get_settings
from entity.dto.monitor_dto import CpuInfo, MemoryInfo, SystemInfo, DiskInfo, PythonEnvInfo
from utils.ip_utils import IpUtil
@ -51,7 +50,7 @@ class ServerInfoUtils:
return res
@staticmethod
def get_cpu_info() -> CpuInfo:
def get_cpu_info() -> dict:
"""获取CPU信息"""
res = {'cpu_num': psutil.cpu_count(logical=True)}
cpu_times = psutil.cpu_times()
@ -63,35 +62,35 @@ class ServerInfoUtils:
res['used'] = round(cpu_times.user / total, 2)
res['wait'] = round(get_attr(cpu_times, 'iowait', 0.0) / total, 2)
res['free'] = round(cpu_times.idle / total, 2)
return CpuInfo(**res)
return res
@staticmethod
def get_mem_info() -> MemoryInfo:
def get_mem_info() -> dict:
"""获取内存信息"""
number = 1024 ** 3
return MemoryInfo(**{
return {
'total': round(psutil.virtual_memory().total / number, 2),
'used': round(psutil.virtual_memory().used / number, 2),
'free': round(psutil.virtual_memory().available / number, 2),
'usage': round(psutil.virtual_memory().percent, 2)})
'usage': round(psutil.virtual_memory().percent, 2)}
@staticmethod
def get_sys_info() -> SystemInfo:
def get_sys_info() -> dict:
"""获取服务器信息"""
return SystemInfo(**{
return {
'computerName': IpUtil.get_host_name(),
'computerIp': IpUtil.get_host_ip(),
'userDir': os.path.dirname(os.path.abspath(os.path.join(__file__, '../..'))),
'osName': platform.system(),
'osArch': platform.machine()})
'osArch': platform.machine()}
@staticmethod
def get_disk_info() -> List[DiskInfo]:
def get_disk_info() -> List[dict]:
"""获取磁盘信息"""
disk_info = []
for disk in psutil.disk_partitions():
usage = psutil.disk_usage(disk.mountpoint)
disk_info.append(DiskInfo(**{
disk_info.append({
'dirName': disk.mountpoint,
'sysTypeName': disk.fstype,
'typeName': disk.device,
@ -99,7 +98,7 @@ class ServerInfoUtils:
'free': ServerInfoUtils.get_size(usage.free),
'used': ServerInfoUtils.get_size(usage.used),
'usage': round(usage.percent, 2),
}))
})
return disk_info
@staticmethod
@ -109,7 +108,7 @@ class ServerInfoUtils:
cur_proc = psutil.Process(os.getpid())
mem_info = cur_proc.memory_info()
start_dt = datetime.fromtimestamp(cur_proc.create_time())
return PythonEnvInfo(**{
return {
'name': 'Python',
'version': platform.python_version(),
'home': sys.executable,
@ -120,4 +119,4 @@ class ServerInfoUtils:
'usage': round(mem_info.rss / number, 2),
'runTime': ServerInfoUtils.fmt_timedelta(datetime.now() - start_dt),
'startTime': start_dt.strftime(ServerInfoUtils.datetime_fmt),
})
}

Loading…
Cancel
Save