mirror of
https://github.com/jumpserver/jumpserver.git
synced 2025-09-01 15:37:19 +00:00
perf: Asset report
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
#
|
#
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from django.db.models import Count, Q
|
from django.db.models import Count
|
||||||
from django.http.response import JsonResponse
|
from django.http.response import JsonResponse
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
@@ -29,9 +29,9 @@ class AssetActivityApi(DateRangeMixin, APIView):
|
|||||||
|
|
||||||
def get_asset_login_metrics(self, queryset):
|
def get_asset_login_metrics(self, queryset):
|
||||||
data = defaultdict(set)
|
data = defaultdict(set)
|
||||||
for t, asset in queryset.values_list('date_start', 'asset'):
|
for t, _id in queryset.values_list('date_start', 'id'):
|
||||||
date_str = str(t.date())
|
date_str = str(t.date())
|
||||||
data[date_str].add(asset)
|
data[date_str].add(_id)
|
||||||
|
|
||||||
metrics = [len(data.get(str(d), set())) for d in self.date_range_list]
|
metrics = [len(data.get(str(d), set())) for d in self.date_range_list]
|
||||||
return metrics
|
return metrics
|
||||||
@@ -47,35 +47,32 @@ class AssetActivityApi(DateRangeMixin, APIView):
|
|||||||
|
|
||||||
stats = qs.aggregate(
|
stats = qs.aggregate(
|
||||||
total=Count(1),
|
total=Count(1),
|
||||||
asset_online=Count(1, filter=Q(is_finished=False)),
|
|
||||||
asset_count=Count('asset_id', distinct=True),
|
asset_count=Count('asset_id', distinct=True),
|
||||||
user_count=Count('user_id', distinct=True),
|
user_count=Count('user_id', distinct=True),
|
||||||
is_success_count=Count(1, filter=Q(is_success=True)),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
asset_ids = {str(_id) for _id in qs.values_list('asset_id', flat=True).distinct()}
|
asset_ids = {str(_id) for _id in qs.values_list('asset_id', flat=True).distinct()}
|
||||||
assets = Asset.objects.filter(id__in=asset_ids)
|
assets = Asset.objects.filter(id__in=asset_ids)
|
||||||
|
|
||||||
asset_login_by_protocol = group_stats(
|
asset_login_by_protocol = group_stats(
|
||||||
qs, 'protocol_label', 'protocol'
|
qs, 'label', 'protocol'
|
||||||
)
|
)
|
||||||
|
|
||||||
asset_login_by_from = group_stats(
|
asset_login_by_from = group_stats(
|
||||||
qs, 'login_from_label', 'login_from', LoginFrom.as_dict()
|
qs, 'label', 'login_from', LoginFrom.as_dict()
|
||||||
)
|
)
|
||||||
|
|
||||||
asset_by_type = group_stats(
|
asset_by_type = group_stats(
|
||||||
assets, 'type', 'platform__type', all_type_dict,
|
assets, 'label', 'platform__type', all_type_dict,
|
||||||
)
|
)
|
||||||
dates_metrics_date = [date.strftime('%m-%d') for date in self.date_range_list] or ['0']
|
|
||||||
|
|
||||||
payload = {
|
payload = {
|
||||||
**stats,
|
'session_stats': stats,
|
||||||
'asset_login_by_type': asset_by_type,
|
'asset_login_by_type': asset_by_type,
|
||||||
'asset_login_by_from': asset_login_by_from,
|
'asset_login_by_from': asset_login_by_from,
|
||||||
'asset_login_by_protocol': asset_login_by_protocol,
|
'asset_login_by_protocol': asset_login_by_protocol,
|
||||||
'asset_login_log_metrics': {
|
'asset_login_log_metrics': {
|
||||||
'dates_metrics_date': dates_metrics_date,
|
'dates_metrics_date': self.dates_metrics_date,
|
||||||
'dates_metrics_total': self.get_asset_login_metrics(qs),
|
'dates_metrics_total': self.get_asset_login_metrics(qs),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,22 +1,23 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
|
from collections import defaultdict, OrderedDict
|
||||||
|
|
||||||
from django.db.models import Count, Q
|
from django.db.models import Count, Q
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from django.utils import timezone
|
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
from assets.const import AllTypes, Connectivity, Category
|
from assets.const import AllTypes, Connectivity
|
||||||
from assets.models import Asset, Platform
|
from assets.models import Asset, Platform
|
||||||
from common.permissions import IsValidLicense
|
from common.permissions import IsValidLicense
|
||||||
from common.utils import lazyproperty
|
from common.utils import lazyproperty
|
||||||
from rbac.permissions import RBACPermission
|
from rbac.permissions import RBACPermission
|
||||||
from reports.api.assets.base import group_stats
|
from reports.api.assets.base import group_stats
|
||||||
|
from reports.mixins import DateRangeMixin
|
||||||
|
|
||||||
__all__ = ['AssetStatisticApi']
|
__all__ = ['AssetStatisticApi']
|
||||||
|
|
||||||
|
|
||||||
class AssetStatisticApi(APIView):
|
class AssetStatisticApi(DateRangeMixin, APIView):
|
||||||
http_method_names = ['get']
|
http_method_names = ['get']
|
||||||
# TODO: Define the required RBAC permissions for this API
|
# TODO: Define the required RBAC permissions for this API
|
||||||
rbac_perms = {
|
rbac_perms = {
|
||||||
@@ -26,49 +27,60 @@ class AssetStatisticApi(APIView):
|
|||||||
|
|
||||||
@lazyproperty
|
@lazyproperty
|
||||||
def base_qs(self):
|
def base_qs(self):
|
||||||
return Asset.objects.only(
|
return Asset.objects.all()
|
||||||
'id', 'platform', 'zone', 'connectivity', 'is_active'
|
|
||||||
)
|
def get_added_asset_metrics(self):
|
||||||
|
filtered_queryset = self.filter_by_date_range(self.base_qs, 'date_created')
|
||||||
|
|
||||||
|
data = defaultdict(set)
|
||||||
|
for t, _id in filtered_queryset.values_list('date_created', 'id'):
|
||||||
|
date_str = str(t.date())
|
||||||
|
data[date_str].add(_id)
|
||||||
|
|
||||||
|
metrics = [len(data.get(str(d), set())) for d in self.date_range_list]
|
||||||
|
return metrics
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
qs = self.base_qs
|
qs = self.base_qs
|
||||||
all_type_dict = dict(AllTypes.choices())
|
all_type_dict = dict(AllTypes.choices())
|
||||||
|
|
||||||
platform_by_type = group_stats(
|
|
||||||
Platform.objects.all(), 'type_label', 'type', all_type_dict,
|
|
||||||
)
|
|
||||||
|
|
||||||
stats = qs.aggregate(
|
stats = qs.aggregate(
|
||||||
total=Count(1),
|
total=Count(1),
|
||||||
active=Count(1, filter=Q(is_active=True)),
|
active=Count(1, filter=Q(is_active=True)),
|
||||||
connected=Count(1, filter=Q(connectivity=Connectivity.OK)),
|
connected=Count(1, filter=Q(connectivity=Connectivity.OK)),
|
||||||
|
zone=Count(1, filter=Q(zone__isnull=False)),
|
||||||
|
directory_services=Count(1, filter=Q(directory_services__isnull=False)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type_category_map = {
|
||||||
|
d['label']: str(d['category'].label)
|
||||||
|
for d in AllTypes.types()
|
||||||
|
}
|
||||||
|
|
||||||
by_type = group_stats(
|
by_type = group_stats(
|
||||||
qs, 'type', 'platform__type', all_type_dict,
|
qs, 'type', 'platform__type', all_type_dict,
|
||||||
)
|
)
|
||||||
|
|
||||||
by_category = group_stats(
|
by_type_category = defaultdict(list)
|
||||||
qs, 'category', 'platform__category', Category.as_dict()
|
for item in by_type:
|
||||||
)
|
category = type_category_map.get(item['label'], 'Other')
|
||||||
|
by_type_category[category].append(item)
|
||||||
|
|
||||||
by_zone = group_stats(
|
sorted_category_assets = OrderedDict()
|
||||||
qs, 'zone_label', 'zone__name'
|
desired_order = [str(i['label']) for i in AllTypes.categories()]
|
||||||
)
|
for category in desired_order:
|
||||||
|
sorted_category_assets[category] = by_type_category.get(category, [])
|
||||||
|
|
||||||
week_start = timezone.now() + timezone.timedelta(days=7)
|
stats.update({
|
||||||
assets_added_this_week_qs = qs.filter(date_created__gte=week_start)
|
'platform_count': Platform.objects.all().count(),
|
||||||
assets_added_this_week_by_type = group_stats(
|
})
|
||||||
assets_added_this_week_qs, 'type', 'platform__type', all_type_dict,
|
|
||||||
)
|
|
||||||
|
|
||||||
payload = {
|
payload = {
|
||||||
**stats,
|
'asset_stats': stats,
|
||||||
'platform_by_type': platform_by_type,
|
'assets_by_type_category': sorted_category_assets,
|
||||||
'assets_by_type': by_type,
|
'added_asset_metrics': {
|
||||||
'assets_by_category': by_category,
|
'dates_metrics_date': self.dates_metrics_date,
|
||||||
'assets_by_zone': by_zone,
|
'dates_metrics_total': self.get_added_asset_metrics(),
|
||||||
'assets_added_this_week_count': assets_added_this_week_qs.count(),
|
}
|
||||||
'assets_added_this_week_by_type': assets_added_this_week_by_type,
|
|
||||||
}
|
}
|
||||||
return JsonResponse(payload, status=200)
|
return JsonResponse(payload, status=200)
|
||||||
|
@@ -59,7 +59,6 @@ class UserChangeSecretApi(DateRangeMixin, APIView):
|
|||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
data = {}
|
data = {}
|
||||||
dates_metrics_date = [date.strftime('%m-%d') for date in self.date_range_list] or ['0']
|
|
||||||
|
|
||||||
qs = self.filter_by_date_range(self.change_password_queryset, 'datetime')
|
qs = self.filter_by_date_range(self.change_password_queryset, 'datetime')
|
||||||
|
|
||||||
@@ -80,7 +79,7 @@ class UserChangeSecretApi(DateRangeMixin, APIView):
|
|||||||
data['change_password_top10_change_bys'] = list(change_password_top10_change_bys)
|
data['change_password_top10_change_bys'] = list(change_password_top10_change_bys)
|
||||||
|
|
||||||
data['user_change_password_metrics'] = {
|
data['user_change_password_metrics'] = {
|
||||||
'dates_metrics_date': dates_metrics_date,
|
'dates_metrics_date': self.dates_metrics_date,
|
||||||
'dates_metrics_total': self.get_change_password_metrics(qs),
|
'dates_metrics_total': self.get_change_password_metrics(qs),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -89,18 +89,17 @@ class UserReportApi(DateRangeMixin, APIView):
|
|||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
data = {}
|
data = {}
|
||||||
dates_metrics_date = [date.strftime('%m-%d') for date in self.date_range_list] or ['0']
|
|
||||||
|
|
||||||
data['user_login_log_metrics'] = {
|
data['user_login_log_metrics'] = {
|
||||||
'dates_metrics_date': dates_metrics_date,
|
'dates_metrics_date': self.dates_metrics_date,
|
||||||
'dates_metrics_total': self.get_user_login_metrics(self.user_login_log_queryset),
|
'dates_metrics_total': self.get_user_login_metrics(self.user_login_log_queryset),
|
||||||
}
|
}
|
||||||
data['user_login_failed_metrics'] = {
|
data['user_login_failed_metrics'] = {
|
||||||
'dates_metrics_date': dates_metrics_date,
|
'dates_metrics_date': self.dates_metrics_date,
|
||||||
'dates_metrics_total': self.get_user_login_metrics(self.user_login_failed_queryset),
|
'dates_metrics_total': self.get_user_login_metrics(self.user_login_failed_queryset),
|
||||||
}
|
}
|
||||||
data['user_login_method_metrics'] = {
|
data['user_login_method_metrics'] = {
|
||||||
'dates_metrics_date': dates_metrics_date,
|
'dates_metrics_date': self.dates_metrics_date,
|
||||||
'dates_metrics_total': self.get_user_login_method_metrics(),
|
'dates_metrics_total': self.get_user_login_method_metrics(),
|
||||||
}
|
}
|
||||||
data['user_login_region_distribution'] = self.get_user_login_region_distribution()
|
data['user_login_region_distribution'] = self.get_user_login_region_distribution()
|
||||||
|
@@ -40,3 +40,7 @@ class DateRangeMixin:
|
|||||||
def filter_by_date_range(self, queryset, field_name: str):
|
def filter_by_date_range(self, queryset, field_name: str):
|
||||||
start, end = self.date_range_bounds
|
start, end = self.date_range_bounds
|
||||||
return queryset.filter(**{f'{field_name}__range': (start, end)})
|
return queryset.filter(**{f'{field_name}__range': (start, end)})
|
||||||
|
|
||||||
|
@lazyproperty
|
||||||
|
def dates_metrics_date(self):
|
||||||
|
return [date.strftime('%m-%d') for date in self.date_range_list] or ['0']
|
||||||
|
Reference in New Issue
Block a user