new metrics

This commit is contained in:
Cayo Puigdefabregas 2021-10-14 12:56:33 +02:00
parent aa7a3ffe12
commit 5e9b9bf08d
3 changed files with 237 additions and 93 deletions

View File

@ -0,0 +1,174 @@
import copy
class Metrics:
"""we want get the data metrics of one device"""
def __init__(self, device):
self.hid = device.hid
self.devicehub_id = device.devicehub_id
self.actions = copy.copy(device.actions)
self.actions.sort(key=lambda x: x.created)
self.rows = []
self.lifetime = 0
self.last_trade = None
self.action_create_by = 'Receiver'
self.status_receiver = 'Use'
self.status_supplier = ''
self.act = None
self.end_users = 0
self.final_user_code = ''
def get_template_row(self):
"""
This is a template of a row.
"""
return {'type': '',
'action_type': 'Status',
'status_receiver': self.status_receiver,
'status_supplier': self.status_supplier,
'trade_supplier': '',
'trade_receiver': self.act.author,
'trade_confirmed': '',
'action_create_by': self.action_create_by,
'devicehubID': self.devicehub_id,
'hid': self.hid,
'finalUserCode': '',
'numEndUsers': 0,
'liveCreate': 0,
'usageTimeHdd': self.lifetime,
'start': self.act.created,
'usageTimeAllocate': 0}
def get_action_status(self):
"""
Mark the status of one device.
If exist one trade before this action, then modify the trade action
else, create one row new.
"""
self.status_receiver = self.act.type
self.status_supplier = ''
if self.act.author != self.act.rol_user:
# It is neccesary exist one trade action before
self.last_trade['status_supplier'] = self.act.type
self.last_trade['status_supplier_created'] = self.act.created
return
if self.last_trade:
# if exist one trade action before
self.last_trade['status_receiver'] = self.act.type
self.last_trade['status_receiver_created'] = self.act.created
return
# If not exist any trade action for this device
self.action_create_by = 'Receiver'
row = self.get_template_row()
row['type'] = 'Status'
self.rows.append(row)
def get_snapshot(self):
"""
If there are one snapshot get the last lifetime for to do a calcul of time of use.
"""
lifestimes = self.act.get_last_lifetimes()
if lifestimes:
self.lifetime = lifestimes[0]['lifetime']
def get_allocate(self):
"""
If the action is one Allocate, need modify the row base.
"""
self.end_users = self.act.end_users
self.final_user_code = self.act.final_user_code
row = self.get_template_row()
row['type'] = 'Allocate'
row['trade_supplier'] = ''
row['finalUserCode'] = self.final_user_code
row['numEndUsers'] = self.end_users
row['start'] = self.act.start_time
row['usageTimeAllocate'] = self.lifetime
self.rows.append(row)
def get_live(self):
"""
If the action is one Live, need modify the row base.
"""
row = self.get_template_row()
row['type'] = 'Live'
row['finalUserCode'] = self.final_user_code
row['numEndUsers'] = self.end_users
row['start'] = self.act.start_time
row['usageTimeAllocate'] = self.lifetime
row['liveCreate'] = self.act.created
if self.act.usage_time_hdd:
row['usageTimeHdd'] = self.act.usage_time_hdd.total_seconds() / 3600
self.rows.append(row)
def get_deallocate(self):
"""
If the action is one Dellocate, need modify the row base.
"""
row = self.get_template_row()
row['type'] = 'Deallocate'
row['start'] = self.act.start_time
self.rows.append(row)
def get_confirms(self):
"""
if the action is one trade action, is possible than have a list of confirmations.
Get the doble confirm for to know if this trade is confirmed or not.
"""
if hasattr(self.act, 'acceptances'):
accept = self.act.acceptances[-1]
if accept.t == 'Confirm' and accept.user == self.act.user_to:
return True
return False
def get_trade(self):
"""
If this action is a trade action modify the base row.
"""
if self.act.author == self.act.user_from:
self.action_create_by = 'Supplier'
row = self.get_template_row()
self.last_trade = row
row['type'] = 'Trade'
row['action_type'] = 'Trade'
row['trade_supplier'] = self.act.user_from
row['trade_receiver'] = self.act.user_to
row['self.status_receiver'] = self.status_receiver
row['self.status_supplier'] = self.status_supplier
row['trade_confirmed'] = self.get_confirms()
self.rows.append(row)
def get_metrics(self):
"""
This method get a list of values for calculate a metrics from a spreadsheet
"""
for act in self.actions:
self.act = act
if act.type in ['Use', 'Refurbish', 'Recycling', 'Management']:
self.get_action_status()
continue
if act.type == 'Snapshot':
self.get_snapshot()
continue
if act.type == 'Allocate':
self.get_allocate()
continue
if act.type == 'Live':
self.get_live()
continue
if act.type == 'Deallocate':
self.get_deallocate()
continue
if act.type == 'Trade':
self.get_trade()
continue
return self.rows

View File

@ -34,6 +34,7 @@ from ereuse_devicehub.resources.enums import BatteryTechnology, CameraFacing, Co
DataStorageInterface, DisplayTech, PrinterTechnology, RamFormat, RamInterface, Severity, TransferState DataStorageInterface, DisplayTech, PrinterTechnology, RamFormat, RamInterface, Severity, TransferState
from ereuse_devicehub.resources.models import STR_SM_SIZE, Thing, listener_reset_field_updated_in_actual_time from ereuse_devicehub.resources.models import STR_SM_SIZE, Thing, listener_reset_field_updated_in_actual_time
from ereuse_devicehub.resources.user.models import User from ereuse_devicehub.resources.user.models import User
from ereuse_devicehub.resources.device.metrics import Metrics
def create_code(context): def create_code(context):
@ -206,10 +207,10 @@ class Device(Thing):
if isinstance(c, ColumnProperty) if isinstance(c, ColumnProperty)
and not getattr(c, 'foreign_keys', None) and not getattr(c, 'foreign_keys', None)
and c.key not in self._NON_PHYSICAL_PROPS} and c.key not in self._NON_PHYSICAL_PROPS}
@property @property
def public_properties(self) -> Dict[str, object or None]: def public_properties(self) -> Dict[str, object or None]:
"""Fields that describe the properties of a device than next show """Fields that describe the properties of a device than next show
in the public page. in the public page.
:return A dictionary: :return A dictionary:
@ -341,7 +342,7 @@ class Device(Thing):
ac = self.last_action_trading ac = self.last_action_trading
if not ac: if not ac:
return return
first_owner = self.which_user_put_this_device_in_trace() first_owner = self.which_user_put_this_device_in_trace()
@ -349,7 +350,7 @@ class Device(Thing):
# can to do revoke_confirmed # can to do revoke_confirmed
return confirm_revoke return confirm_revoke
if ac.type == revoke: if ac.type == revoke:
if ac.user == g.user: if ac.user == g.user:
# can todo revoke_pending # can todo revoke_pending
return revoke_pending return revoke_pending
@ -505,93 +506,8 @@ class Device(Thing):
""" """
This method get a list of values for calculate a metrics from a spreadsheet This method get a list of values for calculate a metrics from a spreadsheet
""" """
actions = copy.copy(self.actions) metrics = Metrics(self)
actions.sort(key=lambda x: x.created) return metrics.get_metrics()
allocates = []
lifetime = 0
for act in actions:
if act.type == 'Snapshot':
snapshot = act
lifestimes = snapshot.get_last_lifetimes()
lifetime = 0
if lifestimes:
lifetime = lifestimes[0]['lifetime']
if act.type == 'Allocate':
allo = {'type': 'Allocate',
'action_type': 'Status',
'status_receiver': 'Use',
'trade_supplier': '',
'trade_receiver': '',
'trade_confirmed': '',
'action_create_by': 'Receiver',
'devicehubID': self.devicehub_id,
'finalUserCode': act.final_user_code,
'numEndUsers': act.end_users,
'hid': self.hid,
'liveCreate': 0,
'usageTimeHdd': 0,
'start': act.start_time,
'usageTimeAllocate': lifetime}
allocates.append(allo)
if act.type == 'Live':
allocate = copy.copy(allo)
allocate['type'] = 'Live'
allocate['liveCreate'] = act.created
allocate['usageTimeHdd'] = 0
if act.usage_time_hdd:
allocate['usageTimeHdd'] = act.usage_time_hdd.total_seconds()/3600
allocates.append(allocate)
if act.type == 'Deallocate':
deallo = {'type': 'Deallocate',
'devicehubID': self.devicehub_id,
'action_type': 'Status',
'status_receiver': 'Use',
'trade_supplier': '',
'trade_receiver': '',
'trade_confirmed': '',
'action_create_by': 'Receiver',
'finalUserCode': '',
'numEndUsers': '',
'hid': self.hid,
'liveCreate': 0,
'usageTimeHdd': lifetime,
'start': act.start_time,
'usageTimeAllocate': 0}
allocates.append(deallo)
if act.type == 'Trade':
confirm = False
if hasattr(act, 'acceptances'):
accept = act.acceptances[-1]
if accept.t == 'Confirm' and accept.user == act.user_to:
confirm = True
action_create_by = 'Receiver'
if act.author == act.user_from:
action_create_by = 'Supplier'
trade = {'type': 'Trade',
'action_type': 'Trade',
'trade_supplier': act.user_from,
'trade_receiver': act.user_to,
'trade_confirmed': confirm,
'action_create_by': action_create_by,
'trade_confirmed': confirm,
'devicehubID': self.devicehub_id,
'finalUserCode': '',
'numEndUsers': '',
'hid': self.hid,
'liveCreate': 0,
'usageTimeHdd': lifetime,
'start': act.start_time,
'status_receiver': 'Use',
'usageTimeAllocate': 0
}
allocates.append(trade)
return allocates
def __lt__(self, other): def __lt__(self, other):
return self.id < other.id return self.id < other.id
@ -790,7 +706,7 @@ class Computer(Device):
return urls return urls
def add_mac_to_hid(self, components_snap=None): def add_mac_to_hid(self, components_snap=None):
"""Returns the Naming.hid with the first mac of network adapter, """Returns the Naming.hid with the first mac of network adapter,
following an alphabetical order. following an alphabetical order.
""" """
self.set_hid() self.set_hid()
@ -923,7 +839,7 @@ class Component(Device):
""" """
assert self.hid is None, 'Don\'t use this method with a component that has HID' assert self.hid is None, 'Don\'t use this method with a component that has HID'
component = self.__class__.query \ component = self.__class__.query \
.filter_by(parent=parent, hid=None, owner_id=self.owner_id, .filter_by(parent=parent, hid=None, owner_id=self.owner_id,
**self.physical_properties) \ **self.physical_properties) \
.filter(~Component.id.in_(blacklist)) \ .filter(~Component.id.in_(blacklist)) \
.first() .first()

View File

@ -2,6 +2,7 @@ import pytest
from ereuse_devicehub.client import UserClient from ereuse_devicehub.client import UserClient
from ereuse_devicehub.resources.action import models as ma from ereuse_devicehub.resources.action import models as ma
from ereuse_devicehub.resources.documents import documents
from tests import conftest from tests import conftest
from tests.conftest import file, yaml2json, json_encode from tests.conftest import file, yaml2json, json_encode
@ -120,3 +121,56 @@ def test_metrics_with_live_null(user: UserClient):
res, _ = user.get("/metrics/") res, _ = user.get("/metrics/")
assert res == metrics assert res == metrics
@pytest.mark.mvp
@pytest.mark.usefixtures(conftest.app_context.__name__)
def test_metrics_action_status(user: UserClient, user2: UserClient):
""" Checks one standard query of metrics """
# Insert computer
lenovo = yaml2json('desktop-9644w8n-lenovo-0169622.snapshot')
snap, _ = user.post(json_encode(lenovo), res=ma.Snapshot)
action = {'type': ma.Use.t, 'devices': [snap['device']['id']]}
action_use, _ = user.post(action, res=ma.Action)
# res, _ = user.get("/metrics/")
csv_str, _ = user.get(res=documents.DocumentDef.t,
item='actions/',
accept='text/csv',
query=[('filter', {'type': ['Computer']})])
import pdb; pdb.set_trace()
@pytest.mark.mvp
@pytest.mark.usefixtures(conftest.app_context.__name__)
def test_complet_metrics(user: UserClient, user2: UserClient):
""" Checks one standard query of metrics """
# Insert computer
lenovo = yaml2json('desktop-9644w8n-lenovo-0169622.snapshot')
acer = yaml2json('acer.happy.battery.snapshot')
snap1, _ = user.post(json_encode(lenovo), res=ma.Snapshot)
snap2, _ = user.post(json_encode(acer), res=ma.Snapshot)
lot, _ = user.post({'name': 'MyLot'}, res=Lot)
devices = [('id', snap1['device']['id']),
('id', snap2['device']['id'])
]
lot, _ = user.post({},
res=Lot,
item='{}/devices'.format(lot['id']),
query=devices)
# request_post = {
# 'type': 'Trade',
# 'devices': [span1['device']['id'], snap2['device']['id']],
# 'userFromEmail': user2.email,
# 'userToEmail': user.email,
# 'price': 10,
# 'date': "2020-12-01T02:00:00+00:00",
# 'lot': lot['id'],
# 'confirms': True,
# }
# user.post(res=models.Action, data=request_post)
# ==============================
# Check metrics
metrics = {'allocateds': 1, 'live': 1}
res, _ = user.get("/metrics/")
assert res == metrics