fix(observability): accept restricted on-demand endpoints
This commit is contained in:
@@ -32,6 +32,12 @@ DEFAULT_ENDPOINTS = [
|
||||
"https://beszel.sherlockhomeless.net",
|
||||
]
|
||||
|
||||
DEFAULT_ACCEPTED_STATUS_CODES = {
|
||||
"https://traefik.sherlockhomeless.net": {200, 301, 302, 303, 307, 308, 401, 403},
|
||||
"https://ots.sherlockhomeless.net": {200, 301, 302, 303, 307, 308, 401, 403},
|
||||
"https://dozzle.sherlockhomeless.net": {200, 301, 302, 303, 307, 308, 401, 403},
|
||||
}
|
||||
|
||||
DEFAULT_TARGET_CONTAINERS = [
|
||||
"traefik",
|
||||
"n8n",
|
||||
@@ -114,6 +120,27 @@ def parse_list_env(raw: str | None, default: list[str]) -> list[str]:
|
||||
return items
|
||||
|
||||
|
||||
def parse_expected_codes(raw: str | None) -> dict[str, set[int]]:
|
||||
expected = {endpoint: set(codes) for endpoint, codes in DEFAULT_ACCEPTED_STATUS_CODES.items()}
|
||||
if not raw:
|
||||
return expected
|
||||
for item in parse_list_env(raw, []):
|
||||
if "=" not in item:
|
||||
continue
|
||||
endpoint, codes_raw = item.split("=", 1)
|
||||
codes = set()
|
||||
for code_raw in re.split(r"[|: ]+", codes_raw.strip()):
|
||||
if not code_raw:
|
||||
continue
|
||||
try:
|
||||
codes.add(int(code_raw))
|
||||
except ValueError:
|
||||
continue
|
||||
if endpoint.strip() and codes:
|
||||
expected[endpoint.strip()] = codes
|
||||
return expected
|
||||
|
||||
|
||||
def resolve_docker_since(since: str) -> str:
|
||||
if re.match(r"^\d+[smhd]$", since):
|
||||
return since
|
||||
@@ -238,6 +265,7 @@ def cmd_health(_args) -> int:
|
||||
retry_delay = env_int("HEALTH_RETRY_DELAY", 8, 0)
|
||||
follow_redirects = env_bool("HEALTH_FOLLOW_REDIRECTS", True)
|
||||
endpoints = parse_list_env(os.environ.get("HEALTH_ENDPOINTS"), DEFAULT_ENDPOINTS)
|
||||
expected_codes = parse_expected_codes(os.environ.get("HEALTH_EXPECTED_CODES"))
|
||||
|
||||
results = []
|
||||
for endpoint in endpoints:
|
||||
@@ -255,7 +283,8 @@ def cmd_health(_args) -> int:
|
||||
http_code = int(response["http_code"])
|
||||
effective_url = response["effective_url"]
|
||||
time_total = response["curl_time_total_seconds"]
|
||||
if 200 <= http_code < 400:
|
||||
accepted = expected_codes.get(endpoint)
|
||||
if 200 <= http_code < 400 or (accepted is not None and http_code in accepted):
|
||||
status = "up"
|
||||
error = ""
|
||||
break
|
||||
@@ -281,6 +310,9 @@ def cmd_health(_args) -> int:
|
||||
item["effective_url"] = effective_url
|
||||
if status == "down":
|
||||
item["error"] = error
|
||||
elif http_code >= 400:
|
||||
item["accepted_http_code"] = True
|
||||
item["status_note"] = "reachable_but_access_restricted"
|
||||
results.append(item)
|
||||
|
||||
up_count = sum(1 for item in results if item["status"] == "up")
|
||||
|
||||
@@ -49,6 +49,7 @@ Entregar un resumen breve para operación diaria sin ruido.
|
||||
- Si `server_summary` indica `openclaw_codex_oauth: OK`, no pidas reautenticación ni marques OpenClaw como degradado por errores OAuth antiguos del `log_digest`.
|
||||
- Si `health_results` marca Traefik/Auth `up` y no hay errores actuales correlacionados, no marques Traefik/Auth como degradados por errores ACME/middleware antiguos.
|
||||
- Si `server_summary` lista `non_running_sablier_managed_containers`, interprétalos como servicios bajo arranque bajo demanda. No los marques como incidente si `health_results` marca su endpoint asociado como `up`; si el endpoint está `down`, entonces sí trátalo como degradación activa.
|
||||
- Si `health_results` marca un endpoint como `up` con `accepted_http_code=true` y `status_note=reachable_but_access_restricted`, interprétalo como endpoint alcanzable con acceso restringido esperado. Puedes mencionarlo como nota de acceso/política, pero no lo contabilices como caída ni degradación.
|
||||
|
||||
## Importante
|
||||
- **No marcar `DEGRADED` ni `CRITICAL` únicamente por prevención**:
|
||||
|
||||
Reference in New Issue
Block a user