Jelajahi Sumber

HUE-9194 [useradmin] Get active users per instance

Ying Chen 5 tahun lalu
induk
melakukan
589b448da1

+ 18 - 0
apps/useradmin/src/useradmin/metrics.py

@@ -19,6 +19,7 @@ import logging
 from datetime import datetime, timedelta
 
 from desktop.lib.metrics import global_registry
+from desktop.lib.security_util import get_localhost_name
 
 LOG = logging.getLogger(__name__)
 
@@ -38,3 +39,20 @@ global_registry().gauge_callback(
     description='Number of users that were active in the last hour',
     numerator='users',
 )
+
+def active_users_per_instance():
+  from useradmin.models import UserProfile
+  try:
+    count = UserProfile.objects.filter(last_activity__gt=datetime.now() - timedelta(hours=1), hostname=get_localhost_name()).count()
+  except:
+    LOG.exception('Could not get active_users per instance')
+    count = 0
+  return count
+
+global_registry().gauge_callback(
+    name='users.active.instance',
+    callback=active_users,
+    label='Active Users per Instance',
+    description='Number of users that were active in the last hour on specific instance',
+    numerator='users',
+)

+ 2 - 0
apps/useradmin/src/useradmin/middleware.py

@@ -31,6 +31,7 @@ from django.utils.translation import ugettext as _
 
 from desktop.auth.views import dt_logout
 from desktop.conf import AUTH, LDAP, SESSION
+from desktop.lib.security_util import get_localhost_name
 
 from useradmin import ldap_access
 from useradmin.models import UserProfile, get_profile, User
@@ -101,6 +102,7 @@ class LastActivityMiddleware(object):
         and not (request.path.strip('/').startswith('oozie/list_oozie_')):
       try:
         profile.last_activity = datetime.now()
+        profile.hostname = get_localhost_name()
         profile.save()
       except DatabaseError:
         LOG.exception('Error saving profile information')

+ 20 - 0
apps/useradmin/src/useradmin/migrations/0004_userprofile_hostname.py

@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.22 on 2020-03-11 15:02
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('useradmin', '0003_auto_20200203_0802'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='userprofile',
+            name='hostname',
+            field=models.CharField(max_length=255, null=True),
+        ),
+    ]

+ 1 - 0
apps/useradmin/src/useradmin/models.py

@@ -87,6 +87,7 @@ class UserProfile(models.Model):
   creation_method = models.CharField(editable=True, null=False, max_length=64, default=CreationMethod.HUE.name)
   first_login = models.BooleanField(default=True, verbose_name=_t('First Login'), help_text=_t('If this is users first login.'))
   last_activity = models.DateTimeField(auto_now=True, db_index=True)
+  hostname = models.CharField(editable=True, max_length=255, null=True)
   json_data = models.TextField(default='{}')
 
   def get_groups(self):

+ 43 - 0
apps/useradmin/src/useradmin/tests.py

@@ -49,14 +49,17 @@ from hadoop.pseudo_hdfs4 import is_live_cluster
 import useradmin.conf
 import useradmin.ldap_access
 from useradmin.forms import UserChangeForm
+from useradmin.metrics import active_users, active_users_per_instance
 from useradmin.middleware import ConcurrentUserSessionMiddleware
 from useradmin.models import HuePermission, GroupPermission, UserProfile, get_profile, get_default_user_group, User, Group
 from useradmin.hue_password_policy import reset_password_policy
 
 if sys.version_info[0] > 2:
   from django.utils.encoding import smart_text as smart_unicode
+  from unittest.mock import patch, Mock
 else:
   from django.utils.encoding import smart_unicode
+  from mock import patch, Mock
 
 
 def reset_all_users():
@@ -296,6 +299,46 @@ class TestUserProfile(BaseUserAdminTests):
     assert_equal('es', userprofile.data['language_preference'])
 
 
+class TestUserAdminMetrics(BaseUserAdminTests):
+
+  @override_settings(AUTHENTICATION_BACKENDS=['desktop.auth.backend.AllowFirstUserDjangoBackend'])
+  def test_active_users(self):
+    with patch('useradmin.middleware.get_localhost_name') as get_hostname:
+      get_hostname.return_value = 'host1'
+
+      c = make_logged_in_client(username='test1', password='test', is_superuser=False, recreate=True)
+      userprofile1 = get_profile(User.objects.get(username='test1'))
+      userprofile1.last_activity = datetime.now()
+      userprofile1.hostname = 'host1'
+      userprofile1.save()
+
+      c = make_logged_in_client(username='test2', password='test', is_superuser=False, recreate=True)
+      userprofile2 = get_profile(User.objects.get(username='test2'))
+      userprofile2.last_activity = datetime.now()
+      userprofile2.hostname = 'host1'
+      userprofile2.save()
+
+    with patch('useradmin.middleware.get_localhost_name') as get_hostname:
+      get_hostname.return_value = 'host2'
+
+      c = make_logged_in_client(username='test3', password='test', is_superuser=False, recreate=True)
+      userprofile3 = get_profile(User.objects.get(username='test3'))
+      userprofile3.last_activity = datetime.now()
+      userprofile3.hostname = 'host2'
+      userprofile3.save()
+
+    with patch('useradmin.metrics.get_localhost_name') as get_hostname:
+      get_hostname.return_value = 'host1'
+      assert_equal(3, active_users())
+      assert_equal(2, active_users_per_instance())
+
+      c = Client()
+      response = c.get('/desktop/metrics/', dict(format='json'))
+      metric = json.loads(response.content)['metric']
+      assert_equal(3, metric['users.active'])
+      assert_equal(2, metric['users.active.instance'])
+
+
 class TestUserAdmin(BaseUserAdminTests):
 
   def test_group_permissions(self):

+ 1 - 1
desktop/core/src/desktop/lib/metrics/views.py

@@ -41,7 +41,7 @@ def index(request):
       'metric': global_registry().dump_metrics(),
   }
 
-  if request.is_ajax():
+  if request.is_ajax() or request.GET.get("format") == "json":
     return JsonResponse(rep, json_dumps_params={'indent': indent})
   else:
     return render("metrics.mako", request, {'metrics': json.dumps(rep['metric']), 'is_embeddable': request.GET.get('is_embeddable', False)})