fix(prometheus): a refused token stops the scraping, as Home Assistant bans an address after a few refusals (#6355)
CI / lint (push) Successful in 2s
CI / unit (push) Successful in 1m36s
CI / integration (push) Successful in 1m55s
CI / publish (push) Successful in 20s

Also names the Home Assistant connection by its address in the audit log and
timeline, where its id showed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-01 09:41:53 -05:00
co-authored by Claude Opus 5.5
parent a1dfa7b821
commit 66a5dd12fd
11 changed files with 94 additions and 11 deletions
@@ -134,3 +134,38 @@ def test_a_scrape_records_series_rates_and_a_down_target_fires_its_rule(app):
assert rows[down].last_ok_at is None
assert down_latest[(down, "is_up")] == 0.0
assert state.state == AlertStateEnum.firing
def test_a_refused_token_is_asked_once(app):
"""Home Assistant bans an address after a few refusals, so a refused token
isn't retried at each interval, however long ago the last scrape was."""
from sqlalchemy import select
scheduler = _prom("scheduler")
PrometheusTarget = _prom("models").PrometheusTarget
TokenRefused = _prom("scraper").TokenRefused
name = f"refused-{uuid.uuid4().hex[:8]}"
asked = []
async def fake_scrape(url, token, verify_tls):
asked.append(url)
raise TokenRefused("Answered 401: the token was refused.")
async def go():
async with app.db_sessionmaker() as s:
async with s.begin():
s.add(PrometheusTarget(name=name, url=f"http://{name}/metrics"))
await scheduler.scrape_due(app, scrape=fake_scrape)
async with app.db_sessionmaker() as s:
async with s.begin():
row = (await s.execute(select(PrometheusTarget).where(PrometheusTarget.name == name))).scalar_one()
refused = row.refused
row.last_scraped_at = row.last_scraped_at.replace(year=2000)
await scheduler.scrape_due(app, scrape=fake_scrape)
async with app.db_sessionmaker() as s:
async with s.begin():
await s.delete((await s.execute(select(PrometheusTarget).where(PrometheusTarget.name == name))).scalar_one())
return refused
assert asyncio.run(go()) is True
assert asked == [f"http://{name}/metrics"]