فهرست منبع

HUE-3808 [core] Offer to live turn on/off debug level

Here is the idea: https://www.dropbox.com/s/9ix1qprb2g8wc7k/demo-live-debug-level.mkv?dl=0

    turn on / off
    show hostname
    restarting Hue removes it, was worried that leaking the state in the os env might bite back
Romain Rigaux 9 سال پیش
والد
کامیت
a50c369b60

+ 29 - 2
desktop/core/src/desktop/log/__init__.py

@@ -34,7 +34,7 @@ from desktop.log.formatter import MessageOnlyFormatter
 DEFAULT_LOG_DIR = 'logs'
 LOG_FORMAT = '[%(asctime)s] %(module)-12s %(levelname)-8s %(message)s'
 DATE_FORMAT = '%d/%b/%Y %H:%M:%S %z'
-
+FORCE_DEBUG = False
 CONF_RE = re.compile('%LOG_DIR%|%PROC_NAME%')
 
 _log_dir = None
@@ -127,6 +127,8 @@ def basic_logging(proc_name, log_dir=None):
 
   This removes all previously installed logging handlers.
   """
+  global FORCE_DEBUG
+
   # Setup log_dir
   if not log_dir:
     log_dir = os.getenv("DESKTOP_LOG_DIR", DEFAULT_LOG_DIR)
@@ -159,7 +161,7 @@ def basic_logging(proc_name, log_dir=None):
 
   # Handle env variables
   env_loglevel = os.getenv("DESKTOP_LOGLEVEL")
-  env_debug = os.getenv('DESKTOP_DEBUG')
+  env_debug = os.getenv('DESKTOP_DEBUG') or FORCE_DEBUG
   if env_debug:
     env_loglevel = 'DEBUG'
 
@@ -197,3 +199,28 @@ def fancy_logging():
   buffer_handler.setFormatter(_formatter)
   root_logger = logging.getLogger()
   root_logger.addHandler(buffer_handler)
+
+
+def get_all_debug():
+  from desktop.settings import ENV_DESKTOP_DEBUG # Circular dependency
+  global FORCE_DEBUG
+
+  return FORCE_DEBUG or os.getenv(ENV_DESKTOP_DEBUG) != None
+
+
+def set_all_debug():
+  from desktop.settings import ENV_DESKTOP_DEBUG, ENV_HUE_PROCESS_NAME # Circular dependency
+  global FORCE_DEBUG
+
+  FORCE_DEBUG = True
+  basic_logging(os.environ[ENV_HUE_PROCESS_NAME])
+  fancy_logging()
+
+
+def reset_all_debug():
+  from desktop.settings import ENV_DESKTOP_DEBUG, ENV_HUE_PROCESS_NAME # Circular dependency
+  global FORCE_DEBUG
+
+  FORCE_DEBUG = False
+  basic_logging(os.environ[ENV_HUE_PROCESS_NAME])
+  fancy_logging()

+ 1 - 1
desktop/core/src/desktop/settings.py

@@ -221,7 +221,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
 # of having multiple apps.  If your app needs
 # to store data related to users, it should
 # manage its own table with an appropriate foreign key.
-AUTH_PROFILE_MODULE=None
+AUTH_PROFILE_MODULE = None
 
 LOGIN_REDIRECT_URL = "/"
 LOGOUT_REDIRECT_URL = "/" # For djangosaml2 bug.

+ 47 - 1
desktop/core/src/desktop/templates/logs.mako

@@ -68,7 +68,14 @@ ${layout.menubar(section='log_view')}
         <input type="text" class="input-xxlarge search-query" placeholder="${_('Search in the logs')}" value="${query}">
       </%def>
       <%def name="creation()">
-        <label class="checkbox" style="display: inline-block; margin-right: 10px"><input id="wrapLogs" type="checkbox" checked="checked">${_('Wrap logs')}</label>
+        ${ _('Host') }: <span style="display: inline-block; margin-right: 10px">${ hostname }</span>
+
+        <label class="checkbox" for="forcedDebug" style="display: inline-block; margin-right: 10px">${_('Force DEBUG level')}</label>
+        <input type="checkbox" id="forcedDebug" data-bind="checked: forcedDebug" style="vertical-align: middle">
+
+        <label class="checkbox" for="wrap" style="display: inline-block; margin-right: 10px">${_('Wrap logs')}</label>
+        <input id="wrapLogs" id="wrap" type="checkbox" checked="checked">
+
         <a href="/desktop/download_logs" class="btn"><i class="fa fa-download"></i> ${_('Download entire log as zip')}</a>
       </%def>
     </%actionbar:render>
@@ -85,8 +92,47 @@ ${layout.menubar(section='log_view')}
 
 </div>
 
+<script src="${ static('desktop/ext/js/knockout.min.js') }" type="text/javascript" charset="utf-8"></script>
+
+
 <script>
+  var LiveDebugging = function () {
+    var self = this;
+
+    self.forcedDebug = ko.observable(false);
+    self.forcedDebug.subscribe(function(newValue) {
+      self.toggleLogLevel();
+    });
+
+    self.getDebugLevel = function() {
+      $.get("/desktop/get_debug_level", function(data) { self.forcedDebug(data.debug_all); });
+    };
+
+    self.toggleLogLevel = function() {
+      var _url = "";
+      if (self.forcedDebug()) {
+        _url = "/desktop/set_all_debug";
+      } else {
+        _url = "/desktop/reset_all_debug";
+      }
+
+      $.post(_url, {}, function(data) {
+        if (data,status != 0) {
+          $(document).trigger("error", data.message);
+        }
+      }).fail(function (xhr, textStatus, errorThrown) {
+        $(document).trigger("error", xhr.responseText);
+      });
+    };
+  }
+
+  var viewModel;
+
   $(document).ready(function () {
+    viewModel = new LiveDebugging();
+    ko.applyBindings(viewModel);
+
+    viewModel.getDebugLevel();
 
     resizeScrollingLogs();
 

+ 3 - 0
desktop/core/src/desktop/urls.py

@@ -75,6 +75,9 @@ dynamic_patterns += patterns('desktop.views',
   (r'^logs$','log_view'),
   (r'^desktop/dump_config$','dump_config'),
   (r'^desktop/download_logs$','download_log_view'),
+  (r'^desktop/get_debug_level','get_debug_level'),
+  (r'^desktop/set_all_debug','set_all_debug'),
+  (r'^desktop/reset_all_debug','reset_all_debug'),
   (r'^bootstrap.js$', 'bootstrap'), # unused
 
   (r'^desktop/prefs/(?P<key>\w+)?$', 'prefs'),

+ 32 - 3
desktop/core/src/desktop/views.py

@@ -20,6 +20,7 @@ import json
 import logging
 import os
 import re
+import socket
 import sys
 import tempfile
 import time
@@ -33,7 +34,7 @@ from django.core.urlresolvers import reverse
 from django.core.servers.basehttp import FileWrapper
 from django.shortcuts import redirect
 from django.utils.translation import ugettext as _
-from django.views.decorators.http import require_http_methods
+from django.views.decorators.http import require_http_methods, require_POST
 import django.views.debug
 
 import desktop.conf
@@ -49,10 +50,12 @@ from desktop.lib.i18n import smart_str
 from desktop.lib.paths import get_desktop_root
 from desktop.lib.thread_util import dump_traceback
 from desktop.log.access import access_log_level, access_warn
+from desktop.log import set_all_debug as _set_all_debug, reset_all_debug as _reset_all_debug, get_all_debug as _get_all_debug
 from desktop.models import UserPreferences, Settings
 from desktop import appmanager
 
 
+
 LOG = logging.getLogger(__name__)
 
 
@@ -99,12 +102,13 @@ def log_view(request):
   if not request.user.is_superuser:
     return HttpResponse(_("You must be a superuser."))
 
+  hostname = socket.gethostname()
   l = logging.getLogger()
   for h in l.handlers:
     if isinstance(h, desktop.log.log_buffer.FixedBufferHandler):
-      return render('logs.mako', request, dict(log=[l for l in h.buf], query=request.GET.get("q", "")))
+      return render('logs.mako', request, dict(log=[l for l in h.buf], query=request.GET.get("q", ""), hostname=hostname))
 
-  return render('logs.mako', request, dict(log=[_("No logs found!")], query=''))
+  return render('logs.mako', request, dict(log=[_("No logs found!")], query='', hostname=hostname))
 
 @access_log_level(logging.WARN)
 def download_log_view(request):
@@ -523,6 +527,31 @@ def check_config_ajax(request):
                 dict(error_list=error_list),
                 force_template=True)
 
+
+def get_debug_level(request):
+  return JsonResponse({'status': 0, 'debug_all': _get_all_debug()})
+
+
+@require_POST
+def set_all_debug(request):
+  if not request.user.is_superuser:
+    return JsonResponse({'status': 1, 'message': _('You must be a superuser.')})
+
+  _set_all_debug()
+
+  return JsonResponse({'status': 0, 'debug_all': True})
+
+
+@require_POST
+def reset_all_debug(request):
+  if not request.user.is_superuser:
+    return JsonResponse({'status': 1, 'message': _('You must be a superuser.')})
+
+  _reset_all_debug()
+
+  return JsonResponse({'status': 0, 'debug_all': False})
+
+
 # This is a global non-view for inline KO i18n
 def _ko(str=""):
   return _(str).replace("'", "\\'")