Merge pull request #352 from OpenBankProject/develop

release update
This commit is contained in:
tesobe-daniel 2023-12-14 13:03:12 +01:00 committed by GitHub
commit a9497f2141
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 20394 additions and 563 deletions

View File

@ -155,7 +155,7 @@ def apicollections_update(request):
'is_sharable': True if request.POST.get('api_collection_is_sharable').strip().lower() == "true" else False,
'description': request.POST.get('api_collection_description').strip()
}
result = api.put(urlpath, payload=payload, version=settings.API_ROOT['v510'])
result = api.put(urlpath, payload=payload, version=settings.API_VERSION['v510'])
return result

View File

@ -117,7 +117,7 @@ TEMPLATES = [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'base.context_processors.api_root',
'base.context_processors.api_version_processor',
'base.context_processors.api_username',
'base.context_processors.api_user_id',
'base.context_processors.api_tester_url',
@ -251,6 +251,9 @@ API_DATE_FORMAT_WITH_SECONDS = '%Y-%m-%dT%H:%M:%SZ'
#Map Java: yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
API_DATE_FORMAT_WITH_MILLISECONDS = '%Y-%m-%dT%H:%M:%S.%fZ'
# the API_Manager the web form datetime format, eg: 2023-11-28 10:49:27
API_DATE_FORMAT_WITH_DAY_DATE_TIME = '%Y-%m-%d %H:%M:%S'
# the API_Manager the web form date format, eg: 2020-10-11
API_DATE_FORMAT_WITH_DAY = '%Y-%m-%d'
API_FIELD_TIME_FORMAT = '%H-%M-%S'
@ -319,8 +322,6 @@ CALLBACK_BASE_URL = ""
# Global
UNDEFINED = "<undefined>"
API_ROOT_KEY = "v500"
# Local settings can replace any value ABOVE
try:
from apimanager.local_settings import * # noqa
@ -331,8 +332,8 @@ except ImportError:
OBPv500 = API_HOST + '/obp/v5.0.0'
OBPv510 = API_HOST + '/obp/v5.1.0'
# Settings here might use parts overwritten in local settings
API_ROOT = {
# API Versions
API_VERSION = {
"v500": OBPv500,
"v510": OBPv510
}
@ -354,8 +355,8 @@ if not OAUTH_CONSUMER_SECRET:
CSP_IMG_SRC = ("'self' data:", 'https://static.openbankproject.com')
CSP_STYLE_SRC = ("'self' 'sha256-z2a+NIknPDE7NIEqE1lfrnG39eWOhJXWsXHYGGNb5oU=' 'sha256-Dn0vMZLidJplZ4cSlBMg/F5aa7Vol9dBMHzBF4fGEtk=' 'sha256-sA0hymKbXmMTpnYi15KmDw4u6uRdLXqHyoYIaORFtjU=' 'sha256-jUuiwf3ITuJc/jfynxWHLwTZifHIlhddD8NPmmVBztk=' 'sha256-RqzjtXRBqP4i+ruV3IRuHFq6eGIACITqGbu05VSVXsI='", 'https://cdnjs.cloudflare.com', )
CSP_SCRIPT_SRC = ("'self' 'unsafe-eval' 'sha256-4Hr8ttnXaUA4A6o0hGi3NUGNP2Is3Ep0W+rvm+W7BAk=' 'sha256-GgQWQ4Ejk4g9XpAZJ4YxIgZDgp7CdQCmqjMOMh9hD2g=' 'sha256-05NIAwVBHkAzKcXTfkYqTnBPtkpX+AmQvM/raql3qo0='", 'http://code.jquery.com', 'https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/', 'https://cdnjs.cloudflare.com')
CSP_SCRIPT_SRC = ("'self' 'unsafe-eval' 'sha256-CAykt4V7LQN6lEkjV8hZQx0GV6LTZZGUvQDqamuUq2Q=' 'sha256-4Hr8ttnXaUA4A6o0hGi3NUGNP2Is3Ep0W+rvm+W7BAk=' 'sha256-GgQWQ4Ejk4g9XpAZJ4YxIgZDgp7CdQCmqjMOMh9hD2g=' 'sha256-05NIAwVBHkAzKcXTfkYqTnBPtkpX+AmQvM/raql3qo0='", 'http://code.jquery.com', 'https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/', 'https://cdnjs.cloudflare.com')
CSP_FONT_SRC = ("'self'", 'http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/fonts/')
CSP_FRAME_ANCESTORS = ("'self'")
CSP_FORM_ACTION = ("'self'")
CSP_CONNECT_SRC = (API_HOST)
CSP_CONNECT_SRC = ("'self'", API_HOST)

View File

@ -204,7 +204,7 @@ class UpdateAtmsView(LoginRequiredMixin, FormView):
template_name = "atms/update.html"
success_url = '/atms/list'
form_class = CreateAtmForm
v510 = settings.API_ROOT['v510']
v510 = settings.API_VERSION['v510']
def dispatch(self, request, *args, **kwargs):
self.api = API(request.session.get('obp'))
@ -410,7 +410,7 @@ def atm_attribute_save(request):
'value': request.POST.get('value').strip(),
'is_active': True
}
result = api.post(urlpath_save, payload = payload, version=settings.API_ROOT['v510'])
result = api.post(urlpath_save, payload = payload, version=settings.API_VERSION['v510'])
return result
@ -428,7 +428,7 @@ def atm_attribute_update(request):
'value': request.POST.get('value').strip(),
'is_active': True
}
result = api.put(urlpath_update, payload=payload, version=settings.API_ROOT['v510'])
result = api.put(urlpath_update, payload=payload, version=settings.API_VERSION['v510'])
return result
@ -441,7 +441,7 @@ def atm_attribute_delete(request):
api = API(request.session.get('obp'))
urlpath_delete = '/banks/{}/atms/{}/attributes/{}'.format(bank_id, atm_id, atm_attribute_id)
result = api.delete(urlpath_delete, version=settings.API_ROOT['v510'])
result = api.delete(urlpath_delete, version=settings.API_VERSION['v510'])
return result

View File

@ -81,7 +81,7 @@ class UpdateBanksView(LoginRequiredMixin, FormView):
template_name = "banks/update.html"
form_class = CreateBankForm
success_url = '/banks/list'
v510 = settings.API_ROOT['v510']
v510 = settings.API_VERSION['v510']
def dispatch(self, request, *args, **kwargs):
self.api = API(request.session.get('obp'))
@ -111,8 +111,6 @@ class UpdateBanksView(LoginRequiredMixin, FormView):
fields['bank_routings_scheme'].initial = result['bank_routings'][0]["scheme"]
fields['bank_routings_address'].initial = result['bank_routings'][0]["address"]
except Exception as err:
if DEBUG:
raise(err)
messages.error(self.request, "Unknown Error {}".format(err))
return form
@ -138,13 +136,9 @@ class UpdateBanksView(LoginRequiredMixin, FormView):
messages.error(self.request, result['message'])
return super(UpdateBanksView, self).form_invalid(form)
except APIError as err:
if DEBUG:
raise(err)
messages.error(self.request, err)
return super(UpdateBanksView, self).form_invalid(form)
except Exception as e:
if DEBUG:
raise(err)
messages.error(self.request, e)
return super(UpdateBanksView, self).form_invalid(form)
msg = 'Bank {} has been updated successfully!'.format( # noqa
@ -183,7 +177,7 @@ def bank_attribute_save(request):
'value': request.POST.get('value').strip(),
'is_active': True
}
result = api.post(urlpath_save, payload = payload, version=settings.API_ROOT['v510'])
result = api.post(urlpath_save, payload = payload, version=settings.API_VERSION['v510'])
return result
@ -201,7 +195,7 @@ def bank_attribute_update(request):
'value': request.POST.get('value').strip(),
'is_active': True
}
result = api.put(urlpath_update, payload=payload, version=settings.API_ROOT['v510'])
result = api.put(urlpath_update, payload=payload, version=settings.API_VERSION['v510'])
return result
@ -212,6 +206,6 @@ def bank_attribute_delete(request):
bank_attribute_id = request.POST.get('bank_attribute_id').strip()
api = API(request.session.get('obp'))
urlpath_delete = '/banks/{}/attributes/{}'.format(bank_id, bank_attribute_id)
result = api.delete(urlpath_delete, version=settings.API_ROOT['v510'])
result = api.delete(urlpath_delete, version=settings.API_VERSION['v510'])
return result

View File

@ -11,9 +11,9 @@ from django.core.cache import cache
USER_CURRENT = "/users/current"
def api_root(request):
"""Returns the configured API_ROOT"""
return {'API_ROOT': settings.API_ROOT['v500']}
def api_version_processor(request):
"""Returns the configured API_VERSION"""
return {'API_VERSION': settings.API_VERSION['v500']}
def portal_page(request):

1314
apimanager/base/static/css/jquery-ui.css vendored Normal file

File diff suppressed because it is too large Load Diff

18706
apimanager/base/static/js/jquery-ui.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,7 @@
<link href="{% static 'css/base.css' %}" rel="stylesheet">
<link href="{% static 'css/jsoneditor.min.css' %}" rel="stylesheet">
<link href="{% static 'css/obpjsoneditor.css' %}" rel="stylesheet">
<link href="{% static 'css/jquery-ui.css' %}" rel="stylesheet">
{% block extracss %}{% endblock extracss %}
</head>
@ -47,7 +48,7 @@
<li {% ifequal request.path my_user_invitation %} class="active" {% endifequal %}><a href="{{ my_user_invitation }}">{% trans "Invite User" %}</a></li>
</ul>
</li>
{% url "api-metrics" as api_metrics_url %} {% url "connector-metrics" as connector_metrics_url %} {% url "metrics-summary" as metrics_summary_url %}
{% url "api-metrics" as api_metrics_url %} {% url "connector-metrics" as connector_metrics_url %} {% url "weekly-summary" as metrics_summary_url %}
<li class="dropdown{% if api_metrics_url in request.path or connector_metrics_url in request.path or metrics_summary_url in request.path %} active{% endif %}">
<a href="#" data-toggle="dropdown" class="dropdown-toggle">{% trans "Metrics" %}</a>
<ul class="dropdown-menu">
@ -148,6 +149,7 @@
<script type="text/javascript" src="{% static 'js/jquery.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/bootstrap.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/jquery.tablesorter.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/jquery-ui.js' %}"></script>
<script src="{% static 'js/base.js' %}"></script>
<script type="text/javascript" src="{% static 'js/jsoneditor.min.js' %}"></script>
<script type="module" defer src="{% static 'js/inactivity.js' %}"></script>

View File

@ -4,7 +4,8 @@ Base utilities
"""
from django.contrib.humanize.templatetags.humanize import naturaltime
from datetime import datetime, timedelta
from apimanager.settings import API_DATE_FORMAT_WITH_MILLISECONDS, API_DATE_FORMAT_WITH_DAY
from apimanager.settings import API_DATE_FORMAT_WITH_MILLISECONDS, API_DATE_FORMAT_WITH_DAY, \
API_DATE_FORMAT_WITH_DAY_DATE_TIME
from base import context_processors
from django.contrib import messages
import functools
@ -61,7 +62,7 @@ def convert_form_date_to_obpapi_datetime_format(form_to_date_string):
"""
convert the String 2020-10-22 to 2020-10-22T00:00:00.000000Z
"""
return datetime.strptime(form_to_date_string, API_DATE_FORMAT_WITH_DAY).strftime(API_DATE_FORMAT_WITH_MILLISECONDS)
return datetime.strptime(form_to_date_string, API_DATE_FORMAT_WITH_DAY_DATE_TIME).strftime(API_DATE_FORMAT_WITH_MILLISECONDS)
def return_to_days_ago(date, days):
"""

View File

@ -4,7 +4,7 @@ Views for base app
"""
from django.contrib import messages
from django.conf import settings
from django.views.generic import TemplateView
from django.views.generic import TemplateView, View
from django.shortcuts import render
from obp.forms import DirectLoginForm, GatewayLoginForm
from obp.api import API, APIError
@ -21,18 +21,6 @@ def get_banks(request):
except APIError as err:
messages.error(request, err)
return []
def get_consumers(request):
api = API(request.session.get('obp'))
try:
urlpath = '/management/consumers'
result = api.get(urlpath)
if 'consumers' in result:
return [consumer['consumer_id'] for consumer in sorted(result['consumers'], key=lambda d: d['consumer_id'])]
else:
return []
except APIError as err:
messages.error(self.request, err)
return []
def get_api_versions(request):
api = API(request.session.get('obp'))
@ -44,7 +32,7 @@ def get_api_versions(request):
else:
return []
except APIError as err:
messages.error(self.request, err)
messages.error(request, err)
return []
class HomeView(TemplateView):

View File

@ -1075,12 +1075,12 @@ msgstr "Medianzeit von der Verbraucherregistrierung bis zum ersten API-Aufruf"
#: metrics/templates/metrics/quarterly_summary.html:108
#: metrics/templates/metrics/weekly_summary.html:106
#: metrics/templates/metrics/yearly_summary.html:106
msgid "Apps with distinct names"
msgid "New apps with distinct names"
msgstr "Apps mit eindeutigen Namen"
#: metrics/templates/metrics/custom_summary.html:115
#: metrics/templates/metrics/monthly_summary.html:118
msgid "Distinct developer email addresses"
msgid "New distinct developer email addresses"
msgstr "Unterschiedliche Entwickler-E-Mail-Adressen"
#: metrics/templates/metrics/custom_summary.html:120
@ -1090,8 +1090,8 @@ msgstr "Unterschiedliche Entwickler-E-Mail-Adressen"
#: metrics/templates/metrics/quarterly_summary.html:117
#: metrics/templates/metrics/weekly_summary.html:115
#: metrics/templates/metrics/yearly_summary.html:115
msgid "Active Apps (at least one API call in the period)"
msgstr "Aktive Apps (mindestens ein API-Aufruf im Zeitraum)"
msgid "Top 100 Active Apps (at least one API call in the period)"
msgstr "Top 100 Aktive Apps (mindestens ein API-Aufruf im Zeitraum)"
#: metrics/templates/metrics/custom_summary.html:124
#: metrics/templates/metrics/daily_summary.html:118
@ -1192,7 +1192,7 @@ msgstr "Durchschnittliche Anzahl der Anrufe pro Stunde"
#: metrics/templates/metrics/hourly_summary.html:110
#: metrics/templates/metrics/quarterly_summary.html:112
#: metrics/templates/metrics/weekly_summary.html:110
msgid "Apps with distinct developer email addresses"
msgid "Apps with New distinct developer email addresses"
msgstr "Apps mit unterschiedlichen Entwickler-E-Mail-Adressen"
#: metrics/templates/metrics/hourly_summary.html:20

View File

@ -1412,12 +1412,12 @@ msgstr ""
#: metrics/templates/metrics/quarterly_summary.html:115
#: metrics/templates/metrics/weekly_summary.html:111
#: metrics/templates/metrics/yearly_summary.html:113
msgid "Apps with distinct names"
msgid "New apps with distinct names"
msgstr "Aplicaciones con nombres distintos"
#: metrics/templates/metrics/custom_summary.html:113
#: metrics/templates/metrics/monthly_summary.html:110
msgid "Distinct developer email addresses"
msgid "New distinct developer email addresses"
msgstr "Distintas direcciones de correo electrónico para desarrolladores"
#: metrics/templates/metrics/custom_summary.html:118
@ -1427,8 +1427,8 @@ msgstr "Distintas direcciones de correo electrónico para desarrolladores"
#: metrics/templates/metrics/quarterly_summary.html:124
#: metrics/templates/metrics/weekly_summary.html:120
#: metrics/templates/metrics/yearly_summary.html:122
msgid "Active Apps (at least one API call in the period)"
msgstr "Aplicaciones activas (al menos una llamada API en el periodo)"
msgid "Top 100 Active Apps (at least one API call in the period)"
msgstr "Top 100 Aplicaciones activas (al menos una llamada API en el periodo)"
#: metrics/templates/metrics/custom_summary.html:122
#: metrics/templates/metrics/daily_summary.html:125
@ -1502,7 +1502,7 @@ msgstr "Número promedio de llamadas"
#: metrics/templates/metrics/hourly_summary.html:117
#: metrics/templates/metrics/quarterly_summary.html:119
#: metrics/templates/metrics/weekly_summary.html:115
msgid "Apps with distinct developer email addresses"
msgid "Apps with New distinct developer email addresses"
msgstr ""
"Aplicaciones con distintas direcciones de correo electrónico de los "
"desarrolladores"

View File

@ -1054,12 +1054,12 @@ msgstr "MYMEMORY WARNING: YOU USED ALL AVAILABLE FREE TRANSLATIONS FOR TODAY. NE
#: metrics/templates/metrics/quarterly_summary.html:108
#: metrics/templates/metrics/weekly_summary.html:106
#: metrics/templates/metrics/yearly_summary.html:106
msgid "Apps with distinct names"
msgid "New apps with distinct names"
msgstr "MYMEMORY WARNING: YOU USED ALL AVAILABLE FREE TRANSLATIONS FOR TODAY. NEXT AVAILABLE IN 00 HOURS 04 MINUTES 16 SECONDS VISIT HTTPS://MYMEMORY.TRANSLATED.NET/DOC/USAGELIMITS.PHP TO TRANSLATE MORE"
#: metrics/templates/metrics/custom_summary.html:115
#: metrics/templates/metrics/monthly_summary.html:118
msgid "Distinct developer email addresses"
msgid "New distinct developer email addresses"
msgstr "MYMEMORY WARNING: YOU USED ALL AVAILABLE FREE TRANSLATIONS FOR TODAY. NEXT AVAILABLE IN 00 HOURS 04 MINUTES 16 SECONDS VISIT HTTPS://MYMEMORY.TRANSLATED.NET/DOC/USAGELIMITS.PHP TO TRANSLATE MORE"
#: metrics/templates/metrics/custom_summary.html:120
@ -1069,7 +1069,7 @@ msgstr "MYMEMORY WARNING: YOU USED ALL AVAILABLE FREE TRANSLATIONS FOR TODAY. NE
#: metrics/templates/metrics/quarterly_summary.html:117
#: metrics/templates/metrics/weekly_summary.html:115
#: metrics/templates/metrics/yearly_summary.html:115
msgid "Active Apps (at least one API call in the period)"
msgid "Top 100 Active Apps (at least one API call in the period)"
msgstr "MYMEMORY WARNING: YOU USED ALL AVAILABLE FREE TRANSLATIONS FOR TODAY. NEXT AVAILABLE IN 00 HOURS 04 MINUTES 14 SECONDS VISIT HTTPS://MYMEMORY.TRANSLATED.NET/DOC/USAGELIMITS.PHP TO TRANSLATE MORE"
#: metrics/templates/metrics/custom_summary.html:124
@ -1171,7 +1171,7 @@ msgstr "MYMEMORY WARNING: YOU USED ALL AVAILABLE FREE TRANSLATIONS FOR TODAY. NE
#: metrics/templates/metrics/hourly_summary.html:110
#: metrics/templates/metrics/quarterly_summary.html:112
#: metrics/templates/metrics/weekly_summary.html:110
msgid "Apps with distinct developer email addresses"
msgid "Apps with New distinct developer email addresses"
msgstr "MYMEMORY WARNING: YOU USED ALL AVAILABLE FREE TRANSLATIONS FOR TODAY. NEXT AVAILABLE IN 00 HOURS 04 MINUTES 02 SECONDS VISIT HTTPS://MYMEMORY.TRANSLATED.NET/DOC/USAGELIMITS.PHP TO TRANSLATE MORE"
#: metrics/templates/metrics/hourly_summary.html:20

View File

@ -50,7 +50,7 @@ class IndexView(LoginRequiredMixin, FormView):
else:
method_routings[i]['parameters'] = json.dumps(method_routings[i]['parameters'], sort_keys=False)
if(str(settings.API_ROOT).find("127.0.0.1") == -1):
if(str(settings.API_VERSION).find("127.0.0.1") == -1):
method_Swagger_Url = '{}/message-docs?connector=stored_procedure_vDec2019#'.format(settings.API_HOST.replace(".openbankproject.", "-explorer.openbankproject."))
else:
method_Swagger_Url = "http://127.0.0.1:8082/message-docs?connector=stored_procedure_vDec2019#"

View File

@ -10,54 +10,32 @@ from django.forms.widgets import SelectMultiple, CheckboxInput, CheckboxSelectMu
from datetime import datetime, timedelta
from django.utils.translation import ugettext_lazy as _
from bootstrap_datepicker_plus import DatePickerInput, DateTimePickerInput
from apimanager.settings import API_DATE_FORMAT_WITH_DAY, API_DATE_FORMAT_WITH_MILLISECONDS
from apimanager.settings import API_DATE_FORMAT_WITH_DAY, API_FIELD_TIME_FORMAT
from bootstrap_datepicker_plus import DateTimePickerInput
from apimanager.settings import API_DATE_FORMAT_WITH_DAY_DATE_TIME
API_DATE_FORMAT_WITH_MILLISECONDS_PLACEHOLDER = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
FORM_CONTROL = 'form-control'
FROM_DATE = 'From Date'
TO_DATE = 'To Date'
FROM_DATE = 'From Date Time'
TO_DATE = 'To Date Time'
PLACEHOLDER = "2013-01-22"
PLACEHOLDER1 = "23:59:59"
PLACEHOLDER1 = "2022-01-01 12:30:45"
PLACEHOLDER2 = "00:00:00"
class MetricsForm(forms.Form):
from_date = forms.DateTimeField(
label=_(FROM_DATE),
widget=DatePickerInput(format=API_DATE_FORMAT_WITH_DAY),
widget=DateTimePickerInput(format=API_DATE_FORMAT_WITH_DAY_DATE_TIME),
required=True,
initial=(datetime.now() - timedelta(1)).strftime(API_DATE_FORMAT_WITH_DAY),
)
from_time = forms.TimeField(
label=_('From Time'),
widget=forms.TimeInput(
format='%H:%M:%S',
attrs={
'placeholder': PLACEHOLDER2,
'class': 'form-control',
}
),
required=False,
initial=(datetime.now() - timedelta(1)).strftime(API_DATE_FORMAT_WITH_DAY_DATE_TIME),
)
to_date = forms.DateTimeField(
label=_(TO_DATE),
widget=DatePickerInput(format=API_DATE_FORMAT_WITH_DAY),
widget=DateTimePickerInput(format=API_DATE_FORMAT_WITH_DAY_DATE_TIME),
required=True,
initial=(datetime.now() - timedelta()).strftime(API_DATE_FORMAT_WITH_DAY),
)
to_date_time = forms.TimeField(
label=_('To Time'),
widget=forms.TimeInput(
format='%H:%M:%S',
attrs={
'placeholder': PLACEHOLDER1,
'class': 'form-control',
}
),
required=False,
initial=(datetime.now() - timedelta()).strftime(API_DATE_FORMAT_WITH_DAY_DATE_TIME),
)
limit = forms.IntegerField(
label=_('Limit'),
widget=forms.NumberInput(
@ -65,7 +43,7 @@ class MetricsForm(forms.Form):
'class': FORM_CONTROL,
}
),
initial=1000,
initial=5,
required=False,
)
offset = forms.IntegerField(
@ -99,7 +77,7 @@ class APIMetricsForm(MetricsForm):
consumer_id = forms.ChoiceField(
label=_('Consumer ID'),
widget=forms.Select(
widget=forms.TextInput(
attrs={
'class': FORM_CONTROL,
}
@ -179,9 +157,9 @@ class ConnectorMetricsForm(MetricsForm):
# override from_date until API returns values without given date
from_date = forms.DateTimeField(
label=_(FROM_DATE),
widget=DatePickerInput(format=API_DATE_FORMAT_WITH_DAY),
widget=DateTimePickerInput(format=API_DATE_FORMAT_WITH_DAY_DATE_TIME),
required=True,
initial=(datetime.now() - timedelta(6)).strftime(API_DATE_FORMAT_WITH_DAY),
initial=(datetime.now() - timedelta(6)).strftime(API_DATE_FORMAT_WITH_DAY_DATE_TIME),
)
connector_name = forms.CharField(
label=_('Connector Name'),
@ -213,39 +191,17 @@ class ConnectorMetricsForm(MetricsForm):
class CustomSummaryForm(forms.Form):
to_date = forms.DateField(
label=_("Date"),
widget=DatePickerInput(format=API_DATE_FORMAT_WITH_DAY),
to_date = forms.DateTimeField(
label=_(TO_DATE),
widget=DateTimePickerInput(format=API_DATE_FORMAT_WITH_DAY_DATE_TIME),
required=True,
initial=str(datetime.now().strftime(API_DATE_FORMAT_WITH_DAY)),
initial=(datetime.now()).strftime(API_DATE_FORMAT_WITH_DAY_DATE_TIME),
)
to_date_time = forms.TimeField(
label=_('Time'),
widget=forms.TimeInput(
format='%H:%M:%S',
attrs={
'placeholder': PLACEHOLDER2,
'class': 'form-control',
}
),
required=False,
)
from_date_custom = forms.DateField(
from_date_custom = forms.DateTimeField(
label=_(FROM_DATE),
widget=DatePickerInput(format=API_DATE_FORMAT_WITH_DAY),
widget=DateTimePickerInput(format=API_DATE_FORMAT_WITH_DAY_DATE_TIME),
required=True,
initial=(datetime.now() - timedelta(6)).strftime(API_DATE_FORMAT_WITH_DAY),
)
from_time_custom = forms.TimeField(
label=_('Time'),
widget=forms.TimeInput(
format='%H:%M:%S',
attrs={
'placeholder': PLACEHOLDER1,
'class': 'form-control',
}
),
required=False,
initial=(datetime.now() - timedelta(6)).strftime(API_DATE_FORMAT_WITH_DAY_DATE_TIME),
)
include_app_names = forms.CharField(
label=_('Include App Names'),
@ -263,22 +219,11 @@ class CustomSummaryForm(forms.Form):
super(CustomSummaryForm, self).__init__(*args, **kwargs)
class MonthlyMetricsSummaryForm(forms.Form):
to_date = forms.DateField(
label=_("To Date"),
widget=DatePickerInput(format=API_DATE_FORMAT_WITH_DAY),
to_date = forms.DateTimeField(
label=_(TO_DATE),
widget=DateTimePickerInput(format=API_DATE_FORMAT_WITH_DAY_DATE_TIME),
required=True,
initial=str(datetime.now().strftime(API_DATE_FORMAT_WITH_DAY)),
)
to_date_time = forms.TimeField(
label=_('Time'),
widget=forms.TimeInput(
format='%H:%M:%S',
attrs={
'placeholder': PLACEHOLDER1,
'class': 'form-control',
}
),
required=False,
initial=(datetime.now()).strftime(API_DATE_FORMAT_WITH_DAY_DATE_TIME),
)
include_app_names = forms.CharField(
label=_('Include App Names'),

View File

@ -9,3 +9,7 @@
#metrics #metrics-list ul {
margin-left: -25px;
}
.hiddenRow {
padding: 0 !important;
}

View File

@ -0,0 +1,16 @@
$(document).ready(function($) {
getMetricLastEndpoint();
});
function getMetricLastEndpoint(){
$.ajax({url: "/metrics/api/last-endpoint", success: function(result){
var content = ""
+result['implemented_by_partial_function']+" took "
+result['duration']+" ms at "
+result['date']+" "
+result['verb']+" "
+ result['url'];
$("#last_endpoint").text(content);
setTimeout(function(){getMetricLastEndpoint();}, 5000); // will call function to update time every 5 seconds
}});
}

View File

@ -1,4 +1,5 @@
$(document).ready(function($) {
const BarchartData = $.parseJSON($('#barchart_data_div').attr("value"));
let barChart = new Chart($("#barchart"), {
type: 'horizontalBar',
data: {

View File

@ -3,7 +3,9 @@
{% load i18n %}
{% block page_title %}{{ block.super }} / API Metrics{% endblock page_title %}
{% block extrajs %}
<script type="text/javascript" src="{% static 'metrics/js/lastEndpointMetric.js' %}"></script>
{% endblock extrajs %}
{% load bootstrap3 %}
{% block content %}
<div id="metrics">
@ -12,7 +14,7 @@
{{ form.media }} {# Form required JS and CSS #}
{% endblock %}
<h1>{% trans "API Metrics" %}</h1>
<p id ="last_endpoint">getBanks took 43ms at 2023-12-06T11:00:49Z GET /obp/v4.0.0/banks ms. </p>
<div id="metrics-filter">
<h2>{% trans "Filter" %}</h2>
<form action="" method="get">
@ -44,13 +46,6 @@
{{ form.to_date }}
</div>
</div>
<div class="col-xs-6 col-sm-3">
{% if form.to_date_time.errors %}<div class="alert alert-danger">{{ form.to_date_time.errors }}</div>{% endif %}
<div class="form-group">
{{ form.to_date_time.label_tag }}
{{ form.to_date_time }}
</div>
</div>
</div>
<div class="row">
@ -150,40 +145,70 @@
<div class="tab-content">
{% block tab_content %}
<div class="tab-pane active">
<div class="table-responsive">
<div class="table-responsive-md">
<table class="table table-hover tablesorter" aria-describedby="api list">
<thead>
<tr>
<th scope="col" class="sortless"></th>
<th scope="col">#</th>
<th scope="col">{% trans "Verb Select" %}</th>
<th scope="col">{% trans "URL" %}</th>
<th scope="col" class="sortless">{% trans "Verb Select" %}</th>
<th scope="col" class="col-2">{% trans "URL" %}</th>
<th scope="col">{% trans "Source IP" %}</th>
<th scope="col">{% trans "Target IP" %}</th>
<th scope="col">{% trans "Date" %}</th>
<th scope="col">{% trans "Duration(ms)" %}</th>
<th scope="col">{% trans "Details" %}</th>
</tr>
</thead>
<tbody>
{% for metric in metrics %}
<tr>
{% with i=forloop.counter|stringformat:"s" %}
{% with data_id="data"|add:i %}
{% with data_id_selector="#"|add:data_id %}
<tr data-toggle="collapse" data-target={{ data_id_selector }} class="accordion-toggle" data-toggle="tooltip" data-placement="top" title="Show Detail">
<td><button type="button" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-eye-open"></span></button></td>
<td>{{ forloop.counter }}</td>
<td>{{ metric.verb_selection }}</td>
<td>
{{ metric.url }}
</td>
<td>{{ metric.date|date:"Y-m-d H:i:s.u" }}</td>
<td>{{ metric.url }}</td>
<td>{{ metric.source_ip}}</td>
<td>{{ metric.target_ip }}</td>
<td>{{ metric.date}}</td>
<td>{{ metric.duration }}</td>
<td>
<ul>
<li>{% trans "User Name" %}: {{ metric.user_name }}</li>
<li>{% trans "User ID" %}: {{ metric.user_id }}</li>
<li>{% trans "Developer Email" %}: {{ metric.developer_email }}</li>
<li>{% trans "App Name" %}: {{ metric.app_name }}</li>
<li>{% trans "Consumer ID" %}: {{ metric.consumer_id }}</li>
<li>{% trans "Implemented by Partial Function" %}: {{ metric.implemented_by_partial_function }}</li>
<li>{% trans "Implemented In Version" %}: {{ metric.implemented_in_version }}</li>
</ul>
</td>
</tr>
<tr class="expand-child">
<td colspan="12" class="hiddenRow">
<div class="accordian-body collapse" id={{ data_id }}>
<table class="table table-hover">
<thead>
<tr class="info filteredRow">
<th scope="col">{% trans "Response Body" %}</th>
<th scope="col">{% trans "Details" %}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ metric.response_body }}</td>
<td>
<ul>
<li>{% trans "User Name" %}: {{ metric.user_name }}</li>
<li>{% trans "User ID" %}: {{ metric.user_id }}</li>
<li>{% trans "Developer Email" %}: {{ metric.developer_email }}</li>
<li>{% trans "App Name" %}: {{ metric.app_name }}</li>
<li>{% trans "Consumer ID" %}: {{ metric.consumer_id }}</li>
<li>{% trans "Implemented by Partial Function" %}: {{ metric.implemented_by_partial_function }}</li>
<li>{% trans "Implemented In Version" %}: {{ metric.implemented_in_version }}</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
{% endwith %}
{% endwith %}
{% endwith %}
{% endfor %}
</tbody>
</table>
@ -198,4 +223,4 @@
{% block extracss %}
<link href="{% static 'metrics/css/metrics.css' %}" rel="stylesheet">
{% endblock extracss %}
{% endblock extracss %}

View File

@ -3,20 +3,20 @@
{% load i18n %}
{% block nav_tabs %}
<ul>
<li><a href="{% url 'api-metrics' %}?{{ request.GET.urlencode }}">{% trans "List" %}</a></li>
<li><a href="{% url 'api-metrics-summary-partial-function' %}?{{ request.GET.urlencode }}">{% trans "Summary by Partial Function" %}</a></li>
</ul>
{% endblock nav_tabs %}
{% block tab_content %}
<div class="tab-pane active">
<canvas id="barchart" width="100%" height="50%"></canvas>
</div>
<span id="barchart_data_div" style="display:none;visibility: hidden;opacity: 0" value= '{{ barchart_data|safe }}'></span>
{% endblock tab_content %}
{% block extrajs %}
<script type="text/javascript" src="{% static 'metrics/js/Chart.min.js' %}"></script>
<script type="text/javascript" src="{% static 'metrics/js/metrics.js' %}"></script>
<script type="text/javascript">
const BarchartData = {{ barchart_data|safe }};
</script>
{% endblock extrajs %}

View File

@ -44,10 +44,6 @@
</div>
<!--<div class="col-xs-6 col-sm-3">
{% if form.from_time_custom.errors %}<div class="alert alert-danger">{{ form.from_time_custom.errors }}</div>{% endif %}
<div class="form-group">
<strong>{% trans "From Time" %} </strong>
{{ form.from_time_custom }}
</div>
</div>-->
<div class="col-xs-6 col-sm-3">
{% if form.to_date.errors %}<div class="alert alert-danger">{{ form.to_date.errors }}</div>{% endif %}
@ -56,20 +52,6 @@
{{ form.to_date }}
</div>
</div>
<!--<div class="col-xs-6 col-sm-3">
{% if form.to_date_time.errors %}<div class="alert alert-danger">{{ form.to_date_time.errors }}</div>{% endif %}
<div class="form-group">
<strong>{% trans "To Time" %} </strong>
{{ form.to_date_time }}
</div>
</div>-->
<div class="col-xs-4 col-sm-3">
{% if form.include_app_names.errors %}<div class="alert alert-danger">{{ form.include_app_names.errors }}</div>{% endif %}
<div class="form-group">
{{ form.include_app_names.label_tag }}
{{ form.include_app_names }}
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">{% trans "Search" %}</button>
</form>
@ -103,22 +85,22 @@
<td>{% trans "Average response time (ms)" %}:</td>
<td>{{ average_response_time }}</td>
</tr>
<tr>
<td>{% trans "Median time from consumer registration to first API call" %}:</td>
<td>{{ median_time_to_first_api_call }}</td>
</tr>
{# <tr>#}
{# <td>{% trans "Median time from consumer registration to first API call" %}:</td>#}
{# <td>{{ median_time_to_first_api_call }}</td>#}
{# </tr>#}
<tr>
<td>{% trans "Apps with distinct names" %}:</td>
<td>{% trans "New apps with distinct names" %}:</td>
<td>{{ number_of_apps_with_unique_app_name }}</td>
</tr>
<tr>
<td>{% trans "Distinct developer email addresses" %}:</td>
<td>{% trans "New distinct developer email addresses" %}:</td>
<td>{{ number_of_apps_with_unique_developer_email }}</td>
</tr>
<tr>
<td>{% trans "Active Apps (at least one API call in the period)" %}:</td>
<td>{% trans "Top 100 Active Apps (at least one API call in the period)" %}:</td>
<td>{%for item in active_apps_list%} <p>{{item.app_name}} ({{ item.developer_email }})</p> {% endfor %}</td>
</tr>
<tr>

View File

@ -49,13 +49,6 @@
{{ form.to_date }}
</div>
</div>
<!--<div class="col-xs-4 col-sm-3">
{% if form.to_date_time.errors %}<div class="alert alert-danger">{{ form.to_date_time.errors }}</div>{% endif %}
<div class="form-group">
{{ form.to_date_time.label_tag }}
{{ form.to_date_time }}
</div>
</div>-->
<div class="col-xs-4 col-sm-3">
{% if form.include_app_names.errors %}<div class="alert alert-danger">{{ form.include_app_names.errors }}</div>{% endif %}
<div class="form-group">
@ -101,22 +94,22 @@
<td>{{ average_response_time }}</td>
</tr>
<tr>
<td>{% trans "Median time from consumer registration to first API call" %}:</td>
<td>{{ median_time_to_first_api_call }}</td>
</tr>
{# <tr>#}
{# <td>{% trans "Median time from consumer registration to first API call" %}:</td>#}
{# <td>{{ median_time_to_first_api_call }}</td>#}
{# </tr>#}
<tr>
<td>{% trans "Apps with distinct names" %}:</td>
<td>{% trans "New apps with distinct names" %}:</td>
<td>{{ number_of_apps_with_unique_app_name }}</td>
</tr>
<tr>
<td>{% trans "Apps with distinct developer email addresses" %}:</td>
<td>{% trans "Apps with New distinct developer email addresses" %}:</td>
<td>{{ number_of_apps_with_unique_developer_email }}</td>
</tr>
<tr>
<td>{% trans "Active Apps (at least one API call in the period)" %}:</td>
<td>{% trans "Top 100 Active Apps (at least one API call in the period)" %}:</td>
<td>{%for item in active_apps_list%} <p>{{item.app_name}} ({{ item.developer_email }})</p> {% endfor %}</td>
</tr>
<tr>

View File

@ -48,13 +48,6 @@
{{ form.to_date }}
</div>
</div>
<!--<div class="col-xs-4 col-sm-3">
{% if form.to_date_time.errors %}<div class="alert alert-danger">{{ form.to_date_time.errors }}</div>{% endif %}
<div class="form-group">
{{ form.to_date_time.label_tag }}
{{ form.to_date_time }}
</div>
</div>-->
<div class="col-xs-4 col-sm-3">
{% if form.include_app_names.errors %}<div class="alert alert-danger">{{ form.include_app_names.errors }}</div>{% endif %}
<div class="form-group">
@ -103,22 +96,22 @@
<td>{{ average_response_time }}</td>
</tr>
<tr>
<td>{% trans "Median time from consumer registration to first API call" %}:</td>
<td>{{ median_time_to_first_api_call }}</td>
</tr>
{# <tr>#}
{# <td>{% trans "Median time from consumer registration to first API call" %}:</td>#}
{# <td>{{ median_time_to_first_api_call }}</td>#}
{# </tr>#}
<tr>
<td>{% trans "Apps with distinct names" %}:</td>
<td>{% trans "New apps with distinct names" %}:</td>
<td>{{ number_of_apps_with_unique_app_name }}</td>
</tr>
<tr>
<td>{% trans "Apps with distinct developer email addresses" %}:</td>
<td>{% trans "Apps with New distinct developer email addresses" %}:</td>
<td>{{ number_of_apps_with_unique_developer_email }}</td>
</tr>
<tr>
<td>{% trans "Active Apps (at least one API call in the period)" %}:</td>
<td>{% trans "Top 100 Active Apps (at least one API call in the period)" %}:</td>
<td>{%for item in active_apps_names%}{{item}}, {% endfor %}</td>
</tr>
<tr>

View File

@ -36,7 +36,6 @@
{% endif %}
<div class="row">
<div class="col-xs-6 col-sm-3">
{% if form.to_date.errors %}<div class="alert alert-danger">{{ form.to_date.errors }}</div>{% endif %}
<div class="form-group">
@ -44,14 +43,6 @@
{{ form.to_date }}
</div>
</div>
<!--<div class="col-xs-4 col-sm-3">
{% if form.to_date_time.errors %}<div class="alert alert-danger">{{ form.to_date_time.errors }}</div>{% endif %}
<div class="form-group">
{{ form.to_date_time.label_tag }}
{{ form.to_date_time }}
</div>
</div>-->
<div class="col-xs-4 col-sm-3">
{% if form.include_app_names.errors %}<div class="alert alert-danger">{{ form.include_app_names.errors }}</div>{% endif %}
<div class="form-group">
@ -96,22 +87,22 @@
<td>{% trans "Average response time (ms)" %}:</td>
<td>{{ average_response_time }}</td>
</tr>
<tr>
<td>{% trans "Median time from consumer registration to first API call" %}:</td>
<td>{{ median_time_to_first_api_call }}</td>
</tr>
{# <tr>#}
{# <td>{% trans "Median time from consumer registration to first API call" %}:</td>#}
{# <td>{{ median_time_to_first_api_call }}</td>#}
{# </tr>#}
<tr>
<td>{% trans "Apps with distinct names" %}:</td>
<td>{% trans "New apps with distinct names" %}:</td>
<td>{{ number_of_apps_with_unique_app_name }}</td>
</tr>
<tr>
<td>{% trans "Distinct developer email addresses" %}:</td>
<td>{% trans "New distinct developer email addresses" %}:</td>
<td>{{ number_of_apps_with_unique_developer_email }}</td>
</tr>
<tr>
<td>{% trans "Active Apps (at least one API call in the period)" %}:</td>
<td>{% trans "Top 100 Active Apps (at least one API call in the period)" %}:</td>
<td>{%for item in active_apps_list%} <p>{{item.app_name}} ({{ item.developer_email }})</p> {% endfor %}</td>
</tr>
<tr>

View File

@ -48,14 +48,6 @@
{{ form.to_date }}
</div>
</div>
<!--<div class="col-xs-4 col-sm-3">
{% if form.to_date_time.errors %}<div class="alert alert-danger">{{ form.to_date_time.errors }}</div>{% endif %}
<div class="form-group">
{{ form.to_date_time.label_tag }}
{{ form.to_date_time }}
</div>
</div>-->
<div class="col-xs-4 col-sm-3">
{% if form.include_app_names.errors %}<div class="alert alert-danger">{{ form.include_app_names.errors }}</div>{% endif %}
<div class="form-group">
@ -105,22 +97,22 @@
<td>{{ average_response_time }}</td>
</tr>
<tr>
<td>{% trans "Median time from consumer registration to first API call" %}:</td>
<td>{{ median_time_to_first_api_call }}</td>
</tr>
{# <tr>#}
{# <td>{% trans "Median time from consumer registration to first API call" %}:</td>#}
{# <td>{{ median_time_to_first_api_call }}</td>#}
{# </tr>#}
<tr>
<td>{% trans "Apps with distinct names" %}:</td>
<td>{% trans "New apps with distinct names" %}:</td>
<td>{{ number_of_apps_with_unique_app_name }}</td>
</tr>
<tr>
<td>{% trans "Apps with distinct developer email addresses" %}:</td>
<td>{% trans "Apps with New distinct developer email addresses" %}:</td>
<td>{{ number_of_apps_with_unique_developer_email }}</td>
</tr>
<tr>
<td>{% trans "Active Apps (at least one API call in the period)" %}:</td>
<td>{% trans "Top 100 Active Apps (at least one API call in the period)" %}:</td>
<td>{%for item in active_apps_list%} <p>{{item.app_name}} ({{ item.developer_email }})</p> {% endfor %}</td>
</tr>
<tr>

View File

@ -50,14 +50,6 @@
{{ form.to_date }}
</div>
</div>
<!--<div class="col-xs-4 col-sm-3">
{% if form.to_date_time.errors %}<div class="alert alert-danger">{{ form.to_date_time.errors }}</div>{% endif %}
<div class="form-group">
{{ form.to_date_time.label_tag }}
{{ form.to_date_time }}
</div>
</div>-->
<div class="col-xs-4 col-sm-3">
{% if form.include_app_names.errors %}<div class="alert alert-danger">{{ form.include_app_names.errors }}</div>{% endif %}
<div class="form-group">
@ -101,22 +93,22 @@
<td>{{ average_response_time }}</td>
</tr>
<tr>
<td>{% trans "Median time from consumer registration to first API call" %}:</td>
<td>{{ median_time_to_first_api_call }}</td>
</tr>
{# <tr>#}
{# <td>{% trans "Median time from consumer registration to first API call" %}:</td>#}
{# <td>{{ median_time_to_first_api_call }}</td>#}
{# </tr>#}
<tr>
<td>{% trans "Apps with distinct names" %}:</td>
<td>{% trans "New apps with distinct names" %}:</td>
<td>{{ number_of_apps_with_unique_app_name }}</td>
</tr>
<tr>
<td>{% trans "Apps with distinct developer email addresses" %}:</td>
<td>{% trans "Apps with New distinct developer email addresses" %}:</td>
<td>{{ number_of_apps_with_unique_developer_email }}</td>
</tr>
<tr>
<td>{% trans "Active Apps (at least one API call in the period)" %}:</td>
<td>{% trans "Top 100 Active Apps (at least one API call in the period)" %}:</td>
<td>{%for item in active_apps_list%} <p>{{item.app_name}} ({{ item.developer_email }})</p> {% endfor %}</td>
</tr>
<tr>

View File

@ -50,13 +50,6 @@
{{ form.to_date }}
</div>
</div>
<!--<div class="col-xs-4 col-sm-3">
{% if form.to_date_time.errors %}<div class="alert alert-danger">{{ form.to_date_time.errors }}</div>{% endif %}
<div class="form-group">
{{ form.to_date_time.label_tag }}
{{ form.to_date_time }}
</div>
</div>-->
<div class="col-xs-4 col-sm-3">
{% if form.include_app_names.errors %}<div class="alert alert-danger">{{ form.include_app_names.errors }}</div>{% endif %}
<div class="form-group">
@ -100,22 +93,22 @@
<td>{{ average_response_time }}</td>
</tr>
<tr>
<td>{% trans "Median time from consumer registration to first API call" %}:</td>
<td>{{ median_time_to_first_api_call }}</td>
</tr>
{# <tr>#}
{# <td>{% trans "Median time from consumer registration to first API call" %}:</td>#}
{# <td>{{ median_time_to_first_api_call }}</td>#}
{# </tr>#}
<tr>
<td>{% trans "Apps with distinct names" %}:</td>
<td>{% trans "New apps with distinct names" %}:</td>
<td>{{ number_of_apps_with_unique_app_name }}</td>
</tr>
<tr>
<td>{% trans "Apps with distinct developer email addresses:" %}</td>
<td>{% trans "Apps with New distinct developer email addresses:" %}</td>
<td>{{ number_of_apps_with_unique_developer_email }}</td>
</tr>
<tr>
<td>{% trans "Active Apps (at least one API call in the period)" %}:</td>
<td>{% trans "Top 100 Active Apps (at least one API call in the period)" %}:</td>
<td>{%for item in active_apps_list%} <p>{{item.app_name}} ({{ item.developer_email }})</p> {% endfor %}</td>
</tr>
<tr>

View File

@ -15,13 +15,17 @@ from .views import (
WeeklySummaryView,
DailySummaryView,
HourlySummaryView,
CustomSummaryView
CustomSummaryView,
get_metric_last_endpoint
)
urlpatterns = [
url(r'^api/$',
APIMetricsView.as_view(),
name='api-metrics'),
url(r'^api/last-endpoint/$',
get_metric_last_endpoint,
name='api-metrics-last-endpoint'),
url(r'^api/summary-partial-function$',
APISummaryPartialFunctionView.as_view(),
name='api-metrics-summary-partial-function'),

View File

@ -10,6 +10,7 @@ from datetime import datetime, timedelta
from enum import Enum
from django.conf import settings
from django.http import JsonResponse
from apimanager import local_settings
from apimanager.settings import API_HOST, EXCLUDE_APPS, EXCLUDE_FUNCTIONS, EXCLUDE_URL_PATTERN, API_EXPLORER_APP_NAME, API_DATE_FORMAT_WITH_MILLISECONDS, API_DATE_FORMAT_WITH_SECONDS , DEBUG
from django.contrib import messages
@ -21,8 +22,7 @@ from obp.api import API, APIError, LOGGER
from .forms import APIMetricsForm, ConnectorMetricsForm, MonthlyMetricsSummaryForm, CustomSummaryForm
from pylab import *
from django.core.cache import cache
from base.views import get_consumers, get_api_versions
import traceback
try:
# Python 2
import cStringIO
@ -115,7 +115,7 @@ class MetricsView(LoginRequiredMixin, TemplateView):
"""
for metric in metrics:
metric['date'] = datetime.datetime.strptime(
metric['date'], settings.API_DATE_FORMAT_WITH_SECONDS )
metric['date'], settings.API_DATE_FORMAT_WITH_MILLISECONDS).isoformat(timespec='milliseconds')
return metrics
def to_api(self, cleaned_data):
@ -146,19 +146,13 @@ class MetricsView(LoginRequiredMixin, TemplateView):
urlpath = '{}?{}'.format(self.api_urlpath, params)
api = API(self.request.session.get('obp'))
try:
metrics = api.get(urlpath)
metrics = api.get(urlpath, version=settings.API_VERSION["v510"])
metrics = self.to_django(metrics['metrics'])
except APIError as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
except KeyError as err:
if DEBUG:
raise(err)
error_once_only(self.request, metrics['message'])
except Exception as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
return metrics
@ -187,11 +181,9 @@ class APIMetricsView(MetricsView):
def get_form(self, *args, **kwargs):
form = super(APIMetricsView, self).get_form(*args, **kwargs)
# Cannot add api in constructor: super complains about unknown kwarg
form.api = self.api
fields = form.fields
try:
fields['consumer_id'].choices = self.api.get_consumer_id_choices()
fields['implemented_in_version'].choices = self.api.get_api_version_choices()
except APIError as err:
messages.error(self.request, err)
@ -199,13 +191,25 @@ class APIMetricsView(MetricsView):
messages.error(self.request, err)
return form
def get_context_data(self, **kwargs):
context = super(APIMetricsView, self).get_context_data(**kwargs)
context.update({
'consumer_id': get_consumers(self.request),
'API_VERSION': get_api_versions(self.request)
})
return context
def get_metric_last_endpoint(request):
to_date = datetime.datetime.now().strftime(settings.API_DATE_FORMAT_WITH_MILLISECONDS)
urlpath = "/management/metrics?limit=1&to_date="+to_date
api = API(request.session.get('obp'))
last_endpoint_metric={}
try:
metric = api.get(urlpath)['metrics'][0]
last_endpoint_metric={
'implemented_by_partial_function':metric['implemented_by_partial_function'],
'duration': metric['duration'],
'date': metric['date'],
'verb': metric['verb'],
'url': metric['url']
}
except Exception as err:
LOGGER.exception('error_once_only - Error Message: {}'.format(err))
return JsonResponse(last_endpoint_metric)
class APISummaryPartialFunctionView(APIMetricsView):
@ -298,13 +302,9 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView):
result = ""
if input_string != "":
input_list = input_string.strip().split(",")
#print("input_list is:", input_list)
cleaned_list = [item.strip() for item in input_list]
#print("cleaned_list is: ", cleaned_list)
cleaned_string=', '.join([str(item) for item in cleaned_list])
#print("cleaned_string is:", cleaned_string)
url_encoded_string = urllib.parse.quote(cleaned_string)
#print("url_encoded_string is:", url_encoded_string)
if len(cleaned_list) == 0:
result = ""
elif len(cleaned_list) == 1:
@ -312,6 +312,7 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView):
else:
result = "&include_app_names={}".format(url_encoded_string)
return result
def get_aggregate_metrics(self, from_date, to_date, include_app_names):
"""
Gets the metrics from the API, using given parameters,
@ -319,48 +320,20 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView):
only_show_api_explorer_metrics has the default value False, because it is just used for app = API_Explorer.
"""
try:
print("get_app_name_parameters is: ", self.get_app_name_parameters(include_app_names))
api_calls_total = 0
average_response_time = 0
url_path = '/management/aggregate-metrics'
#if only_show_api_explorer_metrics:
# urlpath = urlpath + '?from_date={}&to_date={}&app_name={}'.format(from_date, to_date)
#elif (not only_show_api_explorer_metrics):
# urlpath = urlpath + '?from_date={}&to_date={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format(
# from_date, to_date, ",".join(local_settings.EXCLUDE_FUNCTIONS), ",".join(local_settings.EXCLUDE_URL_PATTERN))
#
#else:
url_path = url_path + '?from_date={}&to_date={}{}'.format(from_date, to_date, self.get_app_name_parameters(include_app_names))
#print("get_app_name_parameters(include_app_names) is:", self.get_app_name_parameters(include_app_names))
#print("url_path is: ", url_path)
cache_key = get_cache_key_for_current_call(self.request, url_path)
api_cache = None
try:
api_cache = cache.get(cache_key)
except Exception as err:
api_cache = None
if not api_cache is None:
metrics = api_cache
else:
api = API(self.request.session.get('obp'))
metrics = api.get(url_path)
api_cache = cache.set(cache_key, metrics)
LOGGER.warning('{0}: {1}'.format(CACHE_SETTING_URL_MSG, url_path))
LOGGER.warning('{0}: {1}'.format(CACHE_SETTING_KEY_MSG, cache_key))
url_path = '/management/aggregate-metrics?from_date={}&to_date={}&include_app_names={}'.format(from_date, to_date, self.get_app_name_parameters(include_app_names))
api = API(self.request.session.get('obp'))
metrics = api.get(url_path)
api_calls_total, average_calls_per_day, average_response_time = self.get_internal_api_call_metrics(
api_calls_total, average_response_time, cache_key, from_date, metrics, to_date, url_path)
api_calls_total, average_response_time, from_date, metrics, to_date, url_path)
return api_calls_total, average_response_time, int(average_calls_per_day)
except APIError as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
except Exception as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
def get_internal_api_call_metrics(self, api_calls_total, average_response_time, cache_key, from_date, metrics,
def get_internal_api_call_metrics(self, api_calls_total, average_response_time, from_date, metrics,
to_date, urlpath):
api_calls_total = metrics[0]["count"]
average_response_time = metrics[0]["average_response_time"]
@ -371,71 +344,38 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView):
average_calls_per_day = api_calls_total if (number_of_days == 0) else api_calls_total / number_of_days
return api_calls_total, average_calls_per_day, average_response_time
def get_active_apps(self, from_date, to_date):
def get_top_100_active_apps(self, from_date, to_date):
"""
Gets the metrics from the API, using given parameters,
"""
apps = []
form = self.get_form()
active_apps_list = []
urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}'.format(from_date, to_date)
urlpath = '/management/metrics/top-consumers?limit=100&from_date={}&to_date={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format(
from_date, to_date, ",".join(EXCLUDE_FUNCTIONS), ",".join(EXCLUDE_URL_PATTERN))
api = API(self.request.session.get('obp'))
try:
apps = api.get(urlpath)
if apps is not None and 'code' in apps and apps['code']==403:
error_once_only(self.request, apps['message'])
else:
active_apps_list = list(apps)
active_apps_list = list(apps['top_consumers'])
except APIError as err:
error_once_only(self.request, err)
except Exception as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
else:
urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format(
from_date, to_date, ",".join(EXCLUDE_FUNCTIONS), ",".join(EXCLUDE_URL_PATTERN))
api = API(self.request.session.get('obp'))
try:
apps = api.get(urlpath)
active_apps_list = list(apps['top_consumers'])
except APIError as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
except Exception as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
return active_apps_list
def get_total_number_of_apps(self, cleaned_data, from_date, to_date):
apps = []
from_date = datetime.datetime.strptime(from_date, API_DATE_FORMAT_WITH_MILLISECONDS)
to_date = datetime.datetime.strptime(to_date, API_DATE_FORMAT_WITH_MILLISECONDS)
apps_list = self.get_all_consumers()
for app in apps_list:
app_created_date = datetime.datetime.strptime(app["created"], API_DATE_FORMAT_WITH_SECONDS )
if app_created_date < from_date and app_created_date > to_date:
apps_list.remove(app)
apps_list = self.get_all_consumers(from_date, to_date)
app_names = []
apps = []
for apps in apps_list:
app_names.append(apps["app_name"])
# If include OBP Apps is selected
#if not cleaned_data.get('include_obp_apps'):
# for app in app_names:
# if app in local_settings.EXCLUDE_APPS:
# app_names.remove(app)
app_names = list(filter(None, app_names))
unique_app_names = list(set(app_names))
developer_emails = []
@ -450,32 +390,16 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView):
return unique_app_names, number_of_apps_with_unique_app_name, number_of_apps_with_unique_developer_email
def get_all_consumers(self):
urlpath = '/management/consumers'
def get_all_consumers(self, from_date, to_date):
urlpath = '/management/consumers?limit=1000000&from_date={}&to_date={}'.format(from_date, to_date)
api = API(self.request.session.get('obp'))
cache_key = get_cache_key_for_current_call(self.request, urlpath)
api_cache = None
try:
api_cache = cache.get(cache_key)
apps = api.get(urlpath)
apps_list = apps["consumers"]
except APIError as err:
error_once_only(self.request, err)
except Exception as err:
api_cache = None
if api_cache is not None:
apps_list = api_cache
else:
try:
apps = api.get(urlpath)
apps_list = apps["consumers"]
cache.set(cache_key, apps_list, 60 * 60) # for the consumers we cache for 1 hour, consumers may be increased
LOGGER.warning('{0}: {1}'.format(CACHE_SETTING_URL_MSG, urlpath))
LOGGER.warning('{0}: {1}'.format(CACHE_SETTING_KEY_MSG, cache_key))
except APIError as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
except Exception as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
error_once_only(self.request, err)
return apps_list
def calls_per_delta(self, from_date_string, to_date_string, include_app_names, **delta ):
@ -504,14 +428,11 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView):
result_list.append('{} - {} # {}'.format(from_datetime_object, time_delta_in_loop, result))
date_list.append(from_datetime_object)
except Exception as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
break
from_datetime_object = time_delta_in_loop
time_delta_in_loop = time_delta_in_loop + timedelta(**delta)
print("time_delta_in_loop in **delta is", time_delta_in_loop)
return (result_list, result_list_pure, date_list)
@ -668,33 +589,31 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView):
plt.gcf().clear()
return image_base64
def get_users_cansearchwarehouse(self):
users = []
users_with_cansearchwarehouse = []
email_with_cansearchwarehouse = []
api = API(self.request.session.get('obp'))
try:
urlpath = '/users'
users = api.get(urlpath)
if users is not None and 'code' in users and users['code'] == 403:
error_once_only(self.request, users['message'])
if 'users' not in users:
users['users']=[]
else:
self._update_user_with_cansearchwarehouse(users, users_with_cansearchwarehouse, email_with_cansearchwarehouse)
# fail gracefully in case API provides new structure
except APIError as err:
error_once_only(self.request, err)
except KeyError as err:
messages.error(self.request, 'KeyError: {}'.format(err))
except Exception as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
user_email_cansearchwarehouse = dict(zip(users_with_cansearchwarehouse, email_with_cansearchwarehouse))
number_of_users_with_cansearchwarehouse = len(user_email_cansearchwarehouse)
return user_email_cansearchwarehouse, number_of_users_with_cansearchwarehouse
# def get_users_cansearchwarehouse(self):
# users = []
# users_with_cansearchwarehouse = []
# email_with_cansearchwarehouse = []
# api = API(self.request.session.get('obp'))
# try:
# urlpath = '/users'
# users = api.get(urlpath)
# if users is not None and 'code' in users and users['code'] == 403:
# error_once_only(self.request, users['message'])
# if 'users' not in users:
# users['users']=[]
# else:
# self._update_user_with_cansearchwarehouse(users, users_with_cansearchwarehouse, email_with_cansearchwarehouse)
# # fail gracefully in case API provides new structure
# except APIError as err:
# error_once_only(self.request, err)
# except KeyError as err:
# messages.error(self.request, 'KeyError: {}'.format(err))
# except Exception as err:
# error_once_only(self.request, err)
#
# user_email_cansearchwarehouse = dict(zip(users_with_cansearchwarehouse, email_with_cansearchwarehouse))
# number_of_users_with_cansearchwarehouse = len(user_email_cansearchwarehouse)
# return user_email_cansearchwarehouse, number_of_users_with_cansearchwarehouse
def _update_user_with_cansearchwarehouse(self, users, users_with_cansearchwarehouse, email_with_cansearchwarehouse):
for user in users['users']:
@ -714,23 +633,14 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView):
else:
data = data[data_key]
except APIError as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
except Exception as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
return data
def get_top_apis(self, cleaned_data, from_date, to_date):
top_apis = []
#if cleaned_data.get('include_obp_apps'):
# urlpath = '/management/metrics/top-apis?from_date={}&to_date={}'.format(from_date, to_date)
#else:
# urlpath = '/management/metrics/top-apis?from_date={}&to_date={}&exclude_app_names={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format(
# from_date, to_date, ",".join(local_settings.EXCLUDE_APPS), ",".join(EXCLUDE_FUNCTIONS), ",".join(EXCLUDE_URL_PATTERN))
urlpath = '/management/metrics/top-apis?from_date={}&to_date={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format(
urlpath = '/management/metrics/top-apis?limit=10&from_date={}&to_date={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format(
from_date, to_date, ",".join(EXCLUDE_FUNCTIONS), ",".join(EXCLUDE_URL_PATTERN))
top_apis = self._api_data(urlpath, 'top_apis')
@ -746,12 +656,7 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView):
def get_top_consumers(self, cleaned_data, from_date, to_date):
top_consumers = []
#if cleaned_data.get('include_obp_apps'):
# urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}'.format(from_date, to_date)
#else:
# urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}&exclude_app_names={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format(
# from_date, to_date, ",".join(local_settings.EXCLUDE_APPS), ",".join(EXCLUDE_FUNCTIONS), ",".join(EXCLUDE_URL_PATTERN))
urlpath = '/management/metrics/top-consumers?from_date={}&to_date={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format(
urlpath = '/management/metrics/top-consumers?limit=10&from_date={}&to_date={}&exclude_implemented_by_partial_functions={}&exclude_url_pattern={}'.format(
from_date, to_date, ",".join(EXCLUDE_FUNCTIONS), ",".join(EXCLUDE_URL_PATTERN))
top_consumers = self._api_data(urlpath, 'top_consumers')
@ -759,7 +664,6 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView):
if consumer['app_name'] == "":
top_consumers.remove(consumer)
top_consumers = top_consumers[:10]
top_consumers = reversed(top_consumers)
return top_consumers
@ -772,12 +676,8 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView):
if "elasticSearchWarehouse" in api['Implemented_by_partial_function']:
top_warehouse_calls.append(api)
except APIError as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
except Exception as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
return top_warehouse_calls
@ -795,90 +695,77 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView):
else:
top_apps_using_warehouse = top_apps_using_warehouse["top_consumers"][:2]
except APIError as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
except Exception as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
return top_apps_using_warehouse
def median_time_to_first_api_call(self, from_date, to_date):
return 0 #TODO this cost too much time, do not use this at the moment.
form = self.get_form()
form = self.get_form()
new_apps_list = []
apps = []
apps_list = self.get_all_consumers()
for app in apps_list:
created_date = datetime.datetime.strptime(app['created'], '%Y-%m-%dT%H:%M:%SZ')
created_date = created_date.strftime(API_DATE_FORMAT_WITH_MILLISECONDS)
created_date = datetime.datetime.strptime(created_date, API_DATE_FORMAT_WITH_MILLISECONDS)
if created_date >= datetime.datetime.strptime(from_date, API_DATE_FORMAT_WITH_MILLISECONDS):
new_apps_list.append(app)
times_to_first_call = []
strfrom_date=datetime.datetime.strptime(from_date, API_DATE_FORMAT_WITH_MILLISECONDS)
strto_date=datetime.datetime.strptime(to_date, API_DATE_FORMAT_WITH_MILLISECONDS)
for app in new_apps_list:
urlpath_metrics = '/management/metrics?from_date={}&to_date={}&consumer_id={}&sort_by={}&direction={}&limit={}'.format(
from_date, to_date, app['consumer_id'], 'date', 'asc', '1')
cache_key = get_cache_key_for_current_call(self.request, urlpath_metrics)
api = API(self.request.session.get('obp'))
try:
api_cache=None
try:
api_cache=cache.get(cache_key)
except Exception as err:
api_cache=None
metrics=[]
if not api_cache is None:
metrics=api_cache
else:
metrics = api.get(urlpath_metrics)
if metrics is not None and 'code' in metrics and metrics['code'] == 403:
error_once_only(self.request, metrics['message'])
if(metrics['message'].startswith('OBP-20006')):
break
metrics = []
else:
metrics = list(metrics['metrics'])
cache.set(cache_key, metrics)
LOGGER.warning('The cache is setting, url is: {}'.format(urlpath_metrics))
LOGGER.warning('The cache is setting key is: {}'.format(cache_key))
if metrics:
time_difference = datetime.datetime.strptime(metrics[0]['date'], '%Y-%m-%dT%H:%M:%S.%fZ') - datetime.datetime.strptime(app['created'], '%Y-%m-%dT%H:%M:%SZ')
times_to_first_call.append(time_difference.total_seconds())
except APIError as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
except Exception as err:
if DEBUG:
raise(err)
error_once_only(self.request, 'Unknown Error. {}'.format(err))
if times_to_first_call:
median = statistics.median(times_to_first_call)
delta = datetime.timedelta(seconds=median)
else:
delta = 0
return delta
# def median_time_to_first_api_call(self, from_date, to_date):
# return 0 #TODO this cost too much time, do not use this at the moment.
# strfrom_date=datetime.datetime.strptime(from_date, API_DATE_FORMAT_WITH_MILLISECONDS)
# strto_date=datetime.datetime.strptime(to_date, API_DATE_FORMAT_WITH_MILLISECONDS)
# new_apps_list = []
# apps_list = self.get_all_consumers(strfrom_date,strto_date)
#
# for app in apps_list:
# created_date = datetime.datetime.strptime(app['created'], '%Y-%m-%dT%H:%M:%SZ')
# if created_date >= strfrom_date:
# new_apps_list.append(app)
#
# times_to_first_call = []
#
#
# for app in new_apps_list:
# urlpath_metrics = '/management/metrics?from_date={}&to_date={}&consumer_id={}&sort_by={}&direction={}&limit={}'.format(
# from_date, to_date, app['consumer_id'], 'date', 'asc', '1')
# cache_key = get_cache_key_for_current_call(self.request, urlpath_metrics)
# api = API(self.request.session.get('obp'))
# try:
# api_cache=None
# try:
# api_cache=cache.get(cache_key)
# except Exception as err:
# api_cache=None
# metrics=[]
# if not api_cache is None:
# metrics=api_cache
# else:
# metrics = api.get(urlpath_metrics)
#
# if metrics is not None and 'code' in metrics and metrics['code'] == 403:
# error_once_only(self.request, metrics['message'])
# if(metrics['message'].startswith('OBP-20006')):
# break
# metrics = []
# else:
# metrics = list(metrics['metrics'])
# cache.set(cache_key, metrics)
# LOGGER.warning('The cache is setting, url is: {}'.format(urlpath_metrics))
# LOGGER.warning('The cache is setting key is: {}'.format(cache_key))
# if metrics:
# time_difference = datetime.datetime.strptime(metrics[0]['date'], '%Y-%m-%dT%H:%M:%S.%fZ') - datetime.datetime.strptime(app['created'], '%Y-%m-%dT%H:%M:%SZ')
# times_to_first_call.append(time_difference.total_seconds())
#
#
# except APIError as err:
# error_once_only(self.request, err)
# except Exception as err:
# error_once_only(self.request, 'Unknown Error. {}'.format(err))
#
# if times_to_first_call:
# median = statistics.median(times_to_first_call)
# delta = datetime.timedelta(seconds=median)
# else:
# delta = 0
#
# return delta
def get_context_data(self, **kwargs): return self.prepare_general_context(SummaryType.MONTHLY)
def prepare_general_context(self, web_page_type, **kwargs):
try:
form = self.get_form()
print("form from get_form", form)
per_day_chart=[]
calls_per_month_list=[]
per_month_chart=[]
@ -890,10 +777,7 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView):
#if exclude_app_names not in local_settings.EXCLUDE_APPS:
# error_once_only(self.request, "Invalid Exclude App Name, Please select" + str(local_settings.EXCLUDE_APPS) + "Anyone of these")
form_to_date_string = form.data['to_date']
print(form.data, "Form data")
to_date = convert_form_date_to_obpapi_datetime_format(form_to_date_string)
print("to_date", to_date)
#to_date = datetime.datetime.strptime(f"{form.data['to_date']}T{form.data['to_date_time']}Z", API_DATE_FORMAT_WITH_SECONDS ).strftime(API_DATE_FORMAT_WITH_MILLISECONDS)
if (web_page_type == SummaryType.DAILY):
# for one day, the from_date is 1 day ago.
from_date = return_to_days_ago(to_date, 0)
@ -935,19 +819,19 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView):
per_day_chart = self.plot_line_chart(calls_per_day, date_list, "month")
api_host_name = API_HOST
top_apps_using_warehouse = self.get_top_apps_using_warehouse(from_date, to_date)
user_email_cansearchwarehouse, number_of_users_with_cansearchwarehouse = self.get_users_cansearchwarehouse()
median_time_to_first_api_call = self.median_time_to_first_api_call(from_date, to_date)
# top_apps_using_warehouse = self.get_top_apps_using_warehouse(from_date, to_date)
# top_warehouse_calls = self.get_top_warehouse_calls(form.cleaned_data, from_date, to_date)
# user_email_cansearchwarehouse, number_of_users_with_cansearchwarehouse = self.get_users_cansearchwarehouse()
# median_time_to_first_api_call = self.median_time_to_first_api_call(from_date, to_date)
top_apis = self.get_top_apis(form.cleaned_data, from_date, to_date)
top_apis_bar_chart = self.plot_bar_chart(top_apis)
top_consumers = self.get_top_consumers(form.cleaned_data, from_date, to_date)
top_consumers_bar_chart = self.plot_topconsumer_bar_chart(top_consumers)
top_warehouse_calls = self.get_top_warehouse_calls(form.cleaned_data, from_date, to_date)
api_calls, average_response_time, average_calls_per_day = self.get_aggregate_metrics(from_date, to_date, include_app_names)
unique_app_names, number_of_apps_with_unique_app_name, number_of_apps_with_unique_developer_email = self.get_total_number_of_apps(
form.cleaned_data, from_date, to_date)
active_apps_list = self.get_active_apps(from_date, to_date)
active_apps_list = self.get_top_100_active_apps(from_date, to_date)
context = super(MonthlyMetricsSummaryView, self).get_context_data(**kwargs)
context.update({
@ -964,25 +848,23 @@ class MonthlyMetricsSummaryView(LoginRequiredMixin, TemplateView):
'active_apps_list': active_apps_list,
'average_calls_per_day': average_calls_per_day,
'average_response_time': average_response_time,
'top_warehouse_calls': top_warehouse_calls,
'top_apps_using_warehouse': top_apps_using_warehouse,
'user_email_cansearchwarehouse': user_email_cansearchwarehouse,
'number_of_users_with_cansearchwarehouse': number_of_users_with_cansearchwarehouse,
# 'top_warehouse_calls': top_warehouse_calls,
# 'top_apps_using_warehouse': top_apps_using_warehouse,
# 'user_email_cansearchwarehouse': user_email_cansearchwarehouse,
# 'number_of_users_with_cansearchwarehouse': number_of_users_with_cansearchwarehouse,
'api_host_name': api_host_name,
'from_date': (datetime.datetime.strptime(from_date, API_DATE_FORMAT_WITH_MILLISECONDS)).strftime('%d %B %Y'),
'to_date': (datetime.datetime.strptime(to_date, API_DATE_FORMAT_WITH_MILLISECONDS)).strftime('%d %B %Y'),
'top_apis': top_apis,
'top_apis_bar_chart': top_apis_bar_chart,
'top_consumers_bar_chart': top_consumers_bar_chart,
'median_time_to_first_api_call': median_time_to_first_api_call,
# 'median_time_to_first_api_call': median_time_to_first_api_call,
#'excluded_apps':[exclude_app_names if exclude_app_names in local_settings.EXCLUDE_APPS else "null"],
})
return context
else:
error_once_only(self.request, str(form.errors))
except Exception as err:
if DEBUG:
raise(err)
error_once_only(self.request, err)
def _daily_and_weekly(self, web_page_type,to_date, per_hour_chart, per_day_chart, from_date):
if (web_page_type == SummaryType.DAILY):

View File

@ -43,7 +43,7 @@ class API(object):
self.start_session(session_data)
self.session_data = session_data
def call(self, method='GET', url='', payload=None, version=settings.API_ROOT['v500']):
def call(self, method='GET', url='', payload=None, version=settings.API_VERSION['v500']):
"""Workhorse which actually calls the API"""
log(logging.INFO, '{} {}'.format(method, url))
if payload:
@ -64,11 +64,11 @@ class API(object):
response.execution_time = elapsed
return response
def get(self, urlpath='', version=settings.API_ROOT['v500']):
def get(self, urlpath='', version=settings.API_VERSION['v500']):
"""
Gets data from the API
Convenience call which uses API_ROOT from settings
Convenience call which uses API_VERSION from settings
"""
url = version + urlpath
response = self.handle_response(self.call('GET', url))
@ -77,31 +77,31 @@ class API(object):
else:
return response
def delete(self, urlpath, version=settings.API_ROOT['v500']):
def delete(self, urlpath, version=settings.API_VERSION['v500']):
"""
Deletes data from the API
Convenience call which uses API_ROOT from settings
Convenience call which uses API_VERSION from settings
"""
url = version + urlpath
response = self.call('DELETE', url)
return self.handle_response(response)
def post(self, urlpath, payload, version=settings.API_ROOT['v500']):
def post(self, urlpath, payload, version=settings.API_VERSION['v500']):
"""
Posts data to given urlpath with given payload
Convenience call which uses API_ROOT from settings
Convenience call which uses API_VERSION from settings
"""
url = version + urlpath
response = self.call('POST', url, payload)
return self.handle_response(response)
def put(self, urlpath, payload, version=settings.API_ROOT['v500']):
def put(self, urlpath, payload, version=settings.API_VERSION['v500']):
"""
Puts data on given urlpath with given payload
Convenience call which uses API_ROOT from settings
Convenience call which uses API_VERSION from settings
"""
url = version + urlpath
response = self.call('PUT', url, payload)
@ -160,13 +160,6 @@ class API(object):
for bank in sorted(result['banks'], key=lambda d: d['id']) :
choices.append((bank['id'], bank['id']))
return choices
def get_consumer_id_choices(self):
"""Gets a list of Consumer ids and consumer ids as used by form choices"""
choices = [('', _('Choose ...'))]
result = self.get('/management/consumers')
for consumer in sorted(result['consumers'], key=lambda d: d['consumer_id']) :
choices.append((consumer['consumer_id'], consumer['consumer_id']))
return choices
def get_api_version_choices(self):
"""Gets a list of APIs Version and APIs Version as used by form choices"""

View File

@ -48,7 +48,7 @@ class GatewayLoginAuthenticator(Authenticator):
def prepare_gateway_login_token(self, data):
token = self.create_jwt(data)
# Make a test call to see if the token works
url = '{}{}'.format(settings.API_ROOT, '/users/current')
url = '{}{}'.format(settings.API_VERSION, '/users/current')
api = self.get_session()
try:
response = api.get(url)

View File

@ -133,5 +133,5 @@
{% block extracss %}
<link href="{% static 'users/css/users.css' %}" rel="stylesheet">
<link href="{% static 'users/css/users.css' %}" rel="stylesheet">
{% endblock extracss %}

View File

@ -4,9 +4,10 @@ URLs for users app
"""
from django.conf.urls import url
from django.urls import path
from .views import IndexView, DetailView, MyDetailView, DeleteEntitlementView, InvitationView, UserStatusUpdateView, \
ExportCsvView
ExportCsvView, AutocompleteFieldView
urlpatterns = [
url(r'^all$',
@ -29,5 +30,5 @@ urlpatterns = [
name='user-status-update'),
url(r'^export_csv$',
ExportCsvView.as_view(),
name='export-csv-users')
name='export-csv-users'),
]

View File

@ -5,7 +5,7 @@ Views of users app
import datetime
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseRedirect, HttpResponse
from django.http import HttpResponseRedirect, HttpResponse, JsonResponse
from django.urls import reverse, reverse_lazy
from django.views.generic import FormView, TemplateView, View
@ -24,7 +24,6 @@ class FilterRoleName(BaseFilter):
]]
return filtered
class FilterEmail(BaseFilter):
"""Filter users by email address"""
filter_type = 'email'
@ -439,3 +438,22 @@ class ExportCsvView(LoginRequiredMixin, View):
writer.writerow([user['username'], user['user_id'], user['email'], user['provider_id'], user['provider'],
user['last_marketing_agreement_signed_date']])
return response
# This below code is not yet working, it is intended to provide a json list of results to feed to jquery-ui autocomplete feature
class AutocompleteFieldView(View):
"""Autocompletes a Field Form based on what endpoint the field is filtering"""
def autocomplete_form_field(self, request, *args, **kwargs):
api = API(self.request.session.get('obp'))
term = self.request.GET.get('term', '')
try:
urlpath = '/roles'
response = api.get(urlpath)
if 'code' in response and response['code'] >= 400:
messages.error(self.request, response['message'])
else:
suggestions = response.json()
return JsonResponse(suggestions, safe=False)
except APIError as err:
messages.error(self.request, err)
return [], []