Skip to content
Snippets Groups Projects
Commit e04ccc33 authored by Benjamin Ledel's avatar Benjamin Ledel
Browse files

* add prometheus counter

parent 3fef13ef
Branches
Tags
No related merge requests found
Pipeline #1633589 failed
......@@ -266,4 +266,6 @@ SHIB_ID_CONNECTOR_URL = env("SHIB_ID_CONNECTOR_URL",default="")
SHIB_ID_CONNECTOR_APP_SECRET = env("SHIB_ID_CONNECTOR_APP_SECRET",default="")
SHIB_ID_CONNECTOR_PROCESS_ID = env("SHIB_ID_CONNECTOR_PROCESS_ID",default="PI")
SHIB_ID_CONNECTOR_LINK_TYPE = env("SHIB_ID_CONNECTOR_LINK_TYPE",default="")
SHIB_ID_CONNECTOR_USE_FILE_MAPPING = env("SHIB_ID_CONNECTOR_USE_FILE_MAPPING",default=False)
\ No newline at end of file
SHIB_ID_CONNECTOR_USE_FILE_MAPPING = env("SHIB_ID_CONNECTOR_USE_FILE_MAPPING",default=False)
PROMETHEUS_METRIC_NAMESPACE = "polaris"
\ No newline at end of file
......@@ -48,6 +48,7 @@ def get_static_text(filename):
urlpatterns = [
path('robots.txt', get_static_text('static/robots_deny.txt' if settings.ALLOW_ROBOTS == "False" or settings.ALLOW_ROBOTS == False else "static/robots_allow.txt")),
path("admin/", admin.site.urls),
path('', include('django_prometheus.urls')),
path("api/v1/consents/", include("consents.urls")),
path("api/v1/auth/", include("users.urls")),
path("api/v1/provider/", include("providers.urls")),
......
......@@ -15,6 +15,7 @@ from jsonschema import ValidationError, validate
from jsonschema.validators import validator_for
from rest_framework import status
from rest_framework.views import APIView
from prometheus_client import Counter
from backend.utils import lrs_db
from consents.models import UserConsents
......@@ -28,6 +29,17 @@ from .tasks import retry_forward_statements
PROJECT_PATH = os.path.abspath(os.path.dirname(__name__))
# Prometheus Counters
STATEMENTS_PROCESSED = Counter(
"xapi_statements_processed_total", "Total number of xAPI statements processed"
)
STATEMENTS_ACCEPTED = Counter(
"xapi_statements_accepted_total", "Total number of xAPI statements accepted"
)
STATEMENTS_REJECTED = Counter(
"xapi_statements_rejected_total", "Total number of xAPI statements rejected"
)
with open(os.path.join(PROJECT_PATH, "static/xapi_statement.schema.json")) as f:
schema = json.loads(f.read())
cls = validator_for(schema)
......@@ -285,13 +297,14 @@ def process_tan_statement(x_api_statement):
class CreateStatement(APIView):
"""
xAPI create statements proxy. This endpoint filter xAPI statements based and user settings and passes only consented xAPI statements to the LRS.
xAPI create statements proxy. This endpoint filters xAPI statements based on user settings
and passes only consented xAPI statements to the LRS.
"""
def post(self, request):
# provider authorization
# Provider authorization
auth_header = request.headers.get("Authorization")
if not auth_header.startswith("Basic "):
if not auth_header or not auth_header.startswith("Basic "):
return JsonResponse(
{
"message": "No provider authorization token supplied.",
......@@ -300,6 +313,7 @@ class CreateStatement(APIView):
safe=False,
status=status.HTTP_401_UNAUTHORIZED,
)
auth_key = auth_header.split(" ")[1]
try:
provider_auth = ProviderAuthorization.objects.get(key=auth_key)
......@@ -315,7 +329,7 @@ class CreateStatement(APIView):
provider = provider_auth.provider
# load latest provider schema for essential verbs
# Load latest provider schema for essential verbs
try:
latest_schema = ProviderSchema.objects.get(
provider=provider, superseded_by__isnull=True
......@@ -330,29 +344,52 @@ class CreateStatement(APIView):
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
)
# handle list of xAPI statements as well as single xAPI statement
# Handle list of xAPI statements as well as a single statement
x_api_statements = (
request.data if isinstance(request.data, list) else [request.data]
)
# forward to other LRS without validation etc., if given
if latest_schema.additional_lrs and isinstance(latest_schema.additional_lrs, list) and len(latest_schema.additional_lrs) > 0:
# Track total processed statements
STATEMENTS_PROCESSED.inc(len(x_api_statements))
# Forward to additional LRS if configured
if (
latest_schema.additional_lrs
and isinstance(latest_schema.additional_lrs, list)
and len(latest_schema.additional_lrs) > 0
):
for additional_lrs in latest_schema.additional_lrs:
headers = {"Authorization": additional_lrs["token_type"] + " " + additional_lrs["token"]}
headers = {
"Authorization": additional_lrs["token_type"]
+ " "
+ additional_lrs["token"]
}
try:
res = requests.post(additional_lrs["url"], json=x_api_statements, headers=headers)
res = requests.post(
additional_lrs["url"], json=x_api_statements, headers=headers
)
if res.status_code != 200:
raise RuntimeError("Returned status code other than 200")
if settings.DEBUG:
print("Forwarded statement to ", additional_lrs["url"], ":", res.reason,
"({})".format(res.status_code))
print(
"Forwarded statement to ",
additional_lrs["url"],
":",
res.reason,
"({})".format(res.status_code),
)
except Exception as e:
if settings.DEBUG:
print("Could not forward to ", additional_lrs["url"], ":", e)
retry_forward_statements.delay(x_api_statements, additional_lrs["token_type"], additional_lrs["token"], additional_lrs["url"])
retry_forward_statements.delay(
x_api_statements,
additional_lrs["token_type"],
additional_lrs["token"],
additional_lrs["url"],
)
if settings.SHOW_XAPI_STATEMENTS:
print(x_api_statements)
print(x_api_statements)
try:
result = [
......@@ -367,15 +404,19 @@ class CreateStatement(APIView):
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
)
invalid_or_not_consented = (
len([e for e in result if e["valid"] == False or e["accepted"] == False])
> 0
)
# Count rejected and accepted statements
rejected_count = sum(
1 for e in result if e["valid"] is False or e["accepted"] is False
)
accepted_count = len(x_api_statements) - rejected_count
STATEMENTS_REJECTED.inc(rejected_count)
STATEMENTS_ACCEPTED.inc(accepted_count)
if settings.SHOW_XAPI_STATEMENTS:
print(result)
if invalid_or_not_consented:
if rejected_count > 0:
return JsonResponse(
{
"message": "xAPI statements couldn't be stored in LRS",
......@@ -384,9 +425,13 @@ class CreateStatement(APIView):
status=status.HTTP_400_BAD_REQUEST,
)
else:
# anonymize statements
x_api_statements = [anonymize_statement(statement) if result[i].get("needs_anonymization", False)
else statement for i, statement in enumerate(x_api_statements)]
# Anonymize statements where needed
x_api_statements = [
anonymize_statement(statement)
if result[i].get("needs_anonymization", False)
else statement
for i, statement in enumerate(x_api_statements)
]
uuids = list(map(store_in_db, x_api_statements))
return JsonResponse(
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment