class StatsReportLogin(StatsReport): filename = 'access.pdf' name = _('Users access report by date') # Report name description = _( 'Report of user access to platform by date') # Report description uuid = '0f62f19a-f166-11e4-8f59-10feed05884b' # Input fields startDate = gui.DateField(order=1, label=_('Starting date'), tooltip=_('starting date for report'), defvalue=datetime.date.min, required=True) endDate = gui.DateField(order=2, label=_('Finish date'), tooltip=_('finish date for report'), defvalue=datetime.date.max, required=True) samplingPoints = gui.NumericField( order=3, label=_('Number of intervals'), length=3, minValue=0, maxValue=128, tooltip=_('Number of sampling points used in charts'), defvalue='64') def initialize(self, values): pass def initGui(self): pass def getRangeData(self) -> typing.Tuple[str, typing.List, typing.List]: start = self.startDate.stamp() end = self.endDate.stamp() if self.samplingPoints.num() < 8: self.samplingPoints.value = (self.endDate.date() - self.startDate.date()).days if self.samplingPoints.num() < 2: self.samplingPoints.value = 2 if self.samplingPoints.num() > 128: self.samplingPoints.value = 128 samplingPoints = self.samplingPoints.num() # x axis label format if end - start > 3600 * 24 * 2: xLabelFormat = 'SHORT_DATE_FORMAT' else: xLabelFormat = 'SHORT_DATETIME_FORMAT' samplingIntervals: typing.List[typing.Tuple[int, int]] = [] prevVal = None for val in range(start, end, int( (end - start) / (samplingPoints + 1))): if prevVal is None: prevVal = val continue samplingIntervals.append((prevVal, val)) prevVal = val data = [] reportData = [] for interval in samplingIntervals: key = (interval[0] + interval[1]) / 2 val = events.statsManager().getEvents(events.OT_AUTHENTICATOR, events.ET_LOGIN, since=interval[0], to=interval[1]).count() data.append((key, val)) # @UndefinedVariable reportData.append({ 'date': tools.timestampAsStr(interval[0], xLabelFormat) + ' - ' + tools.timestampAsStr(interval[1], xLabelFormat), 'users': val }) return xLabelFormat, data, reportData def getWeekHourlyData(self): start = self.startDate.stamp() end = self.endDate.stamp() dataWeek = [0] * 7 dataHour = [0] * 24 dataWeekHour = [[0] * 24 for _ in range(7)] for val in events.statsManager().getEvents(events.OT_AUTHENTICATOR, events.ET_LOGIN, since=start, to=end): s = datetime.datetime.fromtimestamp(val.stamp) dataWeek[s.weekday()] += 1 dataHour[s.hour] += 1 dataWeekHour[s.weekday()][s.hour] += 1 logger.debug('Data: %s %s', s.weekday(), s.hour) return dataWeek, dataHour, dataWeekHour def generate(self): # Sample query: # 'SELECT *, count(*) as number, CEIL(stamp/(3600))*3600 as block' # ' FROM {table}' # ' WHERE event_type = 0 and stamp >= {start} and stamp <= {end}' # ' GROUP BY CEIL(stamp/(3600))' # ' ORDER BY block' xLabelFormat, data, reportData = self.getRangeData() # # User access by date graph # graph1 = io.BytesIO() X = [v[0] for v in data] d = { 'title': _('Users Access (global)'), 'x': X, 'xtickFnc': lambda l: filters.date(datetime.datetime.fromtimestamp(l), xLabelFormat), 'xlabel': _('Date'), 'y': [{ 'label': 'Users', 'data': [v[1] for v in data] }], 'ylabel': 'Users', 'allTicks': False } graphs.lineChart(SIZE, d, graph1) graph2 = io.BytesIO() graph3 = io.BytesIO() graph4 = io.BytesIO() dataWeek, dataHour, dataWeekHour = self.getWeekHourlyData() X = list(range(7)) d = { 'title': _('Users Access (by week)'), 'x': X, 'xtickFnc': lambda l: [ _('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday'), _('Sunday') ][l], 'xlabel': _('Day of week'), 'y': [{ 'label': 'Users', 'data': [v for v in dataWeek] }], 'ylabel': 'Users' } graphs.barChart(SIZE, d, graph2) X = list(range(24)) d = { 'title': _('Users Access (by hour)'), 'x': X, 'xlabel': _('Hour'), 'y': [{ 'label': 'Users', 'data': [v for v in dataHour] }], 'ylabel': 'Users' } graphs.barChart(SIZE, d, graph3) X = list(range(24)) Y = list(range(7)) d = { 'title': _('Users Access (by hour)'), 'x': X, 'xlabel': _('Hour'), 'xtickFnc': lambda l: l, 'y': Y, 'ylabel': _('Day of week'), 'ytickFnc': lambda l: [ _('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday'), _('Sunday') ][l], 'z': dataWeekHour, 'zlabel': _('Users') } graphs.surfaceChart(SIZE, d, graph4) return self.templateAsPDF( 'uds/reports/stats/user-access.html', dct={ 'data': reportData, 'beginning': self.startDate.date(), 'ending': self.endDate.date(), 'intervals': self.samplingPoints.num(), }, header=ugettext('Users access to UDS'), water=ugettext('UDS Report for users access'), images={ 'graph1': graph1.getvalue(), 'graph2': graph2.getvalue(), 'graph3': graph3.getvalue(), 'graph4': graph4.getvalue() }, )
class UsageSummaryByUsersPool(StatsReport): filename = 'pool_user_usage.pdf' name = _('Pool Usage by users') # Report name description = _('Generates a report with the summary of users usage for a pool') # Report description uuid = '202c6438-30a8-11e7-80e4-77c1e4cb9e09' # Input fields pool = gui.ChoiceField( order=1, label=_('Pool'), tooltip=_('Pool for report'), required=True ) startDate = gui.DateField( order=2, label=_('Starting date'), tooltip=_('starting date for report'), defvalue=datetime.date.min, required=True ) endDate = gui.DateField( order=3, label=_('Finish date'), tooltip=_('finish date for report'), defvalue=datetime.date.max, required=True ) def initialize(self, values): pass def initGui(self): logger.debug('Initializing gui') vals = [ gui.choiceItem(v.uuid, v.name) for v in ServicePool.objects.all() ] self.pool.setValues(vals) def getPoolData(self, pool) -> typing.Tuple[typing.List[typing.Dict[str, typing.Any]], str]: start = self.startDate.stamp() end = self.endDate.stamp() logger.debug(self.pool.value) items = events.statsManager().getEvents(events.OT_DEPLOYED, (events.ET_LOGIN, events.ET_LOGOUT), owner_id=pool.id, since=start, to=end).order_by('stamp') logins: typing.Dict[str, int] = {} users: typing.Dict[str, typing.Dict] = {} for i in items: # if '\\' in i.fld1: # continue username = i.fld4 if i.event_type == events.ET_LOGIN: logins[username] = i.stamp else: if username in logins: stamp = logins[username] del logins[username] total = i.stamp - stamp if username not in users: users[username] = {'sessions': 0, 'time': 0} users[username]['sessions'] += 1 users[username]['time'] += total # data.append({ # 'name': i.fld4, # 'date': datetime.datetime.fromtimestamp(stamp), # 'time': total # }) # Extract different number of users data = [{ 'user': k, 'sessions': v['sessions'], 'hours': '{:.2f}'.format(float(v['time']) / 3600), 'average': '{:.2f}'.format(float(v['time']) / 3600 / v['sessions']) } for k, v in users.items()] return data, pool.name def getData(self) -> typing.Tuple[typing.List[typing.Dict[str, typing.Any]], str]: return self.getPoolData(ServicePool.objects.get(uuid=self.pool.value)) def generate(self): items, poolName = self.getData() return self.templateAsPDF( 'uds/reports/stats/pool-users-summary.html', dct={ 'data': items, 'pool': poolName, 'beginning': self.startDate.date(), 'ending': self.endDate.date(), }, header=ugettext('Users usage list for {}').format(poolName), water=ugettext('UDS Report of users in {}').format(poolName) )
class CountersPoolAssigned(StatsReport): filename = 'pools_counters.pdf' name = _('Pools usage on a day') # Report name description = _( 'Pools usage counters for an specific day') # Report description uuid = '0b429f70-2fc6-11e7-9a2a-8fc37101e66a' startDate = gui.DateField(order=2, label=_('Date'), tooltip=_('Date for report'), defvalue='', required=True) pools = gui.MultiChoiceField(order=1, label=_('Pools'), tooltip=_('Pools for report'), required=True) def initialize(self, values): pass def initGui(self): logger.debug('Initializing gui') vals = [ gui.choiceItem(v.uuid, v.name) for v in ServicePool.objects.all().order_by('name') ] self.pools.setValues(vals) def getData(self) -> typing.List[typing.Dict[str, typing.Any]]: # Generate the sampling intervals and get dataUsers from db start = self.startDate.date() end = self.startDate.date() + datetime.timedelta(days=1) data = [] pool: ServicePool for poolUuid in self.pools.value: try: pool = ServicePool.objects.get(uuid=poolUuid) except Exception: continue hours = [0] * 24 for x in counters.getCounters(pool, counters.CT_ASSIGNED, since=start, to=end, max_intervals=24, use_max=True, all=False): hour = x[0].hour val = int(x[1]) if hours[hour] < val: hours[hour] = val data.append({'uuid': pool.uuid, 'name': pool.name, 'hours': hours}) logger.debug('data: %s', data) return data def generate(self): items = self.getData() graph1 = io.BytesIO() X = list(range(24)) d = { 'title': _('Services by hour'), 'x': X, 'xtickFnc': lambda xx: '{:02d}'.format(xx), # pylint: disable=unnecessary-lambda 'xlabel': _('Hour'), 'y': [{ 'label': i['name'], 'data': [i['hours'][v] for v in X] } for i in items], 'ylabel': 'Services' } graphs.barChart(SIZE, d, graph1) return self.templateAsPDF( 'uds/reports/stats/pools-usage-day.html', dct={ 'data': items, 'pools': [ v.name for v in ServicePool.objects.filter( uuid__in=self.pools.value) ], 'beginning': self.startDate.date(), }, header=ugettext('Services usage report for a day'), water=ugettext('Service usage report'), images={'graph1': graph1.getvalue()}, )
class PoolPerformanceReport(StatsReport): filename = 'pools_performance.pdf' name = _('Pools performance by date') # Report name description = _('Pools performance report by date') # Report description uuid = '88932b48-1fd3-11e5-a776-10feed05884b' # Input fields pools = gui.MultiChoiceField(order=1, label=_('Pools'), tooltip=_('Pools for report'), required=True) startDate = gui.DateField(order=2, label=_('Starting date'), tooltip=_('starting date for report'), defvalue=datetime.date.min, required=True) endDate = gui.DateField(order=3, label=_('Finish date'), tooltip=_('finish date for report'), defvalue=datetime.date.max, required=True) samplingPoints = gui.NumericField( order=4, label=_('Number of intervals'), length=3, minValue=0, maxValue=32, tooltip=_('Number of sampling points used in charts'), defvalue='8') def initialize(self, values): pass def initGui(self): logger.debug('Initializing gui') vals = [ gui.choiceItem(v.uuid, v.name) for v in ServicePool.objects.all().order_by('name') ] self.pools.setValues(vals) def getPools(self) -> typing.List[typing.Tuple[str, str]]: return [(v.id, v.name) for v in ServicePool.objects.filter(uuid__in=self.pools.value)] def getRangeData(self) -> typing.Tuple[str, typing.List, typing.List]: # pylint: disable=too-many-locals start = self.startDate.stamp() end = self.endDate.stamp() if self.samplingPoints.num() < 2: self.samplingPoints.value = (self.endDate.date() - self.startDate.date()).days if self.samplingPoints.num() < 2: self.samplingPoints.value = 2 if self.samplingPoints.num() > 32: self.samplingPoints.value = 32 samplingPoints = self.samplingPoints.num() pools = self.getPools() if not pools: raise Exception(_('Select at least a service pool for the report')) logger.debug('Pools: %s', pools) # x axis label format if end - start > 3600 * 24 * 2: xLabelFormat = 'SHORT_DATE_FORMAT' else: xLabelFormat = 'SHORT_DATETIME_FORMAT' # Generate samplings interval samplingIntervals: typing.List[typing.Tuple[int, int]] = [] prevVal = None for val in range(start, end, int( (end - start) / (samplingPoints + 1))): if prevVal is None: prevVal = val continue samplingIntervals.append((prevVal, val)) prevVal = val # Store dataUsers for all pools poolsData = [] fld = events.statsManager().getEventFldFor('username') reportData = [] for p in pools: dataUsers = [] dataAccesses = [] for interval in samplingIntervals: key = (interval[0] + interval[1]) / 2 q = events.statsManager().getEvents( events.OT_DEPLOYED, events.ET_ACCESS, since=interval[0], to=interval[1], owner_id=p[0]).values(fld).annotate(cnt=Count(fld)) accesses = 0 for v in q: accesses += v['cnt'] dataUsers.append((key, len(q))) # @UndefinedVariable dataAccesses.append((key, accesses)) reportData.append({ 'name': p[1], 'date': tools.timestampAsStr(interval[0], xLabelFormat) + ' - ' + tools.timestampAsStr(interval[1], xLabelFormat), 'users': len(q), 'accesses': accesses }) poolsData.append({ 'pool': p[0], 'name': p[1], 'dataUsers': dataUsers, 'dataAccesses': dataAccesses, }) return xLabelFormat, poolsData, reportData def generate(self): # Generate the sampling intervals and get dataUsers from db xLabelFormat, poolsData, reportData = self.getRangeData() graph1 = io.BytesIO() graph2 = io.BytesIO() # surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) # @UndefinedVariable # logger.debug('PoolsData: %s', poolsData) X = [v[0] for v in poolsData[0]['dataUsers']] data = { 'title': _('Distinct Users'), 'x': X, 'xtickFnc': lambda l: filters.date(datetime.datetime.fromtimestamp(X[int(l)]), xLabelFormat) if int(l) >= 0 else '', 'xlabel': _('Date'), 'y': [{ 'label': p['name'], 'data': [v[1] for v in p['dataUsers']] } for p in poolsData], 'ylabel': _('Users') } graphs.barChart(SIZE, data, graph1) X = [v[0] for v in poolsData[0]['dataAccesses']] data = { 'title': _('Accesses'), 'x': X, 'xtickFnc': lambda l: filters.date(datetime.datetime.fromtimestamp(X[int(l)]), xLabelFormat) if int(l) >= 0 else '', 'xlabel': _('Date'), 'y': [{ 'label': p['name'], 'data': [v[1] for v in p['dataAccesses']] } for p in poolsData], 'ylabel': _('Accesses') } graphs.barChart(SIZE, data, graph2) # Generate Data for pools, basically joining all pool data return self.templateAsPDF( 'uds/reports/stats/pools-performance.html', dct={ 'data': reportData, 'pools': [i[1] for i in self.getPools()], 'beginning': self.startDate.date(), 'ending': self.endDate.date(), 'intervals': self.samplingPoints.num(), }, header=ugettext('UDS Pools Performance Report'), water=ugettext('Pools Performance'), images={ 'graph1': graph1.getvalue(), 'graph2': graph2.getvalue() }, )
class UsageByPool(StatsReport): filename = 'pools_usage.pdf' name = _('Pools usage by users') # Report name description = _('Pools usage by user report') # Report description uuid = '38ec12dc-beaf-11e5-bd0a-10feed05884b' # Input fields pool = gui.MultiChoiceField(order=1, label=_('Pool'), tooltip=_('Pool for report'), required=True) startDate = gui.DateField( order=2, label=_('Starting date'), tooltip=_('starting date for report'), defvalue=datetime.date.min, required=True, ) endDate = gui.DateField( order=3, label=_('Finish date'), tooltip=_('finish date for report'), defvalue=datetime.date.max, required=True, ) def initialize(self, values): pass def initGui(self): logger.debug('Initializing gui') vals = [gui.choiceItem('0-0-0-0', ugettext('ALL POOLS'))] + [ gui.choiceItem(v.uuid, v.name) for v in ServicePool.objects.all().order_by('name') ] self.pool.setValues(vals) def getData( self ) -> typing.Tuple[typing.List[typing.Dict[str, typing.Any]], str]: # Generate the sampling intervals and get dataUsers from db start = self.startDate.stamp() end = self.endDate.stamp() logger.debug(self.pool.value) if '0-0-0-0' in self.pool.value: pools = ServicePool.objects.all() else: pools = ServicePool.objects.filter(uuid__in=self.pool.value) data = [] for pool in pools: items = (events.statsManager().getEvents( events.OT_DEPLOYED, (events.ET_LOGIN, events.ET_LOGOUT), owner_id=pool.id, since=start, to=end, ).order_by('stamp')) logins = {} for i in items: # if '\\' in i.fld1: # continue if i.event_type == events.ET_LOGIN: logins[i.fld4] = i.stamp else: if i.fld4 in logins: stamp = logins[i.fld4] del logins[i.fld4] total = i.stamp - stamp data.append({ 'name': i.fld4, 'origin': i.fld2.split(':')[0], 'date': datetime.datetime.fromtimestamp(stamp), 'time': total, 'pool': pool.uuid, 'pool_name': pool.name, }) return data, ','.join([p.name for p in pools]) def generate(self): items, poolName = self.getData() return self.templateAsPDF( 'uds/reports/stats/usage-by-pool.html', dct={ 'data': items, 'pool': poolName, }, header=ugettext('Users usage list'), water=ugettext('UDS Report of users usage'), )
def end_date_field(order: int) -> gui.DateField: return gui.DateField(order=order, label=_('Ending date'), tooltip=_('ending date for report'), defvalue=datetime.date.max, required=True)
def single_date_field(order: int) -> gui.DateField: return gui.DateField(order=order, label=_('Date'), tooltip=_('Date for report'), defvalue=datetime.date.today(), required=True)
def start_date_field(order: int) -> gui.DateField: return gui.DateField(order=order, label=_('Starting date'), tooltip=_('Starting date for report'), defvalue=datetime.date.min, required=True)