Эх сурвалжийг харах

HUE-7691 [core] Integrate Metrics as page on /about page

Roohi 8 жил өмнө
parent
commit
786000d

+ 5 - 2
desktop/core/src/desktop/lib/metrics/views.py

@@ -21,7 +21,7 @@ import json
 
 from django.views.decorators.http import require_GET
 
-from desktop.lib.django_util import JsonResponse, login_notrequired
+from desktop.lib.django_util import JsonResponse, login_notrequired, render
 from desktop.lib.metrics.registry import global_registry
 
 
@@ -41,4 +41,7 @@ def index(request):
       'metric': global_registry().dump_metrics(),
   }
   LOG.debug('Metrics: %s' % json.dumps(rep, indent=indent))
-  return JsonResponse(rep, json_dumps_params={'indent': indent})
+  if request.is_ajax():
+    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)})

+ 3 - 0
desktop/core/src/desktop/templates/about_layout.mako

@@ -49,6 +49,9 @@ def is_selected(section, matcher):
                 <li class="${is_selected(section, 'threads')}">
                   <a href="${ url('desktop.views.threads') }">${_('Threads')}</a>
                 </li>
+                <li class="${is_selected(section, 'metrics')}">
+                  <a href="${ url('desktop.lib.metrics.views.index') }">${_('Metrics')}</a>
+                </li>
               % endif
             </ul>
           </div>

+ 3 - 0
desktop/core/src/desktop/templates/hue.mako

@@ -360,6 +360,7 @@ ${ hueIcons.symbols() }
       <div id="embeddable_logs" class="embeddable"></div>
       <div id="embeddable_dump_config" class="embeddable"></div>
       <div id="embeddable_threads" class="embeddable"></div>
+      <div id="embeddable_metrics" class="embeddable"></div>
       <div id="embeddable_403" class="embeddable"></div>
       <div id="embeddable_404" class="embeddable"></div>
       <div id="embeddable_500" class="embeddable"></div>
@@ -593,6 +594,7 @@ ${ smart_unicode(login_modal(request).content) | n,unicode }
         logs: { url: '/logs', title: '${_('Logs')}' },
         dump_config: { url: '/desktop/dump_config', title: '${_('Dump Configuration')}' },
         threads: { url: '/desktop/debug/threads', title: '${_('Threads')}' },
+        metrics: { url: '/desktop/metrics', title: '${_('Metrics')}' },
         sqoop: { url: '/sqoop', title: '${_('Sqoop')}' },
         jobsub: { url: '/jobsub/not_available', title: '${_('Job Designer')}' },
         % if other_apps:
@@ -952,6 +954,7 @@ ${ smart_unicode(login_modal(request).content) | n,unicode }
           { url: '/dashboard/*', app: 'dashboard' },
           { url: '/desktop/dump_config', app: 'dump_config' },
           { url: '/desktop/debug/threads', app: 'threads' },
+          { url: '/desktop/metrics', app: 'metrics' },
           { url: '/desktop/download_logs', app: function () {
             location.href = '/desktop/download_logs';
           }},

+ 121 - 0
desktop/core/src/desktop/templates/metrics.mako

@@ -0,0 +1,121 @@
+## 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 desktop.views import commonheader, commonfooter
+from django.utils.translation import ugettext as _
+from desktop import conf
+%>
+
+<%
+MAIN_SCROLLABLE = is_embeddable and ".page-content" or ".content-panel"
+if conf.CUSTOM.BANNER_TOP_HTML.get():
+  TOP_SNAP = is_embeddable and "78px" or "106px"
+else:
+  TOP_SNAP = is_embeddable and "50px" or "74px"
+%>
+
+<%namespace name="actionbar" file="actionbar.mako" />
+<%namespace name="layout" file="about_layout.mako" />
+
+%if not is_embeddable:
+${ commonheader(_('Metrics'), "about", user, request) | n,unicode }
+%endif
+
+
+<script type="text/javascript">
+
+
+  var MetricsViewModel = function () {
+    var self = this;
+    self.metricsFilter = ko.observable();
+    self.metrics = ${metrics | n,unicode};
+    self.selectedSubMetric = ko.observable(Object.keys(self.metrics)[0]);
+    self.filteredMetrics = ko.pureComputed(function () {
+      if (self.metricsFilter()) {
+        var lowerQuery = self.metricsFilter().toLowerCase();
+        var result = {};
+        Object.keys(self.metrics).forEach(function (key) {
+          var filteredSubMetric = {};
+          var atleastOne = false;
+          Object.keys(self.metrics[key]).forEach(function (subMetricKey) {
+            if (subMetricKey.toLowerCase().indexOf(lowerQuery) !== -1) {
+              filteredSubMetric[subMetricKey] = self.metrics[key][subMetricKey];
+              atleastOne = true;
+            }
+          });
+          if (atleastOne) {
+            result[key] = filteredSubMetric;
+          }
+         });
+        return result;
+      }
+      return self.metrics;
+     });
+  }
+
+  $(document).ready(function () {
+    var metricsViewModel = new MetricsViewModel();
+    ko.cleanNode(document.getElementById("metricsComponent"));
+    ko.applyBindings(metricsViewModel, document.getElementById('metricsComponent'));
+  });
+
+ </script>
+
+${layout.menubar(section='metrics')}
+
+<div id="metricsComponent" class="container-fluid">
+ <span class="card card-small" style="padding-top: 10px">
+  <br>
+  <div data-bind="dockable: { scrollable: '${ MAIN_SCROLLABLE }', jumpCorrection: 0,topSnap: '${ TOP_SNAP }'}">
+   <!-- ko if: $data.metrics -->
+   <ol class="breadcrumb" data-bind="foreach: {'data': Object.keys($data.metrics)}">
+     <li><a href="" data-bind="text: $data,click: function(){$root.selectedSubMetric(this)}"/></li>
+   </ol><!-- /ko -->
+    <br>
+    <!-- ko hueSpinner: { spin: !$data.filteredMetrics(), center: true, size: 'xlarge' } --><!-- /ko -->
+    <form class="form-search">
+      <input type="text" data-bind="clearable: metricsFilter, valueUpdate: 'afterkeydown'"
+             class="input-xlarge search-query float-right" placeholder="${_('Filter metrics...')}">
+    </form>
+  </div>
+  <br>
+  <div>
+    <strong data-bind="text: $data.selectedSubMetric()"/>
+    <table class="table table-condensed">
+     <thead>
+      <tr>
+        <th>${ _('Name') }</th>
+        <th>${ _('Value') }</th>
+      </tr>
+     </thead>
+     <!-- ko if: $data.filteredMetrics()[$data.selectedSubMetric()] -->
+     <tbody data-bind="foreach: {'data': Object.keys($data.filteredMetrics()[$data.selectedSubMetric()])}">
+      <tr>
+        <td data-bind="text: $data"></td>
+        <td data-bind="text: $parent.filteredMetrics()[$parent.selectedSubMetric()][$data]"></td>
+      </tr>
+      </tbody>
+     <!-- /ko -->
+    </table>
+  </div>
+
+ </span>
+</div>
+
+
+%if not is_embeddable:
+${ commonfooter(request, messages) | n,unicode }
+%endif