Add Prometheus metrics endpoint for KYC monitoring
All checks were successful
Build Docker Image / build (push) Successful in 4m13s
All checks were successful
Build Docker Image / build (push) Successful in 4m13s
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from kyc_app.views import UserGraphQLView, M2MGraphQLView, PublicGraphQLView
|
from kyc_app.views import UserGraphQLView, M2MGraphQLView, PublicGraphQLView, metrics_view
|
||||||
from kyc_app.schemas.user_schema import user_schema
|
from kyc_app.schemas.user_schema import user_schema
|
||||||
from kyc_app.schemas.m2m_schema import m2m_schema
|
from kyc_app.schemas.m2m_schema import m2m_schema
|
||||||
from kyc_app.schemas.public_schema import public_schema
|
from kyc_app.schemas.public_schema import public_schema
|
||||||
@@ -11,4 +11,5 @@ urlpatterns = [
|
|||||||
path('graphql/user/', csrf_exempt(UserGraphQLView.as_view(graphiql=True, schema=user_schema))),
|
path('graphql/user/', csrf_exempt(UserGraphQLView.as_view(graphiql=True, schema=user_schema))),
|
||||||
path('graphql/m2m/', csrf_exempt(M2MGraphQLView.as_view(graphiql=True, schema=m2m_schema))),
|
path('graphql/m2m/', csrf_exempt(M2MGraphQLView.as_view(graphiql=True, schema=m2m_schema))),
|
||||||
path('graphql/public/', csrf_exempt(PublicGraphQLView.as_view(graphiql=True, schema=public_schema))),
|
path('graphql/public/', csrf_exempt(PublicGraphQLView.as_view(graphiql=True, schema=public_schema))),
|
||||||
|
path('metrics', metrics_view),
|
||||||
]
|
]
|
||||||
@@ -3,9 +3,16 @@ Views for KYC API.
|
|||||||
|
|
||||||
Authentication is handled by GRAPHENE MIDDLEWARE in settings.py
|
Authentication is handled by GRAPHENE MIDDLEWARE in settings.py
|
||||||
"""
|
"""
|
||||||
|
import os
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from django.db.models import Count, Q
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.utils import timezone
|
||||||
from graphene_django.views import GraphQLView
|
from graphene_django.views import GraphQLView
|
||||||
|
|
||||||
from .graphql_middleware import UserJWTMiddleware
|
from .graphql_middleware import UserJWTMiddleware
|
||||||
|
from .models import KYCProfile
|
||||||
|
|
||||||
|
|
||||||
class UserGraphQLView(GraphQLView):
|
class UserGraphQLView(GraphQLView):
|
||||||
@@ -47,3 +54,37 @@ class PublicGraphQLView(GraphQLView):
|
|||||||
# Use optional auth middleware that doesn't fail on missing token
|
# Use optional auth middleware that doesn't fail on missing token
|
||||||
kwargs['middleware'] = [OptionalUserJWTMiddleware()]
|
kwargs['middleware'] = [OptionalUserJWTMiddleware()]
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def metrics_view(request):
|
||||||
|
"""Prometheus metrics endpoint for KYC monitoring status."""
|
||||||
|
stale_days = int(os.getenv("KYC_STALE_DAYS", "90"))
|
||||||
|
cutoff = timezone.now() - timedelta(days=stale_days)
|
||||||
|
|
||||||
|
stats = KYCProfile.objects.filter(workflow_status="active").aggregate(
|
||||||
|
total=Count("id"),
|
||||||
|
stale=Count("id", filter=Q(updated_at__lt=cutoff) | Q(updated_at__isnull=True)),
|
||||||
|
fresh=Count("id", filter=Q(updated_at__gte=cutoff)),
|
||||||
|
)
|
||||||
|
|
||||||
|
total = int(stats.get("total") or 0)
|
||||||
|
stale = int(stats.get("stale") or 0)
|
||||||
|
fresh = int(stats.get("fresh") or 0)
|
||||||
|
ratio = 0.0 if total == 0 else stale / total
|
||||||
|
|
||||||
|
payload = (
|
||||||
|
"# HELP kyc_monitoring_total Total active profiles in monitoring\n"
|
||||||
|
"# TYPE kyc_monitoring_total gauge\n"
|
||||||
|
f"kyc_monitoring_total {total}\n"
|
||||||
|
"# HELP kyc_monitoring_stale Stale profiles (no refresh within window)\n"
|
||||||
|
"# TYPE kyc_monitoring_stale gauge\n"
|
||||||
|
f"kyc_monitoring_stale {stale}\n"
|
||||||
|
"# HELP kyc_monitoring_fresh Fresh profiles (refreshed within window)\n"
|
||||||
|
"# TYPE kyc_monitoring_fresh gauge\n"
|
||||||
|
f"kyc_monitoring_fresh {fresh}\n"
|
||||||
|
"# HELP kyc_monitoring_stale_ratio Stale / total ratio\n"
|
||||||
|
"# TYPE kyc_monitoring_stale_ratio gauge\n"
|
||||||
|
f"kyc_monitoring_stale_ratio {ratio}\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
return HttpResponse(payload, content_type="text/plain; version=0.0.4; charset=utf-8")
|
||||||
|
|||||||
Reference in New Issue
Block a user