Package coprs :: Package logic :: Module stat_logic
[hide private]
[frames] | no frames]

Source Code for Module coprs.logic.stat_logic

  1  from collections import defaultdict 
  2   
  3  from sqlalchemy.orm.exc import NoResultFound 
  4   
  5  from coprs import app 
  6  from coprs import db 
  7  from coprs.models import CounterStat 
  8  from coprs import helpers 
  9  from coprs.helpers import REPO_DL_STAT_FMT, CHROOT_REPO_MD_DL_STAT_FMT, \ 
 10      CHROOT_RPMS_DL_STAT_FMT, PROJECT_RPMS_DL_STAT_FMT 
 11  from coprs.rmodels import TimedStatEvents 
12 13 14 -class CounterStatLogic(object):
15 16 @classmethod
17 - def get(cls, name):
18 """ 19 :param name: counter name 20 :return: 21 """ 22 return CounterStat.query.filter(CounterStat.name == name)
23 24 @classmethod
25 - def get_multiply_same_type(cls, counter_type, names_list):
26 return ( 27 CounterStat.query 28 .filter(CounterStat.counter_type == counter_type) 29 .filter(CounterStat.name.in_(names_list)) 30 )
31 32 @classmethod
33 - def add(cls, name, counter_type):
34 csl = CounterStat(name=name, counter_type=counter_type) 35 db.session.add(csl) 36 return csl
37 38 @classmethod
39 - def incr(cls, name, counter_type):
40 """ 41 Warning: dirty method: does commit if missing stat record. 42 """ 43 try: 44 csl = CounterStatLogic.get(name).one() 45 csl.counter = CounterStat.counter + 1 46 except NoResultFound: 47 csl = CounterStatLogic.add(name, counter_type) 48 csl.counter = 1 49 50 db.session.add(csl) 51 return csl
52 53 @classmethod
54 - def get_copr_repo_dl_stat(cls, copr):
55 # chroot -> stat_name 56 chroot_by_stat_name = {} 57 for chroot in copr.active_chroots: 58 kwargs = { 59 "copr_user": copr.user.name, 60 "copr_project_name": copr.name, 61 "copr_name_release": chroot.name_release 62 } 63 chroot_by_stat_name[REPO_DL_STAT_FMT.format(**kwargs)] = chroot.name_release 64 65 # [{counter: <value>, name: <stat_name>}, ...] 66 stats = cls.get_multiply_same_type(counter_type=helpers.CounterStatType.REPO_DL, 67 names_list=chroot_by_stat_name.keys()) 68 69 # need: {chroot -> value, ... } 70 repo_dl_stats = defaultdict(int) 71 for stat in stats: 72 repo_dl_stats[chroot_by_stat_name[stat.name]] = stat.counter 73 74 return repo_dl_stats
75
76 77 -def handle_be_stat_message(rc, stat_data):
78 """ 79 :param rc: connection to redis 80 :type rc: StrictRedis 81 82 :param stat_data: stats from backend 83 :type stat_data: dict 84 """ 85 app.logger.debug('Got stat data: {}'.format(stat_data)) 86 87 ts_from = int(stat_data['ts_from']) 88 ts_to = int(stat_data['ts_to']) 89 hits = stat_data['hits'] 90 91 if not ts_from or not ts_to or ts_from > ts_to or not hits: 92 raise Exception("Invalid or empty data received.") 93 94 ts_from_stored = int(rc.get('handle_be_stat_message_ts_from') or 0) 95 ts_to_stored = int(rc.get('handle_be_stat_message_ts_to') or 0) 96 97 app.logger.debug('ts_from: {}'.format(ts_from)) 98 app.logger.debug('ts_to: {}'.format(ts_to)) 99 app.logger.debug('ts_from_stored: {}'.format(ts_from_stored)) 100 app.logger.debug('ts_to_stored: {}'.format(ts_to_stored)) 101 102 if (ts_from < ts_to_stored and ts_to > ts_from_stored): 103 app.logger.debug('Time overlap with already stored data. Skipping.') 104 return 105 106 hits_formatted = defaultdict(int) 107 for key_str, count in hits.items(): 108 key = key_str.split('|') 109 if key[0] == 'chroot_repo_metadata_dl_stat': 110 redis_key = CHROOT_REPO_MD_DL_STAT_FMT.format( 111 copr_user=key[1], 112 copr_project_name=key[2], 113 copr_chroot=key[3]) 114 elif key[0] == 'chroot_rpms_dl_stat': 115 redis_key = CHROOT_RPMS_DL_STAT_FMT.format( 116 copr_user=key[1], 117 copr_project_name=key[2], 118 copr_chroot=key[3]) 119 elif key[0] == 'project_rpms_dl_stat': 120 redis_key = PROJECT_RPMS_DL_STAT_FMT.format( 121 copr_user=key[1], 122 copr_project_name=key[2]) 123 else: 124 raise Exception('Unknown key {}'.format(key[0])) 125 126 hits_formatted[redis_key] += count 127 128 for redis_key, count in hits_formatted.items(): 129 TimedStatEvents.add_event(rc, redis_key, count=count, timestamp=ts_to) 130 131 rc.set('handle_be_stat_message_ts_from', ts_from) 132 rc.set('handle_be_stat_message_ts_to', ts_to)
133