| <!-- |
| 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> </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">< 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> |
| |
| Filter by: <select ng-model="filterType" ng-change="filterInput()" id="nodesPagingFilterType"> |
| <option value="node">Host/node name</option> |
| <option value="collection">Collection name</option> |
| </select> |
| |
| <span ng-show="filterType=='node'"> |
| <input ng-model="nodeFilter" type="text" size="10" name="nodefilter" ng-change="filterInput()" ng-model-options='{ debounce: 500 }' /> |
| </span> |
| <span ng-show="filterType=='collection'"> |
| <input ng-model="collectionFilter" type="text" size="10" name="collectionfilter" ng-change="filterInput()" ng-model-options='{ debounce: 500 }'/> |
| </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 ></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">< Previous</button> |
| <span ng-show="total==0">No collections found.</span> |
| <span ng-hide="total==0">Collections {{start}} - {{last}} of {{total}}.</span> |
| |
| Filter by: <select ng-model="filterType" ng-change="initGraph()" id="cloudGraphPagingFilterType"> |
| <option value="status">Status</option> |
| <option value="name">Name</option> |
| </select> 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()"/> |
| </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 ></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> |