- Backend: FastAPI + SQLAlchemy + Celery (Python 3.11+) - Frontend: Vue 3 + TypeScript + Pinia + Tailwind - Admin Frontend: separate Vue 3 app for management - Docker Compose: 9 services orchestration - Specs: design prototypes, memory system PRD, product roadmap Cleanup performed: - Removed temporary debug scripts from backend root - Removed deprecated admin_app.py (embedded UI) - Removed duplicate docs from admin-frontend - Updated .gitignore for Vite cache and egg-info
101 lines
3.1 KiB
Python
101 lines
3.1 KiB
Python
"""add provider monitoring tables
|
|
|
|
Revision ID: 0003_add_monitoring
|
|
Revises: 0002_add_api_key
|
|
Create Date: 2025-01-01
|
|
"""
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision = "0003_add_monitoring"
|
|
down_revision = "0002_add_api_key"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
# 创建 provider_metrics 表
|
|
op.create_table(
|
|
"provider_metrics",
|
|
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
|
|
sa.Column("provider_id", sa.String(length=36), nullable=False),
|
|
sa.Column(
|
|
"timestamp",
|
|
sa.DateTime(timezone=True),
|
|
server_default=sa.text("now()"),
|
|
nullable=True,
|
|
),
|
|
sa.Column("success", sa.Boolean(), nullable=False),
|
|
sa.Column("latency_ms", sa.Integer(), nullable=True),
|
|
sa.Column("cost_usd", sa.Numeric(precision=10, scale=6), nullable=True),
|
|
sa.Column("error_message", sa.Text(), nullable=True),
|
|
sa.Column("request_id", sa.String(length=100), nullable=True),
|
|
sa.ForeignKeyConstraint(
|
|
["provider_id"],
|
|
["providers.id"],
|
|
ondelete="CASCADE",
|
|
),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
op.create_index(
|
|
"ix_provider_metrics_provider_id",
|
|
"provider_metrics",
|
|
["provider_id"],
|
|
unique=False,
|
|
)
|
|
op.create_index(
|
|
"ix_provider_metrics_timestamp",
|
|
"provider_metrics",
|
|
["timestamp"],
|
|
unique=False,
|
|
)
|
|
|
|
# 创建 provider_health 表
|
|
op.create_table(
|
|
"provider_health",
|
|
sa.Column("provider_id", sa.String(length=36), nullable=False),
|
|
sa.Column("is_healthy", sa.Boolean(), server_default=sa.text("true"), nullable=True),
|
|
sa.Column("last_check", sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column("consecutive_failures", sa.Integer(), server_default=sa.text("0"), nullable=True),
|
|
sa.Column("last_error", sa.Text(), nullable=True),
|
|
sa.ForeignKeyConstraint(
|
|
["provider_id"],
|
|
["providers.id"],
|
|
ondelete="CASCADE",
|
|
),
|
|
sa.PrimaryKeyConstraint("provider_id"),
|
|
)
|
|
|
|
# 创建 provider_secrets 表
|
|
op.create_table(
|
|
"provider_secrets",
|
|
sa.Column("id", sa.String(length=36), nullable=False),
|
|
sa.Column("name", sa.String(length=100), nullable=False),
|
|
sa.Column("encrypted_value", sa.Text(), nullable=False),
|
|
sa.Column(
|
|
"created_at",
|
|
sa.DateTime(timezone=True),
|
|
server_default=sa.text("now()"),
|
|
nullable=True,
|
|
),
|
|
sa.Column(
|
|
"updated_at",
|
|
sa.DateTime(timezone=True),
|
|
server_default=sa.text("now()"),
|
|
nullable=True,
|
|
),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
sa.UniqueConstraint("name"),
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_table("provider_secrets")
|
|
op.drop_table("provider_health")
|
|
op.drop_index("ix_provider_metrics_timestamp", table_name="provider_metrics")
|
|
op.drop_index("ix_provider_metrics_provider_id", table_name="provider_metrics")
|
|
op.drop_table("provider_metrics")
|