Initial commit to support scheduled statistics.

This commit is contained in:
Roberto Rosario
2015-09-09 00:24:53 -04:00
parent d474efe8b3
commit 70c23a19d3
11 changed files with 176 additions and 27 deletions

View File

@@ -72,7 +72,7 @@ from .permissions import (
permission_document_view
)
from .settings import setting_thumbnail_size
from .statistics import DocumentStatistics, DocumentUsageStatistics
from .statistics import document_page_count_per_month
from .widgets import document_thumbnail
@@ -351,12 +351,9 @@ class DocumentsApp(MayanAppConfig):
namespace = StatisticNamespace(name='documents', label=_('Documents'))
namespace.add_statistic(
DocumentStatistics(
name='document_stats', label=_('Document tendencies')
)
)
namespace.add_statistic(DocumentUsageStatistics(
name='document_usage', label=_('Document usage'))
slug='document-page-count-per-month',
label=_('Document page count per month'),
func=document_page_count_per_month
)
post_initial_setup.connect(

View File

@@ -40,15 +40,23 @@ def storage_count(path='.'):
return total_count, total_size
class DocumentStatistics(Statistic):
def get_results(self):
results = []
def document_page_count_per_month():
return (
(
{'August, 2015': 1244},
{'September, 2015': 3123},
),
)
results.extend(
[
_('Document types: %d') % DocumentType.objects.count(),
]
)
#def get_results(self):
# return (
## (
# {_('Document types'): DocumentType.objects.count()},
# ),
# )
"""
document_stats = DocumentVersion.objects.annotate(
page_count=Count('pages')
).aggregate(Min('page_count'), Max('page_count'), Avg('page_count'))
@@ -67,7 +75,7 @@ class DocumentStatistics(Statistic):
)
return results
"""
class DocumentUsageStatistics(Statistic):
def get_results(self):

View File

@@ -0,0 +1,12 @@
from __future__ import unicode_literals
from django.contrib import admin
from .models import StatisticResult
@admin.register(StatisticResult)
class StatisticResultAdmin(admin.ModelAdmin):
list_display = (
'slug', 'datetime', 'serialize_data'
)

View File

@@ -1,7 +1,12 @@
from __future__ import unicode_literals
from datetime import timedelta
from kombu import Exchange, Queue
from django.utils.translation import ugettext_lazy as _
from mayan.celery import app
from common import MayanAppConfig, menu_object, menu_secondary, menu_tools
from .classes import Statistic, StatisticNamespace
@@ -9,6 +14,8 @@ from .links import (
link_execute, link_namespace_details, link_namespace_list,
link_statistics
)
from .literals import STATISTICS_REFRESH_INTERVAL
from .tasks import task_check_statistics # NOQA - Force registration of task
class StatisticsApp(MayanAppConfig):
@@ -18,6 +25,32 @@ class StatisticsApp(MayanAppConfig):
def ready(self):
super(StatisticsApp, self).ready()
app.conf.CELERYBEAT_SCHEDULE.update(
{
'statistics.task_check_statistics': {
'task': 'statistics.tasks.task_check_statistics',
'schedule': timedelta(seconds=STATISTICS_REFRESH_INTERVAL),
},
}
)
app.conf.CELERY_QUEUES.extend(
(
Queue(
'statistics', Exchange('statistics'),
routing_key='statistics', delivery_mode=1
),
)
)
app.conf.CELERY_ROUTES.update(
{
'statistics.tasks.task_check_statistics': {
'queue': 'statistics'
},
}
)
menu_object.bind_links(links=(link_execute,), sources=(Statistic,))
menu_object.bind_links(
links=(link_namespace_details,), sources=(StatisticNamespace,)

View File

@@ -1,3 +1,8 @@
from __future__ import unicode_literals
from .models import StatisticResult
class StatisticNamespace(object):
_registry = {}
@@ -18,9 +23,10 @@ class StatisticNamespace(object):
def __unicode__(self):
return unicode(self.label)
def add_statistic(self, statistic):
self._statistics.append(statistic)
def add_statistic(self, *args, **kwargs):
statistic = Statistic(*args, **kwargs)
statistic.namespace = self
self._statistics.append(statistic)
@property
def id(self):
@@ -39,20 +45,33 @@ class Statistic(object):
return cls._registry.values()
@classmethod
def get(cls, name):
return cls._registry[name]
def get(cls, slug):
return cls._registry[slug]
def __init__(self, name, label):
self.name = name
def __init__(self, slug, label, func):
self.slug = slug
self.label = label
self.__class__._registry[name] = self
self.func = func
self.__class__._registry[slug] = self
def __unicode__(self):
return unicode(self.label)
def get_results(self, *args, **kwargs):
return NotImplementedError
def execute(self):
self.store_results(results=self.func())
@property
def id(self):
return self.name
return self.slug
def store_results(self, results):
StatisticResult.objects.filter(slug=self.slug).delete()
statistic_result = StatisticResult.objects.create(slug=self.slug)
statistic_result.store_data(data=results)
def get_results(self):
try:
return StatisticResult.objects.get(slug=self.slug).get_data()
except StatisticResultDoesNotExist:
return ((),)

View File

@@ -0,0 +1,3 @@
from __future__ import unicode_literals
STATISTICS_REFRESH_INTERVAL = 60 * 60 # Every hour

View File

@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
]
operations = [
migrations.CreateModel(
name='StatisticResult',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('slug', models.SlugField(verbose_name='Slug')),
('datetime', models.DateTimeField(auto_now=True, verbose_name='Date time')),
('serialize_data', models.TextField(verbose_name='Data', blank=True)),
],
options={
'verbose_name': 'Statistics result',
'verbose_name_plural': 'Statistics results',
},
bases=(models.Model,),
),
]

View File

@@ -0,0 +1,30 @@
from __future__ import unicode_literals
import json
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
@python_2_unicode_compatible
class StatisticResult(models.Model):
slug = models.SlugField(verbose_name=_('Slug'))
datetime = models.DateTimeField(
auto_now=True, verbose_name=_('Date time')
)
serialize_data = models.TextField(blank=True, verbose_name=_('Data'))
def get_data(self):
return json.loads(self.serialize_data)
def store_data(self, data):
self.serialize_data = json.dumps(data)
self.save()
def __str__(self):
return self.slug
class Meta:
verbose_name = _('Statistics result')
verbose_name_plural = _('Statistics results')

View File

@@ -0,0 +1,20 @@
from __future__ import unicode_literals
import logging
from mayan.celery import app
from .classes import StatisticNamespace
logger = logging.getLogger(__name__)
@app.task(ignore_result=True)
def task_check_statistics():
logger.info('Executing')
for namespace in StatisticNamespace.get_all():
for statistic in namespace.statistics:
statistic.execute()
logger.info('Finshed')

View File

@@ -12,7 +12,7 @@ urlpatterns = patterns(
NamespaceDetailView.as_view(), name='namespace_details'
),
url(
r'^(?P<statistic_id>\w+)/execute/$', StatisticExecute.as_view(),
r'^(?P<statistic_id>[\w,-]+)/view/$', StatisticExecute.as_view(),
name='statistic_execute'
),
)