Beispiel #1
0
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()
            },
        )
Beispiel #2
0
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()},
        )
Beispiel #4
0
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()
            },
        )
Beispiel #5
0
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'),
        )
Beispiel #6
0
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)
Beispiel #7
0
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)
Beispiel #8
0
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)