PayrollManagementSystem/backend/app/schemas/monitor.py
liuwenxin 1461a8d113 feat(后端): 添加授权体系、系统监控与试用期计提
按 2026-11-02 需求补齐计划交付后端能力:
- 角色授权:权限目录化,接口统一准入校验,未登记默认拒绝;
  管理员判断改为按数据库角色重新判定,防止权限码持有者绕过
- 系统监控:单进程采集资源、请求与异常指标,分钟级聚合,
  阈值配置化;敏感配置增加 repr 保护,Redis 密码 URL 转义
- 试用期计提:按回款日判定并写入快照,年度结清与调整单联动;
  人员模型补试用期、离职日期与工资版本历史字段
- 计提模板:公式骨架受控,页面维护名称与参数绑定
- T+ 采集:自动化配置表与进度查询

内置角色禁停用保护对齐模块注释;核算规则版本提为常量并
补充批量核算失败堆栈日志。

影响范围:后端全部模块、数据库迁移 V22-V28
验证:uv run ruff check 通过;922 个单元测试全部通过;
集成测试因本机 MySQL 数据卷被其他容器锁定暂未运行
2026-11-03 11:20:55 +08:00

79 lines
2.0 KiB
Python

"""监控接口只暴露固定白名单,不传输内部异常或连接配置。"""
from datetime import datetime
from typing import Annotated, Literal
from pydantic import BaseModel, BeforeValidator, ConfigDict, Field
from app.core.response import PageQuery
Status = Literal["normal", "warning", "error", "unknown"]
Hours = Annotated[
Literal[1, 24, 168],
BeforeValidator(lambda value: int(value) if value in ("1", "24", "168") else value),
]
class MonitorWindow(BaseModel):
hours: Hours = 1
end: datetime | None = None
route: str | None = Field(default=None, max_length=256)
class EventQuery(PageQuery):
hours: Hours = 24
end: datetime | None = None
route: str | None = Field(default=None, max_length=256)
kind: Literal["HEALTH", "REQUEST_ERROR", "SLOW_REQUEST", "RUNTIME_ERROR"] | None = None
request_id: str | None = Field(default=None, pattern=r"^[a-f0-9]{32}$")
active_only: bool = False
class EventOut(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
instance_id: str
kind: str
code: str
component: str
level: str
message: str
request_id: str | None = None
method: str | None = None
route: str | None = None
status_code: int | None = None
duration_ms: float | None = None
batch_no: str | None = None
first_seen: datetime
last_seen: datetime
occurrences: int
resolved_at: datetime | None = None
class DependencyOut(BaseModel):
name: str
status: Status
message: str
checked_at: datetime | None = None
duration_ms: float | None = None
class OverviewOut(BaseModel):
status: Status
environment: str
version: str
instance_id: str
uptime_seconds: int
collected_at: datetime | None
last_persisted_at: datetime | None
collection_status: Status
collection_message: str
resources: dict
requests: dict
dependencies: list[DependencyOut]
alerts: list[EventOut]
tasks: dict
dropped_events: int
retention_days: int = 7