datavis: log detailed errors for outdated statistics (#85742)

This commit is contained in:
Benjamin Dauvergne 2024-01-16 16:19:13 +01:00
parent 8a15bacc72
commit 253ae3863b
2 changed files with 64 additions and 0 deletions

View File

@ -1,18 +1,24 @@
import datetime
import json
import logging
from django.conf import settings
from django.utils.timezone import now
from requests.exceptions import RequestException
from combo.utils import requests
from .models import Statistic
logger = logging.getLogger('combo.apps.dataviz')
def update_available_statistics():
if not settings.KNOWN_SERVICES:
return
results = []
temporary_unavailable_sites = []
for provider in settings.STATISTICS_PROVIDERS:
if isinstance(provider, dict):
url = provider['url']
@ -35,6 +41,7 @@ def update_available_statistics():
)
response.raise_for_status()
except RequestException:
temporary_unavailable_sites.append((provider, site_key))
continue
try:
@ -93,4 +100,23 @@ def update_available_statistics():
available_stats = available_stats.exclude(
slug=stat.slug, site_slug=stat.site_slug, service_slug=stat.service_slug
)
# set last_update on all seen statistics
Statistic.objects.exclude(pk__in=available_stats).update(last_update=now())
for service_slug, site_slug in temporary_unavailable_sites:
available_stats = available_stats.exclude(site_slug=site_slug, service_slug=service_slug)
available_stats.update(available=False)
# log errors for outdated statistics
sites_with_outdated_statistics = set()
outdated_hours = 48
for available_stat in Statistic.objects.filter(available=True):
time_since_last_update = now() - available_stat.last_update
if time_since_last_update > datetime.timedelta(hours=outdated_hours):
sites_with_outdated_statistics.add(available_stat.site_title)
for title in sites_with_outdated_statistics:
logger.error(
f'statistics from "{title}" have not been available for more than %s hours.', outdated_hours
)

View File

@ -15,6 +15,7 @@ from httmock import HTTMock, remember_called, urlmatch, with_httmock
from requests.exceptions import HTTPError
from combo.apps.dataviz.models import ChartFiltersCell, ChartNgCell, Gauge, Statistic, UnsupportedDataSet
from combo.apps.dataviz.utils import update_available_statistics
from combo.data.models import Page, ValidityInfo
from combo.utils.spooler import refresh_statistics_data
@ -3451,3 +3452,40 @@ def test_chart_filters_cell_required_boolean(new_api_statistics, app, admin_user
# different value, boolean filter is hidden
resp = app.get('/')
assert not 'filter-test' in resp.form.fields
def test_update_available_statistics(app, settings, caplog, freezer):
caplog.set_level('WARNING')
settings.KNOWN_SERVICES = {
'authentic': {
'connection': {
'title': 'Connection',
'url': 'https://authentic.example.com',
'secret': 'combo',
'orig': 'combo',
}
}
}
settings.STATISTICS_PROVIDERS = ['authentic']
assert Statistic.objects.count() == 0
with HTTMock(new_api_mock):
update_available_statistics()
assert Statistic.objects.count() == len(STATISTICS_LIST['data'])
assert not caplog.messages
# move 47 hours in the future, still no error
freezer.move_to(datetime.timedelta(hours=47))
update_available_statistics()
assert caplog.messages
assert all(record.levelname == 'WARNING' for record in caplog.records)
caplog.clear()
caplog.set_level('ERROR')
# move 2 hours later, an error is logged
freezer.move_to(datetime.timedelta(hours=2))
update_available_statistics()
assert caplog.records
assert caplog.messages == ['statistics from "Connection" have not been available for more than 48 hours.']