Commit 0e0c746b authored by Christos Stavrakakis's avatar Christos Stavrakakis
Browse files

astakos: Improve exposed stats

Until now, Astakos exposed statistics per authentication provider.
However, since a user can have more than one authentication providers,
the administrator cannot sum the values per provider in order to compute
the total values. This commit fixes this issue by extending the Astakos
admin API to expose statistics for all users and resources.

Also, this commit updates the resources per provider response, to
include only the resources that are allocated to users that are using
only this provider.
parent 4b785406
# Copyright 2013 GRNET S.A. All rights reserved. # Copyright 2014 GRNET S.A. All rights reserved.
# #
# Redistribution and use in source and binary forms, with or # Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following # without modification, are permitted provided that the following
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
# or implied, of GRNET S.A. # or implied, of GRNET S.A.
import datetime import datetime
from django.conf import settings from django.conf import settings
from django.db.models import Sum from django.db.models import Sum, Count
from astakos.im.models import AstakosUser, Resource from astakos.im.models import AstakosUser, Resource
from astakos.quotaholder_app.models import Holding from astakos.quotaholder_app.models import Holding
...@@ -55,6 +55,21 @@ def get_astakos_stats(): ...@@ -55,6 +55,21 @@ def get_astakos_stats():
verified = users.filter(email_verified=True) verified = users.filter(email_verified=True)
active = users.filter(is_active=True) active = users.filter(is_active=True)
stats["users"]["all"] = {"total": users.count(),
"verified": verified.count(),
"active": active.count()}
resources_stats = {}
for resource in Resource.objects.all():
info = Holding.objects\
.filter(resource=resource.name)\
.aggregate(usage_sum=Sum("usage_max"),
limit_sum=Sum("limit"))
resources_stats[resource.name] = {"used": info["usage_sum"] or 0,
"allocated": info["limit_sum"] or 0,
"unit": resource.unit,
"description": resource.desc}
stats["resources"]["all"] = resources_stats
for provider in settings.ASTAKOS_IM_MODULES: for provider in settings.ASTAKOS_IM_MODULES:
# Add provider # Add provider
stats["providers"].append(provider) stats["providers"].append(provider)
...@@ -63,13 +78,19 @@ def get_astakos_stats(): ...@@ -63,13 +78,19 @@ def get_astakos_stats():
users = AstakosUser.objects.filter(auth_providers__module=provider) users = AstakosUser.objects.filter(auth_providers__module=provider)
verified = users.filter(email_verified=True) verified = users.filter(email_verified=True)
active = users.filter(is_active=True) active = users.filter(is_active=True)
exclusive = AstakosUser.objects.filter(email_verified=True,
is_active=True)\
.annotate(num_providers=Count("auth_providers"))\
.filter(auth_providers__module=provider)\
.filter(num_providers=1)
stats["users"][provider] = {"total": users.count(), stats["users"][provider] = {"total": users.count(),
"verified": verified.count(), "verified": verified.count(),
"active": active.count()} "active": active.count(),
"exclusive": exclusive.count()}
# Add stats about resources # Add stats about resources
users_uuids = users.values_list("uuid", flat=True) users_uuids = exclusive.values_list("uuid", flat=True)
resources_stats = {} resources_stats = {}
for resource in Resource.objects.all(): for resource in Resource.objects.all():
info = Holding.objects\ info = Holding.objects\
...@@ -77,10 +98,16 @@ def get_astakos_stats(): ...@@ -77,10 +98,16 @@ def get_astakos_stats():
resource=resource.name)\ resource=resource.name)\
.aggregate(usage_sum=Sum("usage_max"), .aggregate(usage_sum=Sum("usage_max"),
limit_sum=Sum("limit")) limit_sum=Sum("limit"))
resources_stats[resource.name] = {"used": info["usage_sum"], resources_stats[resource.name] = {
"limit": info["limit_sum"], "used": info["usage_sum"] or 0,
"unit": resource.unit, "allocated": info["limit_sum"] or 0,
"description": resource.desc} "unit": resource.unit,
"description": resource.desc}
stats["resources"][provider] = resources_stats stats["resources"][provider] = resources_stats
return stats return stats
if __name__ == "__main__":
import json
print json.dumps(get_astakos_stats())
...@@ -37,8 +37,6 @@ from optparse import make_option ...@@ -37,8 +37,6 @@ from optparse import make_option
from snf_django.management.commands import SynnefoCommand, CommandError from snf_django.management.commands import SynnefoCommand, CommandError
from snf_django.management.utils import pprint_table from snf_django.management.utils import pprint_table
#from astakos.im.models import AstakosUser, Resource
#from astakos.quotaholder_app.models import Holding
from astakos.admin import stats as statistics from astakos.admin import stats as statistics
from astakos.im.models import Resource from astakos.im.models import Resource
from synnefo.util import units from synnefo.util import units
...@@ -46,7 +44,7 @@ from astakos.im.management.commands import _common as common ...@@ -46,7 +44,7 @@ from astakos.im.management.commands import _common as common
RESOURCES = Resource.objects.values_list("name", "desc") RESOURCES = Resource.objects.values_list("name", "desc")
HELP_MSG = """Get available statistics of Astakos Service HELP_MSG = """Get available statistics of Astakos Service.
Display statistics for users and resources for each Authentication Display statistics for users and resources for each Authentication
Provider. Provider.
...@@ -56,14 +54,16 @@ Users ...@@ -56,14 +54,16 @@ Users
* total: Number of users * total: Number of users
* verified: Number of verified users * verified: Number of verified users
* active: Number of activated users * active: Number of activated users
* exclusive: Number of activated users that are using *only* this
authentication provider
Resources Resources
--------- ---------
For each resource the following information is displayed: For each resource the following information is displayed:
* used: Current allocated resources * used: Currently used allocated resources
* limit: Maximum allowed allocation * allocated: Currently allocated resources
* usage: used/allocated
The available resources are the following: The available resources are the following:
...@@ -112,51 +112,43 @@ def pretty_print_stats(stats, unit_style, stdout): ...@@ -112,51 +112,43 @@ def pretty_print_stats(stats, unit_style, stdout):
user_stats = stats.get("users", {}) user_stats = stats.get("users", {})
table = [] table = []
headers = ["Provider Name", "Verified Users", "Active Users", headers = ["Provider", "Total Users", "Verified Users",
"Total Users"] "Active Users", "Exclusive Users per Provider"]
for provider, user_info in sorted(user_stats.items()): for provider, user_info in sorted(user_stats.items()):
table.append((provider, user_info["verified"], user_info["active"], table.append((provider, user_info["total"], user_info["verified"],
user_info["total"])) user_info["active"], user_info.get("exclusive", "-")))
pprint_table(stdout, table, headers, pprint_table(stdout, table, headers, separator=" | ", title="Users")
title="Users")
newline() newline()
resource_stats = stats.get("resources", {}) resource_stats = stats.get("resources", {})
total_resources = {} total_resources = resource_stats.pop("all", {})
headers = ["Resource Name", "Used", "Limit", "Usage"] headers = ["Resource Name", "Used", "Allocated", "Usage"]
table = []
for resource_name, resource_info in sorted(total_resources.items()):
unit = resource_info["unit"]
used = resource_info["used"]
allocated = resource_info["allocated"]
usage = "%.2f%%" % (100 * (used / allocated))\
if allocated != 0 else "-"
table.append((resource_name,
units.show(used, unit, style=unit_style),
units.show(allocated, unit, style=unit_style),
usage))
pprint_table(stdout, table, headers, separator=" | ",
title="Resources for all providers")
newline()
for provider, resources in sorted(resource_stats.items()): for provider, resources in sorted(resource_stats.items()):
table = [] table = []
for resource_name, resource_info in sorted(resources.items()): for resource_name, resource_info in sorted(resources.items()):
unit = resource_info["unit"] unit = resource_info["unit"]
used = resource_info["used"] used = resource_info["used"]
limit = resource_info["limit"] allocated = resource_info["allocated"]
usage = round(used / limit, 1) usage = "%.2f%%" % (100 * (used / allocated)) \
table.append((resource_name, if allocated != 0 else "-"
units.show(used, unit, style=unit_style),
units.show(limit, unit, style=unit_style),
usage))
# Also count them for total
total_resources.setdefault(resource_name, {})
total_resources[resource_name].setdefault("used", 0)
total_resources[resource_name].setdefault("limit", 0)
total_resources[resource_name]["used"] += used
total_resources[resource_name]["limit"] += limit
total_resources[resource_name]["unit"] = unit
pprint_table(stdout, table, headers,
title="Resources for Provider '%s'" % provider)
newline()
if len(resource_stats) > 1:
table = []
for resource_name, resource_info in sorted(total_resources.items()):
unit = resource_info["unit"]
used = resource_info["used"]
limit = resource_info["limit"]
usage = round(used / limit, 1)
table.append((resource_name, table.append((resource_name,
units.show(used, unit, style=unit_style), units.show(used, unit, style=unit_style),
units.show(limit, unit, style=unit_style), units.show(allocated, unit, style=unit_style),
usage)) usage))
pprint_table(stdout, table, headers, pprint_table(stdout, table, headers, separator=" | ",
title="Resources for all Providers") title=("Resources for users with only the '%s' provider"
newline() % provider))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment