Improved system stats
parent
eb200b7607
commit
3531b440bd
|
@ -437,6 +437,7 @@ FEEDBACK_EMAIL = "support@taiga.io"
|
||||||
|
|
||||||
# Stats module settings
|
# Stats module settings
|
||||||
STATS_ENABLED = False
|
STATS_ENABLED = False
|
||||||
|
STATS_CACHE_TIMEOUT = 60*60 # In second
|
||||||
|
|
||||||
# 0 notifications will work in a synchronous way
|
# 0 notifications will work in a synchronous way
|
||||||
# >0 an external process will check the pending notifications and will send them
|
# >0 an external process will check the pending notifications and will send them
|
||||||
|
|
|
@ -69,6 +69,7 @@ DATABASES = {
|
||||||
|
|
||||||
# STATS MODULE
|
# STATS MODULE
|
||||||
#STATS_ENABLED = False
|
#STATS_ENABLED = False
|
||||||
|
#FRONT_SITEMAP_CACHE_TIMEOUT = 60*60 # In second
|
||||||
|
|
||||||
# SITEMAP
|
# SITEMAP
|
||||||
# If is True /front/sitemap.xml show a valid sitemap of taiga-front client
|
# If is True /front/sitemap.xml show a valid sitemap of taiga-front client
|
||||||
|
|
|
@ -12,6 +12,10 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.views.decorators.cache import cache_page
|
||||||
|
|
||||||
from taiga.base.api import viewsets
|
from taiga.base.api import viewsets
|
||||||
from taiga.base import response
|
from taiga.base import response
|
||||||
|
@ -24,10 +28,15 @@ class SystemStatsViewSet(viewsets.ViewSet):
|
||||||
permission_classes = (permissions.SystemStatsPermission,)
|
permission_classes = (permissions.SystemStatsPermission,)
|
||||||
|
|
||||||
def list(self, request, **kwargs):
|
def list(self, request, **kwargs):
|
||||||
stats = {
|
import ipdb; ipdb.set_trace()
|
||||||
"total_users": services.get_total_users(),
|
stats = OrderedDict()
|
||||||
"total_projects": services.get_total_projects(),
|
stats["users"] = services.get_users_stats()
|
||||||
"total_userstories": services.grt_total_user_stories(),
|
stats["projects"] = services.get_projects_stats()
|
||||||
"total_issues": services.get_total_issues(),
|
stats["userstories"] = services.get_user_stories_stats()
|
||||||
}
|
|
||||||
return response.Ok(stats)
|
return response.Ok(stats)
|
||||||
|
|
||||||
|
def _get_cache_timeout(self):
|
||||||
|
return getattr(settings, "STATS_CACHE_TIMEOUT", 0)
|
||||||
|
|
||||||
|
def dispatch(self, *args, **kwargs):
|
||||||
|
return cache_page(self._get_cache_timeout())(super().dispatch)(*args, **kwargs)
|
||||||
|
|
|
@ -12,33 +12,96 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from contextlib import closing
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
from django.db import connection
|
||||||
|
from django.utils import timezone
|
||||||
|
from datetime import timedelta
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
|
||||||
def get_total_projects():
|
def get_users_stats():
|
||||||
|
model = apps.get_model("users", "User")
|
||||||
|
queryset = model.objects.filter(is_active=True, is_system=False)
|
||||||
|
stats = OrderedDict()
|
||||||
|
|
||||||
|
# Total
|
||||||
|
stats["total"] = queryset.count()
|
||||||
|
|
||||||
|
# Average last 7 days
|
||||||
|
today = timezone.now()
|
||||||
|
seven_days_ago = today-timedelta(days=7)
|
||||||
|
stats["average_last_seven_days"] = (queryset.filter(date_joined__range=(seven_days_ago, today))
|
||||||
|
.count()) / 7
|
||||||
|
|
||||||
|
# Graph: users last year
|
||||||
|
a_year_ago = timezone.now() - timedelta(days=365)
|
||||||
|
sql_query = """
|
||||||
|
SELECT date_trunc('week', "filtered_users"."date_joined") AS "week",
|
||||||
|
count(*)
|
||||||
|
FROM (SELECT *
|
||||||
|
FROM "users_user"
|
||||||
|
WHERE "users_user"."is_active" = TRUE
|
||||||
|
AND "users_user"."is_system" = FALSE
|
||||||
|
AND "users_user"."date_joined" >= %s) AS "filtered_users"
|
||||||
|
GROUP BY "week"
|
||||||
|
ORDER BY "week";
|
||||||
|
"""
|
||||||
|
with closing(connection.cursor()) as cursor:
|
||||||
|
cursor.execute(sql_query, [a_year_ago])
|
||||||
|
rows = cursor.fetchall()
|
||||||
|
|
||||||
|
counts_last_year_per_week = OrderedDict()
|
||||||
|
sumatory = queryset.filter(date_joined__lt=rows[0][0]).count()
|
||||||
|
for row in rows:
|
||||||
|
sumatory += row[1]
|
||||||
|
counts_last_year_per_week[str(row[0].date())] = sumatory
|
||||||
|
|
||||||
|
stats["counts_last_year_per_week"] = counts_last_year_per_week
|
||||||
|
|
||||||
|
return stats
|
||||||
|
|
||||||
|
|
||||||
|
def get_projects_stats():
|
||||||
model = apps.get_model("projects", "Project")
|
model = apps.get_model("projects", "Project")
|
||||||
queryset = model.objects.all()
|
queryset = model.objects.all()
|
||||||
return queryset.count()
|
stats = OrderedDict()
|
||||||
|
|
||||||
|
stats["total"] = queryset.count()
|
||||||
|
|
||||||
|
today = timezone.now()
|
||||||
|
seven_days_ago = today-timedelta(days=7)
|
||||||
|
stats["average_last_seven_days"] = (queryset.filter(created_date__range=(seven_days_ago, today))
|
||||||
|
.count()) / 7
|
||||||
|
|
||||||
|
stats["total_with_backlog"] = (queryset.filter(is_backlog_activated=True,
|
||||||
|
is_kanban_activated=False)
|
||||||
|
.count())
|
||||||
|
stats["percent_with_backlog"] = stats["total_with_backlog"] * 100 / stats["total"]
|
||||||
|
|
||||||
|
stats["total_with_kanban"] = (queryset.filter(is_backlog_activated=False,
|
||||||
|
is_kanban_activated=True)
|
||||||
|
.count())
|
||||||
|
stats["percent_with_kanban"] = stats["total_with_kanban"] * 100 / stats["total"]
|
||||||
|
|
||||||
|
stats["total_with_backlog_and_kanban"] = (queryset.filter(is_backlog_activated=True,
|
||||||
|
is_kanban_activated=True)
|
||||||
|
.count())
|
||||||
|
stats["percent_with_backlog_and_kanban"] = stats["total_with_backlog_and_kanban"] * 100 / stats["total"]
|
||||||
|
|
||||||
|
return stats
|
||||||
|
|
||||||
|
|
||||||
def grt_total_user_stories():
|
def get_user_stories_stats():
|
||||||
model = apps.get_model("userstories", "UserStory")
|
model = apps.get_model("userstories", "UserStory")
|
||||||
queryset = model.objects.all()
|
queryset = model.objects.all()
|
||||||
return queryset.count()
|
stats = OrderedDict()
|
||||||
|
|
||||||
|
stats["total"] = queryset.count()
|
||||||
|
|
||||||
def get_total_issues():
|
today = timezone.now()
|
||||||
model = apps.get_model("issues", "Issue")
|
seven_days_ago = today-timedelta(days=7)
|
||||||
queryset = model.objects.all()
|
stats["average_last_seven_days"] = (queryset.filter(created_date__range=(seven_days_ago, today))
|
||||||
return queryset.count()
|
.count()) / 7
|
||||||
|
return stats
|
||||||
|
|
||||||
def get_total_users(only_active=True, no_system=True):
|
|
||||||
model = apps.get_model("users", "User")
|
|
||||||
queryset = model.objects.all()
|
|
||||||
if only_active:
|
|
||||||
queryset = queryset.filter(is_active=True)
|
|
||||||
if no_system:
|
|
||||||
queryset = queryset.filter(is_system=False)
|
|
||||||
return queryset.count()
|
|
||||||
|
|
Loading…
Reference in New Issue