浏览代码

[desktop] Track authentication login times

Erick Tryzelaar 10 年之前
父节点
当前提交
329a7225d5

+ 7 - 0
desktop/core/src/desktop/auth/backend.py

@@ -33,6 +33,7 @@ from django.contrib.auth.models import User
 import django.contrib.auth.backends
 import django.contrib.auth.backends
 import logging
 import logging
 import desktop.conf
 import desktop.conf
+from desktop import metrics
 from django.utils.importlib import import_module
 from django.utils.importlib import import_module
 from django.core.exceptions import ImproperlyConfigured
 from django.core.exceptions import ImproperlyConfigured
 from useradmin.models import get_profile, get_default_user_group, UserProfile
 from useradmin.models import get_profile, get_default_user_group, UserProfile
@@ -200,6 +201,7 @@ class OAuthBackend(DesktopBackendBase):
   build/env/bin/pip install httplib2
   build/env/bin/pip install httplib2
   """
   """
 
 
+  @metrics.oauth_authentication_time
   def authenticate(self, access_token):
   def authenticate(self, access_token):
     username = access_token['screen_name']
     username = access_token['screen_name']
     password = access_token['oauth_token_secret']
     password = access_token['oauth_token_secret']
@@ -286,6 +288,8 @@ class PamBackend(DesktopBackendBase):
   Authentication backend that uses PAM to authenticate logins. The first user to
   Authentication backend that uses PAM to authenticate logins. The first user to
   login will become the superuser.
   login will become the superuser.
   """
   """
+
+  @metrics.pam_authentication_time
   def check_auth(self, username, password):
   def check_auth(self, username, password):
     if pam.authenticate(username, password, desktop.conf.AUTH.PAM_SERVICE.get()):
     if pam.authenticate(username, password, desktop.conf.AUTH.PAM_SERVICE.get()):
       is_super = False
       is_super = False
@@ -403,6 +407,7 @@ class LdapBackend(object):
     else:
     else:
       self.add_ldap_config(desktop.conf.LDAP)
       self.add_ldap_config(desktop.conf.LDAP)
 
 
+  @metrics.ldap_authentication_time
   def authenticate(self, username=None, password=None, server=None):
   def authenticate(self, username=None, password=None, server=None):
     self.add_ldap_config_for_server(server)
     self.add_ldap_config_for_server(server)
 
 
@@ -472,6 +477,8 @@ class SpnegoDjangoBackend(django.contrib.auth.backends.ModelBackend):
   the KRB5_KTNAME environment variable to point to another location
   the KRB5_KTNAME environment variable to point to another location
   (e.g. /etc/hue/hue.keytab).
   (e.g. /etc/hue/hue.keytab).
   """
   """
+
+  @metrics.spnego_authentication_time
   def authenticate(self, username=None):
   def authenticate(self, username=None):
     username = self.clean_username(username)
     username = self.clean_username(username)
     is_super = False
     is_super = False

+ 23 - 1
desktop/core/src/desktop/lib/metrics/registry.py

@@ -18,6 +18,7 @@
 All Hue metrics should be defined in the APP/metrics.py file so they are discoverable.
 All Hue metrics should be defined in the APP/metrics.py file so they are discoverable.
 """
 """
 
 
+import functools
 import pyformance
 import pyformance
 
 
 
 
@@ -53,7 +54,7 @@ class MetricsRegistry(object):
 
 
   def timer(self, name, **kwargs):
   def timer(self, name, **kwargs):
     self._schemas.append(MetricDefinition('timer', name, **kwargs))
     self._schemas.append(MetricDefinition('timer', name, **kwargs))
-    return self._registry.timer(name)
+    return Timer(self._registry.timer(name))
 
 
   def dump_metrics(self):
   def dump_metrics(self):
     return self._registry.dump_metrics()
     return self._registry.dump_metrics()
@@ -74,6 +75,27 @@ class MetricDefinition(object):
     self.context = context
     self.context = context
 
 
 
 
+class Timer(object):
+  """
+  Wrapper around the pyformance Timer object to allow it to be used in an
+  annotation.
+  """
+
+  def __init__(self, timer):
+    self._timer = timer
+
+  def __call__(self, fn, *args, **kwargs):
+    @functools.wraps(fn)
+    def wrapper(*args, **kwargs):
+      with self._timer.time():
+        return fn(*args, **kwargs)
+
+    return wrapper
+
+  def __getattr__(self, *args, **kwargs):
+    return getattr(self._timer, *args, **kwargs)
+
+
 _global_registry = MetricsRegistry()
 _global_registry = MetricsRegistry()
 
 
 
 

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

@@ -23,6 +23,7 @@ from django.views.decorators.http import require_GET
 from desktop.lib.django_util import JsonResponse, render, login_notrequired
 from desktop.lib.django_util import JsonResponse, render, login_notrequired
 from desktop.lib.metrics.registry import global_registry
 from desktop.lib.metrics.registry import global_registry
 
 
+@login_notrequired
 @require_GET
 @require_GET
 def index(request):
 def index(request):
   if request.GET.get('pretty') == 'true':
   if request.GET.get('pretty') == 'true':

+ 26 - 0
desktop/core/src/desktop/metrics.py

@@ -155,3 +155,29 @@ def user_logged_in_handler(sender, **kwargs):
 @receiver(user_logged_out)
 @receiver(user_logged_out)
 def user_logged_out_handler(sender, **kwargs):
 def user_logged_out_handler(sender, **kwargs):
   logged_in_users.dec()
   logged_in_users.dec()
+
+# ------------------------------------------------------------------------------
+
+ldap_authentication_time = global_registry().timer(
+    name='desktop.auth.ldap.authentication-time',
+    label='LDAP Authentication time',
+    description='Time taken to authenticate a user with LDAP',
+)
+
+oauth_authentication_time = global_registry().timer(
+    name='desktop.auth.oauth.authentication-time',
+    label='OAUTH Authentication time',
+    description='Time taken to authenticate a user with OAUTH',
+)
+
+pam_authentication_time = global_registry().timer(
+    name='desktop.auth.pam.authentication-time',
+    label='PAM Authentication time',
+    description='Time taken to authenticate a user with PAM',
+)
+
+spnego_authentication_time = global_registry().timer(
+    name='desktop.auth.spnego.authentication-time',
+    label='SPNEGO Authentication time',
+    description='Time taken to authenticate a user with SPNEGO',
+)

+ 2 - 0
desktop/libs/liboauth/src/liboauth/backend.py

@@ -30,6 +30,7 @@ from django.contrib.auth.models import User
 from django.http import HttpResponseRedirect
 from django.http import HttpResponseRedirect
 from django.utils.translation import ugettext as _
 from django.utils.translation import ugettext as _
 
 
+from desktop import metrics
 from desktop.auth.backend import DesktopBackendBase
 from desktop.auth.backend import DesktopBackendBase
 from desktop.auth.backend import rewrite_user
 from desktop.auth.backend import rewrite_user
 from useradmin.models import get_profile, get_default_user_group, UserProfile
 from useradmin.models import get_profile, get_default_user_group, UserProfile
@@ -47,6 +48,7 @@ LOG = logging.getLogger(__name__)
 
 
 class OAuthBackend(DesktopBackendBase):
 class OAuthBackend(DesktopBackendBase):
 
 
+  @metrics.oauth_authentication_time
   def authenticate(self, access_token):
   def authenticate(self, access_token):
     username = access_token['screen_name']
     username = access_token['screen_name']
     password = access_token['oauth_token_secret']
     password = access_token['oauth_token_secret']

+ 8 - 0
desktop/libs/libopenid/src/libopenid/backend.py

@@ -17,6 +17,8 @@
 """
 """
 See desktop/auth/backend.py
 See desktop/auth/backend.py
 """
 """
+from __future__ import absolute_import
+
 import logging
 import logging
 import sys
 import sys
 from django.contrib.auth import logout as auth_logout
 from django.contrib.auth import logout as auth_logout
@@ -25,6 +27,7 @@ from django_openid_auth.auth import OpenIDBackend as _OpenIDBackend
 from desktop.auth.backend import rewrite_user
 from desktop.auth.backend import rewrite_user
 from useradmin.models import get_profile, get_default_user_group, UserProfile
 from useradmin.models import get_profile, get_default_user_group, UserProfile
 
 
+from libopenid import metrics
 
 
 LOG = logging.getLogger(__name__)
 LOG = logging.getLogger(__name__)
 
 
@@ -33,6 +36,11 @@ class OpenIDBackend(_OpenIDBackend):
   """
   """
   Wrapper around openid backend.
   Wrapper around openid backend.
   """
   """
+
+  @metrics.openid_authentication_time
+  def authenticate(self, *args, **kwargs):
+    return super(OpenIDBackend, self).authenticate(*args, **kwargs)
+
   def update_user_details(self, user, details, openid_response):
   def update_user_details(self, user, details, openid_response):
     # Do this check up here, because the auth call creates a django user upon first login per user
     # Do this check up here, because the auth call creates a django user upon first login per user
     is_super = False
     is_super = False

+ 25 - 0
desktop/libs/libopenid/src/libopenid/metrics.py

@@ -0,0 +1,25 @@
+# Licensed to Cloudera, Inc. under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  Cloudera, Inc. licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import
+
+from desktop.lib.metrics import global_registry
+
+openid_authentication_time = global_registry().timer(
+    name='desktop.auth.openid.authentication-time',
+    label='OpenID Authentication time',
+    description='Time taken to authenticate a user with OpenID',
+)

+ 10 - 1
desktop/libs/libsaml/src/libsaml/backend.py

@@ -17,6 +17,9 @@
 """
 """
 See desktop/auth/backend.py
 See desktop/auth/backend.py
 """
 """
+
+from __future__ import absolute_import
+
 import logging
 import logging
 from django.contrib.auth import logout as auth_logout
 from django.contrib.auth import logout as auth_logout
 from django.contrib.auth.models import User
 from django.contrib.auth.models import User
@@ -24,9 +27,9 @@ from djangosaml2.backends import Saml2Backend as _Saml2Backend
 from djangosaml2.views import logout as saml_logout
 from djangosaml2.views import logout as saml_logout
 from desktop.auth.backend import rewrite_user
 from desktop.auth.backend import rewrite_user
 from libsaml import conf
 from libsaml import conf
+from libsaml import metrics
 from useradmin.models import get_profile, get_default_user_group, UserProfile
 from useradmin.models import get_profile, get_default_user_group, UserProfile
 
 
-
 LOG = logging.getLogger(__name__)
 LOG = logging.getLogger(__name__)
 
 
 
 
@@ -34,6 +37,12 @@ class SAML2Backend(_Saml2Backend):
   """
   """
   Wrapper around djangosaml2 backend.
   Wrapper around djangosaml2 backend.
   """
   """
+
+  @metrics.saml2_authentication_time
+  def authenticate(self, *args, **kwargs):
+    return super(SAML2Backend, self).authenticate(*args, **kwargs)
+
+
   def update_user(self, user, attributes, attribute_mapping, force_save=False):
   def update_user(self, user, attributes, attribute_mapping, force_save=False):
     # Do this check up here, because the auth call creates a django user upon first login per user
     # Do this check up here, because the auth call creates a django user upon first login per user
     is_super = False
     is_super = False

+ 25 - 0
desktop/libs/libsaml/src/libsaml/metrics.py

@@ -0,0 +1,25 @@
+# Licensed to Cloudera, Inc. under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  Cloudera, Inc. licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import
+
+from desktop.lib.metrics import global_registry
+
+saml2_authentication_time = global_registry().timer(
+    name='desktop.auth.saml2.authentication-time',
+    label='SAML2 Authentication time',
+    description='Time taken to authenticate a user with SAML2',
+)