"""监控数据独立保存,不关联工资或审计表;仅这些新表按七天保留。""" 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="恢复时间,仅用于健康异常" )