Add /realm_activity report.

This report will eventually replace the per-realm report that is
now accessible through /activity.  In order not to disrupt Waseem,
I'm leaving the old reports around until we've polished the new
ones.

The old report does 24 different queries to get per-realm user data.
The new approach gets all the data at once, and it slices and dices
the data in Python to accomodate our slightly quirky data model.

On localhost, this is a typical query:

LOG:  duration: 5.668 ms  statement: SELECT "zerver_useractivity"."id", "zerver_useractivity"."user_profile_id", "zerver_useractivity"."client_id", "zerver_useractivity"."query", "zerver_useractivity"."count", "zerver_useractivity"."last_visit", "zerver_userprofile"."id", "zerver_userprofile"."email", "zerver_client"."id", "zerver_client"."name" FROM "zerver_useractivity" INNER JOIN "zerver_userprofile" ON ("zerver_useractivity"."user_profile_id" = "zerver_userprofile"."id") INNER JOIN "zerver_realm" ON ("zerver_userprofile"."realm_id" = "zerver_realm"."id") INNER JOIN "zerver_client" ON ("zerver_useractivity"."client_id" = "zerver_client"."id") WHERE "zerver_realm"."domain" = 'zulip.com'  ORDER BY "zerver_userprofile"."email" ASC, "zerver_useractivity"."last_visit" DESC

(imported from commit 0c71f4e32fe5a40f4496749dc29ad3463868d55e)
This commit is contained in:
Steve Howell 2013-11-01 09:44:29 -04:00
parent 3577ba7585
commit 95dc0894d8
2 changed files with 85 additions and 1 deletions

View File

@ -7,7 +7,7 @@ from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect, HttpResponseForbidden
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext, loader
from django.utils.timezone import now
from django.utils.timezone import now, utc
from django.utils.html import mark_safe
from django.utils.cache import patch_cache_control
from django.core.exceptions import ValidationError
@ -2392,6 +2392,22 @@ def get_activity(request, realm=REQ(default=None)):
context_instance=RequestContext(request)
)
def get_user_activity_records_for_realm(realm):
fields = [
'user_profile__email',
'query',
'client__name',
'count',
'last_visit',
]
records = UserActivity.objects.filter(
user_profile__realm__domain=realm
)
records = records.order_by("user_profile__email", "-last_visit")
records = records.select_related('user_profile', 'client').only(*fields)
return records
def get_user_activity_records_for_email(email):
fields = [
'query',
@ -2504,6 +2520,73 @@ def user_activity_summary_table(user_summary):
)
return content
def realm_user_summary_table(all_records):
user_records = {}
def by_email(record):
return record.user_profile.email
for email, records in itertools.groupby(all_records, by_email):
user_records[email] = get_user_activity_summary(list(records))
def get_last_visit(user_summary, k):
if k in user_summary:
return user_summary[k]['last_visit']
else:
return None
rows = []
for email, user_summary in user_records.items():
send_time = get_last_visit(user_summary, 'send')
pointer_time = get_last_visit(user_summary, 'pointer')
rows.append((email, send_time, pointer_time))
never = datetime.datetime(1970, 1, 1).replace(tzinfo=utc)
def by_send_time(row):
return row[1] or never
rows = sorted(rows, key=by_send_time, reverse=True)
cols = [
'email',
'send_time',
'pointer_time'
]
title = 'Summary'
data = dict(
rows=rows,
cols=cols,
title=title
)
content = loader.render_to_string(
'zerver/ad_hoc_query.html',
dict(data=data)
)
return content
@zulip_internal
def get_realm_activity(request, realm):
all_records = get_user_activity_records_for_realm(realm)
all_records = list(all_records)
data = []
content = realm_user_summary_table(all_records)
user_content = dict(content=content)
data += [('Summary', user_content)]
realm = None
title = realm
return render_to_response(
'zerver/activity.html',
dict(data=data, realm=realm, title=title),
context_instance=RequestContext(request)
)
@zulip_internal
def get_user_activity(request, email):
records = get_user_activity_records_for_email(email)

View File

@ -40,6 +40,7 @@ urlpatterns = patterns('',
url(r'^activity$', 'zerver.views.get_activity'),
url(r'^realm_activity/(?P<realm>[\S]+)/$', 'zerver.views.get_realm_activity'),
url(r'^user_activity/(?P<email>[\S]+)/$', 'zerver.views.get_user_activity'),
# Registration views, require a confirmation ID.