feat(alerting): add Telegram callback ingress sensor
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / tests (push) Has been cancelled

This commit is contained in:
Your Name
2026-07-18 18:02:06 +08:00
parent 5f8f89c97b
commit f493fe8dcb
10 changed files with 730 additions and 0 deletions

View File

@@ -0,0 +1,164 @@
from __future__ import annotations
import re
from pathlib import Path
import pytest
import yaml
from src.core.metrics import (
TELEGRAM_CALLBACK_INGRESS_LAST_RECEIPT_TIMESTAMP,
)
from src.services import telegram_gateway as telegram_gateway_module
from src.services.controlled_alert_target_router import resolve_typed_alert_target
from src.services.telegram_gateway import TelegramGateway
ROOT = Path(__file__).resolve().parents[3]
CATALOG = ROOT / "apps" / "api" / "src" / "services" / "awooop_ansible_audit_service.py"
POST_VERIFIER = (
ROOT / "apps" / "api" / "src" / "services" / "awooop_ansible_post_verifier.py"
)
PLAYBOOK = (
ROOT
/ "infra"
/ "ansible"
/ "playbooks"
/ "110-telegram-callback-ingress-sensor.yml"
)
RULE_SOURCES = (
ROOT / "ops" / "monitoring" / "alerts-unified.yml",
ROOT / "ops" / "monitoring" / "alerts.yml",
ROOT / "k8s" / "monitoring" / "alert-chain-monitor.yaml",
)
class _ConfiguredGateway(TelegramGateway):
@property
def bot_token(self) -> str:
return "configured"
@property
def chat_id(self) -> str:
return "configured"
class _Redis:
def __init__(self) -> None:
self.values: dict[str, str] = {}
async def setex(self, key: str, _ttl: int, value: str) -> None:
self.values[key] = value
async def get(self, key: str) -> str | None:
return self.values.get(key)
def _rule(path: Path) -> dict:
payload = yaml.safe_load(path.read_text(encoding="utf-8"))
groups = payload["spec"]["groups"] if "spec" in payload else payload["groups"]
return next(
rule
for group in groups
for rule in group.get("rules", [])
if rule.get("alert") == "TelegramCallbackIngressUnverified"
)
def test_callback_ingress_sensor_is_identical_and_exact_typed_in_all_sources() -> None:
rules = [_rule(path) for path in RULE_SOURCES]
expressions = {re.sub(r"\s+", "", str(rule["expr"])) for rule in rules}
assert len(expressions) == 1
expression = expressions.pop()
assert "awoooi_telegram_callback_ingress_last_receipt_timestamp_seconds" in expression
assert ">300" in expression
assert "absent(" in expression
for rule in rules:
assert rule["for"] == "2m"
assert rule["labels"] == {
"severity": "warning",
"layer": "docker-188",
"component": "openclaw",
"host": "188",
"team": "platform",
"auto_repair": "true",
"alert_category": "ai_agent",
"canonical_asset_id": "service:openclaw:host188",
"domain_router": "docker_container",
}
route = resolve_typed_alert_target(
alertname="TelegramCallbackIngressUnverified",
target_resource=rule["labels"]["component"],
namespace="default",
labels=rule["labels"],
alert_category=rule["labels"]["alert_category"],
)
assert route["canonical_asset_id"] == "service:openclaw:host188"
assert route["allowed_catalog_ids"] == [
"ansible:188-openclaw-callback-forwarder"
]
assert route["cross_domain_fallback_allowed"] is False
def test_sensor_has_exact_host110_catalog_rollback_and_independent_verifier() -> None:
catalog = CATALOG.read_text(encoding="utf-8")
verifier = POST_VERIFIER.read_text(encoding="utf-8")
playbook = PLAYBOOK.read_text(encoding="utf-8")
assert '"catalog_id": "ansible:110-telegram-callback-ingress-sensor"' in catalog
assert '"inventory_hosts": ["host_110"]' in catalog
assert '"auto_apply_enabled": False' in catalog
assert '"canonical_asset_id": "service:prometheus"' in catalog
assert '"ansible:110-telegram-callback-ingress-sensor": (' in verifier
assert "host_110_telegram_callback_ingress_rule_healthy" in verifier
assert "host_110_telegram_callback_ingress_metric_visible" in verifier
assert "host_110_telegram_callback_ingress_rule_hash_converged" in verifier
assert "promtool" in playbook
assert "callback-sensor.bak" in playbook
assert "rescue:" in playbook
assert "Require exact rollback proof after any started apply" in playbook
assert "TelegramCallbackIngressUnverified" in playbook
play = yaml.safe_load(playbook)[0]
assert play["hosts"] == "host_110"
assert "--force-recreate" in playbook
assert "prometheus_runtime_rules" in playbook
assert "sensor_rollback_hashes" in playbook
@pytest.mark.asyncio
async def test_durable_callback_receipt_updates_prometheus_timestamp(
monkeypatch,
) -> None:
redis = _Redis()
monkeypatch.setattr(telegram_gateway_module, "get_redis", lambda: redis)
TELEGRAM_CALLBACK_INGRESS_LAST_RECEIPT_TIMESTAMP.set(0)
gateway = _ConfiguredGateway()
await gateway.record_callback_ingress_receipt(
source="openclaw_188_hmac_forwarder",
update_id=99,
)
assert TELEGRAM_CALLBACK_INGRESS_LAST_RECEIPT_TIMESTAMP._value.get() > 0
@pytest.mark.asyncio
async def test_separate_scraped_replica_refreshes_shared_receipt_metric(
monkeypatch,
) -> None:
redis = _Redis()
monkeypatch.setattr(telegram_gateway_module, "get_redis", lambda: redis)
writer = _ConfiguredGateway()
scraped_replica = _ConfiguredGateway()
await writer.record_callback_ingress_receipt(
source="openclaw_188_hmac_forwarder",
update_id=100,
)
TELEGRAM_CALLBACK_INGRESS_LAST_RECEIPT_TIMESTAMP.set(0)
assert await scraped_replica.refresh_callback_ingress_receipt() is True
assert TELEGRAM_CALLBACK_INGRESS_LAST_RECEIPT_TIMESTAMP._value.get() > 0