40 lines
4.5 KiB
Python
40 lines
4.5 KiB
Python
|
|
"""新增运行监控快照、接口聚合与诊断事件。"""
|
|||
|
|
|
|||
|
|
from alembic import op
|
|||
|
|
from sqlalchemy import text
|
|||
|
|
|
|||
|
|
revision: str = "23b4c5d6e7f8"
|
|||
|
|
down_revision: str | None = "22a3b4c5d6e7"
|
|||
|
|
branch_labels = None
|
|||
|
|
depends_on = None
|
|||
|
|
|
|||
|
|
DDL = [
|
|||
|
|
"CREATE TABLE monitor_snapshots (\n\tid BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, \n\tinstance_id VARCHAR(32) NOT NULL COMMENT '应用实例标识', \n\tminute DATETIME NOT NULL COMMENT '采集分钟,北京时间', \n\tsample_count INTEGER NOT NULL COMMENT '实际采样次数', \n\tresources JSON NOT NULL COMMENT '资源均值与采集范围,不含配置', \n\trequests JSON NOT NULL COMMENT '请求汇总与固定耗时直方图', \n\tCONSTRAINT pk_monitor_snapshots PRIMARY KEY (id), \n\tCONSTRAINT uk_monitor_snapshots_instance_minute UNIQUE (instance_id, minute)\n)ENGINE=InnoDB CHARSET=utf8mb4 COMMENT='分钟级运行监控快照' COLLATE utf8mb4_general_ci",
|
|||
|
|
"CREATE INDEX idx_monitor_snapshots_minute ON monitor_snapshots (minute)",
|
|||
|
|
"CREATE TABLE monitor_request_minutes (\n\tid BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, \n\tinstance_id VARCHAR(32) NOT NULL COMMENT '应用实例标识', \n\tminute DATETIME NOT NULL COMMENT '请求分钟,北京时间', \n\tmethod VARCHAR(8) NOT NULL COMMENT 'HTTP方法,固定集合', \n\troute VARCHAR(256) NOT NULL COMMENT '路由模板,不含原始地址及参数', \n\tmetrics JSON NOT NULL COMMENT '请求数、状态分类与固定直方图', \n\tCONSTRAINT pk_monitor_request_minutes PRIMARY KEY (id), \n\tCONSTRAINT uk_monitor_request_minutes_endpoint UNIQUE (instance_id, minute, method, route)\n)ENGINE=InnoDB CHARSET=utf8mb4 COMMENT='接口分钟级运行统计' COLLATE utf8mb4_general_ci",
|
|||
|
|
"CREATE INDEX idx_monitor_request_minutes_minute ON monitor_request_minutes (minute)",
|
|||
|
|
"CREATE TABLE monitor_events (\n\tid BIGINT UNSIGNED NOT NULL COMMENT '主键ID' AUTO_INCREMENT, \n\tinstance_id VARCHAR(32) NOT NULL COMMENT '应用实例标识', \n\tkind VARCHAR(24) NOT NULL COMMENT '事件类型,固定集合', \n\tcode VARCHAR(64) NOT NULL COMMENT '稳定错误码', \n\tcomponent VARCHAR(128) NOT NULL COMMENT '所属组件或日志模块', \n\tlevel VARCHAR(16) NOT NULL COMMENT '异常级别', \n\tmessage VARCHAR(256) NOT NULL COMMENT '通用说明,不保存内部异常文本', \n\tfingerprint VARCHAR(64) COMMENT '同类健康异常合并键', \n\trequest_id VARCHAR(32) COMMENT '请求关联编号', \n\tmethod VARCHAR(8) COMMENT 'HTTP方法', \n\troute VARCHAR(256) COMMENT '路由模板', \n\tstatus_code INTEGER COMMENT 'HTTP状态码', \n\tduration_ms FLOAT COMMENT '请求耗时,毫秒', \n\tbatch_no VARCHAR(32) COMMENT '相关同步批次编号', \n\tfirst_seen DATETIME NOT NULL COMMENT '首次发生时间', \n\tlast_seen DATETIME NOT NULL COMMENT '最近发生时间', \n\toccurrences INTEGER NOT NULL COMMENT '发生或持续采样次数', \n\tresolved_at DATETIME COMMENT '恢复时间,仅用于健康异常', \n\tCONSTRAINT pk_monitor_events PRIMARY KEY (id)\n)ENGINE=InnoDB CHARSET=utf8mb4 COMMENT='脱敏诊断事件与异常恢复记录' COLLATE utf8mb4_general_ci",
|
|||
|
|
"CREATE INDEX idx_monitor_events_fingerprint ON monitor_events (fingerprint, resolved_at)",
|
|||
|
|
"CREATE INDEX idx_monitor_events_last_seen ON monitor_events (last_seen)",
|
|||
|
|
"CREATE INDEX idx_monitor_events_request_id ON monitor_events (request_id)",
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
|
|||
|
|
def upgrade():
|
|||
|
|
for statement in DDL:
|
|||
|
|
op.execute(text(statement))
|
|||
|
|
op.execute(text("INSERT INTO permissions (perm_code,perm_name,perm_type,sort_order,status) VALUES ('system:monitor:view','系统监控:查看',1,100,1)"))
|
|||
|
|
op.execute(text("INSERT INTO role_permissions (role_id,permission_id) SELECT r.id,p.id FROM roles r JOIN permissions p ON p.perm_code='system:monitor:view' WHERE r.role_code='admin'"))
|
|||
|
|
|
|||
|
|
|
|||
|
|
def downgrade():
|
|||
|
|
# 应用回滚可保留新增监控表;有历史数据时拒绝隐式删除。
|
|||
|
|
bind = op.get_bind()
|
|||
|
|
for table in ("monitor_events", "monitor_request_minutes", "monitor_snapshots"):
|
|||
|
|
if bind.execute(text(f"SELECT COUNT(*) FROM {table}")).scalar():
|
|||
|
|
raise RuntimeError("存在监控历史,拒绝自动删除;请回退应用并保留新增表")
|
|||
|
|
for table in ("monitor_events", "monitor_request_minutes", "monitor_snapshots"):
|
|||
|
|
op.drop_table(table)
|
|||
|
|
bind.execute(text("DELETE rp FROM role_permissions rp JOIN permissions p ON p.id=rp.permission_id WHERE p.perm_code='system:monitor:view'"))
|
|||
|
|
bind.execute(text("DELETE FROM permissions WHERE perm_code='system:monitor:view'"))
|