Commit adcb26cc authored by Christos Stavrakakis's avatar Christos Stavrakakis
Browse files

cyclades: Improvements to Astakos stats

Improve the exposed stats from the Astakos API and the way they are
displayed in 'stats-astakos' management command.
parent 48edca4a
......@@ -46,43 +46,41 @@ def get_public_stats():
def get_astakos_stats():
stats = {"datetime": datetime.datetime.now().strftime("%c")}
resources = Resource.objects.values_list("name", flat=True)
stats = {"datetime": datetime.datetime.now().strftime("%c"),
"providers": [],
"users": {},
"resources": {}}
users = AstakosUser.objects.all()
verified = users.filter(email_verified=True)
active = users.filter(is_active=True)
user_stats = {}
user_stats["total"] = {"total": users.count(),
"verified": verified.count(),
"active": active.count(),
"usage": {}}
for resource in resources:
usage = Holding.objects.filter(resource=resource)\
.aggregate(summ=Sum("usage_max"))
user_stats["total"]["usage"][resource] = int(usage["summ"])
for provider in settings.ASTAKOS_IM_MODULES:
# Add provider
stats["providers"].append(provider)
# Add stats about users
users = AstakosUser.objects.filter(auth_providers__module=provider)
verified = users.filter(email_verified=True)
active = users.filter(is_active=True)
user_stats[provider] = {"total": users.count(),
"verified": verified.count(),
"active": active.count(),
"usage": {}}
stats["users"][provider] = {"total": users.count(),
"verified": verified.count(),
"active": active.count()}
# Add stats about resources
users_uuids = users.values_list("uuid", flat=True)
for resource in resources:
usage = Holding.objects\
.filter(holder__in=users_uuids, resource=resource)\
.aggregate(summ=Sum("usage_max"))
user_stats[provider]["usage"][resource] = int(usage["summ"])
stats["users"] = user_stats
resources_stats = {}
for resource in Resource.objects.all():
info = Holding.objects\
.filter(holder__in=users_uuids,
resource=resource.name)\
.aggregate(usage_sum=Sum("usage_max"),
limit_sum=Sum("limit"))
resources_stats[resource.name] = {"used": info["usage_sum"],
"limit": info["limit_sum"],
"unit": resource.unit,
"description": resource.desc}
stats["resources"][provider] = resources_stats
return stats
......@@ -30,32 +30,70 @@
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from __future__ import division
import json
import string
#from optparse import make_option
from optparse import make_option
from snf_django.management.commands import SynnefoCommand, CommandError
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.im.models import Resource
from synnefo.util import units
from astakos.im.management.commands import _common as common
RESOURCES = Resource.objects.values_list("name", "desc")
HELP_MSG = """Get available statistics of Astakos Service
Display statistics for users and resources for each Authentication
Provider.
Users
------
* total: Number of users
* verified: Number of verified users
* active: Number of activated users
Resources
---------
For each resource the following information is displayed:
* used: Current allocated resources
* limit: Maximum allowed allocation
The available resources are the following:
* {resources}
""".format(resources="\n * ".join(["%s: %s" % (name, desc)
for name, desc in RESOURCES]))
class Command(SynnefoCommand):
help = "Get available statistics of Astakos service"
help = HELP_MSG
can_import_settings = True
option_list = SynnefoCommand.option_list + (
make_option('--unit-style',
default='auto',
help=("Specify display unit for resource values "
"(one of %s); defaults to auto") %
common.style_options),
)
def handle(self, *args, **options):
stats = statistics.get_astakos_stats()
unit_style = options["unit_style"]
common.check_style(unit_style)
output_format = options["output_format"]
if output_format == "json":
self.stdout.write(json.dumps(stats, indent=4) + "\n")
elif output_format == "pretty":
pretty_print_stats(stats, self.stdout)
pretty_print_stats(stats, unit_style, self.stdout)
else:
raise CommandError("Output format '%s' not supported." %
output_format)
......@@ -65,32 +103,60 @@ def columns_from_fields(fields, values):
return zip(map(string.lower, fields), [values.get(f, 0) for f in fields])
def pretty_print_stats(stats, stdout):
def pretty_print_stats(stats, unit_style, stdout):
newline = lambda: stdout.write("\n")
_datetime = stats.get("datetime")
stdout.write("datetime: %s\n" % _datetime)
newline()
users = stats.get("users", {})
all_providers = users.pop("total")
if all_providers is not None:
fields = ["total", "verified", "active"]
table = columns_from_fields(fields, all_providers)
usage = all_providers.get("usage", {})
for name, val in sorted(usage.items()):
table.append((name, val))
pprint_table(stdout, table, None,
title="Statistics for All Providers")
user_stats = stats.get("users", {})
table = []
headers = ["Provider Name", "Verified Users", "Active Users",
"Total Users"]
for provider, user_info in sorted(user_stats.items()):
table.append((provider, user_info["verified"], user_info["active"],
user_info["total"]))
pprint_table(stdout, table, headers,
title="Users")
newline()
resource_stats = stats.get("resources", {})
total_resources = {}
headers = ["Resource Name", "Used", "Limit", "Usage"]
for provider, resources in sorted(resource_stats.items()):
table = []
for resource_name, resource_info in sorted(resources.items()):
unit = resource_info["unit"]
used = resource_info["used"]
limit = resource_info["limit"]
usage = round(used / limit, 1)
table.append((resource_name,
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()
for provider_name, provider_info in sorted(users.items()):
fields = ["total", "verified", "active"]
table = columns_from_fields(fields, provider_info)
usage = provider_info.get("usage", {})
for name, val in sorted(usage.items()):
table.append((name, val))
pprint_table(stdout, table, None,
title="Statistics for Provider '%s'" % provider_name)
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,
units.show(used, unit, style=unit_style),
units.show(limit, unit, style=unit_style),
usage))
pprint_table(stdout, table, headers,
title="Resources for all Providers")
newline()
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