[IMP] maintenance_service_http_monitoring : modify logic to avoid false-positive http alerts
Some checks failed
pre-commit / pre-commit (pull_request) Has been cancelled
Some checks failed
pre-commit / pre-commit (pull_request) Has been cancelled
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import logging
|
||||
import time
|
||||
from datetime import timedelta
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
@@ -10,8 +10,8 @@ except ImportError:
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
HTTP_CHECK_TIMEOUT = 10 # seconds
|
||||
HTTP_RETRY_DELAY = 2 # seconds between pass 1 and pass 2
|
||||
HTTP_CHECK_TIMEOUT = 20 # seconds
|
||||
HTTP_KO_CONFIRMATION_DELAY = timedelta(minutes=10)
|
||||
|
||||
|
||||
class ServiceInstance(models.Model):
|
||||
@@ -36,14 +36,20 @@ class ServiceInstance(models.Model):
|
||||
string="HTTP Maintenance Request",
|
||||
readonly=True,
|
||||
)
|
||||
http_first_ko_at = fields.Datetime(
|
||||
string="First HTTP KO Check (current streak)",
|
||||
readonly=True,
|
||||
)
|
||||
|
||||
def check_http_status(self):
|
||||
"""
|
||||
Perform HTTP check for each record and return the KO recordset.
|
||||
|
||||
Writes last_http_status_code, last_http_check_date and http_status_ok on every
|
||||
checked record. Does NOT create maintenance.request — that decision belongs to
|
||||
the caller (cron) after optional retry logic.
|
||||
checked record. Does NOT create maintenance.request — the cron only opens one
|
||||
once the service has been continuously KO for at least
|
||||
HTTP_KO_CONFIRMATION_DELAY, to avoid flagging transient outages (e.g. a short
|
||||
server overload) as real incidents.
|
||||
"""
|
||||
ko_records = self.browse()
|
||||
for rec in self:
|
||||
@@ -63,13 +69,16 @@ class ServiceInstance(models.Model):
|
||||
status_ok = status_code == 200
|
||||
except requests.exceptions.RequestException as e:
|
||||
_logger.warning("HTTP check failed for %s: %s", rec.service_url, e)
|
||||
rec.write(
|
||||
{
|
||||
"last_http_status_code": status_code,
|
||||
"last_http_check_date": now,
|
||||
"http_status_ok": status_ok,
|
||||
}
|
||||
)
|
||||
vals = {
|
||||
"last_http_status_code": status_code,
|
||||
"last_http_check_date": now,
|
||||
"http_status_ok": status_ok,
|
||||
}
|
||||
if status_ok:
|
||||
vals["http_first_ko_at"] = False
|
||||
elif not rec.http_first_ko_at:
|
||||
vals["http_first_ko_at"] = now
|
||||
rec.write(vals)
|
||||
if not status_ok:
|
||||
ko_records |= rec
|
||||
return ko_records
|
||||
@@ -106,13 +115,12 @@ class ServiceInstance(models.Model):
|
||||
@api.model
|
||||
def cron_check_http_services(self):
|
||||
"""
|
||||
Check all active services with a URL, with one retry on failure.
|
||||
Check all active services with a URL.
|
||||
|
||||
Pass 1: test every eligible service.
|
||||
- Services that had an open request and are now OK are auto-resolved.
|
||||
- Services still KO after pass 1 are retested after HTTP_RETRY_DELAY seconds.
|
||||
maintenance.request is created only for services that fail both passes,
|
||||
reducing noise from transient HTTP errors.
|
||||
A service must be continuously KO for at least HTTP_KO_CONFIRMATION_DELAY
|
||||
before a maintenance.request is created — this tolerates transient outages
|
||||
(e.g. a temporary server overload) regardless of how often this cron runs.
|
||||
Services that had an open request and are now OK are auto-resolved.
|
||||
"""
|
||||
domain = [
|
||||
("active", "=", True),
|
||||
@@ -123,25 +131,22 @@ class ServiceInstance(models.Model):
|
||||
lambda s: not s.equipment_id.maintenance_mode
|
||||
)
|
||||
|
||||
# Snapshot services that currently have an open request before pass 1
|
||||
# Snapshot services that currently have an open request before the check
|
||||
services_with_open_request = services.filtered(
|
||||
lambda s: s.http_maintenance_request
|
||||
and not s.http_maintenance_request.stage_id.done
|
||||
)
|
||||
|
||||
ko_after_pass1 = services.check_http_status()
|
||||
ko_services = services.check_http_status()
|
||||
|
||||
# Auto-resolve services that recovered during pass 1
|
||||
# Auto-resolve services that recovered
|
||||
recovered = services_with_open_request.filtered(lambda s: s.http_status_ok)
|
||||
if recovered:
|
||||
recovered._close_http_maintenance_request()
|
||||
|
||||
if not ko_after_pass1:
|
||||
return
|
||||
|
||||
time.sleep(HTTP_RETRY_DELAY)
|
||||
|
||||
ko_confirmed = ko_after_pass1.check_http_status()
|
||||
|
||||
for service in ko_confirmed:
|
||||
confirmed_ko = ko_services.filtered(
|
||||
lambda s: s.last_http_check_date - s.http_first_ko_at
|
||||
>= HTTP_KO_CONFIRMATION_DELAY
|
||||
)
|
||||
for service in confirmed_ko:
|
||||
service.equipment_id.create_http_maintenance_request(service)
|
||||
|
||||
Reference in New Issue
Block a user