TTS backlog: no dar falsa alarma los dias sin cron (#188)
El informe avisaba de "ninguna ventana dejo rastro en 24 h" los miercoles y jueves, que son dias de carta y no tienen cron por diseno. Ahora lee el crontab, cuenta cuantas ventanas TENIAN que correr y solo avisa si de verdad tocaba. Si Rafa cambia los dias del cron, el informe le sigue solo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -121,6 +121,61 @@ def logs_24h() -> tuple[int, int, list[str]]:
|
|||||||
return corridas, saltadas, fallos
|
return corridas, saltadas, fallos
|
||||||
|
|
||||||
|
|
||||||
|
def _campo_cron(campo: str, valores: range) -> set[int]:
|
||||||
|
"""Expande un campo de crontab ('*', '*/5', '1,5,6,0', '0-4') a un set."""
|
||||||
|
if campo == "*":
|
||||||
|
return set(valores)
|
||||||
|
out: set[int] = set()
|
||||||
|
for trozo in campo.split(","):
|
||||||
|
paso = 1
|
||||||
|
if "/" in trozo:
|
||||||
|
trozo, p = trozo.split("/", 1)
|
||||||
|
paso = int(p)
|
||||||
|
if trozo == "*":
|
||||||
|
base = list(valores)
|
||||||
|
elif "-" in trozo:
|
||||||
|
a, b = (int(x) for x in trozo.split("-", 1))
|
||||||
|
base = list(range(a, b + 1))
|
||||||
|
else:
|
||||||
|
base = [int(trozo)]
|
||||||
|
out.update(base[::paso] if paso > 1 else base)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def previstas_24h(ahora: datetime | None = None) -> int | None:
|
||||||
|
"""Cuántas ventanas TENÍA que haber corrido el cron en las últimas 24 h.
|
||||||
|
|
||||||
|
Sin esto, los martes/miércoles/jueves (días de carta, sin cron) el informe
|
||||||
|
daba la alarma de 'ninguna ventana dejó rastro' estando todo correcto. La
|
||||||
|
verdad está en el crontab, no aquí: si Rafa cambia los días, esto le sigue.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
linea = next(
|
||||||
|
l for l in subprocess.run(["crontab", "-l"], text=True, capture_output=True,
|
||||||
|
check=True).stdout.splitlines()
|
||||||
|
if "tts_backlog_cron.sh" in l and not l.lstrip().startswith("#"))
|
||||||
|
except Exception: # noqa: BLE001
|
||||||
|
return None
|
||||||
|
campos = linea.split(None, 5)
|
||||||
|
if len(campos) < 5:
|
||||||
|
return None
|
||||||
|
minutos = _campo_cron(campos[0], range(60))
|
||||||
|
horas = _campo_cron(campos[1], range(24))
|
||||||
|
dows = {d % 7 for d in _campo_cron(campos[4], range(7))} # cron: 0 y 7 = domingo
|
||||||
|
|
||||||
|
ahora = ahora or datetime.now()
|
||||||
|
n = 0
|
||||||
|
for h in range(25):
|
||||||
|
t = (ahora - timedelta(hours=h)).replace(second=0, microsecond=0)
|
||||||
|
for m in minutos:
|
||||||
|
cand = t.replace(minute=m)
|
||||||
|
if not (ahora - timedelta(hours=24) < cand <= ahora):
|
||||||
|
continue
|
||||||
|
if cand.hour in horas and (cand.weekday() + 1) % 7 in dows:
|
||||||
|
n += 1
|
||||||
|
return n
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
hechos = hechos_24h()
|
hechos = hechos_24h()
|
||||||
total = sum(len(v) for v in hechos.values())
|
total = sum(len(v) for v in hechos.values())
|
||||||
@@ -151,11 +206,16 @@ def main() -> int:
|
|||||||
lineas.append("Cuota MiniMax: no se pudo leer")
|
lineas.append("Cuota MiniMax: no se pudo leer")
|
||||||
else:
|
else:
|
||||||
lineas.append(f"Cuota MiniMax: 5h {p5:.0f}% · semana {pw:.0f}%")
|
lineas.append(f"Cuota MiniMax: 5h {p5:.0f}% · semana {pw:.0f}%")
|
||||||
lineas.append(f"Ventanas 24 h: {corridas} ejecutadas, {saltadas} saltadas por cuota")
|
previstas = previstas_24h()
|
||||||
|
de = "" if previstas is None else f" de {previstas} previstas"
|
||||||
|
lineas.append(f"Ventanas 24 h: {corridas} ejecutadas{de}, {saltadas} saltadas por cuota")
|
||||||
|
if previstas == 0:
|
||||||
|
lineas.append(" (sin ventanas previstas: día sin cron, toca carta)")
|
||||||
|
|
||||||
# Una ventana que ni arranca ni se salta es un fallo mudo: el cron no llegó a
|
# Una ventana que ni arranca ni se salta es un fallo mudo: el cron no llegó a
|
||||||
# correr (bit +x, WSL apagada...). Es exactamente lo que pasó el 2-ago.
|
# correr (bit +x, WSL apagada...). Es exactamente lo que pasó el 2-ago.
|
||||||
if corridas == 0 and saltadas == 0:
|
# Solo es alarma si de verdad tocaba correr; si no, es martes.
|
||||||
|
if corridas == 0 and saltadas == 0 and previstas != 0:
|
||||||
lineas.append("")
|
lineas.append("")
|
||||||
lineas.append("⚠️ Ninguna ventana dejó rastro en 24 h. Si tocaba que corriera, "
|
lineas.append("⚠️ Ninguna ventana dejó rastro en 24 h. Si tocaba que corriera, "
|
||||||
f"comprobar: crontab -l | grep tts_backlog · ls -l {CRON}")
|
f"comprobar: crontab -l | grep tts_backlog · ls -l {CRON}")
|
||||||
|
|||||||
Reference in New Issue
Block a user