forked from shaba/openuds
Upgraded reporting to weasyprint & python3.
Caution!!. pycha does not supports python3. Right now, we have patched pycha on our servers, and will look for an updated alternative.
This commit is contained in:
parent
8f38ae8f4a
commit
54136ae077
@ -39,14 +39,15 @@ from uds.core.ui.UserInterface import UserInterface
|
||||
from uds.core.util import encoders
|
||||
from . import stock
|
||||
|
||||
import six
|
||||
from weasyprint import HTML, CSS, default_url_fetcher
|
||||
from datetime import datetime
|
||||
|
||||
import logging
|
||||
import six
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__updated__ = '2018-02-07'
|
||||
__updated__ = '2018-02-08'
|
||||
|
||||
|
||||
class Report(UserInterface):
|
||||
@ -103,8 +104,8 @@ class Report(UserInterface):
|
||||
mime_type='image/png')
|
||||
elif url.startswith('image://'):
|
||||
if isinstance(images, dict):
|
||||
logger.debug('Getting image {} --> {}'.format(url[8:], images.get(url[8:])))
|
||||
img = images.get(url[8:])
|
||||
img = images.get(url[8:], None)
|
||||
logger.debug('Getting image {}? {}'.format(url[8:], img != None))
|
||||
return dict(string=img,
|
||||
mime_type='image/png')
|
||||
else:
|
||||
|
@ -1,38 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2015 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from .geraldo_graphics import UDSImage
|
||||
from .report import UDSGeraldoReport
|
||||
|
||||
__updated__ = '2015-06-21'
|
@ -1,27 +0,0 @@
|
||||
from geraldo.base import BAND_WIDTH, BAND_HEIGHT, Element
|
||||
from geraldo.utils import cm, black
|
||||
from geraldo import Image
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UDSImage(Image):
|
||||
def _get_height(self):
|
||||
ret = self._height or (self.image and (self.image.size[1] * cm / 118) or 0)
|
||||
return ret
|
||||
|
||||
def _set_height(self, value):
|
||||
self._height = value
|
||||
|
||||
height = property(_get_height, _set_height)
|
||||
|
||||
def _get_width(self):
|
||||
ret = self._width or (self.image and (self.image.size[0] * cm / 118) or 0)
|
||||
return ret
|
||||
|
||||
def _set_width(self, value):
|
||||
self._width = value
|
||||
|
||||
width = property(_get_width, _set_width)
|
@ -1,97 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# Copyright (c) 2015 Virtual Cable S.L.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""
|
||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
from uds.core.reports import stock
|
||||
|
||||
from geraldo import Report, landscape, ReportBand, ObjectValue, SystemField, BAND_WIDTH, Label, SubReport, Rect, Line
|
||||
from uds.core.reports.tools.geraldo_graphics import UDSImage
|
||||
from reportlab.lib.pagesizes import A4
|
||||
from reportlab.lib.units import cm, mm
|
||||
from reportlab.lib.enums import TA_RIGHT, TA_CENTER
|
||||
from reportlab.lib import colors
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__updated__ = '2016-05-17'
|
||||
|
||||
|
||||
class UDSGeraldoReport(Report):
|
||||
author = 'UDS Enterprise'
|
||||
title = 'UDS Report'
|
||||
|
||||
print_if_empty = True
|
||||
page_size = A4
|
||||
margin_left = 0.5 * cm
|
||||
margin_top = 0.5 * cm
|
||||
margin_right = 0.5 * cm
|
||||
margin_bottom = 0.5 * cm
|
||||
|
||||
header_elements = []
|
||||
header_height = 1.8 * cm
|
||||
|
||||
class band_page_header(ReportBand):
|
||||
height = 1.8 * cm
|
||||
bElements = [
|
||||
SystemField(expression='%(report_title)s', top=0.5 * cm, left=0, width=BAND_WIDTH,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 14, 'alignment': TA_CENTER}),
|
||||
|
||||
SystemField(expression=_('Page %(page_number)d of %(page_count)d'), top=0.1 * cm,
|
||||
width=BAND_WIDTH, style={'alignment': TA_RIGHT}),
|
||||
UDSImage(filename=stock.getStockImagePath(stock.LOGO), left=0.0 * cm, top=0.0 * cm, width=2.0 * cm, height=2.0 * cm),
|
||||
]
|
||||
borders = {'bottom': Line(stroke_color=colors.red, stroke_width=3)}
|
||||
|
||||
class band_page_footer(ReportBand):
|
||||
height = 0.5 * cm
|
||||
bElements = [
|
||||
Label(text=_('Generated by UDS'), top=0.1 * cm),
|
||||
SystemField(expression=_('Printed in %(now:%Y, %b %d)s at %(now:%H:%M)s'), top=0.1 * cm,
|
||||
width=BAND_WIDTH, style={'alignment': TA_RIGHT}),
|
||||
]
|
||||
borders = {'top': True}
|
||||
|
||||
def __init__(self, queryset=None):
|
||||
self.band_page_header.elements = self.band_page_header.bElements + self.header_elements
|
||||
self.band_page_header.height = self.header_height
|
||||
Report.__init__(self, queryset=queryset)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def viewSize():
|
||||
return (
|
||||
UDSGeraldoReport.page_size - UDSGeraldoReport.mar
|
||||
)
|
@ -45,7 +45,7 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__updated__ = '2018-02-07'
|
||||
__updated__ = '2018-02-08'
|
||||
|
||||
|
||||
class ListReportUsers(ListReport):
|
||||
@ -86,7 +86,7 @@ class ListReportUsers(ListReport):
|
||||
'auth': auth.name,
|
||||
},
|
||||
header=ugettext('Users List for {}').format(auth.name),
|
||||
water=ugettext('UDS Report of users in {}'.format(auth.name))
|
||||
water=ugettext('UDS Report of users in {}').format(auth.name)
|
||||
)
|
||||
|
||||
|
||||
|
@ -31,10 +31,16 @@
|
||||
@author: Adolfo Gómez, dkmaster at dkmon dot com
|
||||
"""
|
||||
|
||||
# from .usage import StatsReportUsage
|
||||
from .login import StatsReportLogin, StatsReportLoginCSV
|
||||
# from .pool_performance import PoolPerformanceReport
|
||||
# We just need to import. Report loader will look for Report subclasses
|
||||
# from . import usage
|
||||
from . import login
|
||||
from . import pools_performance
|
||||
from . import pools_usage_day
|
||||
from . import usage_by_pool
|
||||
from . import pool_usage_summary
|
||||
# from .login import StatsReportLogin, StatsReportLoginCSV
|
||||
# from .pools_performance import PoolPerformanceReport
|
||||
# from .pools_usage_day import CountersPoolAssigned
|
||||
# from .usage_by_pool import UsageByPool
|
||||
# from .pools_usage import CountersPoolAssigned
|
||||
# from .usage_summary_pool import UsageSummaryByPool
|
||||
# from .pool_usage_summary import UsageSummaryByPool
|
||||
|
||||
|
@ -54,7 +54,7 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__updated__ = '2018-02-07'
|
||||
__updated__ = '2018-02-08'
|
||||
|
||||
# several constants as Width height
|
||||
WIDTH, HEIGHT = 1920, 1080
|
||||
@ -230,7 +230,7 @@ class StatsReportLogin(StatsReport):
|
||||
surface.write_to_png(graph1)
|
||||
|
||||
del chart
|
||||
del surface # calls finish, flushing to SVG
|
||||
del surface # calls finish, flushing to image
|
||||
|
||||
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) # @UndefinedVariable
|
||||
|
||||
@ -263,7 +263,7 @@ class StatsReportLogin(StatsReport):
|
||||
surface.write_to_png(graph2)
|
||||
|
||||
del chart
|
||||
del surface # calls finish, flushing to SVG
|
||||
del surface # calls finish, flushing to image
|
||||
|
||||
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) # @UndefinedVariable
|
||||
|
||||
@ -291,17 +291,17 @@ class StatsReportLogin(StatsReport):
|
||||
|
||||
surface.write_to_png(graph3)
|
||||
|
||||
del chart
|
||||
del surface # calls finish, flushing to SVG
|
||||
with open('/home/dkmaster/kk/kk.png', 'wb') as f:
|
||||
f.write(graph3.getvalue())
|
||||
|
||||
with open('/home/dkmaster/kk/g1.svg', 'wb') as f:
|
||||
f.write(graph1.getvalue())
|
||||
del chart
|
||||
del surface # calls finish, flushing to image
|
||||
|
||||
return self.templateAsPDF(
|
||||
'uds/reports/stats/user-access.html',
|
||||
dct={
|
||||
'data': reportData,
|
||||
'begining': self.startDate.date(),
|
||||
'beginning': self.startDate.date(),
|
||||
'ending': self.endDate.date(),
|
||||
'intervals': self.samplingPoints.num(),
|
||||
},
|
||||
|
@ -35,7 +35,6 @@ from __future__ import unicode_literals
|
||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
|
||||
from uds.core.ui.UserInterface import gui
|
||||
from uds.core.reports.tools import UDSGeraldoReport
|
||||
from uds.core.util.stats import events
|
||||
|
||||
import six
|
||||
@ -45,44 +44,16 @@ import six
|
||||
from .base import StatsReport
|
||||
|
||||
from uds.models import ServicePool
|
||||
from geraldo.generators.pdf import PDFGenerator
|
||||
from geraldo import ReportBand, ObjectValue, Label
|
||||
from reportlab.lib.units import cm, mm
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__updated__ = '2017-05-09'
|
||||
__updated__ = '2018-02-08'
|
||||
|
||||
# several constants as Width height, margins, ..
|
||||
WIDTH, HEIGHT = 1800, 1000
|
||||
GERALDO_WIDTH = 120 * mm
|
||||
GERALDO_HEIGHT = GERALDO_WIDTH * HEIGHT / WIDTH
|
||||
|
||||
|
||||
class UsersSumaryReport(UDSGeraldoReport):
|
||||
title = ''
|
||||
author = 'UDS'
|
||||
|
||||
header_elements = [
|
||||
Label(text=_('User'), top=2.0 * cm, left=0.5 * cm),
|
||||
Label(text=_('Sessions'), top=2.0 * cm, left=5.5 * cm),
|
||||
Label(text=_('Hours'), top=2.0 * cm, left=7.5 * cm),
|
||||
Label(text=_('Average'), top=2.0 * cm, left=12 * cm),
|
||||
]
|
||||
|
||||
header_height = 2.5 * cm
|
||||
|
||||
class band_detail(ReportBand):
|
||||
height = 0.5 * cm
|
||||
elements = (
|
||||
ObjectValue(attribute_name='user', left=0.5 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
|
||||
ObjectValue(attribute_name='sessions', left=5.5 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
|
||||
ObjectValue(attribute_name='hours', left=7.5 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
|
||||
ObjectValue(attribute_name='average', left=12 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
|
||||
)
|
||||
WIDTH, HEIGHT = 1920, 1080
|
||||
|
||||
|
||||
class UsageSummaryByPool(StatsReport):
|
||||
@ -174,12 +145,17 @@ class UsageSummaryByPool(StatsReport):
|
||||
def generate(self):
|
||||
items, poolName = self.getData()
|
||||
|
||||
output = six.StringIO()
|
||||
|
||||
report = UsersSumaryReport(queryset=items)
|
||||
report.title = _('Users usage list for {}').format(poolName)
|
||||
report.generate_by(PDFGenerator, filename=output)
|
||||
return output.getvalue()
|
||||
return self.templateAsPDF(
|
||||
'uds/reports/stats/pool-usage-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 UsageSummaryByPoolCSV(UsageSummaryByPool):
|
@ -37,95 +37,30 @@ from django.db.models import Count
|
||||
import django.template.defaultfilters as filters
|
||||
|
||||
from uds.core.ui.UserInterface import gui
|
||||
from uds.core.reports.tools import UDSImage, UDSGeraldoReport
|
||||
from uds.core.util.stats import events
|
||||
|
||||
import csv
|
||||
import six
|
||||
|
||||
import cairo
|
||||
import pycha.line
|
||||
import pycha.bar
|
||||
# import pycha.line
|
||||
# import pycha.bar
|
||||
import pycha.stackedbar
|
||||
|
||||
from .base import StatsReport
|
||||
|
||||
from uds.core.util import tools
|
||||
from uds.models import ServicePool
|
||||
from geraldo.generators.pdf import PDFGenerator
|
||||
from geraldo import ReportBand, ObjectValue, BAND_WIDTH, Label, SubReport, SystemField, Line
|
||||
from reportlab.lib.units import cm, mm
|
||||
from reportlab.lib.enums import TA_RIGHT, TA_CENTER
|
||||
# from reportlab.lib import colors
|
||||
from PIL import Image as PILImage
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__updated__ = '2017-05-04'
|
||||
__updated__ = '2018-02-08'
|
||||
|
||||
# several constants as Width height, margins, ..
|
||||
WIDTH, HEIGHT = 1800, 1000
|
||||
GERALDO_WIDTH = 120 * mm
|
||||
GERALDO_HEIGHT = GERALDO_WIDTH * HEIGHT / WIDTH
|
||||
|
||||
|
||||
class AccessReport(UDSGeraldoReport):
|
||||
|
||||
header_elements = []
|
||||
|
||||
class band_detail(ReportBand):
|
||||
height = 400 * mm # Height bigger than a page, so a new page is launched for listings
|
||||
# auto_expand_height = True
|
||||
elements = (
|
||||
Label(text=_('Distinct users by pool'), top=0.6 * cm, left=0, width=BAND_WIDTH,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 10, 'alignment': TA_CENTER}),
|
||||
UDSImage(left=4 * cm, top=1 * cm,
|
||||
width=GERALDO_WIDTH, height=GERALDO_HEIGHT,
|
||||
get_image=lambda x: x.instance['image']),
|
||||
|
||||
Label(text=_('Accesses by pool'), top=GERALDO_HEIGHT + 1.2 * cm, left=0, width=BAND_WIDTH,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 10, 'alignment': TA_CENTER}),
|
||||
UDSImage(left=4 * cm, top=GERALDO_HEIGHT + 1.6 * cm,
|
||||
width=GERALDO_WIDTH, height=GERALDO_HEIGHT,
|
||||
get_image=lambda x: x.instance['image2']),
|
||||
)
|
||||
|
||||
subreports = [
|
||||
SubReport(
|
||||
queryset_string='%(object)s["data"]',
|
||||
band_header=ReportBand(
|
||||
height=1 * cm,
|
||||
auto_expand_height=True,
|
||||
elements=(
|
||||
# Label(text=_('Users access by date'), top=0.2 * cm, left=0, width=BAND_WIDTH,
|
||||
# style={'fontName': 'Helvetica-Bold', 'fontSize': 12, 'alignment': TA_CENTER}),
|
||||
|
||||
Label(text=_('Pool'), top=1.0 * cm, left=1.2 * cm,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 9}),
|
||||
Label(text=_('Date range'), top=1.0 * cm, left=8 * cm,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 9}),
|
||||
Label(text=_('Users'), top=1.0 * cm, left=14 * cm,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 9}),
|
||||
Label(text=_('Accesses'), top=1.0 * cm, left=16 * cm,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 9}),
|
||||
),
|
||||
# borders={'bottom': True}
|
||||
),
|
||||
band_detail=ReportBand(
|
||||
height=0.5 * cm,
|
||||
elements=(
|
||||
ObjectValue(attribute_name='name', top=0, left=1.2 * cm, width=12 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
|
||||
ObjectValue(attribute_name='date', top=0, left=8 * cm, width=12 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
|
||||
ObjectValue(attribute_name='users', top=0, left=14 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
|
||||
ObjectValue(attribute_name='accesses', top=0, left=16 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
|
||||
)
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
WIDTH, HEIGHT = 1920, 1080
|
||||
|
||||
|
||||
class PoolPerformanceReport(StatsReport):
|
||||
@ -174,10 +109,13 @@ class PoolPerformanceReport(StatsReport):
|
||||
def initGui(self):
|
||||
logger.debug('Initializing gui')
|
||||
vals = [
|
||||
gui.choiceItem(v.uuid, v.name) for v in ServicePool.objects.all()
|
||||
gui.choiceItem(v.uuid, v.name) for v in ServicePool.objects.all().order_by('name')
|
||||
]
|
||||
self.pools.setValues(vals)
|
||||
|
||||
def getPools(self):
|
||||
return [(v.id, v.name) for v in ServicePool.objects.filter(uuid__in=self.pools.value)]
|
||||
|
||||
def getRangeData(self):
|
||||
start = self.startDate.stamp()
|
||||
end = self.endDate.stamp()
|
||||
@ -191,7 +129,8 @@ class PoolPerformanceReport(StatsReport):
|
||||
|
||||
samplingPoints = self.samplingPoints.num()
|
||||
|
||||
pools = [(v.id, v.name) for v in ServicePool.objects.filter(uuid__in=self.pools.value)]
|
||||
pools = self.getPools()
|
||||
|
||||
if len(pools) == 0:
|
||||
raise Exception(_('Select at least a service pool for the report'))
|
||||
|
||||
@ -206,7 +145,7 @@ class PoolPerformanceReport(StatsReport):
|
||||
# Generate samplings interval
|
||||
samplingIntervals = []
|
||||
prevVal = None
|
||||
for val in range(start, end, (end - start) / (samplingPoints + 1)):
|
||||
for val in range(start, end, int((end - start) / (samplingPoints + 1))):
|
||||
if prevVal is None:
|
||||
prevVal = val
|
||||
continue
|
||||
@ -255,6 +194,9 @@ class PoolPerformanceReport(StatsReport):
|
||||
|
||||
xLabelFormat, poolsData, reportData = self.getRangeData()
|
||||
|
||||
graph1 = six.BytesIO()
|
||||
graph2 = six.BytesIO()
|
||||
|
||||
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) # @UndefinedVariable
|
||||
|
||||
options = {
|
||||
@ -262,7 +204,7 @@ class PoolPerformanceReport(StatsReport):
|
||||
'axis': {
|
||||
'x': {
|
||||
'ticks': [
|
||||
dict(v=i, label=filters.date(datetime.datetime.fromtimestamp(l), xLabelFormat)) for i, l in enumerate(range(start, end, (end - start) / self.samplingPoints.num()))
|
||||
dict(v=i, label=filters.date(datetime.datetime.fromtimestamp(l), xLabelFormat)) for i, l in enumerate(range(start, end, int((end - start) / self.samplingPoints.num())))
|
||||
],
|
||||
'range': (0, self.samplingPoints.num()),
|
||||
'showLines': True,
|
||||
@ -279,7 +221,7 @@ class PoolPerformanceReport(StatsReport):
|
||||
'lineColor': '#187FF2'
|
||||
},
|
||||
'colorScheme': {
|
||||
'name': 'rainbow',
|
||||
'name': 'gradient',
|
||||
'args': {
|
||||
'initialColor': 'blue',
|
||||
},
|
||||
@ -317,7 +259,12 @@ class PoolPerformanceReport(StatsReport):
|
||||
|
||||
chart.render()
|
||||
|
||||
img = PILImage.frombuffer("RGBA", (surface.get_width(), surface.get_height()), surface.get_data(), "raw", "BGRA", 0, 1)
|
||||
surface.write_to_png(graph1)
|
||||
|
||||
del chart
|
||||
del surface # calls finish, flushing to image
|
||||
|
||||
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) # @UndefinedVariable
|
||||
|
||||
# Accesses
|
||||
chart = pycha.stackedbar.StackedVerticalBarChart(surface, options)
|
||||
@ -334,26 +281,26 @@ class PoolPerformanceReport(StatsReport):
|
||||
|
||||
chart.render()
|
||||
|
||||
img2 = PILImage.frombuffer("RGBA", (surface.get_width(), surface.get_height()), surface.get_data(), "raw", "BGRA", 0, 1)
|
||||
surface.write_to_png(graph2)
|
||||
|
||||
del chart
|
||||
del surface # calls finish, flushing to image
|
||||
|
||||
# Generate Data for pools, basically joining all pool data
|
||||
|
||||
queryset = [
|
||||
{'image': img, 'image2': img2, 'data': reportData }
|
||||
]
|
||||
|
||||
logger.debug(queryset)
|
||||
|
||||
output = six.StringIO()
|
||||
|
||||
try:
|
||||
report = AccessReport(queryset=queryset)
|
||||
report.title = ugettext('UDS Pools Performance Report')
|
||||
report.generate_by(PDFGenerator, filename=output)
|
||||
return output.getvalue()
|
||||
except Exception:
|
||||
logger.exception('Errool')
|
||||
return None
|
||||
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 PoolPerformanceReportCSV(PoolPerformanceReport):
|
||||
@ -369,7 +316,7 @@ class PoolPerformanceReportCSV(PoolPerformanceReport):
|
||||
samplingPoints = PoolPerformanceReport.samplingPoints
|
||||
|
||||
def generate(self):
|
||||
output = StringIO.StringIO()
|
||||
output = six.StringIO()
|
||||
writer = csv.writer(output)
|
||||
|
||||
reportData = self.getRangeData()[2]
|
||||
|
@ -35,28 +35,19 @@ from __future__ import unicode_literals
|
||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
|
||||
from uds.core.ui.UserInterface import gui
|
||||
from uds.core.reports.tools import UDSGeraldoReport, UDSImage
|
||||
from uds.core.util.stats import counters
|
||||
|
||||
|
||||
import six
|
||||
import csv
|
||||
|
||||
|
||||
from .base import StatsReport
|
||||
|
||||
from uds.models import ServicePool
|
||||
from geraldo.generators.pdf import PDFGenerator
|
||||
from geraldo import ReportBand, ObjectValue, Label, BAND_WIDTH, SubReport
|
||||
from reportlab.lib.units import cm, mm
|
||||
from reportlab.lib.enums import TA_RIGHT, TA_CENTER
|
||||
|
||||
import cairo
|
||||
import pycha.line
|
||||
import pycha.bar
|
||||
# import pycha.line
|
||||
# import pycha.bar
|
||||
import pycha.stackedbar
|
||||
from PIL import Image as PILImage
|
||||
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
@ -64,60 +55,10 @@ import six
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__updated__ = '2017-05-03'
|
||||
__updated__ = '2018-02-08'
|
||||
|
||||
# several constants as Width height, margins, ..
|
||||
WIDTH, HEIGHT = 1800, 1000
|
||||
GERALDO_WIDTH = 120 * mm
|
||||
GERALDO_HEIGHT = GERALDO_WIDTH * HEIGHT / WIDTH
|
||||
|
||||
|
||||
class CountersPoolsReport(UDSGeraldoReport):
|
||||
title = ''
|
||||
author = 'UDS'
|
||||
|
||||
header_elements = []
|
||||
|
||||
header_height = 2.5 * cm
|
||||
|
||||
class band_detail(ReportBand):
|
||||
height = 400 * mm # Height bigger than a page, so a new page is launched for listings
|
||||
elements = (
|
||||
Label(text=_('Services Asignation'), top=0.6 * cm, left=0, width=BAND_WIDTH,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 10, 'alignment': TA_CENTER}),
|
||||
UDSImage(left=4 * cm, top=1 * cm,
|
||||
width=GERALDO_WIDTH, height=GERALDO_HEIGHT,
|
||||
get_image=lambda x: x.instance['image']),
|
||||
)
|
||||
|
||||
subreports = [
|
||||
SubReport(
|
||||
queryset_string='%(object)s["data"]',
|
||||
band_header=ReportBand(
|
||||
height=1 * cm,
|
||||
auto_expand_height=True,
|
||||
elements=(
|
||||
Label(text=_('Service asignation by hour'), top=0.2 * cm, left=0, width=BAND_WIDTH,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 12, 'alignment': TA_CENTER}),
|
||||
Label(text=_('Pool'), top=1.0 * cm, left=1.2 * cm,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 10}),
|
||||
Label(text=_('Hour'), top=1.0 * cm, left=10 * cm,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 10}),
|
||||
Label(text=_('Services'), top=1.0 * cm, left=14 * cm,
|
||||
style={'fontName': 'Helvetica-Bold', 'fontSize': 10}),
|
||||
),
|
||||
# borders={'bottom': True}
|
||||
),
|
||||
band_detail=ReportBand(
|
||||
height=0.5 * cm,
|
||||
elements=(
|
||||
ObjectValue(attribute_name='name', top=0, left=1.2 * cm, width=8.8 * cm, style={'fontName': 'Helvetica', 'fontSize': 9}),
|
||||
ObjectValue(attribute_name='time', top=0, left=10 * cm, width=4 * cm, style={'fontName': 'Helvetica', 'fontSize': 9}),
|
||||
ObjectValue(attribute_name='value', top=0, left=14 * cm, width=4 * cm, style={'fontName': 'Helvetica', 'fontSize': 9}),
|
||||
)
|
||||
),
|
||||
)
|
||||
]
|
||||
WIDTH, HEIGHT = 1920, 1080
|
||||
|
||||
|
||||
class CountersPoolAssigned(StatsReport):
|
||||
@ -130,7 +71,7 @@ class CountersPoolAssigned(StatsReport):
|
||||
order=2,
|
||||
label=_('Date'),
|
||||
tooltip=_('Date for report'),
|
||||
defvalue=datetime.date.min,
|
||||
defvalue='',
|
||||
required=True
|
||||
)
|
||||
|
||||
@ -147,7 +88,7 @@ class CountersPoolAssigned(StatsReport):
|
||||
def initGui(self):
|
||||
logger.debug('Initializing gui')
|
||||
vals = [
|
||||
gui.choiceItem(v.uuid, v.name) for v in ServicePool.objects.all()
|
||||
gui.choiceItem(v.uuid, v.name) for v in ServicePool.objects.all().order_by('name')
|
||||
]
|
||||
self.pools.setValues(vals)
|
||||
|
||||
@ -176,7 +117,6 @@ class CountersPoolAssigned(StatsReport):
|
||||
|
||||
data.append({'uuid':pool.uuid, 'name': pool.name, 'hours': hours})
|
||||
|
||||
|
||||
logger.debug('data: {}'.format(data))
|
||||
|
||||
return data
|
||||
@ -184,6 +124,8 @@ class CountersPoolAssigned(StatsReport):
|
||||
def generate(self):
|
||||
items = self.getData()
|
||||
|
||||
graph1 = six.BytesIO()
|
||||
|
||||
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) # @UndefinedVariable
|
||||
|
||||
options = {
|
||||
@ -208,7 +150,7 @@ class CountersPoolAssigned(StatsReport):
|
||||
'lineColor': '#187FF2'
|
||||
},
|
||||
'colorScheme': {
|
||||
'name': 'rainbow',
|
||||
'name': 'gradient',
|
||||
'args': {
|
||||
'initialColor': 'blue',
|
||||
},
|
||||
@ -238,30 +180,32 @@ class CountersPoolAssigned(StatsReport):
|
||||
for pool in items:
|
||||
logger.debug(pool['hours'])
|
||||
ds = list((i, pool['hours'][i]) for i in range(24))
|
||||
logger.debug(ds)
|
||||
# logger.debug(ds)
|
||||
dataset.append((ugettext('Services for {}').format(pool['name']), ds))
|
||||
|
||||
logger.debug('Dataset: {}'.format(dataset))
|
||||
# logger.debug('Dataset: {}'.format(dataset))
|
||||
chart.addDataset(dataset)
|
||||
|
||||
chart.render()
|
||||
|
||||
img = PILImage.frombuffer("RGBA", (surface.get_width(), surface.get_height()), surface.get_data(), "raw", "BGRA", 0, 1)
|
||||
surface.write_to_png(graph1)
|
||||
|
||||
output = six.StringIO()
|
||||
del chart
|
||||
del surface # calls finish, flushing to image
|
||||
|
||||
# Regenerate data
|
||||
logger.debug('Items: {}'.format(items))
|
||||
|
||||
# Generate data
|
||||
data = []
|
||||
for i in items:
|
||||
for j in range(24):
|
||||
data.append({'name': i['name'], 'time': '{:02d}'.format(j), 'value': i['hours'][j]})
|
||||
|
||||
report = CountersPoolsReport(queryset=[{'data': data, 'image': img}])
|
||||
report.title = six.text_type(_('Services usage report'))
|
||||
report.generate_by(PDFGenerator, filename=output)
|
||||
return output.getvalue()
|
||||
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 CountersPoolAssignedCSV(CountersPoolAssigned):
|
||||
|
@ -35,54 +35,24 @@ from __future__ import unicode_literals
|
||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
|
||||
from uds.core.ui.UserInterface import gui
|
||||
from uds.core.reports.tools import UDSGeraldoReport
|
||||
from uds.core.util.stats import events
|
||||
|
||||
|
||||
import six
|
||||
import csv
|
||||
|
||||
|
||||
from .base import StatsReport
|
||||
|
||||
from uds.models import ServicePool
|
||||
from geraldo.generators.pdf import PDFGenerator
|
||||
from geraldo import ReportBand, ObjectValue, Label
|
||||
from reportlab.lib.units import cm, mm
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__updated__ = '2016-05-17'
|
||||
__updated__ = '2018-02-08'
|
||||
|
||||
# several constants as Width height, margins, ..
|
||||
WIDTH, HEIGHT = 1800, 1000
|
||||
GERALDO_WIDTH = 120 * mm
|
||||
GERALDO_HEIGHT = GERALDO_WIDTH * HEIGHT / WIDTH
|
||||
|
||||
|
||||
class UsersReport(UDSGeraldoReport):
|
||||
title = ''
|
||||
author = 'UDS'
|
||||
|
||||
header_elements = [
|
||||
Label(text=_('Access Datetime'), top=2.0 * cm, left=0.5 * cm),
|
||||
Label(text=_('User'), top=2.0 * cm, left=5.5 * cm),
|
||||
Label(text=_('Duration(seconds)'), top=2.0 * cm, left=12 * cm),
|
||||
]
|
||||
|
||||
header_height = 2.5 * cm
|
||||
|
||||
|
||||
class band_detail(ReportBand):
|
||||
height = 0.5 * cm
|
||||
elements = (
|
||||
ObjectValue(attribute_name='date', left=0.5 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
|
||||
ObjectValue(attribute_name='name', left=5.5 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
|
||||
ObjectValue(attribute_name='time', left=12 * cm, style={'fontName': 'Helvetica', 'fontSize': 8}),
|
||||
)
|
||||
WIDTH, HEIGHT = 1920, 1080
|
||||
|
||||
|
||||
class UsageByPool(StatsReport):
|
||||
@ -153,19 +123,22 @@ class UsageByPool(StatsReport):
|
||||
'time': total
|
||||
})
|
||||
|
||||
logger.debug('data')
|
||||
logger.debug('data: {}'.format(data))
|
||||
|
||||
return data, pool.name
|
||||
|
||||
def generate(self):
|
||||
items, poolName = self.getData()
|
||||
|
||||
output = six.StringIO()
|
||||
|
||||
report = UsersReport(queryset=items)
|
||||
report.title = _('Users usage list for {}').format(poolName)
|
||||
report.generate_by(PDFGenerator, filename=output)
|
||||
return output.getvalue()
|
||||
return self.templateAsPDF(
|
||||
'uds/reports/stats/usage-by-pool.html',
|
||||
dct={
|
||||
'data': items,
|
||||
'pool': poolName,
|
||||
},
|
||||
header=ugettext('Users usage list for {}').format(poolName),
|
||||
water=ugettext('UDS Report of users in {}').format(poolName)
|
||||
)
|
||||
|
||||
|
||||
class UsageByPoolCSV(UsageByPool):
|
||||
@ -180,7 +153,7 @@ class UsageByPoolCSV(UsageByPool):
|
||||
endDate = UsageByPool.endDate
|
||||
|
||||
def generate(self):
|
||||
output = StringIO.StringIO()
|
||||
output = six.StringIO()
|
||||
writer = csv.writer(output)
|
||||
|
||||
reportData, poolName = self.getData()
|
||||
|
@ -0,0 +1,35 @@
|
||||
{% load l10n i18n %}
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Users usage summary for {{ pool }}</title>
|
||||
<meta name="author" content="UDS">
|
||||
<meta name="description" content="Users usage summary for {{ pool }} from {{ beginning }} to {{ ending }}">
|
||||
<meta name="keywords" content="uds,report,usage,users,summary">
|
||||
<meta name="generator" content="UDS Reporting">
|
||||
</head>
|
||||
<body>
|
||||
<table style="width: 100%; font-size: 0.8em;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 25%">{% trans 'User' %}</th>
|
||||
<th style="width: 50%">{% trans 'Sessions' %}</th>
|
||||
<th style="width: 25%">{% trans 'Hours' %}</th>
|
||||
<th style="width: 25%">{% trans 'Average' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for d in data %}
|
||||
<tr>
|
||||
<td>{{ d.user }}</td>
|
||||
<td>{{ d.sessions }}</td>
|
||||
<td>{{ d.hours }}</td>
|
||||
<td>{{ d.average }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<!-- <p style="page-break-before: always">
|
||||
This is a new page
|
||||
</p> -->
|
||||
</body>
|
||||
</html>
|
@ -6,7 +6,7 @@
|
||||
</title>
|
||||
<meta name="author" content="UDS">
|
||||
<meta name="description" content="Report of pools usage of {{ pools|join:", " }}, for day {{ beginning }}">
|
||||
<meta name="keywords" content="uds,report,access">
|
||||
<meta name="keywords" content="uds,report,usage,pools">
|
||||
<meta name="generator" content="UDS Reporting">
|
||||
</head>
|
||||
<body>
|
||||
|
@ -0,0 +1,33 @@
|
||||
{% load l10n i18n %}
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Users usage list for {{ pool }}</title>
|
||||
<meta name="author" content="UDS">
|
||||
<meta name="description" content="Users usage list for {{ pool }}">
|
||||
<meta name="keywords" content="uds,report,usage,users,list">
|
||||
<meta name="generator" content="UDS Reporting">
|
||||
</head>
|
||||
<body>
|
||||
<table style="width: 100%; font-size: 0.8em;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 25%">{% trans 'Access date/time' %}</th>
|
||||
<th style="width: 50%">{% trans 'User' %}</th>
|
||||
<th style="width: 25%">{% trans 'Duration' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user in data %}
|
||||
<tr>
|
||||
<td>{{ user.date }}</td>
|
||||
<td>{{ user.name }}</td>
|
||||
<td>{{ user.time }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<!-- <p style="page-break-before: always">
|
||||
This is a new page
|
||||
</p> -->
|
||||
</body>
|
||||
</html>
|
@ -4,7 +4,7 @@
|
||||
<title>Users Access Report</title>
|
||||
<meta name="author" content="UDS">
|
||||
<meta name="description" content="List of UDS accesses from {{ beginning }} to {{ ending }} with {{ intervals }} intervals">
|
||||
<meta name="keywords" content="uds,report,access">
|
||||
<meta name="keywords" content="uds,report,access,user">
|
||||
<meta name="generator" content="UDS Reporting">
|
||||
</head>
|
||||
<body>
|
||||
|
Loading…
x
Reference in New Issue
Block a user