blob: 01d63499ee3f609f8da116a17e93e4420432fc2d [file] [log] [blame]
<!--
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 id="cloud" class="clearfix">
<div id="frame">
<div id="zk-status-content" class="content clearfix" ng-show="showZkStatus">
<div id="zk-controls">
<a class="reload" ng-click="initZookeeper()"><span>Refresh</span></a>
<a class="details-button" ng-click="toggleDetails()" ng-class="{on:showDetails}">
<span>Toggle details</span>
</a>
</div>
<div class="zookeeper-status">Status: <span class="zkstatus-{{zkState.status}}">{{zkState.status}}</span></div>
<div class="zookeeper-errors" ng-show="zkState.errors">
Errors:
<ul>
<li ng-repeat="error in zkState.errors">{{error}}</li>
</ul>
</div>
<div>ZK connection string: {{zkState.zkHost}}</div>
<div>Ensemble size: {{zkState.ensembleSize}}</div>
<div>Ensemble mode: {{zkState.mode}}</div>
<div>Dynamic reconfig enabled: {{zkState.dynamicReconfig}}</div>
<table id="zk-table">
<thead>
<tr>
<th></th>
<th ng-repeat="host in zkState.details">{{host.host}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="key in mainKeys">
<td>{{key}}</td>
<td ng-repeat="host in zkState.details" ng-style="key === 'zk_server_state' && host[key] === 'leader' ? {'font-weight': 'bold'} : {'font-weight': 'normal'}">
{{key === 'zk_version' ? host[key].split("-")[0] : host[key]}}
</td>
</tr>
<tr ng-repeat="key in ensembleMainKeys" ng-show="zkState.mode === 'ensemble'">
<td>{{key}}</td>
<td ng-repeat="host in zkState.details">
{{host[key]}}
</td>
</tr>
<tr id="detail-divider" ng-show="showDetails" >
<td ng-class="details"></td>
<td ng-repeat="host in zkState.details" ng-class="details"></td>
</tr>
<tr ng-repeat="key in detailKeys | filter: notEmptyRow" ng-show="showDetails">
<td>{{key}}</td>
<td ng-repeat="host in zkState.details">
{{host[key]}}
</td>
</tr>
<tr ng-repeat="key in ensembleDetailKeys | filter: notEmptyRow" ng-show="showDetails && zkState.mode === 'ensemble'">
<td>{{key}}</td>
<td ng-repeat="host in zkState.details">
{{host[key]}}
</td>
</tr>
</tbody>
</table>
</div>
<div id="tree-content" class="content clearfix" ng-show="showTree">
<jstree class="tree" on-select="showTreeLink(url)" id="tree" data="tree"></jstree>
<div id="file-content" class="clearfix">
<a id="toggle" ng-click="showProps = !showProps" ng-show="showData" ng-class="showProps ? 'minus' : 'plus'">Metadata</a>
<div id="prop" ng-show="znode.prop && showData && showProps">
<ul>
<li ng-class="{odd:$odd}" ng-repeat="(key, prop) in znode.prop">
<dl class="clearfix">
<dt>{{ key }}</dt>
<dd>{{ prop }}</dd>
</dl>
</li>
</ul>
</div>
<div id="data" ng-show="showData">
<em ng-show="!znode.data">Node "{{znode.path }}" has no utf8 Content</em>
<pre ng-show="znode.data" class="syntax language-{{lang}}"
ng-bind-html="znode.data | highlight:lang | unsafe">
</pre>
<a class="close" ng-click="hideData()"><span>&nbsp;</span></a>
</div>
</div>
</div>
<div id="nodes-content" class="content clearfix" ng-show="showNodes">
<div id="controls">
<a class="reload" ng-click="initClusterState()"><span>Refresh</span></a>
<a class="details-button" ng-click="toggleAllDetails()" ng-class="{on:showAllDetails}">
<span>Show all details</span>
</a>
</div>
<div>
<div id="nodesPaging">
<button ng-show="prevEnabled" ng-click="previousPage()" id="nodesPagingPrev">&lt; Previous</button>
<span ng-show="filteredHosts.length==0">No hosts found.</span>
<span ng-hide="filteredHosts.length==0">Hosts {{from+1}} - {{from + hostsToShow.length}} of {{filteredHosts.length}}.</span>&nbsp;
Filter by:&nbsp;<select ng-model="filterType" ng-change="filterInput()" id="nodesPagingFilterType">
<option value="node">Host/node name</option>
<option value="collection">Collection name</option>
</select>&nbsp;
<span ng-show="filterType=='node'">
<input ng-model="nodeFilter" type="text" size="10" name="nodefilter" ng-change="filterInput()" ng-model-options='{ debounce: 500 }' />&nbsp;
</span>
<span ng-show="filterType=='collection'">
<input ng-model="collectionFilter" type="text" size="10" name="collectionfilter" ng-change="filterInput()" ng-model-options='{ debounce: 500 }'/>&nbsp;
</span>
Show <input ng-model="pageSize" ng-change="filterInput()" type="text" size="2" name="rows" ng-model-options='{ debounce: 500 }'/> hosts per page.
<button ng-show="nextEnabled" ng-click="nextPage()">Next &gt;</button>
</div>
</div>
<table id="nodes-table">
<thead>
<tr>
<th>Host</th>
<th>Node</th>
<th>CPU</th>
<th>Heap</th>
<th>Disk usage</th>
<th>Requests</th>
<th>Collections</th>
<th>Replicas</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="key in nodesToShow | orderBy:'key.order'" ng-init="n = nodes[key]; h = nodes[firstLiveNodeForHost(key)]">
<td rowspan="{{hosts[h.host].nodes.length}}" ng-show="isFirstNodeForHost(key)">
<div class="host-name">{{h.host}}</div>
<span class="host-spec" ng-show="!showDetails[h.host]">
<span title="{{h.system.system.uptime}}">{{h.system.system.name}}</span>
<span title="free: {{h.memFree}}">{{h.memTotal}}</span>
<span title="{{h.system.jvm.name}} {{h.system.jvm.version}}">Java {{h.system.jvm.spec.version}}</span>
<br/>Load: {{h.loadAvg}}
</span>
<div class="host-spec" ng-show="showDetails[h.host]">
{{h.system.system.name}} {{h.system.system.version}}, {{h.system.system.availableProcessors}}cpu<br/>
Uptime: {{h.uptime}}<br/>
<span title="Used: {{h.memUsed}} - includes OS file-cache, and it is normal for it to approach 100%">Memory: {{h.memTotal}}</span><br/>
File descriptors: {{h.openFileDescriptorCount}}/{{h.maxFileDescriptorCount}}<br/>
Disk: <span class="{{h.diskUsedPctStyle}}" title="Nodes may use other disks too">{{h.diskTotal}} used: {{h.diskUsedPct}}%</span><br/>
Load: {{h.loadAvg}}
</div>
<div class="node-spec" ng-click="toggleHostDetails(h.host)">
<a ng-show="showDetails[h.host]">hide details...</a>
<a ng-show="!showDetails[h.host]">show details...</a>
</div>
</td>
<td ng-class="{'dead-node': n.dead}"><div class="node-name"><a href="{{n.base_url}}">{{key.replace(n.host+':', '')}}</a></div>
<div ng-show="n.dead" class="node-down">(DEAD)</div>
<div ng-show="!n.dead">
Uptime: {{n.jvmUptime}}<br/>
<div class="node-spec" ng-show="showDetails[key]">
Java <span title="{{n.system.jvm.jre.vendor}}">{{n.system.jvm.jre.version}}</span><br/>
Solr {{n.system.lucene['solr-impl-version'].split(" ")[0]}}<br>
</div>
<div class="node-spec" ng-click="toggleDetails(key)">
<a ng-show="showDetails[key]">hide details...</a>
<a ng-show="!showDetails[key]">show details...</a>
</div>
</div>
</td>
<td ng-class="{'dead-node': n.dead}">
<div class="node-cpu" ng-show="!n.dead">
<span class="{{n.cpuPctStyle}}">{{n.cpuPct}}%</span>
</div>
</td>
<td ng-class="{'dead-node': n.dead}">
<div class="node-heap" title="total: {{n.heapTotal}} free: {{n.heapFree}} used%: {{n.heapUsedPct}}%" ng-show="!n.dead">
<span class="{{n.heapUsedPctStyle}}">{{n.heapUsedPct}}%</span>
</div>
<div class="node-spec" ng-show="showDetails[key] && !n.dead">
Max: {{n.heapTotal}}<br/>
Used: {{n.heapUsed}}
</div>
</td>
<td class="scroll-height-250" ng-class="{'dead-node': n.dead}">
<div>
<div class="node-disk" title="Available disk: {{n.diskTotal}} free: {{n.diskFree}} used by this node: {{n.size}}" ng-show="!n.dead">
{{n.size}}
</div>
<div class="node-spec" ng-show="showDetails[key] && !n.dead">
Total #docs: {{n.numDocs}}<br/>
Avg size/doc: {{n.sizePerDoc}}
</div>
<div id="chart{{n.id}}" ng-show="showDetails[key] && !n.dead"></div>
</div>
</td>
<td ng-class="{'dead-node': n.dead}"><div class="node-requests" title="1minRate: {{n.req1minRate}} 5minRate: {{n.req5minRate}} 15minRate: {{n.req15minRate}} p75: {{n.reqp75_ms}} p99: {{n.reqp99_ms}}" ng-show="!n.dead">
RPM: {{n.req15minRate}}<br/>p95: {{n.reqp95_ms}}ms</div>
</td>
<td ng-class="{'dead-node': n.dead}">
<div ng-show="!n.collections">(none)</div>
<div ng-repeat="c in n.collections | limitTo:showDetails[key]?999:2 track by $index">
<a href="{{h.base_url + '/#/~collections/' + c}}">{{ c }}</a>
</div>
<div class="more" ng-show="n.collections.length > 2 && !showDetails[key]">
<a ng-click="toggleDetails(key)">({{n.collections.length - 2}} more...)</a>
</div>
</td>
<td class="scroll-height-250" ng-class="{'dead-node': n.dead}">
<div ng-show="!n.cores">(none)</div>
<div ng-repeat="core in n.cores | limitTo:showDetails[key]?999:2 track by $index">
<div ng-show="!n.dead"><a class="{{core.leader ? 'leader' : 'replica'}}" href="{{core.base_url + '/#/' + core.core + '/core-overview'}}">{{ core.label }}</a> ({{core.numDocsHuman}} docs)</div>
<div ng-show="n.dead">{{ core.label }}</div>
<ul class="core-details" ng-show="showDetails[key] && !n.dead" >
<li>deleted: {{core.deletedDocsHuman}}</li>
<li>warmupTime: {{core.warmupTime}}</li>
<li ng-show="core.numDocs > 0">avg size/doc: {{core.avgSizePerDoc}}</li>
</ul>
</div>
<div class="more" ng-show="n.cores.length > 2 && !showDetails[key] && !n.dead">
<a ng-click="toggleDetails(key)">({{n.cores.length - 2}} more...)</a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div graph data="graphData" leaf-count="leafCount" helper-data="helperData" id="graph-content" class="content clearfix" ng-show="showGraph">
<div id="canvas"></div>
<div id="legend">
<ul>
<li class="leader"><svg width="15" height="15"><g transform="translate(5,2)"><g transform="translate(0,5)"><circle r="4.5"></circle></g></g></svg> Leader</li>
<li class="active"><svg width="15" height="15"><g transform="translate(5,2)"><g transform="translate(0,5)"><circle r="4.5"></circle></g></g></svg> Active</li>
<li class="recovering"><svg width="15" height="15"><g transform="translate(5,2)"><g transform="translate(0,5)"><circle r="4.5"></circle></g></g></svg> Recovering</li>
<li class="down"><svg width="15" height="15"><g transform="translate(5,2)"><g transform="translate(0,5)"><circle r="4.5"></circle></g></g></svg> Down</li>
<li class="recovery_failed"><svg width="15" height="15"><g transform="translate(5,2)"><g transform="translate(0,5)"><circle r="4.5"></circle></g></g></svg> Recovery Failed</li>
<li class="shard-inactive"><svg width="15" height="15"><g transform="translate(5,2)"><g transform="translate(0,5)"><circle r="4.5"></circle></g></g></svg> Inactive</li>
<li class="gone"><svg width="15" height="15"><g transform="translate(5,2)"><g transform="translate(0,5)"><circle r="4.5"></circle></g></g></svg> Gone</li>
<li class="replicatype"><svg width="15" height="15"><g transform="translate(5,2)"><g transform="translate(0,5)"><rect width="8" height="8"></rect></g></g></svg>Replica Type:<br/>N(NRT),T(TLOG),<br/>P(PULL) </li>
</ul>
</div>
<div style="width: 100%; text-align: center;" ng-show="showPaging">
<div id="cloudGraphPaging">
<button ng-show="prevEnabled" ng-click="previous()" id="cloudGraphPagingPrev">&lt; Previous</button>
<span ng-show="total==0">No collections found.</span>
<span ng-hide="total==0">Collections {{start}} - {{last}} of {{total}}.</span>&nbsp;
Filter by:&nbsp;<select ng-model="filterType" ng-change="initGraph()" id="cloudGraphPagingFilterType">
<option value="status">Status</option>
<option value="name">Name</option>
</select>&nbsp;T:{{filterType}}
<span ng-show="filterType=='status'">
<select ng-model="pagingStatusFilter" id="cloudGraphPagingStatusFilter" ng-change="resetGraph()">
<option value=""> - Any - </option>
<option value="healthy">Healthy</option>
<option value="degraded">Degraded</option>
<option value="downed_shard">Downed Shard</option>
<option value="recovering">Replica in Recovery</option>
</select>
</span>
<span ng-show="filterType=='name'">
<input ng-model="pagingFilter" type="text" size="10" name="filter" ng-change="resetGraph()"/>&nbsp;
</span>
Show <input ng-model="rows" ng-change="resetGraph()" type="text" size="2" name="rows" /> per page.
<button ng-show="nextEnabled" ng-click="next()">Next &gt;</button>
</div>
</div>
</div>
</div>
<div id="debug" ng-show="showDebug">
<ul class="clearfix">
<li class="clipboard"><a href="#" data-copied="Copied to Clipboard!">Copy to Clipboard (BUGGY!)</a></li>
<li class="close"><a ng-click="closeDebug()">Close</a></li>
</ul>
<pre class="debug"></pre>
</div>
</div>