From ec05163a045e0eadaccf94bdb46ad6451c875565 Mon Sep 17 00:00:00 2001 From: nessi Date: Thu, 12 Feb 2026 15:44:30 +0100 Subject: [PATCH] Add minimum total connection threshold for active ratio alerts Introduced `ALERT_ACTIVE_CONNECTION_RATIO_MIN_TOTAL_CONNECTIONS` to reduce false positives by requiring a minimum number of total connections before evaluating the active connection ratio. Updated the logic and description in relevant files for clarity and configurability. --- .env.example | 3 +++ backend/app/core/config.py | 1 + backend/app/services/alerts.py | 11 +++++++++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 124c479..495ae60 100644 --- a/.env.example +++ b/.env.example @@ -42,6 +42,9 @@ ENCRYPTION_KEY=REPLACE_WITH_FERNET_KEY CORS_ORIGINS=http://localhost:5173,http://localhost:8080 # Target polling interval in seconds. POLL_INTERVAL_SECONDS=30 +# Active Connection Ratio alert is only evaluated when total sessions +# are at least this number (reduces false positives on low-traffic DBs). +ALERT_ACTIVE_CONNECTION_RATIO_MIN_TOTAL_CONNECTIONS=5 # Initial admin bootstrap user (created on first startup if not present). INIT_ADMIN_EMAIL=admin@example.com INIT_ADMIN_PASSWORD=ChangeMe123! diff --git a/backend/app/core/config.py b/backend/app/core/config.py index 21c0ba1..3222c3e 100644 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -25,6 +25,7 @@ class Settings(BaseSettings): encryption_key: str cors_origins: str = "http://localhost:5173" poll_interval_seconds: int = 30 + alert_active_connection_ratio_min_total_connections: int = 5 init_admin_email: str = "admin@example.com" init_admin_password: str = "ChangeMe123!" diff --git a/backend/app/services/alerts.py b/backend/app/services/alerts.py index d3b7bcc..ef6a8d5 100644 --- a/backend/app/services/alerts.py +++ b/backend/app/services/alerts.py @@ -268,7 +268,11 @@ async def _build_standard_rules(db: AsyncSession, target: Target) -> tuple[list[ slowest_query_total = await _latest_query_snapshot_max(db, target.id, "total_time") active_ratio = None - if active_connections is not None and total_connections and total_connections > 0: + if ( + active_connections is not None + and total_connections is not None + and total_connections >= settings.alert_active_connection_ratio_min_total_connections + ): active_ratio = active_connections / total_connections rollback_ratio_15m, tx_total_15m = await _rollback_ratio_recent( @@ -280,7 +284,10 @@ async def _build_standard_rules(db: AsyncSession, target: Target) -> tuple[list[ _RuleInput( key="active_connections_ratio", name="Active Connection Ratio", - description="Share of active sessions over total sessions.", + description=( + "Share of active sessions over total sessions. " + f"Only evaluated when total sessions >= {settings.alert_active_connection_ratio_min_total_connections}." + ), category="capacity", value=active_ratio, warning_threshold=0.70,