Explorar o código

HUE-8674 [jb] Added overview details on profile.

jdesjean %!s(int64=6) %!d(string=hai) anos
pai
achega
60dc8c9

+ 4 - 4
apps/jobbrowser/src/jobbrowser/apis/query_api.py

@@ -191,9 +191,9 @@ class QueryApi(Api):
         if re.search(r'broadcast', o['label_detail'], re.IGNORECASE):
           return { 'svg': 'hi-broadcast' }
         elif re.search(r'hash', o['label_detail'], re.IGNORECASE):
-          return { 'font': 'fa-random' }
+          return { 'svg': 'hi-random' }
         else:
-          return { 'font': 'fa-exchange' }
+          return { 'svg': 'hi-exchange' }
       def get_sigma_icon (o):
         if re.search(r'streaming', o['label_detail'], re.IGNORECASE):
           return { 'svg': 'hi-sigma-stream' }
@@ -204,8 +204,8 @@ class QueryApi(Api):
         'SORT': { 'type': 'SORT', 'icon': { 'svg': 'hi-sort' } },
         'MERGING-EXCHANGE': {'type': 'EXCHANGE', 'icon': { 'fn': get_exchange_icon } },
         'EXCHANGE': { 'type': 'EXCHANGE', 'icon': { 'fn': get_exchange_icon } },
-        'SCAN HDFS': { 'type': 'SCAN_HDFS', 'icon': { 'font': 'fa-files-o' } },
-        'SCAN KUDU': { 'type': 'SCAN_KUDU', 'icon': { 'font': 'fa-table' } },
+        'SCAN HDFS': { 'type': 'SCAN_HDFS', 'icon': { 'svg': 'hi-copy' } },
+        'SCAN KUDU': { 'type': 'SCAN_KUDU', 'icon': { 'font': 'hi-table' } },
         'SCAN HBASE': { 'type': 'SCAN_HBASE', 'icon': { 'font': 'fa-th-large' } },
         'HASH JOIN': { 'type': 'HASH_JOIN', 'icon': { 'svg': 'hi-join' } },
         'AGGREGATE': { 'type': 'AGGREGATE', 'icon': { 'fn': get_sigma_icon } },

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
apps/jobbrowser/src/jobbrowser/static/jobbrowser/css/jobbrowser-embeddable.css


+ 106 - 72
apps/jobbrowser/src/jobbrowser/static/jobbrowser/js/impala_dagre.js

@@ -58,8 +58,8 @@ function impalaDagre(id) {
 
   function createActions () {
     svg.on('click', function () {
-      hideDetail();
       clearSelection();
+      showDetailGlobal();
     });
     d3.select("#"+id)
       .style('position', 'relative')
@@ -172,11 +172,13 @@ function impalaDagre(id) {
   }
 
   function getNode(id) {
-    return _impalaDagree._plan && _impalaDagree._plan.metrics && _impalaDagree._plan.metrics.nodes[id];
+    return _impalaDagree._plan && _impalaDagree._plan.metrics && (_impalaDagree._plan.metrics.nodes[id] || _impalaDagree._plan.metrics[id]);
   }
 
   function getId(key) {
-    return parseInt(key.split(':')[0], 10);
+    var id = key.split(':')[0];
+    var nid = parseInt(id, 10);
+    return Number.isNaN(nid) ? id : nid;
   }
 
   function getKey(node) {
@@ -244,7 +246,10 @@ function impalaDagre(id) {
     }
     var timeline = node.timeline;
     var hosts = getProperty(node, path);
-    if (timeline[minmax]) {
+    if (!hosts) {
+      return '';
+    }
+    if (timeline[minmax] && hosts[timeline[minmax]]) {
       return hosts[timeline[minmax]][metric];
     } else {
       return Object.keys(hosts).filter(function (key) { return key !== 'averaged'; }).reduce(function (previous, host) {
@@ -289,16 +294,12 @@ function impalaDagre(id) {
 
   // This is not exact, but shows some approximation of reality.
   function getCPUTimelineData(key) {
-    var datum = getTimelineData(key);
-    if (!datum || !datum.hosts[datum.min] || !datum.hosts[datum.min]['Node Lifecycle Event Timeline']) {
+    var timeline = getTimelineData(key);
+    if (!timeline) {
       return;
     }
     var id = getId(key);
     var localTime = getMaxValue(key, 'LocalTime');
-    var timeline = datum.hosts[datum.min]['Node Lifecycle Event Timeline'];
-    if (!timeline.length) {
-      return;
-    }
     var last = timeline.filter(function(time) {
       return time.name !== 'Closed';
     }); // Close time is normally wait time;
@@ -322,10 +323,14 @@ function impalaDagre(id) {
       time = { start_time: openFinished.start_time + middle, duration: localTime.value, value: openFinished.value - middle, unit: last.unit, clazz: 'cpu', name: window.HUE_I18n.profile.cpu };
     } else if (key.indexOf('UNION') >= 0 || (key.indexOf('AGGREGATE') >= 0 && states_by_name[key].detail.indexOf('STREAMING') >= 0)) {
       time = { start_time: openFinished.value, duration: localTime.value, value: localTime.value + openFinished.value, unit: last.unit, clazz: 'cpu', name: window.HUE_I18n.profile.cpu };
-    } else if (key.indexOf('SCAN') >= 0 && firstBatchReturned) {
+    } else if (key.indexOf('SCAN') >= 0) {
       var doublet = getScanCPUIOTimelineData(key);
       var doubletSum = sum(doublet, 'value');
-      time = [{ start_time: firstBatchReturned.start_time, duration: doublet[0].value, value: firstBatchReturned.start_time + doublet[0].value, unit: last.unit, clazz: 'io', name: window.HUE_I18n.profile.io }, { start_time: firstBatchReturned.start_time + doublet[0].value, duration: doublet[1].value, value: firstBatchReturned.start_time + doubletSum, unit: last.unit, clazz: 'cpu', name: window.HUE_I18n.profile.cpu }];
+      if (firstBatchReturned && firstBatchReturned.start_time + doubletSum < last.value) {
+        time = [{ start_time: firstBatchReturned.start_time, duration: doublet[0].value, value: firstBatchReturned.start_time + doublet[0].value, unit: last.unit, clazz: 'io', name: window.HUE_I18n.profile.io }, { start_time: firstBatchReturned.start_time + doublet[0].value, duration: doublet[1].value, value: firstBatchReturned.start_time + doubletSum, unit: last.unit, clazz: 'cpu', name: window.HUE_I18n.profile.cpu }];
+      } else {
+        time = [{ start_time: last.value - doubletSum, duration: doublet[0].value, value: last.value - doublet[1].value, unit: last.unit, clazz: 'io', name: window.HUE_I18n.profile.io }, { start_time: last.value - doublet[1].value, duration: doublet[1].value, value: last.value, unit: last.unit, clazz: 'cpu', name: window.HUE_I18n.profile.cpu }];
+      }
     } else {
       time = { start_time: last.value - localTime.value, duration: localTime.value, value: last.value, unit: last.unit, clazz: 'cpu', name: window.HUE_I18n.profile.cpu };
     }
@@ -337,16 +342,14 @@ function impalaDagre(id) {
     if (!timeline) {
       return timeline;
     }
-    var fragment = getFragment(key);
-    if (fragment) {
-      return timeline;
-    }
     var initTime = getMaxFragmentMetric(key, 'TotalTime', 'children.CodeGen.hosts');
     if (!initTime) {
       return timeline;
     }
     initTime.duration = initTime.value;
     initTime.name = window.HUE_I18n.profile.codegen;
+    initTime.color = colors[2];
+    initTime.start_time = 0;
     return [initTime].concat(timeline);
   }
 
@@ -365,6 +368,16 @@ function impalaDagre(id) {
     return [ioTime, cpuExchange];
   }
 
+  function getTopNodes() {
+    return Object.keys(states_by_name).map(function (key) {
+      var timeline = getCPUTimelineData(key);
+      var sumTime = sum(timeline, 'duration')
+      return { name: states_by_name[key].label, duration: sumTime, unit: 5, key: key, icon: states_by_name[key].icon  };
+    }).sort(function (a, b) {
+      return b.duration - a.duration;
+    });
+  }
+
   function getExchangeCPUIOTimelineData(key) {
     var id = getId(key);
     var node = getNode(id);
@@ -382,54 +395,78 @@ function impalaDagre(id) {
     return [ krpcTime, networkTime, cpuExchange];
   }
 
-  function getTimelineData(key) {
+  function getTimelineData(key, name) {
     var id = getId(key);
     var node = getNode(id);
-    if (!node || !node.timeline) {
-      return;
+    if (!name) {
+      name = 'Node Lifecycle Event Timeline';
     }
-    var timeline = node.timeline;
-    var times = Object.keys(timeline.hosts);
-    for (var i = 0; i < times.length; i++) {
-      if (!timeline.hosts[times[i]]['Node Lifecycle Event Timeline']) {
-        continue;
-      }
-      timeline.hosts[times[i]]['Node Lifecycle Event Timeline'].forEach(function (time, index, array) {
-        time.color = colors[index % colors.length];
-        return time;
-      });
-    }
-    return timeline;
+    return node && node.timeline && ((node.timeline.hosts && node.timeline.hosts[node.timeline.min]) || node.timeline)[name];
+  }
+  
+  function getMinData(data) {
+    return data && ((data.hosts && data.hosts[data.min]) || data);
   }
 
-  function renderTimeline(key) {
-    var datum = getTimelineData(key);
-    if (!datum || !datum.hosts[datum.min] || !datum.hosts[datum.min]['Node Lifecycle Event Timeline']) {
+  function renderTimeline(timeline, max) {
+    if (!timeline) {
       return '';
     }
-    var end = getMetricsMax() || 10;
+    var end = max || timeline[timeline.length - 1].value;
     var divider = end > 33554428 ? 1000000 : 1; // values are in NS, scaling to MS as max pixel value is 33554428px ~9h in MS
     var html = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' + (end / divider) + ' 10" class="timeline" preserveAspectRatio="none">';
-    html += datum.hosts[datum.min]['Node Lifecycle Event Timeline'].map(function(time, index) {
-      return '<rect x="' + (time.start_time / divider) + '" width="' + (time.duration / divider)  + '" height="10" style="fill:' + time.color  +'"></rect>';
+    html += timeline.map(function(time, index) {
+      var clazz = time.clazz ? 'class="' + time.clazz + '"' : '';
+      var fill = time.clazz ? '' : 'style="fill:' + (time.color || colors[index % colors.length]) + '"';
+      return '<rect ' + clazz + ' x="' + (time.start_time / divider) + '" width="' + (time.duration / divider)  + '" height="10" ' + fill + '></rect>';
     }).join('');
     html += '</svg>';
     return html;
   }
 
-  function renderCPUTimeline(key) {
-    var datum = getCPUTimelineData(key);
-    if (!datum) {
-      return '';
+  function showDetailGlobal() {
+    var details = d3.select('.query-plan .details');
+    var key = getKey(id);
+    details.html('<header class="metric-title">' + getIcon({ svg: 'hi-sitemap' }) + '<h4>' + window.HUE_I18n.profile.overview + '</h4></div>')
+    var detailsContent = details.append('div').classed('details-content', true);
+
+    var topNodes = getTopNodes();
+    if (topNodes && topNodes.length) {
+      var cpuTimelineSection = detailsContent.append('div').classed('details-section', true);
+      var cpuTimelineTitle = cpuTimelineSection.append('header');
+      cpuTimelineTitle.append('svg').classed('hi', true).append('use').attr('xlink:href', '#hi-filter');
+      cpuTimelineTitle.append('h5').text(window.HUE_I18n.profile.topnodes + ' (' + ko.bindingHandlers.numberFormat.human(getMetricsMax(), 5) + ')');
+      var cpuTimelineSectionTable = cpuTimelineSection.append('table').classed('clickable', true);
+      var cpuTimelineSectionTableRows = cpuTimelineSectionTable.selectAll('tr').data(topNodes).enter().append('tr').on('click', function (node) {
+        select(node.key);
+        zoomToNode(node.key);
+      });
+      cpuTimelineSectionTableRows.append('td').html(function (time) { return '' + getIcon(time.icon) + '<div class="metric-name" title="' + time.name + '">' + time.name + '</div>'; });
+      cpuTimelineSectionTableRows.append('td').text(function (datum) { return ko.bindingHandlers.numberFormat.human(datum.duration, datum.unit); });
+    }
+
+    appendTimelineAndLegend(detailsContent, getTimelineData('summary', 'Query Compilation'), 'Compilation', null);
+    appendTimelineAndLegend(detailsContent, getTimelineData('summary', 'Query Timeline'), window.HUE_I18n.profile.execution, null);
+
+    d3.select('.query-plan .details .metric-title').on('click', function () {
+      toggleDetails();
+    });
+  }
+
+  function appendTimelineAndLegend(detailsContent, data, title, max) {
+    var timeline = renderTimeline(data, max);
+    if (timeline) {
+      var executionSum = sum(data, 'duration');
+      var cpuTimelineSection = detailsContent.append('div').classed('details-section', true);
+      var cpuTimelineTitle = cpuTimelineSection.append('header');
+      cpuTimelineTitle.append('svg').classed('hi', true).append('use').attr('xlink:href', '#hi-access-time');
+      cpuTimelineTitle.append('h5').text(title + ' (' + ko.bindingHandlers.numberFormat.human(executionSum, 5) + ')');
+      cpuTimelineSection.node().appendChild($.parseXML(timeline).children[0]);
+
+      var cpuTimelineSectionTable = cpuTimelineSection.append('table').classed('column', true);
+      cpuTimelineSectionTable.append('tr').selectAll('td').data(data).enter().append('td').html(function (time, index) { return '<div class="legend-icon ' + (time.clazz ? time.clazz : '') + '" style="' + (!time.clazz && 'background-color: ' + (time.color || colors[index % colors.length])) + '"></div><div class="metric-name" title="' + time.name + '">' + time.name + '</div>'; });
+      cpuTimelineSectionTable.append('tr').selectAll('td').data(data).enter().append('td').text(function (datum) { return ko.bindingHandlers.numberFormat.human(datum.duration, datum.unit); });
     }
-    var end = getMetricsMax() || 10;
-    var divider = end > 33554428 ? 1000000 : 1; // values are in NS, scaling to MS as max pixel value is 33554428px ~9h in MS
-    var html = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' + (end / divider) + ' 10" class="timeline" preserveAspectRatio="none">';
-    html += datum.map(function(time, index) {
-      return '<rect class="' + time.clazz + '" x="' + (time.start_time / divider) + '" width="' + (time.duration / divider)  + '" height="10"></rect>';
-    }).join('');
-    html += '</svg>';
-    return html;
   }
 
   function showDetail(id) {
@@ -446,22 +483,8 @@ function impalaDagre(id) {
     details.html('<header class="metric-title">' + getIcon(states_by_name[key].icon) + '<h4>' + states_by_name[key].label+ '</h4></div>')
     var detailsContent = details.append('div').classed('details-content', true);
 
-    var executionTimeline = renderCPUTimeline(key);
-    var executionTimelineData = getExecutionTimelineData(key);
-    if (executionTimeline) {
-      var executionSum = sum(executionTimelineData, 'duration');
-      var cpuTimelineSection = detailsContent.append('div').classed('details-section', true);
-      var cpuTimelineTitle = cpuTimelineSection.append('header');
-      cpuTimelineTitle.append('svg').classed('hi', true).append('use').attr('xlink:href', '#hi-access-time');
-      cpuTimelineTitle.append('h5').text(window.HUE_I18n.profile.execution + ' (' + ko.bindingHandlers.numberFormat.human(executionSum, 5) + ')');
-      cpuTimelineSection.node().appendChild($.parseXML(executionTimeline).children[0]);
-
-      var cpuTimelineSectionTable = cpuTimelineSection.append('table');
-      cpuTimelineSectionTable.append('tr').selectAll('td').data(executionTimelineData).enter().append('td').html(function (time) { return '<div class="legend-icon ' + time.clazz + '"></div><div class="metric-name" title="' + time.name + '">' + time.name + '</div>'; });
-      cpuTimelineSectionTable.append('tr').selectAll('td').data(executionTimelineData).enter().append('td').text(function (datum) { return ko.bindingHandlers.numberFormat.human(datum.duration, datum.unit); });
-    }
-
-    var timeline = renderTimeline(key, '');
+    appendTimelineAndLegend(detailsContent, getExecutionTimelineData(key), window.HUE_I18n.profile.execution, getMetricsMax());
+    var timeline = renderTimeline(getTimelineData(key), getMetricsMax());
     if (timeline) {
       var timelineSection = detailsContent.append('div').classed('details-section', true);
       var timelineTitle = timelineSection.append('header');
@@ -469,13 +492,13 @@ function impalaDagre(id) {
       timelineTitle.append('h5').text(window.HUE_I18n.profile.timeline);
       timelineSection.node().appendChild($.parseXML(timeline).children[0]);
 
-      var timelineSectionTable = timelineSection.append('table');
+      var timelineSectionTable = timelineSection.append('table').classed('column', true);
       timelineSectionTable.append('thead').selectAll('tr').data(['\u00A0'].concat(Object.keys(node.timeline.hosts).sort())).enter().append('tr').append('td').text(function (host, i) { return i > 0 ? 'Host ' + i : host; }).attr('title', function (host) { return host; });
       var timelineSectionTableBody = timelineSectionTable.append('tbody');
       var timelineHosts = Object.keys(node.timeline.hosts).sort().map(function (host) { return node.timeline.hosts[host]; });
       var timelineSectionTableCols = timelineSectionTableBody.selectAll('tr').data(timelineHosts);
       var timelineSectionTableCol0 = timelineSectionTableBody.selectAll('tr').data(timelineHosts.slice(0,1));
-      timelineSectionTableCol0.enter().append('tr').selectAll('td').data(function (x) { return x['Node Lifecycle Event Timeline']; }).enter().append('td').html(function (time) { return '<div class="legend-icon" style="background-color:' + time.color +' "></div><div class="metric-name" title="' + time.name + '">' + time.name + '</div>'; });
+      timelineSectionTableCol0.enter().append('tr').selectAll('td').data(function (x) { return x['Node Lifecycle Event Timeline']; }).enter().append('td').html(function (time, index) { return '<div class="legend-icon" style="background-color:' + colors[index % colors.length]+' "></div><div class="metric-name" title="' + time.name + '">' + time.name + '</div>'; });
       timelineSectionTableCols.enter().append('tr').selectAll('td').data(function (x) { return x['Node Lifecycle Event Timeline']; }).enter().append('td').text(function (datum) { return ko.bindingHandlers.numberFormat.human(datum.duration, datum.unit); });
     }
 
@@ -486,7 +509,7 @@ function impalaDagre(id) {
     metricsTitle.append('svg').classed('hi', true).append('use').attr('xlink:href', '#hi-bar-chart');
     metricsTitle.append('h5').text(window.HUE_I18n.profile.metrics);
 
-    var metricsContent = metricsSection.append('table').classed('metrics', true);
+    var metricsContent = metricsSection.append('table').classed('column metrics', true);
     var metricsHosts = Object.keys(data.properties.hosts).sort().map(function (key) { return data.properties.hosts[key]; });
     var metricsCols = metricsContent.selectAll('tr').data(metricsHosts);
     var metricsCols0 = metricsContent.selectAll('tr').data(metricsHosts.slice(0,1));
@@ -496,13 +519,17 @@ function impalaDagre(id) {
 
     var metricsChildSectionsContent = metricsChildSections.enter().append('div');
     metricsChildSectionsContent.append('header').append('h5').text(function (key) { return key; });
-    var metricsChildSectionsContentTable = metricsChildSectionsContent.append('table').classed('metrics', true);
+    var metricsChildSectionsContentTable = metricsChildSectionsContent.append('table').classed('column metrics', true);
     var fChildrenHosts = function (key) { return Object.keys(data.children[key].hosts).sort().map(function (host) { return data.children[key].hosts[host]; }); };
     var metricsChildSectionsContentCols = metricsChildSectionsContentTable.selectAll('tr').data(function (key) { return fChildrenHosts(key); });
     var metricsChildSectionsContentCols0 = metricsChildSectionsContentTable.selectAll('tr').data(function (key) { return fChildrenHosts(key).slice(0,1); });
     metricsChildSectionsContentCols0.enter().append('tr').selectAll('td').data(function (host) { return Object.keys(host).sort(); }).enter().append('td').text(function (x) { return x; }).attr('title', function (x) { return x; });
     metricsChildSectionsContentCols.enter().append('tr').selectAll('td').data(function (x) { return Object.keys(x).sort().map(function (key) {return x[key]; }) }).enter().append('td').text(function(datum) { return ko.bindingHandlers.numberFormat.human(datum.value, datum.unit);});
     metricsChildSectionsContentTable.append('thead').selectAll('tr').data(function (key) { return ['\u00A0'].concat(Object.keys(data.children[key].hosts).sort()); }).enter().append('tr').append('td').text(function (x, i) { return i > 0 ? x === 'averaged' ? x : 'Host ' + (i - 1) : x; }).attr('title', function (x) {return x;});
+
+    d3.select('.query-plan .details .metric-title').on('click', function () {
+      toggleDetails();
+    });
   }
 
   function hideDetail(id) {
@@ -540,13 +567,17 @@ function impalaDagre(id) {
     return (avg1 * count1 + avg2 * count2) / (count1 + count2);
   }
 
+  function toggleDetails() {
+    var queryPlan = d3.select('.query-plan');
+    queryPlan.classed('open', !queryPlan.classed('open'));
+  }
+
   function renderGraph() {
     var plan = _impalaDagree._plan;
     if (!plan || !plan.plan_json.plan_nodes || !plan.plan_json.plan_nodes.length) return;
     var states = [];
     var edges = [];
     var colour_idx = 0;
-
     var max_node_time = 0;
     plan.plan_json["plan_nodes"].forEach(function(parent) {
       max_node_time = Math.max(
@@ -554,6 +585,7 @@ function impalaDagre(id) {
       // Pick a new colour for each plan fragment
       colour_idx = (colour_idx + 1) % colours.length;
     });
+    showDetailGlobal();
     var avgStates = average(states, 'max_time_val');
     var edgesIO = edges.filter(function (edge) {
       return edge.content.unit === 5;
@@ -578,7 +610,7 @@ function impalaDagre(id) {
         html += "<span class='detail'>" + state.predicates + "</span><br/>";
       }
       html += "<span class='id'>" + state.name + "</span></span>";
-      html += renderCPUTimeline(state.name);
+      html += renderTimeline(getCPUTimelineData(state.name), getMetricsMax());
       html += "</div>";
 
       var style = state.style;
@@ -605,6 +637,9 @@ function impalaDagre(id) {
       var node = g.node(v);
       node.rx = node.ry = 5;
     });
+    d3.select('.query-plan .details .metric-title').on('click', function () {
+      toggleDetails();
+    });
 
     // Create the renderer
     var render = new dagreD3.render();
@@ -616,7 +651,6 @@ function impalaDagre(id) {
     if (is_first) {
       var initialScale = 1;
       _impalaDagree.init(initialScale);
-      svg.attr('height', Math.min(g.graph().height * initialScale + 40, 600));
       is_first = false;
     }
 

+ 64 - 39
apps/jobbrowser/src/jobbrowser/static/jobbrowser/less/jobbrowser-embeddable.less

@@ -135,19 +135,9 @@
       width: 2.2em !important;
       height: 2.2em !important;
     }
-    .buttons {
-      .hi {
-        color: @cui-gray-600 !important;
-        width: 2.2em !important;
-        height: 2.2em !important;
-        padding-left: 2px;
-      }
-      .divider {
-        background-color: @cui-gray-300;
-        width: 10px;
-        height: 1px;
-        margin-left: 5px;
-      }
+    .clickable .hi {
+      width: 1.4em !important;
+      height: 1.4em !important;
     }
     .id {
       display: none;
@@ -160,10 +150,18 @@
       }
     }
     .node {
+      cursor: pointer;
+      rect {
+        fill: @cui-white;
+        stroke-width: 1px;
+      }
       rect.active {
         fill: @hue-primary-color-dark;
       }
     }
+    .node:hover rect {
+      fill: @cui-purple-gray-050;
+    }
     .output {
       path,
       .node > rect {
@@ -174,7 +172,7 @@
       position: absolute;
       background-color: white;
       box-shadow: 0px 0px 5px 0px;
-      right: 5px;
+      right: 45px;
       bottom: 5px;
       color: @cui-gray-600;
       div {
@@ -183,14 +181,22 @@
         width: 32px;
         height: 32px;
       }
+      .hi {
+        color: @cui-gray-600 !important;
+        width: 2.2em !important;
+        height: 2.2em !important;
+        padding-left: 2px;
+      }
+      .divider {
+        background-color: @cui-gray-300;
+        width: 10px;
+        height: 1px;
+        margin-left: 5px;
+      }
     }
     .buttons div:hover {
       color: @hue-primary-color-dark;
     }
-    .node rect {
-      fill: @cui-white;
-      stroke-width: 1px
-    }
     .edgePath > path {
       fill: none;
       stroke-width: 1.5px;
@@ -230,9 +236,8 @@
       box-shadow: 0px 0px 10px 0px;
       color: @cui-gray-600;
       position: absolute;
-      display: none;
       top: 0px;
-      right: 0px;
+      right: -164px;
       width: 200px;
       height: 100%;
       flex-direction: column;
@@ -264,6 +269,7 @@
       }
       .details-content {
         overflow: scroll;
+        visibility: hidden;
       }
       .details-section {
         padding: 4px;
@@ -273,6 +279,7 @@
       }
       .metric-title {
         background-color: @hue-primary-color-light;
+        cursor: pointer;
         padding: 4px;
         .fa {
           padding-top: 0px;
@@ -285,7 +292,6 @@
         }
       }
       .metrics {
-        overflow-y: scroll;
         max-height: calc(~"100% - 40px");
       }
       .legend-icon {
@@ -302,44 +308,63 @@
       .details-section .timeline {
         margin-bottom: 10px;
       }
-      table {
-        display: table;
+      table.clickable tr {
+        cursor: pointer;
       }
-      table tr {
-        display: table-cell;
+      table.clickable tr:hover {
+        background-color: @cui-purple-gray-050;
       }
       table tr td {
         color: @cui-gray-800;
         max-width: 107px;
         overflow: hidden;
-        display: block;
         white-space: nowrap;
         padding-right: 5px;
         text-overflow: ellipsis;
       }
-      table thead tr td {
-        background-color: #FFFFFF;
-        border-bottom: 1px solid @cui-gray-300;
-        text-transform: capitalize;
+      table thead tr:nth-child(odd) {
+        background-color:@cui-white;
       }
-      table tr:nth-child(1) td {
+      table tr:nth-child(odd) {
+        background-color: @cui-gray-050;
+      }
+      table.column {
+        display: table;
+      }
+      table.column tr {
+        display: table-cell;
+      }
+      table.column tr td {
+        display: block;
+      }
+      table.column tr:nth-child(1) td {
         border-right: 1px solid @cui-gray-300;
       }
-      table thead tr td:nth-child(odd) {
+      table.column thead tr td:nth-child(odd) {
         background-color:@cui-white;
       }
-      table tr td:nth-child(odd) {
+      table.column tr td:nth-child(odd) {
         background-color: @cui-gray-050;
       }
+      table.column thead tr td {
+        background-color: #FFFFFF;
+        border-bottom: 1px solid @cui-gray-300;
+        text-transform: capitalize;
+      }
     }
   }
-  .query-plan.open .details {
-    display: flex;
-  }
-  .query-plan.open .buttons {
-    right: 208px;
+  .query-plan.open {
+    .details {
+      right: 0px;
+      display: flex;
+      .details-content {
+        visibility: visible;
+      }
+    }
+    .buttons {
+      right: 208px;
+    }
   }
-
   div[data-jobType="queries"] pre {
     overflow-x: auto;
     white-space: pre;

+ 6 - 3
desktop/core/src/desktop/static/desktop/js/ko.hue-bindings.js

@@ -7589,10 +7589,12 @@
           return value + " ns";
         } else if (value - Math.pow(10, 6) < -Math.pow(10, 3) / 2) { // Make sure rounding doesn't cause numbers to have more than 4 significant digits.
           value = (value * 1.0) / Math.pow(10, 3);
-          return sprintf("%.1f us", value);
+          var sprint = value > 100 ? "%i us" : "%.1f us";
+          return sprintf(sprint, value);
         } else if (value - Math.pow(10, 9) < -Math.pow(10, 6) / 2) {
           value = (value * 1.0) / Math.pow(10, 6);
-          return sprintf("%.1f ms", value);
+          var sprint = value > 100 ? "%i ms" : "%.1f ms";
+          return sprintf(sprint, value);
         } else {
           // get the ms value
           var SECOND = 1;
@@ -7612,7 +7614,8 @@
           }
 
           if (value > SECOND) {
-            buffer += sprintf("%.1f s", value * 1.0 / SECOND);
+            var sprint = buffer.length ? "%i s" : "%.1f s";
+            buffer += sprintf(sprint, value * 1.0 / SECOND);
           }
           return buffer;
         }

+ 4 - 1
desktop/core/src/desktop/templates/global_js_constants.mako

@@ -182,7 +182,10 @@
       cpu: "${ _('CPU') }",
       io: "${ _('IO') }",
       execution: "${ _('Execution') }",
-      codegen: "${ _('CodeGen') }"
+      codegen: "${ _('CodeGen') }",
+      overview: "${ _('Overview') }",
+      topnodes: "${ _('Top Nodes') }",
+      compilation: "${ _('Compilation') }"
     }
   };
 

+ 15 - 0
desktop/core/src/desktop/templates/hue_icons.mako

@@ -369,6 +369,21 @@
     <symbol id="hi-access-time" viewBox="0 0 24 24">
       <path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/><path d="M0 0h24v24H0z" fill="none"/><path d="M12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z"/>
     </symbol>
+    <symbol id="hi-sitemap" viewBox="0 0 640 512">
+      <path d="M128 352H32c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h96c17.67 0 32-14.33 32-32v-96c0-17.67-14.33-32-32-32zm-24-80h192v48h48v-48h192v48h48v-57.59c0-21.17-17.23-38.41-38.41-38.41H344v-64h40c17.67 0 32-14.33 32-32V32c0-17.67-14.33-32-32-32H256c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h40v64H94.41C73.23 224 56 241.23 56 262.41V320h48v-48zm264 80h-96c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h96c17.67 0 32-14.33 32-32v-96c0-17.67-14.33-32-32-32zm240 0h-96c-17.67 0-32 14.33-32 32v96c0 17.67 14.33 32 32 32h96c17.67 0 32-14.33 32-32v-96c0-17.67-14.33-32-32-32z"></path>
+    </symbol>
+    <symbol id="hi-random" viewBox="0 0 512 512">
+      <path d="M504.971 359.029c9.373 9.373 9.373 24.569 0 33.941l-80 79.984c-15.01 15.01-40.971 4.49-40.971-16.971V416h-58.785a12.004 12.004 0 0 1-8.773-3.812l-70.556-75.596 53.333-57.143L352 336h32v-39.981c0-21.438 25.943-31.998 40.971-16.971l80 79.981zM12 176h84l52.781 56.551 53.333-57.143-70.556-75.596A11.999 11.999 0 0 0 122.785 96H12c-6.627 0-12 5.373-12 12v56c0 6.627 5.373 12 12 12zm372 0v39.984c0 21.46 25.961 31.98 40.971 16.971l80-79.984c9.373-9.373 9.373-24.569 0-33.941l-80-79.981C409.943 24.021 384 34.582 384 56.019V96h-58.785a12.004 12.004 0 0 0-8.773 3.812L96 336H12c-6.627 0-12 5.373-12 12v56c0 6.627 5.373 12 12 12h110.785c3.326 0 6.503-1.381 8.773-3.812L352 176h32z"></path>
+    </symbol>
+    <symbol id="hi-exchange" viewBox="0 0 512 512">
+      <path d="M0 168v-16c0-13.255 10.745-24 24-24h360V80c0-21.367 25.899-32.042 40.971-16.971l80 80c9.372 9.373 9.372 24.569 0 33.941l-80 80C409.956 271.982 384 261.456 384 240v-48H24c-13.255 0-24-10.745-24-24zm488 152H128v-48c0-21.314-25.862-32.08-40.971-16.971l-80 80c-9.372 9.373-9.372 24.569 0 33.941l80 80C102.057 463.997 128 453.437 128 432v-48h360c13.255 0 24-10.745 24-24v-16c0-13.255-10.745-24-24-24z"></path>
+    </symbol>
+    <symbol id="hi-table" viewBox="0 0 512 512">
+      <path d="M464 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zM224 416H64v-96h160v96zm0-160H64v-96h160v96zm224 160H288v-96h160v96zm0-160H288v-96h160v96z"></path>
+    </symbol>
+    <symbol id="hi-copy" viewBox="0 0 512 512">
+      <path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"></path>
+    </symbol>
   </svg>
 
   <script type="text/html" id="app-switcher-icon-template">

+ 1 - 1
desktop/libs/libanalyze/src/libanalyze/analyze.py

@@ -313,7 +313,7 @@ def metrics(profile):
   plan_json = utils.parse_plan_details(summary.val.info_strings.get('Plan')) if summary.val.info_strings.get('Plan') else {}
   if not execution_profile:
     return {}
-  counter_map = {'nodes': {}, 'max': 0}
+  counter_map = {'nodes': {}, 'max': 0, 'summary': {'timeline': summary.event_list(), 'properties': summary.metric_map()}}
   def flatten(node, counter_map=counter_map):
     is_plan_node = node.is_plan_node()
     is_parent_node = is_plan_node

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio