Home | History | Annotate | Download | only in jsp
      1 <%--
      2   ~ Copyright (c) 2016 Google Inc. All Rights Reserved.
      3   ~
      4   ~ Licensed under the Apache License, Version 2.0 (the "License"); you
      5   ~ may not use this file except in compliance with the License. You may
      6   ~ obtain a copy of the License at
      7   ~
      8   ~     http://www.apache.org/licenses/LICENSE-2.0
      9   ~
     10   ~ Unless required by applicable law or agreed to in writing, software
     11   ~ distributed under the License is distributed on an "AS IS" BASIS,
     12   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
     13   ~ implied. See the License for the specific language governing
     14   ~ permissions and limitations under the License.
     15   --%>
     16 <%@ page contentType='text/html;charset=UTF-8' language='java' %>
     17 <%@ taglib prefix='fn' uri='http://java.sun.com/jsp/jstl/functions' %>
     18 <%@ taglib prefix='c' uri='http://java.sun.com/jsp/jstl/core'%>
     19 
     20 <html>
     21   <%@ include file="header.jsp" %>
     22   <link type='text/css' href='/css/datepicker.css' rel='stylesheet'>
     23   <link type='text/css' href='/css/show_graph.css' rel='stylesheet'>
     24   <link rel='stylesheet' href='https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.0/jquery-ui.css'>
     25   <script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'></script>
     26   <script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js'></script>
     27   <body>
     28     <script type='text/javascript'>
     29         google.charts.load('current', {packages:['corechart', 'table', 'line']});
     30         google.charts.setOnLoadCallback(drawAllGraphs);
     31 
     32         ONE_DAY = 86400000000;
     33         MICRO_PER_MILLI = 1000;
     34         N_BUCKETS = 200;
     35 
     36         var graphs = ${graphs};
     37 
     38         $(function() {
     39             $('select').material_select();
     40             var date = $('#date').datepicker({
     41                 showAnim: 'slideDown',
     42                 maxDate: new Date()
     43             });
     44             date.datepicker('setDate', new Date(${endTime} / MICRO_PER_MILLI));
     45             $('#load').click(load);
     46             $('#outlier-select').change(drawAllGraphs);
     47         });
     48 
     49         // Draw all graphs.
     50         function drawAllGraphs() {
     51             $('#profiling-container').empty();
     52             var percentileIndex = Number($('#outlier-select').val());
     53 
     54             // Get histogram extrema
     55             var histMin = null;
     56             var histMax = null;
     57             graphs.forEach(function(g) {
     58                 if (g.type != 'HISTOGRAM') return;
     59                 var minVal;
     60                 var maxVal;
     61                 if (percentileIndex == -1) {
     62                     minVal = g.min;
     63                     maxVal = g.max;
     64                 } else {
     65                     minVal = g.percentile_values[percentileIndex];
     66                     var endIndex = g.percentiles.length - percentileIndex - 1
     67                     maxVal = g.percentile_values[endIndex];
     68                 }
     69                 if (!histMin || minVal < histMin) histMin = minVal;
     70                 if (!histMax || maxVal > histMax) histMax = maxVal;
     71             });
     72 
     73             graphs.forEach(function(graph) {
     74                 if (graph.type == 'LINE_GRAPH') drawLineGraph(graph);
     75                 else if (graph.type == 'HISTOGRAM')
     76                     drawHistogram(graph, histMin, histMax);
     77             });
     78         }
     79 
     80        /**
     81         * Draw a line graph.
     82         *
     83         * Args:
     84         *     lineGraph: a JSON object containing the following fields:
     85         *                - name: the name of the graph
     86         *                - values: an array of numbers
     87         *                - ticks: an array of strings to use as x-axis labels
     88         *                - ids: an array of string labels for each point (e.g. the
     89         *                       build info for the run that produced the point)
     90         *                - x_label: the string label for the x axis
     91         *                - y_label: the string label for the y axis
     92         */
     93         function drawLineGraph(lineGraph) {
     94             if (!lineGraph.ticks || lineGraph.ticks.length < 1) {
     95                 return;
     96             }
     97             var title = 'Performance';
     98             if (lineGraph.name) title += ' (' + lineGraph.name + ')';
     99             lineGraph.ticks.forEach(function (label, i) {
    100                 lineGraph.values[i].unshift(label);
    101             });
    102             var data = new google.visualization.DataTable();
    103             data.addColumn('string', lineGraph.x_label);
    104             lineGraph.ids.forEach(function(id) {
    105                 data.addColumn('number', id);
    106             });
    107             data.addRows(lineGraph.values);
    108             var options = {
    109               chart: {
    110                   title: title,
    111                   subtitle: lineGraph.y_label
    112               },
    113               legend: { position: 'none' }
    114             };
    115             var container = $('<div class="row card center-align col s12 graph-wrapper"></div>');
    116             container.appendTo('#profiling-container');
    117             var chartDiv = $('<div class="col s12 graph"></div>');
    118             chartDiv.appendTo(container);
    119             var chart = new google.charts.Line(chartDiv[0]);
    120             chart.draw(data, options);
    121         }
    122 
    123        /**
    124         * Draw a histogram.
    125         *
    126         * Args:
    127         *     hist: a JSON object containing the following fields:
    128         *           - name: the name of the graph
    129         *           - values: an array of numbers
    130         *           - ids: an array of string labels for each point (e.g. the
    131         *                  build info for the run that produced the point)
    132         *           - x_label: the string label for the x axis
    133         *           - y_label: the string label for the y axis
    134         *     min: the minimum value to display
    135         *     max: the maximum value to display
    136         */
    137         function drawHistogram(hist, min, max) {
    138             if (!hist.values || hist.values.length == 0) return;
    139             var title = 'Performance';
    140             if (hist.name) title += ' (' + hist.name + ')';
    141             var values = hist.values;
    142             var histogramData = values.reduce(function(result, d, i) {
    143                 if (d <= max && d >= min) result.push([hist.ids[i], d]);
    144                 return result;
    145             }, []);
    146 
    147             var data = google.visualization.arrayToDataTable(histogramData, true);
    148             var bucketSize = (max - min) / N_BUCKETS;
    149 
    150             var options = {
    151                 title: title,
    152                 titleTextStyle: {
    153                     color: '#757575',
    154                     fontSize: 16,
    155                     bold: false
    156                 },
    157                 legend: { position: 'none' },
    158                 colors: ['#4285F4'],
    159                 fontName: 'Roboto',
    160                 vAxis:{
    161                     title: hist.y_label,
    162                     titleTextStyle: {
    163                         color: '#424242',
    164                         fontSize: 12,
    165                         italic: false
    166                     },
    167                     textStyle: {
    168                         fontSize: 12,
    169                         color: '#757575'
    170                     },
    171                 },
    172                 hAxis: {
    173                     title: hist.x_label,
    174                     textStyle: {
    175                         fontSize: 12,
    176                         color: '#757575'
    177                     },
    178                     titleTextStyle: {
    179                         color: '#424242',
    180                         fontSize: 12,
    181                         italic: false
    182                     }
    183                 },
    184                 bar: { gap: 0 },
    185                 histogram: {
    186                     minValue: min,
    187                     maxValue: max,
    188                     maxNumBuckets: N_BUCKETS,
    189                     bucketSize: bucketSize
    190                 },
    191                 chartArea: {
    192                     width: '100%',
    193                     top: 40,
    194                     left: 60,
    195                     height: 375
    196                 }
    197             };
    198             var container = $('<div class="row card col s12 graph-wrapper"></div>');
    199             container.appendTo('#profiling-container');
    200 
    201             var chartDiv = $('<div class="col s12 graph"></div>');
    202             chartDiv.appendTo(container);
    203             var chart = new google.visualization.Histogram(chartDiv[0]);
    204             chart.draw(data, options);
    205 
    206             var tableDiv = $('<div class="col s12"></div>');
    207             tableDiv.appendTo(container);
    208 
    209             var tableHtml = '<table class="percentile-table"><thead><tr>';
    210             hist.percentiles.forEach(function(p) {
    211                 tableHtml += '<th data-field="id">' + p + '%</th>';
    212             });
    213             tableHtml += '</tr></thead><tbody><tr>';
    214             hist.percentile_values.forEach(function(v) {
    215                 tableHtml += '<td>' + v + '</td>';
    216             });
    217             tableHtml += '</tbody></table>';
    218             $(tableHtml).appendTo(tableDiv);
    219         }
    220 
    221         // Reload the page.
    222         function load() {
    223             var endTime = $('#date').datepicker('getDate').getTime();
    224             endTime = endTime + (ONE_DAY / MICRO_PER_MILLI) - 1;
    225             var filterVal = $('#outlier-select').val();
    226             var ctx = '${pageContext.request.contextPath}';
    227             var link = ctx + '/show_graph?profilingPoint=${profilingPointName}' +
    228                 '&testName=${testName}' +
    229                 '&endTime=' + (endTime * MICRO_PER_MILLI) +
    230                 '&filterVal=' + filterVal;
    231             if ($('#device-select').prop('selectedIndex') > 1) {
    232                 link += '&device=' + $('#device-select').val();
    233             }
    234             window.open(link,'_self');
    235         }
    236     </script>
    237     <div id='download' class='fixed-action-btn'>
    238       <a id='b' class='btn-floating btn-large red waves-effect waves-light'>
    239         <i class='large material-icons'>file_download</i>
    240       </a>
    241     </div>
    242     <div class='container wide'>
    243       <div class='row card'>
    244         <div id='header-container' class='valign-wrapper col s12'>
    245           <div class='col s3 valign'>
    246             <h5>Profiling Point:</h5>
    247           </div>
    248           <div class='col s9 right-align valign'>
    249             <h5 class='profiling-name truncate'>${profilingPointName}</h5>
    250           </div>
    251         </div>
    252         <div id='date-container' class='col s12'>
    253           <c:set var='offset' value='${showFilterDropdown ? 0 : 2}' />
    254           <c:if test='${showFilterDropdown}'>
    255             <div id='outlier-select-wrapper' class='col s2'>
    256               <select id='outlier-select'>
    257                 <option value='-1' ${filterVal eq -1 ? 'selected' : ''}>Show outliers</option>
    258                 <option value='0' ${filterVal eq 0 ? 'selected' : ''}>Filter outliers (1%)</option>
    259                 <option value='1' ${filterVal eq 1 ? 'selected' : ''}>Filter outliers (2%)</option>
    260                 <option value='2' ${filterVal eq 2 ? 'selected' : ''}>Filter outliers (5%)</option>
    261               </select>
    262             </div>
    263           </c:if>
    264           <div id='device-select-wrapper' class='input-field col s5 m3 offset-m${offset + 4} offset-s${offset}'>
    265             <select id='device-select'>
    266               <option value='' disabled>Select device</option>
    267               <option value='0' ${empty selectedDevice ? 'selected' : ''}>All Devices</option>
    268               <c:forEach items='${devices}' var='device' varStatus='loop'>
    269                 <option value=${device} ${selectedDevice eq device ? 'selected' : ''}>${device}</option>
    270               </c:forEach>
    271             </select>
    272           </div>
    273           <input type='text' id='date' name='date' class='col s4 m2'>
    274           <a id='load' class='btn-floating btn-medium red right waves-effect waves-light'>
    275             <i class='medium material-icons'>cached</i>
    276           </a>
    277         </div>
    278       </div>
    279       <div id='profiling-container'>
    280       </div>
    281       <c:if test='${not empty error}'>
    282         <div id='error-container' class='row card'>
    283           <div class='col s10 offset-s1 center-align'>
    284             <!-- Error in case of profiling data is missing -->
    285             <h5>${error}</h5>
    286           </div>
    287         </div>
    288       </c:if>
    289     </div>
    290     <%@ include file="footer.jsp" %>
    291   </body>
    292 </html>
    293