| <!-- |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF 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. |
| --> |
| |
| <div ng-controller="CubeCtrl" class="nav-tabs-custom" style="margin-top:40px;"> |
| <ul class="nav nav-tabs"> |
| <li class="{{(!cube.visiblePage || cube.visiblePage=='metadata')? 'active':''}}"> |
| <a href="" ng-click="cube.visiblePage='metadata'">Grid</a> |
| </li> |
| <!--</li>--> |
| <li class="{{cube.visiblePage=='sql'? 'active':''}}"> |
| <a href="" ng-click="cube.visiblePage='sql';getCubeSql(cube)">SQL</a> |
| </li> |
| <li class="{{cube.visiblePage=='json'? 'active':''}}" |
| ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission('cube',cube, permissions.ADMINISTRATION.mask) && !newAccess"> |
| <a href="" ng-click="cube.visiblePage='json';">JSON(Cube)</a> |
| </li> |
| <!--<li class="{{cube.visiblePage=='access'? 'active':''}}"--> |
| <!--ng-if="!kylinConfig.isExternalAclEnabled()">--> |
| <!--<a href="" ng-click="cube.visiblePage='access';listAccess(cube, 'CubeInstance');">Access</a>--> |
| <!--</li>--> |
| <li class="{{cube.visiblePage=='notification'? 'active':''}}" |
| ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission('cube',cube, permissions.ADMINISTRATION.mask) && !newAccess"> |
| <a href="" ng-click="cube.visiblePage='notification';getNotifyListString(cube);">Notification</a> |
| </li> |
| <li class="{{cube.visiblePage=='hbase'? 'active':''}}" |
| ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission('cube' ,cube, permissions.ADMINISTRATION.mask) && !newAccess"> |
| <a href="" ng-click="cube.visiblePage='hbase';getHbaseInfo(cube)">Storage</a> |
| </li> |
| <li class="{{cube.visiblePage=='planner'? 'active':''}}" ng-if="(userService.hasRole('ROLE_ADMIN') || hasPermission('cube', cube, permissions.ADMINISTRATION.mask) && !newAccess) && isShowCubeplanner"> |
| <a href="" ng-click="cube.visiblePage='planner';getCubePlanner(cube);">Planner</a> |
| </li> |
| <li class="{{cube.visiblePage=='streaming'? 'active':''}}" ng-if="(userService.hasRole('ROLE_ADMIN') || hasPermission('cube', cube, permissions.ADMINISTRATION.mask) && !newAccess) && cube.streamingV2"> |
| <a href="" ng-click="cube.visiblePage='streaming';getStreamingInfo(cube)">Streaming</a> |
| </li> |
| </ul> |
| |
| <div class="cube-detail" ng-if="!cube.visiblePage || cube.visiblePage=='metadata'"> |
| <div ng-include="'partials/cubes/cube_schema.html'" ng-controller="CubeSchemaCtrl" |
| ng-init="state={mode:'view', cubeName:cube.name};"></div> |
| </div> |
| |
| <div ng-show="cube.visiblePage=='sql'" class="cube-detail"> |
| <div ng-if="cube.sql"> |
| <pre style="background-color: white;border: 0px">{{cube.sql}}</pre> |
| </div> |
| <div ng-if="!cube.sql"> |
| <span calss="text-info">No SQL GENERATED.</span> |
| </div> |
| </div> |
| |
| <div ng-show="cube.visiblePage=='json'" class="cube-detail"> |
| <pre ng-if="!state.jsonEdit" |
| style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(cube.detail), true)}}</pre> |
| </div> |
| |
| <!--<div ng-show="cube.visiblePage=='json_model'" class="cube-detail">--> |
| <!--<pre ng-if="!state.jsonEdit"--> |
| <!--style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(model), true)}}</pre>--> |
| <!--</div>--> |
| <!--<div ng-show="cube.visiblePage=='graph'" id="cube_graph_{{cube.name}}" class="cube-detail cube_graph">--> |
| <!--</div>--> |
| |
| <!--<div class="cube-detail" ng-if="cube.visiblePage=='access'">--> |
| <!--<div class="row">--> |
| <!--<div class="col-xs-1"></div>--> |
| <!--<div class="col-xs-10">--> |
| <!--<div ng-include src="'partials/common/access.html'" ng-init="entity=cube;type='CubeInstance';"></div>--> |
| <!--</div>--> |
| <!--<div class="col-xs-1"></div>--> |
| <!--</div>--> |
| <!--</div>--> |
| |
| <div class="cube-detail" ng-show="cube.visiblePage=='notification'"> |
| <div style="margin: 15px;"> |
| <form> |
| <h5>Notification List(Comma Separated)</h5> |
| <div class="form-group"> |
| <input ng-model="cube.notifyListString" class="form-control" placeholder="Notification List..." /> |
| </div> |
| <div class="form-group"> |
| <button class="btn btn-primary btn-sm" ng-click="updateNotifyList(cube)">Save</button> |
| </div> |
| <div class="space-4"></div> |
| </form> |
| </div> |
| </div> |
| |
| <div class="cube-detail" ng-show="cube.visiblePage=='hbase'"> |
| <div style="margin: 15px; overflow: hidden;"> |
| <div ng-if="cube.hbase"> |
| <div class="hr hr8 hr-double hr-dotted"></div> |
| <h5><b>Segment Number:</b> <span class="blue">{{cube.hbase.length}}</span> <b>Total Size:</b> <span class="blue">{{cube.totalSize | bytes}}</span></h5> |
| </div> |
| <div ng-repeat="table in cube.hbase" class="cube-segment-list" ng-class="{'cube-broken-segment': table.regionCount === 0}"> |
| <h5><b>Segment:</b> {{table.segmentName}}</h5> |
| <ul> |
| <li ng-if="cube.streaming">Status: <span>{{table.segmentStatus}}</span></li> |
| <li ng-if="cube.model.partition_desc.partition_date_column">Start Time: <span>{{table.dateRangeStart | reverseToGMT0}}</span></li> |
| <li ng-if="cube.model.partition_desc.partition_date_column">End Time: <span>{{table.dateRangeEnd | reverseToGMT0}}</span></li> |
| <li>Source Count: <span>{{table.sourceCount}}</span></li> |
| <li>HBase Table: <span>{{table.tableName}}</span></li> |
| <li>Region Count: <span ng-class="{'red': table.regionCount == 0}">{{table.regionCount}}</span></li> |
| <li>Size: <span>{{table.tableSize | bytes}}</span></li> |
| </ul> |
| </div> |
| <div ng-if="cube.hbase.length == 0"> |
| <h5>No Storage Info.</h5> |
| </div> |
| </div> |
| </div> |
| <div class="cube-detail" ng-if="cube.visiblePage=='planner'"> |
| <div style="padding: 15px;"> |
| <div class="row"> |
| <div class="col-sm-12"> |
| <h4 style="display: inline;">Cuboid Distribution</h4> |
| <button ng-if="enableRecommend" class="btn btn-success btn-sm pull-right" ng-click="getRecommendCuboids(cube)" ng-if="currentData"> |
| Recommend |
| </button> |
| <div ng-if="cube.cuboid_last_optimized" class="pull-right" style="padding: 5px;">Last Optimized Time: {{cube.cuboid_last_optimized | utcToConfigTimeZone}}</div> |
| </div> |
| </div> |
| <div class="row"> |
| <div class="col-md-6 col-sm-12"> |
| <nvd3 options="currentOptions" data="currentData" api="currentChart.api"></nvd3> |
| </div> |
| <div class="col-md-6 col-sm-12" ng-if="recommendData"> |
| <nvd3 options="recommendOptions" data="recommendData"></nvd3> |
| </div> |
| </div> |
| <div class="row cube-planner-column" ng-if="currentData || recommendData"> |
| <table class="table table-bordered"> |
| <tbody> |
| <tr ng-repeat="row in cube.detail.rowkey.rowkey_columns track by $index" ng-if="$index % 5 == 0" class="row"> |
| <th ng-class="{'column-in-cuobid': selectCuboid.charAt($index) == 1, 'column-not-in-cuboid': selectCuboid.charAt($index) == 0}">{{cube.detail.rowkey.rowkey_columns[$index].column}}</th> |
| <th ng-class="{'column-in-cuobid': selectCuboid.charAt($index + 1) == 1, 'column-not-in-cuboid': selectCuboid.charAt($index + 1) == 0}">{{cube.detail.rowkey.rowkey_columns[$index + 1].column}}</th> |
| <th ng-class="{'column-in-cuobid': selectCuboid.charAt($index + 2) == 1, 'column-not-in-cuboid': selectCuboid.charAt($index + 2) == 0}">{{cube.detail.rowkey.rowkey_columns[$index + 2].column}}</th> |
| <th ng-class="{'column-in-cuobid': selectCuboid.charAt($index + 3) == 1, 'column-not-in-cuboid': selectCuboid.charAt($index + 3) == 0}">{{cube.detail.rowkey.rowkey_columns[$index + 3].column}}</th> |
| <th ng-class="{'column-in-cuobid': selectCuboid.charAt($index + 4) == 1, 'column-not-in-cuboid': selectCuboid.charAt($index + 4) == 0}">{{cube.detail.rowkey.rowkey_columns[$index + 4].column}}</th> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| <div class="row"> |
| <div class="col-sm-12"> |
| <div class="dropup pull-right" style="margin-left: 10px;" ng-if="recommendData"> |
| <button class="btn btn-default dropdown-toggle" type="button" id="export" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> |
| Export |
| <span class="caret"></span> |
| </button> |
| <ul class="dropdown-menu" aria-labelledby="export"> |
| <li><a ng-href="{{config.service.url}}cubes/{{cube.name}}/cuboids/export?top=10" target="_blank" >Top 10</a></li> |
| <li><a ng-href="{{config.service.url}}cubes/{{cube.name}}/cuboids/export?top=50" target="_blank" >Top 50</a></li> |
| <li><a ng-href="{{config.service.url}}cubes/{{cube.name}}/cuboids/export?top=100" target="_blank" >Top 100</a></li> |
| </ul> |
| </div> |
| <button class="btn btn-success btn-next pull-right" ng-click="optimizeCuboids(cube)" ng-if="recommendData"> |
| Optimize |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| <div class="cube-detail" ng-if="cube.visiblePage=='streaming'"> |
| <div style="padding: 15px; color: #212121;"> |
| <div class="row" ng-repeat="(rsId, replicaSet) in replicaSets" style="padding-left: 10px; padding-right: 10px;"> |
| <div class="col-sm-1" style="text-align: center; background-color: #f5f5f5; border: 1px solid #ffffff; height: 100px; padding-top: 30px; padding-bottom: 30px; color: #455A64;"> |
| <span>Replica Set ID: {{rsId}}</span> |
| </div> |
| |
| <div class="col-sm-11" style="padding-left: 0px; padding-right: 0px;"> |
| <div class="cube-receiver-stats" ng-class="receiverStats.style" ng-repeat="(node, receiverStats) in replicaSet" ng-click="nodeStatsDetail(node, receiverStats)"> |
| <div class="col-sm-12 node-info" ng-class="{'text-red':receiverStats.receiver_state != 'HEALTHY'}"> |
| {{node}} |
| </div> |
| <div class="col-sm-12 rate-metric" ng-if="receiverStats.partition_consume_stats"> |
| {{receiverStats.consumer_info.one_min_rate | number:0}} <span class="unit">msg/s</span> |
| </div> |
| <div class="col-sm-12 rate-metric" ng-if="!receiverStats.partition_consume_stats"> |
| N/A |
| </div> |
| <div class="row"> |
| <div class="col-sm-2 col-sm-offset-1 detail-metric"> |
| 5' |
| </div> |
| <div class="col-sm-2 detail-metric"> |
| 15' |
| </div> |
| <div class="col-sm-2 detail-metric"> |
| avg |
| </div> |
| <div class="col-sm-2 detail-metric"> |
| consume |
| </div> |
| <div class="col-sm-2 detail-metric"> |
| ingest |
| </div> |
| </div> |
| <div class="row" ng-if="receiverStats.partition_consume_stats"> |
| <div class="col-sm-2 col-sm-offset-1 detail-metric"> |
| {{receiverStats.consumer_info.five_min_rate | number:0}}<span>msg/s</span> |
| </div> |
| <div class="col-sm-2 detail-metric"> |
| {{receiverStats.consumer_info.fifteen_min_rate | number:0}}<span>msg/s</span> |
| </div> |
| <div class="col-sm-2 detail-metric"> |
| {{receiverStats.consumer_info.avg_rate | number:0}}<span>msg/s</span> |
| </div> |
| <div class="col-sm-2 detail-metric"> |
| {{receiverStats.consumer_info.total_consume}} |
| </div> |
| <div class="col-sm-2 detail-metric"> |
| {{receiverStats.total_ingest}} |
| </div> |
| </div> |
| <div class="row" ng-if="!receiverStats.partition_consume_stats"> |
| <div class="col-sm-2 col-sm-offset-1 detail-metric"> |
| N/A |
| </div> |
| <div class="col-sm-2 detail-metric"> |
| N/A |
| </div> |
| <div class="col-sm-2 detail-metric"> |
| N/A |
| </div> |
| <div class="col-sm-2 detail-metric"> |
| N/A |
| </div> |
| <div class="col-sm-2 detail-metric"> |
| {{receiverStats.total_ingest || 'N/A'}} |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| <script type="text/ng-template" id="nodeStatsDetail.html"> |
| <div class="modal-header"> |
| <div class="box-header"> |
| <h3 class="box-title">{{node}}</h3> |
| <div class="box-tools pull-right"> |
| <button type="button" class="btn btn-box-tool" ng-click="cancel()"><i class="fa fa-times"></i></button> |
| </div> |
| </div> |
| </div> |
| <div class="modal-body"> |
| <div class="row"> |
| <div class="col-md-offset-1 col-md-3 text-right">Latest Event Time</div> |
| <div class="col-md-7">{{receiverStats.latest_event_time ? (receiverStats.latest_event_time | reverseToGMT0) : ''}}</div> |
| </div> |
| <div class="row"> |
| <div class="col-md-offset-1 col-md-3 text-right">Latest Event Ingest Time</div> |
| <div class="col-md-7">{{receiverStats.latest_event_ingest_time ? (receiverStats.latest_event_ingest_time | reverseToGMT0) : ''}}</div> |
| </div> |
| <div class="row"> |
| <div class="col-md-offset-1 col-md-3 text-right">Segments</div> |
| <div class="col-md-7"> |
| <!-- TODO add color for segment & partition--> |
| <a href="javascript:void(0);" ng-repeat="(segmentName, segmentInfo) in receiverStats.segment_stats" kylinpopover placement="top" class="segment" title="Segment Info" trigger="focus" content="segment name: {{segmentName}}</br>segment state: {{segmentInfo.segment_state}}</br>fragment number: {{segmentInfo.store_stats.num_fragments}}</br>row number in memory: {{segmentInfo.store_stats.num_rows_in_mem}}</br>latest event latency: {{segmentInfo.latest_event_latency}}ms</br>latest event time: {{!!segmentInfo.latest_event_time ? (segmentInfo.latest_event_time | reverseToGMT0) : ''}}</br>segement create time: {{segmentInfo.segment_create_time | reverseToGMT0}}</br>last update time: {{segmentInfo.segment_last_update_time | reverseToGMT0}}"> |
| <i class="fa fa-database" style="font-size: 1.5em; color: #86bad8; margin-right: 5px;" ng-class="{'active': segmentInfo.segment_state === 'ACTIVE'}"></i> |
| </a> |
| </div> |
| </div> |
| <div class="row"> |
| <div class="col-md-offset-1 col-md-3 text-right">Partitions</div> |
| <div class="col-md-7" ng-if="receiverStats.partition_consume_stats"> |
| <a href="javascript:void(0);" ng-repeat="partitionInfo in receiverStats.partition_consume_stats" kylinpopover placement="top" title="Partition Info" trigger="focus" content="Partition Id: {{partitionInfo.partition_id}}</br>Offset Info: {{partitionInfo.offset_info}}</br>1 Minute Rate: {{partitionInfo.one_min_rate | number:0}} msg/s</br>5 Minute Rate: {{partitionInfo.five_min_rate | number:0}} msg/s</br>15 Minute Rate: {{partitionInfo.fifteen_min_rate | number:0}} msg/s</br>AVG Rate: {{partitionInfo.avg_rate | number:0}} msg/s</br>Total Consume: {{partitionInfo.total_consume}}<br/>Cosume Lag: {{partitionInfo.consume_lag}}"> |
| <i class="fa fa-list-ul" style="font-size:1.5em; color:#3c8dbc; margin-right: 5px;"></i> |
| </a> |
| </div> |
| </div> |
| <div class="row"> |
| <div class="col-md-offset-1 col-md-3 text-right">Cosume Lag</div> |
| <div class="col-md-7">{{receiverStats.consume_lag}}</div> |
| </div> |
| </div> |
| </script> |