Просмотр исходного кода

HUE-8523 [jb] Display Impala backends & instances

jdesjean 7 лет назад
Родитель
Сommit
e201177

+ 30 - 0
apps/impala/src/impala/server.py

@@ -251,3 +251,33 @@ class ImpalaDaemonApi(object):
         return resp
     except ValueError, e:
       raise ImpalaDaemonApiException('ImpalaDaemonApi kill did not return valid JSON: %s' % e)
+
+  def get_query_backends(self, query_id):
+    params = {
+      'query_id': query_id,
+      'json': 'true'
+    }
+
+    resp = self._root.get('query_backends', params=params)
+    try:
+      if isinstance(resp, basestring):
+        return json.loads(resp)
+      else:
+        return resp
+    except ValueError, e:
+      raise ImpalaDaemonApiException('ImpalaDaemonApi query_backends did not return valid JSON: %s' % e)
+
+  def get_query_finstances(self, query_id):
+    params = {
+      'query_id': query_id,
+      'json': 'true'
+    }
+
+    resp = self._root.get('query_finstances', params=params)
+    try:
+      if isinstance(resp, basestring):
+        return json.loads(resp)
+      else:
+        return resp
+    except ValueError, e:
+      raise ImpalaDaemonApiException('ImpalaDaemonApi query_finstances did not return valid JSON: %s' % e)

+ 13 - 2
apps/jobbrowser/src/jobbrowser/apis/query_api.py

@@ -122,13 +122,14 @@ class QueryApi(Api):
       'properties': {
         'memory': '',
         'profile': '',
-        'plan': ''
+        'plan': '',
+        'backends': '',
+        'finstances': ''
       }
     })
 
     return app
 
-
   def action(self, appid, action):
     message = {'message': '', 'status': 0}
 
@@ -153,6 +154,10 @@ class QueryApi(Api):
       return self._memory(appid, app_type, app_property, app_filters)
     elif app_property == 'profile':
       return self._query_profile(appid)
+    elif app_property == 'backends':
+      return self._query_backends(appid)
+    elif app_property == 'finstances':
+      return self._query_finstances(appid)
     else:
       return self._query(appid)
 
@@ -168,6 +173,12 @@ class QueryApi(Api):
   def _query_profile(self, appid):
     return self.api.get_query_profile(query_id=appid)
 
+  def _query_backends(self, appid):
+    return self.api.get_query_backends(query_id=appid)
+
+  def _query_finstances(self, appid):
+    return self.api.get_query_finstances(query_id=appid)
+
   def _api_status_filter(self, status):
     if status == 'FINISHED':
       return 'COMPLETED'

+ 1 - 1
apps/jobbrowser/src/jobbrowser/static/jobbrowser/css/jobbrowser-embeddable.css

@@ -14,4 +14,4 @@ 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.
- */.jobbrowser-mini .span12.no-margin{margin-left:0 !important}.jobbrowser-full .content-panel-inner{padding:10px}.jobbrowser-full .jb-breadcrumbs{margin-bottom:0}.jobbrowser-full .jb-panel{padding-left:10px;padding-right:10px}.jobbrowser-components .hue-uncheck::before{padding-left:2px}.jobbrowser-components .tab-content{padding:10px;border:none !important}.jobbrowser-components .hue-breadcrumbs-bar{padding:0}.jobbrowser-components .hue-breadcrumbs-bar li{padding:12px}.jobbrowser-components .hue-breadcrumbs-bar li:first-child{padding-left:0;padding-right:0}.jobbrowser-components .hue-breadcrumbs-bar a{color:#0B7FAD !important;display:inline !important}.jobbrowser-components .divider{color:#C8C8C8;padding-right:12px}.jobbrowser-components .app-icon{vertical-align:text-top}.jobbrowser-components .sidebar-nav .progress{margin-bottom:0}.jobbrowser-components .sidebar-nav .nav-list>li>a{margin-top:0 !important;margin-bottom:0 !important}.jobbrowser-components .sidebar-nav .nav-list li:not(.nav-header){text-overflow:ellipsis;overflow-x:hidden;white-space:nowrap}.jobbrowser-components .query-plan{border:1px solid #DCDCDC}.jobbrowser-components .node rect{stroke:#DCDCDC;fill:#FFFFFF}.jobbrowser-components .edgePath path{stroke:#424242;fill:#424242;stroke-width:1.5px}
+ */.jobbrowser-mini .span12.no-margin{margin-left:0 !important}.jobbrowser-full .content-panel-inner{padding:10px}.jobbrowser-full .jb-breadcrumbs{margin-bottom:0}.jobbrowser-full .jb-panel{padding-left:10px;padding-right:10px}.jobbrowser-components .hue-uncheck::before{padding-left:2px}.jobbrowser-components .tab-content{padding:10px;border:none !important}.jobbrowser-components .hue-breadcrumbs-bar{padding:0}.jobbrowser-components .hue-breadcrumbs-bar li{padding:12px}.jobbrowser-components .hue-breadcrumbs-bar li:first-child{padding-left:0;padding-right:0}.jobbrowser-components .hue-breadcrumbs-bar a{color:#0B7FAD !important;display:inline !important}.jobbrowser-components .divider{color:#C8C8C8;padding-right:12px}.jobbrowser-components .app-icon{vertical-align:text-top}.jobbrowser-components .sidebar-nav .progress{margin-bottom:0}.jobbrowser-components .sidebar-nav .nav-list>li>a{margin-top:0 !important;margin-bottom:0 !important}.jobbrowser-components .sidebar-nav .nav-list li:not(.nav-header){text-overflow:ellipsis;overflow-x:hidden;white-space:nowrap}.jobbrowser-components .query-plan{border:1px solid #DCDCDC}.jobbrowser-components .node rect{stroke:#DCDCDC;fill:#FFFFFF}.jobbrowser-components .edgePath path{stroke:#424242;fill:#424242;stroke-width:1.5px}.jobbrowser-components div[data-jobType="queries"] pre{overflow-x:auto;white-space:pre}

+ 5 - 0
apps/jobbrowser/src/jobbrowser/static/jobbrowser/less/jobbrowser-embeddable.less

@@ -103,4 +103,9 @@
     fill: @cui-gray-800;
     stroke-width: 1.5px;
   }
+
+  div[data-jobType="queries"] pre {
+    overflow-x: auto;
+    white-space: pre;
+  }
 }

+ 58 - 0
apps/jobbrowser/src/jobbrowser/templates/job_browser.mako

@@ -1181,6 +1181,14 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
           <a href="#queries-page-memory${ SUFFIX }" data-bind="click: function(){ $('a[href=\'#queries-page-memory${ SUFFIX }\']').tab('show'); }, event: {'shown': function () { if (!properties.memory || !properties.memory().mem_usage) { fetchProfile('memory'); } } }">
             ${ _('Memory') }</a>
         </li>
+        <li>
+          <a href="#queries-page-backends${ SUFFIX }" data-bind="click: function(){ $('a[href=\'#queries-page-backends${ SUFFIX }\']').tab('show'); }, event: {'shown': function () { if (!properties.backends || !properties.backends().backend_states) { fetchProfile('backends'); } } }">
+            ${ _('Backends') }</a>
+        </li>
+        <li>
+          <a href="#queries-page-finstances${ SUFFIX }" data-bind="click: function(){ $('a[href=\'#queries-page-finstances${ SUFFIX }\']').tab('show'); }, event: {'shown': function () { if (!properties.finstances || !properties.finstances().backend_instances) { fetchProfile('finstances'); } } }">
+            ${ _('Instances') }</a>
+        </li>
       </ul>
 
       <div class="clearfix"></div>
@@ -1211,6 +1219,56 @@ ${ commonheader("Job Browser", "jobbrowser", user, request) | n,unicode }
         <div class="tab-pane" id="queries-page-memory${ SUFFIX }" data-profile="mem_usage">
           <pre data-bind="text: (properties.memory && properties.memory().mem_usage) || _('The selected tab has no data')"/>
         </div>
+        <div class="tab-pane" id="queries-page-backends${ SUFFIX }" data-profile="backends">
+          <!-- ko if: properties.backends && properties.backends().backend_states -->
+          <div id="queries-page-memory-backends-template${ SUFFIX }" style="overflow-x: scroll;">
+            <table class="table table-condensed">
+              <thead>
+              <tr>
+                <!-- ko foreach: Object.keys(properties.backends().backend_states[0]).sort() -->
+                <th data-bind="text: $data"></th>
+                <!-- /ko -->
+              </tr>
+              </thead>
+              <tbody data-bind="foreach: { data: $data.properties.backends().backend_states, minHeight: 20, container: '#queries-page-memory-backends-template${ SUFFIX }'}">
+                <tr>
+                  <!-- ko foreach: Object.keys($data).sort() -->
+                  <td data-bind="text: $parent[$data]"></td>
+                  <!-- /ko -->
+                </tr>
+              </tbody>
+            </table>
+          </div>
+          <!-- /ko -->
+          <!-- ko if: !properties.backends || !properties.backends().backend_states -->
+          <pre data-bind="text: _('The selected tab has no data')"/>
+          <!-- /ko -->
+        </div>
+        <div class="tab-pane" id="queries-page-finstances${ SUFFIX }" data-profile="finstances">
+          <!-- ko if: properties.finstances && properties.finstances().backend_instances -->
+          <div id="queries-page-memory-finstances-template${ SUFFIX }" style="overflow-x: scroll;">
+            <table class="table table-condensed">
+              <thead>
+              <tr>
+                <!-- ko foreach: [_('host')].concat(Object.keys($data.properties.finstances().backend_instances[0].instance_stats[0])).sort() -->
+                <th data-bind="text: $data"></th>
+                <!-- /ko -->
+              </tr>
+              </thead>
+              <tbody data-bind="foreach: { data: $data.properties.finstances().backend_instances.reduce( function(arr, instance) { instance.instance_stats.forEach(function(stats) { stats.host = instance.host; }); return arr.concat(instance.instance_stats); }, []), minHeight: 20, container: '#queries-page-memory-finstances-template${ SUFFIX }'}">
+                <tr>
+                  <!-- ko foreach: Object.keys($data).sort() -->
+                  <td data-bind="text: $parent[$data]"></td>
+                  <!-- /ko -->
+                </tr>
+              </tbody>
+            </table>
+          </div>
+          <!-- /ko -->
+          <!-- ko if: !properties.finstances || !properties.finstances().backend_instances -->
+          <pre data-bind="text: _('The selected tab has no data')"/>
+          <!-- /ko -->
+        </div>
       </div>
     </div>
     <!-- /ko -->

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
desktop/core/src/desktop/static/desktop/css/hue-embedded.css


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
desktop/core/src/desktop/static/desktop/css/hue.css


+ 5 - 1
desktop/core/src/desktop/static/desktop/less/hue4.less

@@ -709,7 +709,7 @@ a:visited {
 }
 
 #mini_jobbrowser {
-  overflow-y: auto;
+  overflow-y: hidden;
   height: 550px;
   max-height: 550px;
   input.search-query {
@@ -730,6 +730,10 @@ a:visited {
   }
 }
 
+#mini_jobbrowser:hover {
+  overflow-y: overlay;
+}
+
 .uploadstatus {
   border: 1px solid @cui-gray-300;
   border-bottom: none;

+ 1 - 1
desktop/core/src/desktop/templates/ko_components/ko_job_browser_links.mako

@@ -155,7 +155,7 @@ from desktop.views import _ko
           success: function (response) {
             params.onePageViewModel.processHeaders(response).done(function (rawHtml) {
               $('#mini_jobbrowser').html(rawHtml);
-              ko.bindingHandlers.delayedOverflow.init($('#mini_jobbrowser')[0]);
+              //ko.bindingHandlers.delayedOverflow.init($('#mini_jobbrowser')[0]);
             });
           }
         });

Некоторые файлы не были показаны из-за большого количества измененных файлов