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

Source Code for Module coprs.logic.stat_logic

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