按 2026-11-02 需求补齐计划交付后端能力: - 角色授权:权限目录化,接口统一准入校验,未登记默认拒绝; 管理员判断改为按数据库角色重新判定,防止权限码持有者绕过 - 系统监控:单进程采集资源、请求与异常指标,分钟级聚合, 阈值配置化;敏感配置增加 repr 保护,Redis 密码 URL 转义 - 试用期计提:按回款日判定并写入快照,年度结清与调整单联动; 人员模型补试用期、离职日期与工资版本历史字段 - 计提模板:公式骨架受控,页面维护名称与参数绑定 - T+ 采集:自动化配置表与进度查询 内置角色禁停用保护对齐模块注释;核算规则版本提为常量并 补充批量核算失败堆栈日志。 影响范围:后端全部模块、数据库迁移 V22-V28 验证:uv run ruff check 通过;922 个单元测试全部通过; 集成测试因本机 MySQL 数据卷被其他容器锁定暂未运行
80 lines
4.2 KiB
Python
80 lines
4.2 KiB
Python
"""监控数据独立保存,不关联工资或审计表;仅这些新表按七天保留。"""
|
||
|
||
from datetime import datetime
|
||
|
||
from sqlalchemy import JSON, DateTime, Float, Index, Integer, String, UniqueConstraint
|
||
from sqlalchemy.orm import Mapped, mapped_column
|
||
|
||
from app.models.base import BIGINT_UNSIGNED, Base, mysql_table_args
|
||
|
||
|
||
class MonitorSnapshot(Base):
|
||
__tablename__ = "monitor_snapshots"
|
||
__table_args__ = mysql_table_args(
|
||
"分钟级运行监控快照",
|
||
UniqueConstraint("instance_id", "minute", name="uk_monitor_snapshots_instance_minute"),
|
||
Index("idx_monitor_snapshots_minute", "minute"),
|
||
)
|
||
|
||
id: Mapped[int] = mapped_column(
|
||
BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID"
|
||
)
|
||
instance_id: Mapped[str] = mapped_column(String(32), comment="应用实例标识")
|
||
minute: Mapped[datetime] = mapped_column(DateTime, comment="采集分钟,北京时间")
|
||
sample_count: Mapped[int] = mapped_column(Integer, comment="实际采样次数")
|
||
resources: Mapped[dict] = mapped_column(JSON, comment="资源均值与采集范围,不含配置")
|
||
requests: Mapped[dict] = mapped_column(JSON, comment="请求汇总与固定耗时直方图")
|
||
|
||
|
||
class MonitorRequestMinute(Base):
|
||
__tablename__ = "monitor_request_minutes"
|
||
__table_args__ = mysql_table_args(
|
||
"接口分钟级运行统计",
|
||
UniqueConstraint(
|
||
"instance_id", "minute", "method", "route", name="uk_monitor_request_minutes_endpoint"
|
||
),
|
||
Index("idx_monitor_request_minutes_minute", "minute"),
|
||
)
|
||
|
||
id: Mapped[int] = mapped_column(
|
||
BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID"
|
||
)
|
||
instance_id: Mapped[str] = mapped_column(String(32), comment="应用实例标识")
|
||
minute: Mapped[datetime] = mapped_column(DateTime, comment="请求分钟,北京时间")
|
||
method: Mapped[str] = mapped_column(String(8), comment="HTTP方法,固定集合")
|
||
route: Mapped[str] = mapped_column(String(256), comment="路由模板,不含原始地址及参数")
|
||
metrics: Mapped[dict] = mapped_column(JSON, comment="请求数、状态分类与固定直方图")
|
||
|
||
|
||
class MonitorEvent(Base):
|
||
__tablename__ = "monitor_events"
|
||
__table_args__ = mysql_table_args(
|
||
"脱敏诊断事件与异常恢复记录",
|
||
Index("idx_monitor_events_last_seen", "last_seen"),
|
||
Index("idx_monitor_events_request_id", "request_id"),
|
||
Index("idx_monitor_events_fingerprint", "fingerprint", "resolved_at"),
|
||
)
|
||
|
||
id: Mapped[int] = mapped_column(
|
||
BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID"
|
||
)
|
||
instance_id: Mapped[str] = mapped_column(String(32), comment="应用实例标识")
|
||
kind: Mapped[str] = mapped_column(String(24), comment="事件类型,固定集合")
|
||
code: Mapped[str] = mapped_column(String(64), comment="稳定错误码")
|
||
component: Mapped[str] = mapped_column(String(128), comment="所属组件或日志模块")
|
||
level: Mapped[str] = mapped_column(String(16), comment="异常级别")
|
||
message: Mapped[str] = mapped_column(String(256), comment="通用说明,不保存内部异常文本")
|
||
fingerprint: Mapped[str | None] = mapped_column(String(64), comment="同类健康异常合并键")
|
||
request_id: Mapped[str | None] = mapped_column(String(32), comment="请求关联编号")
|
||
method: Mapped[str | None] = mapped_column(String(8), comment="HTTP方法")
|
||
route: Mapped[str | None] = mapped_column(String(256), comment="路由模板")
|
||
status_code: Mapped[int | None] = mapped_column(Integer, comment="HTTP状态码")
|
||
duration_ms: Mapped[float | None] = mapped_column(Float, comment="请求耗时,毫秒")
|
||
batch_no: Mapped[str | None] = mapped_column(String(32), comment="相关同步批次编号")
|
||
first_seen: Mapped[datetime] = mapped_column(DateTime, comment="首次发生时间")
|
||
last_seen: Mapped[datetime] = mapped_column(DateTime, comment="最近发生时间")
|
||
occurrences: Mapped[int] = mapped_column(Integer, comment="发生或持续采样次数")
|
||
resolved_at: Mapped[datetime | None] = mapped_column(
|
||
DateTime, comment="恢复时间,仅用于健康异常"
|
||
)
|