Skip to content

Commit 791b7cd

Browse files
authored
[feature] Add way to specify global defaults #106
Implements and closes #106
1 parent 4fc6f46 commit 791b7cd

30 files changed

+1334
-526
lines changed

README.rst

Lines changed: 286 additions & 88 deletions
Large diffs are not rendered by default.

openwisp_monitoring/check/classes/config_applied.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from swapper import load_model
22

33
from ...device.utils import SHORT_RP
4-
from ..settings import CONFIG_CHECK_MAX_TIME
54
from .base import BaseCheck
65

76
AlertSettings = load_model('monitoring', 'AlertSettings')
@@ -28,8 +27,6 @@ def _get_metric(self):
2827
return metric
2928

3029
def _create_alert_setting(self, metric):
31-
alert_s = AlertSettings(
32-
metric=metric, operator='<', value=1, seconds=CONFIG_CHECK_MAX_TIME * 60
33-
)
30+
alert_s = AlertSettings(metric=metric)
3431
alert_s.full_clean()
3532
alert_s.save()

openwisp_monitoring/check/classes/ping.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ def _get_metric(self):
154154
return metric
155155

156156
def _create_alert_settings(self, metric):
157-
alert_settings = AlertSettings(metric=metric, operator='<', value=1, seconds=0)
157+
alert_settings = AlertSettings(metric=metric)
158158
alert_settings.full_clean()
159159
alert_settings.save()
160160

openwisp_monitoring/check/settings.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,4 @@
1212
AUTO_CONFIG_CHECK = getattr(
1313
settings, 'OPENWISP_MONITORING_AUTO_DEVICE_CONFIG_CHECK', True
1414
)
15-
# Input in minutes
16-
CONFIG_CHECK_MAX_TIME = getattr(
17-
settings, 'OPENWISP_MONITORING_DEVICE_CONFIG_CHECK_MAX_TIME', 5
18-
)
1915
MANAGEMENT_IP_ONLY = getattr(settings, 'OPENWISP_MONITORING_MANAGEMENT_IP_ONLY', True)

openwisp_monitoring/db/backends/influxdb/tests.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,9 @@ def test_read_with_rp(self):
226226
'Test metric write on short retention_policy immediate alert'
227227
):
228228
m = self._create_general_metric(name='dummy')
229-
self._create_alert_settings(metric=m, operator='<', value=1, seconds=0)
229+
self._create_alert_settings(
230+
metric=m, custom_operator='<', custom_threshold=1, custom_tolerance=0
231+
)
230232
m.write(0, retention_policy=SHORT_RP)
231233
self.assertEqual(m.read(retention_policy=SHORT_RP)[0][m.field_name], 0)
232234
self.assertFalse(m.is_healthy)
@@ -235,7 +237,9 @@ def test_read_with_rp(self):
235237
'Test metric write on short retention_policy with deferred alert'
236238
):
237239
m2 = self._create_general_metric(name='dummy2')
238-
self._create_alert_settings(metric=m2, operator='<', value=1, seconds=60)
240+
self._create_alert_settings(
241+
metric=m2, custom_operator='<', custom_threshold=1, custom_tolerance=1
242+
)
239243
m.write(0, retention_policy=SHORT_RP, time=now() - timedelta(minutes=2))
240244
self.assertEqual(m.read(retention_policy=SHORT_RP)[0][m.field_name], 0)
241245
self.assertFalse(m.is_healthy)

openwisp_monitoring/device/admin.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from django.contrib.contenttypes.admin import GenericStackedInline
55
from django.contrib.contenttypes.forms import BaseGenericInlineFormSet
66
from django.contrib.contenttypes.models import ContentType
7+
from django.forms import ModelForm
78
from django.urls import reverse
89
from django.utils.html import format_html
910
from django.utils.safestring import mark_safe
@@ -58,11 +59,24 @@ def has_delete_permission(self, request, obj=None):
5859
return False
5960

6061

62+
class AlertSettingsForm(ModelForm):
63+
def __init__(self, *args, **kwargs):
64+
instance = kwargs.get('instance')
65+
if instance:
66+
kwargs['initial'] = {
67+
'custom_tolerance': instance.tolerance,
68+
'custom_operator': instance.operator,
69+
'custom_threshold': instance.threshold,
70+
}
71+
super().__init__(*args, **kwargs)
72+
73+
6174
class AlertSettingsInline(NestedStackedInline):
6275
model = AlertSettings
6376
extra = 0
6477
max_num = 0
6578
exclude = ['created', 'modified']
79+
form = AlertSettingsForm
6680

6781
def get_queryset(self, request):
6882
return super().get_queryset(request).order_by('created')

openwisp_monitoring/device/api/views.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
from ... import settings as monitoring_settings
2121
from ...monitoring.exceptions import InvalidChartConfigException
2222
from ..schema import schema
23-
from ..settings import DEVICE_RESOURCES_ALERTSETTINGS
2423
from ..signals import device_metrics_received
2524

2625
logger = logging.getLogger(__name__)
@@ -352,10 +351,7 @@ def _create_resources_chart(self, metric, resource):
352351
chart.save()
353352

354353
def _create_resources_alert_settings(self, metric, resource):
355-
value = DEVICE_RESOURCES_ALERTSETTINGS[resource]
356-
alert_settings = AlertSettings(
357-
metric=metric, operator='>', value=value, seconds=0
358-
)
354+
alert_settings = AlertSettings(metric=metric)
359355
alert_settings.full_clean()
360356
alert_settings.save()
361357

openwisp_monitoring/device/apps.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ def register_notifcation_types(self):
151151
register_notification_type(
152152
'connection_is_working',
153153
{
154-
'name': 'Device Alert',
154+
'verbose_name': 'Device Alert',
155155
'verb': 'working',
156156
'level': 'info',
157157
'email_subject': '[{site.name}] RECOVERY: Connection to device {notification.target}',
@@ -165,7 +165,7 @@ def register_notifcation_types(self):
165165
register_notification_type(
166166
'connection_is_not_working',
167167
{
168-
'name': 'Device Alert',
168+
'verbose_name': 'Device Alert',
169169
'verb': 'not working',
170170
'level': 'error',
171171
'email_subject': '[{site.name}] PROBLEM: Connection to device {notification.target}',

openwisp_monitoring/device/settings.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,3 @@ def get_health_status_labels():
5858
MAC_VENDOR_DETECTION = getattr(
5959
settings, 'OPENWISP_MONITORING_MAC_VENDOR_DETECTION', True
6060
)
61-
62-
DEVICE_RESOURCES_ALERTSETTINGS = getattr(
63-
settings,
64-
'OPENWISP_MONITORING_DEVICE_RESOURCES_ALERTSETTINGS',
65-
{'memory': 0.95, 'cpu': 0.90, 'disk': 0.80},
66-
)

openwisp_monitoring/device/tests/test_models.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -493,14 +493,21 @@ def _create_env(self):
493493
ping = self._create_object_metric(
494494
name='ping', key='ping', field_name='reachable', content_object=d
495495
)
496-
self._create_alert_settings(metric=ping, operator='<', value=1, seconds=0)
496+
self._create_alert_settings(
497+
metric=ping, custom_operator='<', custom_threshold=1, custom_tolerance=0
498+
)
497499
load = self._create_object_metric(name='load', content_object=d)
498-
self._create_alert_settings(metric=load, operator='>', value=90, seconds=0)
500+
self._create_alert_settings(
501+
metric=load, custom_operator='>', custom_threshold=90, custom_tolerance=0
502+
)
499503
process_count = self._create_object_metric(
500504
name='process_count', content_object=d
501505
)
502506
self._create_alert_settings(
503-
metric=process_count, operator='>', value=20, seconds=0
507+
metric=process_count,
508+
custom_operator='>',
509+
custom_threshold=20,
510+
custom_tolerance=0,
504511
)
505512
return dm, ping, load, process_count
506513

openwisp_monitoring/monitoring/admin.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from django.contrib import admin
2+
from django.forms import ModelForm
23
from django.utils.translation import gettext_lazy as _
34
from swapper import load_model
45

@@ -9,8 +10,21 @@
910
AlertSettings = load_model('monitoring', 'AlertSettings')
1011

1112

13+
class AlertSettingsForm(ModelForm):
14+
def __init__(self, *args, **kwargs):
15+
instance = kwargs.get('instance')
16+
if instance:
17+
kwargs['initial'] = {
18+
'custom_tolerance': instance.tolerance,
19+
'custom_threshold': instance.threshold,
20+
'custom_operator': instance.operator,
21+
}
22+
super().__init__(*args, **kwargs)
23+
24+
1225
class AlertSettingsInline(TimeReadonlyAdminMixin, admin.StackedInline):
1326
model = AlertSettings
27+
form = AlertSettingsForm
1428
extra = 0
1529

1630

openwisp_monitoring/monitoring/apps.py

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
from django.apps import AppConfig
44
from django.conf import settings
55
from django.utils.translation import gettext_lazy as _
6-
from openwisp_notifications.types import register_notification_type
76
from requests.exceptions import ConnectionError
87

98
from ..db import timeseries_db
9+
from .configuration import get_metric_configuration, register_metric_notifications
1010

1111

1212
class MonitoringConfig(AppConfig):
@@ -19,7 +19,9 @@ class MonitoringConfig(AppConfig):
1919
def ready(self):
2020
self.create_database()
2121
setattr(settings, 'OPENWISP_ADMIN_SHOW_USERLINKS_BLOCK', True)
22-
self.register_notification_types()
22+
metrics = get_metric_configuration()
23+
for metric_name, metric_config in metrics.items():
24+
register_metric_notifications(metric_name, metric_config)
2325

2426
def create_database(self):
2527
# create Timeseries database if it doesn't exist yet
@@ -38,31 +40,3 @@ def warn_and_delay(self, attempt_number):
3840
f'Retrying again in 3 seconds (attempt n. {attempt_number} out of 5).'
3941
)
4042
sleep(self.retry_delay)
41-
42-
def register_notification_types(self):
43-
default_message = (
44-
'{notification.actor.name} for device [{notification.target}]'
45-
'({notification.target_link}) {notification.verb}.'
46-
)
47-
48-
register_notification_type(
49-
'threshold_crossed',
50-
{
51-
'name': 'Monitoring Alert',
52-
'verb': 'crossed the threshold',
53-
'level': 'warning',
54-
'email_subject': '[{site.name}] PROBLEM: {notification.actor.name} {notification.target}',
55-
'message': default_message,
56-
},
57-
)
58-
59-
register_notification_type(
60-
'threshold_recovery',
61-
{
62-
'name': 'Monitoring Alert',
63-
'verb': 'returned within the threshold',
64-
'level': 'info',
65-
'email_subject': '[{site.name}] RECOVERY: {notification.actor.name} {notification.target}',
66-
'message': default_message,
67-
},
68-
)

0 commit comments

Comments
 (0)