def api_calls_daily(request): today = datetime.date.today() a_year_ago = today - datetime.timedelta(days=365) ignore_internal_keys = parse_bool_param(request, "ignore_internal_keys", True) begin_date = parse_date_param(request, "begin_date", a_year_ago) end_date = parse_date_param(request, "end_date", today) if begin_date > end_date: return HttpResponseBadRequest("begin_date must be before end_date") cal = calendar.Calendar() daily_calls = dict( ( (dt, {"date": dt.strftime("%Y-%m-%d"), "calls": 0}) for y in range(begin_date.year, end_date.year + 1) for m in range(1, 13) for dt in cal.itermonthdates(y, m) if dt.month == m and dt >= begin_date and dt <= end_date ) ) qry = Report.objects.filter(date__range=(begin_date, end_date)) if ignore_internal_keys: qry = exclude_internal_key_reports(qry) daily_aggs = qry.values("date").annotate(calls=Sum("calls")) for daily in daily_aggs: dt = daily["date"] daily_calls[dt]["calls"] = daily["calls"] result = {"daily": daily_calls.values()} return HttpResponse(content=json.dumps(result), status=200, content_type="application/json")
def calls_to_api_daily(request, api_id=None, api_name=None): if api_id is None and api_name is None: return HttpResponseBadRequest("Must specify API id or name.") try: api = resolve_model(Api, [("id", api_id), ("name", api_name)]) except Api.DoesNotExist: return HttpResponseNotFound("The requested API was not found.") ignore_internal_keys = parse_bool_param(request, "ignore_internal_keys", True) end_date = parse_date_param(request, "end_date") begin_date = end_date - datetime.timedelta(days=7) qry = Report.objects.filter(api=api) if ignore_internal_keys: qry = exclude_internal_key_reports(qry) qry = qry.filter(date__gte=begin_date, date__lte=end_date) agg = qry.aggregate(calls=Sum("calls")) daily_aggs = qry.values("date").annotate(calls=Sum("calls")) result = {"api_id": api.id, "api_name": api.name, "calls": agg["calls"], "daily": []} for d in daily_aggs: result["daily"].append({"date": d["date"].strftime("%m-%d-%Y"), "calls": d["calls"]}) return HttpResponse(content=json.dumps(result), status=200, content_type="application/json")
def api_calls(request): begin_date = parse_date_param(request, "begin_date") end_date = parse_date_param(request, "end_date") ignore_deprecated = parse_bool_param(request, "ignore_deprecated", False) ignore_internal_keys = parse_bool_param(request, "ignore_internal_keys", True) qry = Report.objects if ignore_deprecated == True: qry = qry.filter(api__push_enabled=True) if ignore_internal_keys: qry = exclude_internal_key_reports(qry) if begin_date: qry = qry.filter(date__gte=begin_date) if end_date: qry = qry.filter(date__lte=end_date) agg_qry = qry.aggregate(calls=Sum("calls")) by_api_qry = qry.values("api__id", "api__name").annotate(calls=Sum("calls")) def obj_for_group(grp): return {"api_id": grp["api__id"], "api_name": grp["api__name"], "calls": grp["calls"] or 0} result = {"calls": agg_qry["calls"] or 0, "by_api": [obj_for_group(grp) for grp in by_api_qry]} if begin_date is not None: result["begin_date"] = begin_date.isoformat() if end_date is not None: result["end_date"] = end_date.isoformat() return HttpResponse(content=json.dumps(result), status=200, content_type="application/json")
def calls_to_api_monthly(request, api_id=None, api_name=None): if api_id is None and api_name is None: return HttpResponseBadRequest("Must specify API id or name.") try: api = resolve_model(Api, [("id", api_id), ("name", api_name)]) except Api.DoesNotExist: return HttpResponseNotFound("The requested API was not found.") ignore_internal_keys = parse_bool_param(request, "ignore_internal_keys", True) year = parse_int_param(request, "year") if year is None: return HttpResponseBadRequest("You must specify a year parameter.") qry = Report.objects.filter(api=api) if ignore_internal_keys: qry = exclude_internal_key_reports(qry) qry = qry.filter(date__gte=datetime.date(year, 1, 1), date__lte=datetime.date(year, 12, 31)) agg = qry.aggregate(calls=Sum("calls")) daily_aggs = qry.values("date").annotate(calls=Sum("calls")) monthly = dict(((m, {"month": m, "calls": 0}) for m in range(1, 13))) for daily in daily_aggs: month = daily["date"].month monthly[month]["calls"] += daily["calls"] result = {"api_id": api.id, "api_name": api.name, "calls": agg["calls"], "monthly": monthly.values()} return HttpResponse(content=json.dumps(result), status=200, content_type="application/json")
def calls_to_api(request, api_id=None, api_name=None): begin_date = parse_date_param(request, "begin_date") end_date = parse_date_param(request, "end_date") ignore_internal_keys = parse_bool_param(request, "ignore_internal_keys", True) if api_id is None and api_name is None: return HttpResponseBadRequest("Must specify API id or name.") try: api = resolve_model(Api, [("id", api_id), ("name", api_name)]) except Api.DoesNotExist: return HttpResponseNotFound("The requested API was not found.") qry = Report.objects.filter(api=api) if ignore_internal_keys: qry = exclude_internal_key_reports(qry) if begin_date: qry = qry.filter(date__gte=begin_date) if end_date: qry = qry.filter(date__lte=end_date) qry = qry.aggregate(calls=Sum("calls")) result = {"api_id": api.id, "api_name": api.name, "calls": qry["calls"]} if begin_date is not None: result["begin_date"] = begin_date.isoformat() if end_date is not None: result["end_date"] = end_date.isoformat() return HttpResponse(content=json.dumps(result), status=200, content_type="application/json")
def all_calls(request): ignore_deprecated = parse_bool_param(request, "ignore_deprecated", False) ignore_internal_keys = parse_bool_param(request, "ignore_internal_keys", True) if request.GET.has_key("year"): year = int(request.GET["year"]) qry = Report.objects.filter(date__gte=datetime.date(year, 1, 1), date__lte=datetime.date(year, 12, 31)) if ignore_deprecated == True: qry = qry.filter(api__push_enabled=True) if ignore_internal_keys: qry = exclude_internal_key_reports(qry) agg = qry.aggregate(calls=Sum("calls")) daily_aggs = qry.values("date").annotate(calls=Sum("calls")) monthly = dict(((m, {"month": m, "calls": 0}) for m in range(1, 13))) for daily in daily_aggs: month = daily["date"].month monthly[month]["calls"] += daily["calls"] result = {"calls": agg["calls"], "monthly": monthly.values(), "year": year} return HttpResponse(content=json.dumps(result), status=200, content_type="application/json") else: # yearly = Report.objects.raw("select id, extract(YEAR from reported_time) as year, SUM(calls) as total from locksmith_hub_report group by extract(YEAR from reported_time)") qry = Report.objects if ignore_deprecated == True: qry = qry.filter(api__push_enabled=True) if ignore_internal_keys: qry = exclude_internal_key_reports(qry) daily_aggs = qry.values("date").annotate(calls=Sum("calls")) yearly = {} for daily in daily_aggs: yr = daily["date"].year if yr not in yearly: yearly[yr] = {"year": yr, "calls": 0} yearly[yr]["calls"] += daily["calls"] result = {"earliest_year": min(yearly.keys()), "latest_year": max(yearly.keys()), "yearly": yearly.values()} return HttpResponse(content=json.dumps(result), status=200, content_type="application/json")
def _callers_in_period( begin_date, end_date, api=None, min_calls=100, ignore_internal_keys=True, ignore_autoactivated_keys=True ): calls_by_key = Report.objects.filter(date__gte=begin_date, date__lte=end_date) if ignore_internal_keys: calls_by_key = exclude_internal_key_reports(calls_by_key) if api is not None: calls_by_key = calls_by_key.filter(api=api) calls_by_key = calls_by_key.values("key__key", "key__email").annotate(calls=Sum("calls")).order_by("-calls") return [ {"key": c["key__key"], "email": c["key__email"], "calls": c["calls"]} for c in calls_by_key if c["calls"] >= min_calls ]
def calls_by_endpoint(request, api_id=None, api_name=None): if api_id is None and api_name is None: return HttpResponseBadRequest("Must specify API id or name.") try: api = resolve_model(Api, [("id", api_id), ("name", api_name)]) except Api.DoesNotExist: return HttpResponseNotFound("The requested API was not found.") ignore_internal_keys = parse_bool_param(request, "ignore_internal_keys", True) qry = Report.objects.filter(api=api) if ignore_internal_keys: qry = exclude_internal_key_reports(qry) endpoint_aggs = qry.values("endpoint").annotate(calls=Sum("calls")) result = {"api": {"id": api.id, "name": api.name}, "by_endpoint": list(endpoint_aggs)} return HttpResponse(content=json.dumps(result), status=200, content_type="application/json")
def _active_keys_by_month(ignore_internal_keys, monthly_minimum, cached=True): """ Returns a dict of (year, month) -> active_keys. The dict will contain a key for each month observed in the data. """ cache_key = "_active_keys_by_month({0!r},{1!r})[{date!s}]".format( ignore_internal_keys, monthly_minimum, date=datetime.date.today() ) if cached == True: result = cache.get(cache_key) if result is not None: return result keys_issued_period = _keys_issued_date_range() # We first do a (date, key) aggregation for the number of daily calls. # We would do monthly aggregation here if we were using a newer version # of django with ORM month accessors. This rolls up the per-method reports. calls_by_key = Report.objects if ignore_internal_keys: calls_by_key = exclude_internal_key_reports(calls_by_key) calls_by_key = calls_by_key.values("date", "key__key", "key__email").annotate(calls=Sum("calls")).order_by("-calls") # Aggregate the daily aggregates into monthly aggregates (still on a per-key # basis). This facilitates filtering keys by monthly usage. grp_by = lambda r: (r["date"].year, r["date"].month, r["key__key"]) def sum_calls(grp, records): return {"calls": sum([r["calls"] for r in records])} calls_per_key_monthly = generic_aggregation(calls_by_key, key=grp_by, agg_func=sum_calls) calls_per_key_monthly1 = ( (grp, agg) for (grp, agg) in calls_per_key_monthly.iteritems() if agg["calls"] >= monthly_minimum ) # Now aggregate the (year, month, key) into the size of (year, month) groups. grp_by_month = lambda ((year, month, key), agg): (year, month) active_keys_per_month = generic_aggregation( calls_per_key_monthly1, key=grp_by_month, agg_func=lambda grp, records: len(records) ) cache.set(cache_key, active_keys_per_month, timeout=(60 * 60 * 25)) return active_keys_per_month
def calls_to_api_yearly(request, api_id=None, api_name=None): if api_id is None and api_name is None: return HttpResponseBadRequest("Must specify API id or name.") try: api = resolve_model(Api, [("id", api_id), ("name", api_name)]) except Api.DoesNotExist: return HttpResponseNotFound("The requested API was not found.") ignore_internal_keys = parse_bool_param(request, "ignore_internal_keys", True) date_extents = _keys_issued_date_range() if date_extents["earliest"] and date_extents["latest"]: earliest_year = date_extents["earliest"].year latest_year = date_extents["latest"].year qry = Report.objects.filter(api=api) if ignore_internal_keys: qry = exclude_internal_key_reports(qry) agg = qry.aggregate(calls=Sum("calls")) daily_aggs = qry.values("date").annotate(calls=Sum("calls")) yearly = dict(((y, {"year": y, "calls": 0}) for y in range(earliest_year, latest_year + 1))) for daily in daily_aggs: yr = daily["date"].year yearly[yr]["calls"] += daily["calls"] else: earliest_year = None latest_year = None agg = {"calls": 0} yearly = {} result = { "api_id": api.id, "api_name": api.name, "earliest_year": earliest_year, "latest_year": latest_year, "calls": agg["calls"], "yearly": yearly.values(), } return HttpResponse(content=json.dumps(result), status=200, content_type="application/json")
def api_calls_monthly(request): ignore_internal_keys = parse_bool_param(request, "ignore_internal_keys", True) keys_issued_period = _keys_issued_date_range() earliest_month = (keys_issued_period["earliest"].year, keys_issued_period["earliest"].month) latest_month = (keys_issued_period["latest"].year, keys_issued_period["latest"].month) monthly = {} for (year, month) in cycle_generator(cycle=(1, 12), begin=earliest_month, end=latest_month): monthly[(year, month)] = {"year": year, "month": month, "calls": 0} qry = Report.objects if ignore_internal_keys: qry = exclude_internal_key_reports(qry) daily_aggs = qry.values("date").annotate(calls=Sum("calls")) for daily in daily_aggs: dt = daily["date"] month = (dt.year, dt.month) monthly[month]["calls"] += daily["calls"] result = {"monthly": monthly.values()} return HttpResponse(content=json.dumps(result), status=200, content_type="application/json")
def callers_of_api(request, api_id=None, api_name=None): if api_id is None and api_name is None: return HttpResponseBadRequest("Must specify API id or name.") try: api = resolve_model(Api, [("id", api_id), ("name", api_name)]) except Api.DoesNotExist: return HttpResponseNotFound("The requested API was not found.") ignore_internal_keys = parse_bool_param(request, "ignore_internal_keys", True) min_calls = parse_int_param(request, "min_calls") max_calls = parse_int_param(request, "max_calls") top = parse_int_param(request, "top") qry = api.reports if ignore_internal_keys: qry = exclude_internal_key_reports(qry) qry = qry.values("key__email", "key__key").exclude(key__status="S").annotate(calls=Sum("calls")) if min_calls is not None: qry = qry.filter(calls__gte=min_calls) if max_calls is not None: qry = qry.filter(calls__lte=max_calls) qry = qry.order_by("-calls") if top is not None: qry = qry[:top] result = { "callers": [ { "key": c["key__key"], "email": c["key__email"], "profile_url": reverse("key_analytics", args=(c["key__key"],)), "calls": c["calls"], } for c in qry ] } return HttpResponse(content=json.dumps(result), status=200, content_type="application/json")