feat: 【应用】概览中增加应用的用量统计 - 后端
parent
e60f08b352
commit
a6aa386523
|
|
@ -0,0 +1,76 @@
|
||||||
|
# coding=utf-8
|
||||||
|
"""
|
||||||
|
@project: maxkb
|
||||||
|
@Author:虎
|
||||||
|
@file: application_statistics_serializers.py
|
||||||
|
@date:2024/3/27 10:55
|
||||||
|
@desc:
|
||||||
|
"""
|
||||||
|
import datetime
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
from django.db.models.query import QuerySet
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from application.models.api_key_model import ApplicationPublicAccessClient
|
||||||
|
from common.db.search import native_search, get_dynamics_model
|
||||||
|
from common.util.field_message import ErrMessage
|
||||||
|
from common.util.file_util import get_file_content
|
||||||
|
from smartdoc.conf import PROJECT_DIR
|
||||||
|
|
||||||
|
|
||||||
|
class ApplicationStatisticsSerializer(serializers.Serializer):
|
||||||
|
application_id = serializers.UUIDField(required=True, error_messages=ErrMessage.char("应用id"))
|
||||||
|
history_day = serializers.IntegerField(required=True, error_messages=ErrMessage.integer("历史天数"))
|
||||||
|
|
||||||
|
def get_end_time(self):
|
||||||
|
history_day = self.data.get('history_day')
|
||||||
|
return datetime.datetime.now() - datetime.timedelta(days=history_day)
|
||||||
|
|
||||||
|
def get_customer_count(self, with_valid=True):
|
||||||
|
if with_valid:
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
return native_search(
|
||||||
|
QuerySet(ApplicationPublicAccessClient).filter(application_id=self.data.get('application_id'),
|
||||||
|
create_time__gte=self.get_end_time()),
|
||||||
|
select_string=get_file_content(
|
||||||
|
os.path.join(PROJECT_DIR, "apps", "application", 'sql', 'customer_count.sql')),
|
||||||
|
with_search_one=True)
|
||||||
|
|
||||||
|
def get_customer_count_trend(self, with_valid=True):
|
||||||
|
if with_valid:
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
return native_search(
|
||||||
|
{'default_sql': QuerySet(ApplicationPublicAccessClient).filter(
|
||||||
|
application_id=self.data.get('application_id'),
|
||||||
|
create_time__gte=self.get_end_time())},
|
||||||
|
select_string=get_file_content(
|
||||||
|
os.path.join(PROJECT_DIR, "apps", "application", 'sql', 'customer_count_trend.sql')))
|
||||||
|
|
||||||
|
def get_chat_record_aggregate(self, with_valid=True):
|
||||||
|
if with_valid:
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
return native_search(
|
||||||
|
QuerySet(model=get_dynamics_model(
|
||||||
|
{'application_chat.application_id': models.UUIDField(),
|
||||||
|
'application_chat_record.create_time': models.DateTimeField()})).filter(
|
||||||
|
**{'application_chat.application_id': self.data.get('application_id'),
|
||||||
|
'application_chat_record.create_time__gte': self.get_end_time()}
|
||||||
|
),
|
||||||
|
select_string=get_file_content(
|
||||||
|
os.path.join(PROJECT_DIR, "apps", "application", 'sql', 'chat_record_count.sql')),
|
||||||
|
with_search_one=True)
|
||||||
|
|
||||||
|
def get_chat_record_aggregate_trend(self, with_valid=True):
|
||||||
|
if with_valid:
|
||||||
|
self.is_valid(raise_exception=True)
|
||||||
|
return native_search(
|
||||||
|
{'default_sql': QuerySet(model=get_dynamics_model(
|
||||||
|
{'application_chat.application_id': models.UUIDField(),
|
||||||
|
'application_chat_record.create_time': models.DateTimeField()})).filter(
|
||||||
|
**{'application_chat.application_id': self.data.get('application_id'),
|
||||||
|
'application_chat_record.create_time__gte': self.get_end_time()}
|
||||||
|
)},
|
||||||
|
select_string=get_file_content(
|
||||||
|
os.path.join(PROJECT_DIR, "apps", "application", 'sql', 'chat_record_count_trend.sql')))
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
SELECT SUM
|
||||||
|
( CASE WHEN application_chat_record.vote_status = '0' THEN 1 ELSE 0 END ) AS "star_num",
|
||||||
|
SUM ( CASE WHEN application_chat_record.vote_status = '1' THEN 1 ELSE 0 END ) AS "trample_num",
|
||||||
|
SUM ( application_chat_record.message_tokens + application_chat_record.answer_tokens ) as "tokens_sum",
|
||||||
|
"count"(application_chat_record."id") as chat_record_count
|
||||||
|
FROM
|
||||||
|
application_chat_record application_chat_record
|
||||||
|
LEFT JOIN application_chat application_chat ON application_chat."id" = application_chat_record.chat_id
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
SELECT SUM
|
||||||
|
( CASE WHEN application_chat_record.vote_status = '0' THEN 1 ELSE 0 END ) AS "star_num",
|
||||||
|
SUM ( CASE WHEN application_chat_record.vote_status = '1' THEN 1 ELSE 0 END ) AS "trample_num",
|
||||||
|
SUM ( application_chat_record.message_tokens + application_chat_record.answer_tokens ) as "tokens_sum",
|
||||||
|
"count"(application_chat_record."id") as chat_record_count,
|
||||||
|
application_chat_record.create_time :: DATE as "day"
|
||||||
|
FROM
|
||||||
|
application_chat_record application_chat_record
|
||||||
|
LEFT JOIN application_chat application_chat ON application_chat."id" = application_chat_record.chat_id
|
||||||
|
${default_sql}
|
||||||
|
GROUP BY "day"
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
SELECT
|
||||||
|
( SUM ( CASE WHEN create_time :: DATE = CURRENT_DATE THEN 1 ELSE 0 END ) ) AS "today_added_count",
|
||||||
|
COUNT ( "application_public_access_client"."id" ) AS "added_count"
|
||||||
|
FROM
|
||||||
|
"application_public_access_client"
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
SELECT
|
||||||
|
COUNT ( "application_public_access_client"."id" ) AS "added_count",
|
||||||
|
create_time :: DATE as "day"
|
||||||
|
FROM
|
||||||
|
"application_public_access_client"
|
||||||
|
${default_sql}
|
||||||
|
GROUP BY "day"
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
# coding=utf-8
|
||||||
|
"""
|
||||||
|
@project: maxkb
|
||||||
|
@Author:虎
|
||||||
|
@file: application_statistics_api.py
|
||||||
|
@date:2024/3/27 15:09
|
||||||
|
@desc:
|
||||||
|
"""
|
||||||
|
from drf_yasg import openapi
|
||||||
|
|
||||||
|
from common.mixins.api_mixin import ApiMixin
|
||||||
|
|
||||||
|
|
||||||
|
class ApplicationStatisticsApi(ApiMixin):
|
||||||
|
@staticmethod
|
||||||
|
def get_request_params_api():
|
||||||
|
return [openapi.Parameter(name='application_id',
|
||||||
|
in_=openapi.IN_PATH,
|
||||||
|
type=openapi.TYPE_STRING,
|
||||||
|
required=True,
|
||||||
|
description='应用id'),
|
||||||
|
openapi.Parameter(name='history_day',
|
||||||
|
in_=openapi.IN_QUERY,
|
||||||
|
type=openapi.TYPE_NUMBER,
|
||||||
|
required=True,
|
||||||
|
description='历史天数'),
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
class ChatRecordAggregate(ApiMixin):
|
||||||
|
@staticmethod
|
||||||
|
def get_response_body_api():
|
||||||
|
return openapi.Schema(
|
||||||
|
type=openapi.TYPE_OBJECT,
|
||||||
|
required=['star_num', 'trample_num', 'tokens_sum', 'chat_record_count'],
|
||||||
|
properties={
|
||||||
|
'star_num': openapi.Schema(type=openapi.TYPE_NUMBER, title="点赞数量",
|
||||||
|
description="点赞数量"),
|
||||||
|
|
||||||
|
'trample_num': openapi.Schema(type=openapi.TYPE_NUMBER, title="点踩数量", description="点踩数量"),
|
||||||
|
'tokens_sum': openapi.Schema(type=openapi.TYPE_NUMBER, title="token使用数量",
|
||||||
|
description="token使用数量"),
|
||||||
|
'chat_record_count': openapi.Schema(type=openapi.TYPE_NUMBER, title="对话次数",
|
||||||
|
description="对话次数"),
|
||||||
|
'day': openapi.Schema(type=openapi.TYPE_STRING,
|
||||||
|
title="日期",
|
||||||
|
description="日期,只有查询趋势的时候才有该字段"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
class CustomerCountTrend(ApiMixin):
|
||||||
|
@staticmethod
|
||||||
|
def get_response_body_api():
|
||||||
|
return openapi.Schema(
|
||||||
|
type=openapi.TYPE_OBJECT,
|
||||||
|
required=['added_count'],
|
||||||
|
properties={
|
||||||
|
'added_count': openapi.Schema(type=openapi.TYPE_NUMBER, title="新增数量", description="新增数量"),
|
||||||
|
|
||||||
|
'day': openapi.Schema(type=openapi.TYPE_STRING,
|
||||||
|
title="时间",
|
||||||
|
description="时间"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
class CustomerCount(ApiMixin):
|
||||||
|
@staticmethod
|
||||||
|
def get_response_body_api():
|
||||||
|
return openapi.Schema(
|
||||||
|
type=openapi.TYPE_OBJECT,
|
||||||
|
required=['added_count'],
|
||||||
|
properties={
|
||||||
|
'today_added_count': openapi.Schema(type=openapi.TYPE_NUMBER, title="今日新增数量",
|
||||||
|
description="今日新增数量"),
|
||||||
|
'added_count': openapi.Schema(type=openapi.TYPE_NUMBER, title="新增数量", description="新增数量"),
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
@ -8,6 +8,14 @@ urlpatterns = [
|
||||||
path('application/profile', views.Application.Profile.as_view()),
|
path('application/profile', views.Application.Profile.as_view()),
|
||||||
path('application/embed', views.Application.Embed.as_view()),
|
path('application/embed', views.Application.Embed.as_view()),
|
||||||
path('application/authentication', views.Application.Authentication.as_view()),
|
path('application/authentication', views.Application.Authentication.as_view()),
|
||||||
|
path('application/<str:application_id>/statistics/customer_count',
|
||||||
|
views.ApplicationStatistics.CustomerCount.as_view()),
|
||||||
|
path('application/<str:application_id>/statistics/customer_count_trend',
|
||||||
|
views.ApplicationStatistics.CustomerCountTrend.as_view()),
|
||||||
|
path('application/<str:application_id>/statistics/chat_record_aggregate',
|
||||||
|
views.ApplicationStatistics.ChatRecordAggregate.as_view()),
|
||||||
|
path('application/<str:application_id>/statistics/chat_record_aggregate_trend',
|
||||||
|
views.ApplicationStatistics.ChatRecordAggregateTrend.as_view()),
|
||||||
path('application/<str:application_id>/model', views.Application.Model.as_view()),
|
path('application/<str:application_id>/model', views.Application.Model.as_view()),
|
||||||
path('application/<str:application_id>/hit_test', views.Application.HitTest.as_view()),
|
path('application/<str:application_id>/hit_test', views.Application.HitTest.as_view()),
|
||||||
path('application/<str:application_id>/api_key', views.Application.ApplicationKey.as_view()),
|
path('application/<str:application_id>/api_key', views.Application.ApplicationKey.as_view()),
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,9 @@ from rest_framework.request import Request
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
from application.serializers.application_serializers import ApplicationSerializer
|
from application.serializers.application_serializers import ApplicationSerializer
|
||||||
|
from application.serializers.application_statistics_serializers import ApplicationStatisticsSerializer
|
||||||
from application.swagger_api.application_api import ApplicationApi
|
from application.swagger_api.application_api import ApplicationApi
|
||||||
|
from application.swagger_api.application_statistics_api import ApplicationStatisticsApi
|
||||||
from common.auth import TokenAuth, has_permissions
|
from common.auth import TokenAuth, has_permissions
|
||||||
from common.constants.permission_constants import CompareConstants, PermissionConstants, Permission, Group, Operate, \
|
from common.constants.permission_constants import CompareConstants, PermissionConstants, Permission, Group, Operate, \
|
||||||
ViewPermission, RoleConstants
|
ViewPermission, RoleConstants
|
||||||
|
|
@ -25,6 +27,95 @@ from common.util.common import query_params_to_single_dict
|
||||||
from dataset.serializers.dataset_serializers import DataSetSerializers
|
from dataset.serializers.dataset_serializers import DataSetSerializers
|
||||||
|
|
||||||
|
|
||||||
|
class ApplicationStatistics(APIView):
|
||||||
|
class CustomerCount(APIView):
|
||||||
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
@action(methods=["GET"], detail=False)
|
||||||
|
@swagger_auto_schema(operation_summary="用户统计",
|
||||||
|
operation_id="用户统计",
|
||||||
|
tags=["应用/统计"],
|
||||||
|
manual_parameters=ApplicationStatisticsApi.get_request_params_api(),
|
||||||
|
responses=result.get_api_response(
|
||||||
|
ApplicationStatisticsApi.CustomerCount.get_response_body_api())
|
||||||
|
)
|
||||||
|
@has_permissions(ViewPermission(
|
||||||
|
[RoleConstants.ADMIN, RoleConstants.USER],
|
||||||
|
[lambda r, keywords: Permission(group=Group.APPLICATION, operate=Operate.USE,
|
||||||
|
dynamic_tag=keywords.get('application_id'))],
|
||||||
|
compare=CompareConstants.AND))
|
||||||
|
def get(self, request: Request, application_id: str):
|
||||||
|
return result.success(
|
||||||
|
ApplicationStatisticsSerializer(data={'application_id': application_id,
|
||||||
|
'history_day': request.query_params.get(
|
||||||
|
'history_day')}).get_customer_count())
|
||||||
|
|
||||||
|
class CustomerCountTrend(APIView):
|
||||||
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
@action(methods=["GET"], detail=False)
|
||||||
|
@swagger_auto_schema(operation_summary="用户统计趋势",
|
||||||
|
operation_id="用户统计趋势",
|
||||||
|
tags=["应用/统计"],
|
||||||
|
manual_parameters=ApplicationStatisticsApi.get_request_params_api(),
|
||||||
|
responses=result.get_api_array_response(
|
||||||
|
ApplicationStatisticsApi.CustomerCountTrend.get_response_body_api()))
|
||||||
|
@has_permissions(ViewPermission(
|
||||||
|
[RoleConstants.ADMIN, RoleConstants.USER],
|
||||||
|
[lambda r, keywords: Permission(group=Group.APPLICATION, operate=Operate.USE,
|
||||||
|
dynamic_tag=keywords.get('application_id'))],
|
||||||
|
compare=CompareConstants.AND))
|
||||||
|
def get(self, request: Request, application_id: str):
|
||||||
|
return result.success(
|
||||||
|
ApplicationStatisticsSerializer(data={'application_id': application_id,
|
||||||
|
'history_day': request.query_params.get(
|
||||||
|
'history_day')}).get_customer_count_trend())
|
||||||
|
|
||||||
|
class ChatRecordAggregate(APIView):
|
||||||
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
@action(methods=["GET"], detail=False)
|
||||||
|
@swagger_auto_schema(operation_summary="对话相关统计",
|
||||||
|
operation_id="对话相关统计",
|
||||||
|
tags=["应用/统计"],
|
||||||
|
manual_parameters=ApplicationStatisticsApi.get_request_params_api(),
|
||||||
|
responses=result.get_api_response(
|
||||||
|
ApplicationStatisticsApi.ChatRecordAggregate.get_response_body_api())
|
||||||
|
)
|
||||||
|
@has_permissions(ViewPermission(
|
||||||
|
[RoleConstants.ADMIN, RoleConstants.USER],
|
||||||
|
[lambda r, keywords: Permission(group=Group.APPLICATION, operate=Operate.USE,
|
||||||
|
dynamic_tag=keywords.get('application_id'))],
|
||||||
|
compare=CompareConstants.AND))
|
||||||
|
def get(self, request: Request, application_id: str):
|
||||||
|
return result.success(
|
||||||
|
ApplicationStatisticsSerializer(data={'application_id': application_id,
|
||||||
|
'history_day': request.query_params.get(
|
||||||
|
'history_day')}).get_chat_record_aggregate())
|
||||||
|
|
||||||
|
class ChatRecordAggregateTrend(APIView):
|
||||||
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
@action(methods=["GET"], detail=False)
|
||||||
|
@swagger_auto_schema(operation_summary="对话相关统计趋势",
|
||||||
|
operation_id="对话相关统计趋势",
|
||||||
|
tags=["应用/统计"],
|
||||||
|
manual_parameters=ApplicationStatisticsApi.get_request_params_api(),
|
||||||
|
responses=result.get_api_array_response(
|
||||||
|
ApplicationStatisticsApi.ChatRecordAggregate.get_response_body_api())
|
||||||
|
)
|
||||||
|
@has_permissions(ViewPermission(
|
||||||
|
[RoleConstants.ADMIN, RoleConstants.USER],
|
||||||
|
[lambda r, keywords: Permission(group=Group.APPLICATION, operate=Operate.USE,
|
||||||
|
dynamic_tag=keywords.get('application_id'))],
|
||||||
|
compare=CompareConstants.AND))
|
||||||
|
def get(self, request: Request, application_id: str):
|
||||||
|
return result.success(
|
||||||
|
ApplicationStatisticsSerializer(data={'application_id': application_id,
|
||||||
|
'history_day': request.query_params.get(
|
||||||
|
'history_day')}).get_chat_record_aggregate_trend())
|
||||||
|
|
||||||
|
|
||||||
class Application(APIView):
|
class Application(APIView):
|
||||||
authentication_classes = [TokenAuth]
|
authentication_classes = [TokenAuth]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue