Fixes on resource monitoring
This commit is contained in:
parent
5344e732fc
commit
bc398644b7
68
orchestra/apps/resources/helpers.py
Normal file
68
orchestra/apps/resources/helpers.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
import datetime
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models.loading import get_model
|
||||
from django.utils import timezone
|
||||
|
||||
from orchestra.models.utils import get_model_field_path
|
||||
|
||||
from .backends import ServiceMonitor
|
||||
|
||||
|
||||
def get_used_resource(data):
|
||||
""" Computes MonitorData.used based on related monitors """
|
||||
MonitorData = type(data)
|
||||
resource = data.resource
|
||||
today = timezone.now()
|
||||
result = 0
|
||||
has_result = False
|
||||
for monitor in resource.monitors:
|
||||
# Get related dataset
|
||||
resource_model = data.content_type.model_class()
|
||||
monitor_model = get_model(ServiceMonitor.get_backend(monitor).model)
|
||||
if resource_model == monitor_model:
|
||||
dataset = MonitorData.objects.filter(monitor=monitor,
|
||||
content_type=data.content_type_id, object_id=data.object_id)
|
||||
else:
|
||||
path = get_model_field_path(monitor_model, resource_model)
|
||||
fields = '__'.join(path)
|
||||
objects = monitor_model.objects.filter(**{fields: data.object_id})
|
||||
pks = objects.values_list('id', flat=True)
|
||||
ct = ContentType.objects.get_for_model(monitor_model)
|
||||
dataset = MonitorData.objects.filter(monitor=monitor,
|
||||
content_type=ct, object_id__in=pks)
|
||||
|
||||
# Process dataset according to resource.period
|
||||
if resource.period == resource.MONTHLY_AVG:
|
||||
try:
|
||||
last = dataset.latest()
|
||||
except MonitorData.DoesNotExist:
|
||||
continue
|
||||
has_result = True
|
||||
epoch = datetime(year=today.year, month=today.month, day=1,
|
||||
tzinfo=timezone.utc)
|
||||
total = (epoch-last.date).total_seconds()
|
||||
dataset = dataset.filter(date__year=today.year,
|
||||
date__month=today.month)
|
||||
for data in dataset:
|
||||
slot = (previous-data.date).total_seconds()
|
||||
result += data.value * slot/total
|
||||
elif resource.period == resource.MONTHLY_SUM:
|
||||
dataset = dataset.filter(date__year=today.year, date__month=today.month)
|
||||
# FIXME Aggregation of 0s returns None! django bug?
|
||||
# value = dataset.aggregate(models.Sum('value'))['value__sum']
|
||||
values = dataset.values_list('value', flat=True)
|
||||
if values:
|
||||
has_result = True
|
||||
result += sum(values)
|
||||
elif resource.period == resource.LAST:
|
||||
try:
|
||||
result += dataset.latest().value
|
||||
except MonitorData.DoesNotExist:
|
||||
continue
|
||||
has_result = True
|
||||
else:
|
||||
msg = "%s support not implemented" % data.period
|
||||
raise NotImplementedError(msg)
|
||||
|
||||
return result if has_result else None
|
|
@ -1,18 +1,13 @@
|
|||
import datetime
|
||||
|
||||
from django.db import models
|
||||
from django.db.models.loading import get_model
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core import validators
|
||||
from django.utils import timezone
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from djcelery.models import PeriodicTask, CrontabSchedule
|
||||
|
||||
from orchestra.models.fields import MultiSelectField
|
||||
from orchestra.models.utils import get_model_field_path
|
||||
from orchestra.utils.apps import autodiscover
|
||||
|
||||
from . import helpers
|
||||
from .backends import ServiceMonitor
|
||||
|
||||
|
||||
|
@ -131,56 +126,7 @@ class ResourceData(models.Model):
|
|||
allocated=resource.default_allocation)
|
||||
|
||||
def get_used(self):
|
||||
resource = self.resource
|
||||
today = timezone.now()
|
||||
result = 0
|
||||
has_result = False
|
||||
for monitor in resource.monitors:
|
||||
resource_model = self.content_type.model_class()
|
||||
monitor_model = get_model(ServiceMonitor.get_backend(monitor).model)
|
||||
if resource_model == monitor_model:
|
||||
dataset = MonitorData.objects.filter(monitor=monitor,
|
||||
content_type=self.content_type_id, object_id=self.object_id)
|
||||
else:
|
||||
path = get_model_field_path(monitor_model, resource_model)
|
||||
fields = '__'.join(path)
|
||||
objects = monitor_model.objects.filter(**{fields: self.object_id})
|
||||
pks = objects.values_list('id', flat=True)
|
||||
ct = ContentType.objects.get_for_model(monitor_model)
|
||||
dataset = MonitorData.objects.filter(monitor=monitor,
|
||||
content_type=ct, object_id__in=pks)
|
||||
if resource.period == resource.MONTHLY_AVG:
|
||||
try:
|
||||
last = dataset.latest()
|
||||
except MonitorData.DoesNotExist:
|
||||
continue
|
||||
has_result = True
|
||||
epoch = datetime(year=today.year, month=today.month, day=1,
|
||||
tzinfo=timezone.utc)
|
||||
total = (epoch-last.date).total_seconds()
|
||||
dataset = dataset.filter(date__year=today.year,
|
||||
date__month=today.month)
|
||||
for data in dataset:
|
||||
slot = (previous-data.date).total_seconds()
|
||||
result += data.value * slot/total
|
||||
elif resource.period == resource.MONTHLY_SUM:
|
||||
data = dataset.filter(date__year=today.year, date__month=today.month)
|
||||
# FIXME Aggregation of 0s returns None! django bug?
|
||||
# value = data.aggregate(models.Sum('value'))['value__sum']
|
||||
values = data.values_list('value', flat=True)
|
||||
if values:
|
||||
has_result = True
|
||||
result += sum(values)
|
||||
elif resource.period == resource.LAST:
|
||||
try:
|
||||
result += dataset.latest().value
|
||||
except MonitorData.DoesNotExist:
|
||||
continue
|
||||
has_result = True
|
||||
else:
|
||||
msg = "%s support not implemented" % self.period
|
||||
raise NotImplementedError(msg)
|
||||
return result if has_result else None
|
||||
return helpers.get_used(self)
|
||||
|
||||
|
||||
class MonitorData(models.Model):
|
||||
|
|
|
@ -4,7 +4,6 @@ from django.utils import importlib
|
|||
|
||||
|
||||
def get_model(label, import_module=True):
|
||||
""" returns the modeladmin registred for model """
|
||||
app_label, model_name = label.split('.')
|
||||
model = loading.get_model(app_label, model_name)
|
||||
if model is None:
|
||||
|
@ -43,21 +42,20 @@ def get_field_value(obj, field_name):
|
|||
try:
|
||||
rel = getattr(rel, name)
|
||||
except AttributeError:
|
||||
# maybe it is a query manager
|
||||
# maybe is a query manager
|
||||
rel = getattr(rel.get(), name)
|
||||
return rel
|
||||
|
||||
|
||||
def get_model_field_path(origin, target):
|
||||
""" BFS search on model relaion fields """
|
||||
mqueue = []
|
||||
mqueue.append([origin])
|
||||
pqueue = [[]]
|
||||
while mqueue:
|
||||
model = mqueue.pop(0)
|
||||
path = pqueue.pop(0)
|
||||
queue = []
|
||||
queue.append(([origin], []))
|
||||
while queue:
|
||||
model, path = queue.pop(0)
|
||||
if len(model) > 4:
|
||||
raise RuntimeError('maximum recursion depth exceeded while looking for %s" % target')
|
||||
msg = "maximum recursion depth exceeded while looking for %s"
|
||||
raise RuntimeError(msg % target)
|
||||
node = model[-1]
|
||||
if node == target:
|
||||
return path
|
||||
|
@ -65,7 +63,6 @@ def get_model_field_path(origin, target):
|
|||
if field.rel:
|
||||
new_model = list(model)
|
||||
new_model.append(field.rel.to)
|
||||
mqueue.append(new_model)
|
||||
new_path = list(path)
|
||||
new_path.append(field.name)
|
||||
pqueue.append(new_path)
|
||||
queue.append((new_model, new_path))
|
||||
|
|
Loading…
Reference in a new issue