django-orchestra/orchestra/contrib/resources/helpers.py
2023-07-09 07:51:51 +00:00

135 lines
5.2 KiB
Python

import decimal
from django.template.defaultfilters import date as date_format
def get_history_data(queryset):
resources = {}
needs_aggregation = False
for rdata in queryset:
resource = rdata.resource
try:
(options, aggregation) = resources[resource]
except KeyError:
aggregation = resource.aggregation_instance
options = {
'aggregation': str(aggregation.verbose_name),
'aggregated_history': aggregation.aggregated_history,
'content_type': rdata.content_type.model,
'content_object': rdata.content_object_repr,
'unit': resource.unit,
'scale': resource.get_scale(),
'verbose_name': str(resource.verbose_name),
'dates': set() if aggregation.aggregated_history else None,
'objects': [],
}
resources[resource] = (options, aggregation)
if aggregation.aggregated_history:
needs_aggregation = True
monitors = []
scale = options['scale']
all_dates = options['dates']
for monitor_name, dataset in rdata.get_monitor_datasets():
datasets = {}
for content_object, datas in aggregation.aggregate_history(dataset):
if aggregation.aggregated_history:
serie = {}
for data in datas:
value = round(float(data.value)/scale, 3) if data.value is not None else None
all_dates.add(data.date)
serie[data.date] = value
else:
serie = []
for data in datas:
date = data.created_at.timestamp()
date = int(str(date).split('.')[0] + '000')
value = round(float(data.value)/scale, 3) if data.value is not None else None
serie.append(
(date, value)
)
datasets[content_object] = serie
monitors.append({
'name': monitor_name,
'datasets': datasets,
})
options['objects'].append({
'object_name': rdata.content_object_repr,
'current': round(float(rdata.used or 0), 3),
'allocated': float(rdata.allocated) if rdata.allocated is not None else None,
'updated_at': rdata.updated_at.isoformat() if rdata.updated_at else None,
'monitors': monitors,
})
if needs_aggregation:
result = []
for options, aggregation in resources.values():
if aggregation.aggregated_history:
all_dates = sorted(options['dates'])
options['dates'] = [date_format(date) for date in all_dates]
for obj in options['objects']:
for monitor in obj['monitors']:
series = []
for content_object, dataset in monitor['datasets'].items():
data = []
for date in all_dates:
data.append(dataset.get(date, 0.0))
series.append({
'name': content_object,
'data': data,
})
monitor['datasets'] = series
result.append(options)
else:
result = [resource[0] for resource in resources.values()]
return result
def delete_old_equal_values(dataset):
""" only first and last values of an equal serie (+-error) are kept """
prev_value = None
prev_key = None
delete_count = 0
error = decimal.Decimal('0.005')
third = False
for mdata in dataset.order_by('content_type_id', 'object_id', 'created_at'):
key = (mdata.content_type_id, mdata.object_id)
if prev_key == key:
if prev_value is not None and mdata.value*(1-error) < prev_value < mdata.value*(1+error):
if third:
prev.delete()
delete_count += 1
else:
third = True
else:
third = False
prev_value = mdata.value
prev_key = key
else:
prev_value = None
prev_key = key
prev = mdata
return delete_count
def monthly_sum_old_values(dataset):
aggregated = 0
prev_key = None
prev = None
to_delete = []
delete_count = 0
for mdata in dataset.order_by('content_type_id', 'object_id', 'created_at'):
key = (mdata.content_type_id, mdata.object_id, mdata.created_at.year, mdata.created_at.month)
if prev_key is not None and prev_key != key:
if prev.value != aggregated:
prev.value = aggregated
prev.save(update_fields=('value',))
for obj in to_delete[:-1]:
obj.delete()
delete_count += 1
aggregated = 0
to_delete = []
prev = mdata
prev_key = key
aggregated += mdata.value
to_delete.append(mdata)
return delete_count