ote discord notifikace error
Some checks failed
CI and deploy / migration-check (push) Failing after 13s
CI and deploy / deploy (push) Has been skipped

This commit is contained in:
Dusan Vojacek
2026-04-29 14:07:42 +02:00
parent 93193fd5dc
commit 2eeab58c8e
3 changed files with 65 additions and 0 deletions

View File

@@ -15,6 +15,7 @@ from app.config import get_settings
logger = logging.getLogger(__name__)
_WEBHOOK_CACHE: dict[tuple[int, str], str] = {}
_OTE_IMPORT_ALERT_CACHE: dict[tuple[str, str], float] = {}
async def _get_site_webhook_url(
@@ -214,6 +215,46 @@ async def send_discord(
return False
def _should_send_ote_alert(date_str: str, signature: str, *, cooldown_s: float) -> bool:
now = datetime.now(timezone.utc).timestamp()
key = (str(date_str), str(signature))
last = _OTE_IMPORT_ALERT_CACHE.get(key)
if last is not None and (now - last) < cooldown_s:
return False
_OTE_IMPORT_ALERT_CACHE[key] = now
return True
async def notify_ote_import_format_changed(
conn: asyncpg.Connection | None,
*,
report_date: str,
error_detail: str,
url: str,
) -> None:
"""
Discord alert pro situaci, kdy OTE změnilo formát chart-data a import selže na parseru v DB.
Dedup: stejný report_date + stejná chyba se pošle max 1× za cooldown.
"""
signature = (error_detail or "").strip().splitlines()[0][:160]
if not _should_send_ote_alert(report_date, signature, cooldown_s=6 * 3600):
return
detail = (error_detail or "").strip()
if len(detail) > 1600:
detail = detail[:1600] + ""
msg = (
f"**OTE import selhal pravděpodobná změna formátu dat**\n"
f"Report date: `{report_date}`\n"
f"URL: `{url}`\n"
f"Chyba: {detail}\n"
f"Doporučení: zkontrolovat `ems.fn_ote_parse_15m_price_json` (tooltipy / struktura payloadu) "
f"a upravit parser."
)
await send_discord(conn, site_id=None, message=msg, level="critical")
async def notify_modbus_mismatch(
conn: asyncpg.Connection | None,
site_id: int | None,

View File

@@ -12,6 +12,7 @@ import httpx
from app.config import get_settings
from app.db_json import fetch_json
from services.notification_service import notify_ote_import_format_changed
logger = logging.getLogger(__name__)
@@ -170,6 +171,17 @@ async def import_ote_prices_for_day(
except Exception as e:
detail = str(e).strip() or e.__class__.__name__
logger.error("OTE import DB error pro %s: %s", day_str, detail, exc_info=True)
if (
"OTE price dataLine not found" in detail
or "OTE price series:" in detail
or "cannot parse date from graph.title" in detail
):
await notify_ote_import_format_changed(
conn,
report_date=day_str,
error_detail=detail,
url=OTE_URL.format(date=day_str),
)
short = detail[:200] if len(detail) > 200 else detail
return -1, day_str, 0.0, f"db_import:{e.__class__.__name__}: {short}"
@@ -318,5 +330,16 @@ async def import_ote_prices(
except Exception as e:
detail = str(e).strip() or e.__class__.__name__
logger.error("OTE import DB error: %s", detail, exc_info=True)
if (
"OTE price dataLine not found" in detail
or "OTE price series:" in detail
or "cannot parse date from graph.title" in detail
):
await notify_ote_import_format_changed(
db,
report_date=date_str,
error_detail=detail,
url=OTE_URL.format(date=date_str),
)
short = detail[:200] if len(detail) > 200 else detail
return -1, date_str, 0.0, f"db_import:{e.__class__.__name__}: {short}"

View File

@@ -149,6 +149,7 @@ PRICE_IMPORT_RETRY_BACKOFF_SEC=300
## Monitoring a alerting
- Alert pokud do 16:00 nejsou v DB ceny na zítřek
- Discord (CRITICAL) pokud OTE změní formát `@@chart-data` tak, že DB parser (`ems.fn_ote_parse_15m_price_json`) nenajde vhodnou sérii (`dataLine[].tooltip`) nebo narazí na neočekávaný počet bodů; posílá `services.notification_service.notify_ote_import_format_changed`.
- Log každého importu (datum, počet intervalů, zdroj, trvání)
- Endpoint `GET /health/prices?date=YYYY-MM-DD` → vrátí počet importovaných intervalů