]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: performance counter browsers 19922/head
authorRubab-Syed <rubab.syed21@gmail.com>
Tue, 9 Jan 2018 23:32:42 +0000 (04:32 +0500)
committerRubab-Syed <rubab.syed21@gmail.com>
Fri, 26 Jan 2018 00:20:21 +0000 (05:20 +0500)
Signed-off-by: Rubab-Syed <rubab.syed21@gmail.com>
src/pybind/mgr/dashboard/module.py
src/pybind/mgr/dashboard/monitors.html
src/pybind/mgr/dashboard/osd_perf.html
src/pybind/mgr/dashboard/perf_counters.html [new file with mode: 0644]
src/pybind/mgr/dashboard/rgw_detail.html
src/pybind/mgr/dashboard/servers.html
src/pybind/mgr/mgr_module.py
src/pybind/mgr/prometheus/module.py

index de9b889a2eeaa6879b5e2867381c7aa7dbe9f764..257abfed05c75acec914b156d7351e4f7e51876d 100644 (file)
@@ -776,6 +776,7 @@ class Module(MgrModule):
                 mon_status = global_instance().get_sync_object(MonStatus).data
                 for mon in mon_status["monmap"]["mons"]:
                     mon["stats"] = {}
+                    mon["url_perf"] = "/perf_counters/mon/" + mon["name"]
                     for counter in counters:
                         data = global_instance().get_counter("mon", mon["name"], counter)
                         if data is not None:
@@ -803,6 +804,43 @@ class Module(MgrModule):
             def servers_data(self):
                 return self._servers()
 
+            @cherrypy.expose
+            def perf_counters(self, service_type, service_id):
+                template = env.get_template("perf_counters.html")
+                toplevel_data = self._toplevel_data()
+                
+                return template.render(
+                    url_prefix = global_instance().url_prefix,
+                    ceph_version=global_instance().version,
+                    path_info=cherrypy.request.path_info,
+                    toplevel_data=json.dumps(toplevel_data, indent=2),
+                    content_data=json.dumps(self.perf_counters_data(service_type, service_id), indent=2)
+                )
+            
+            @cherrypy.expose
+            @cherrypy.tools.json_out()
+            def perf_counters_data(self, service_type, service_id):
+                schema = global_instance().get_perf_schema(service_type, str(service_id)).values()[0]
+                counters = []
+                
+                for key, value in sorted(schema.items()):
+                    counter = dict()
+                    counter["name"] = str(key)
+                    counter["description"] = value["description"]
+                    if global_instance()._stattype_to_str(value["type"]) == 'counter':
+                        counter["value"] = global_instance().get_rate(service_type, service_id, key)
+                        counter["unit"]  = "/s"
+                    else:
+                        counter["value"] = global_instance().get_latest(service_type, service_id, key)
+                        counter["unit"] = ""
+                    counters.append(counter)
+                                                    
+                return {
+                    'service_type': service_type,
+                    'service_id': service_id,
+                    'counters': counters,
+                }  
+                
             def _health(self):
                 # Fuse osdmap with pg_summary to get description of pools
                 # including their PG states
@@ -1022,7 +1060,8 @@ class Module(MgrModule):
                 return {
                     "osd": osd,
                     "osd_metadata": osd_metadata,
-                    "osd_histogram": histogram
+                    "osd_histogram": histogram,
+                    "url_perf": "/perf_counters/osd/" + str(osd_id)
                 }
 
             @cherrypy.expose
@@ -1196,6 +1235,7 @@ class Module(MgrModule):
 
                 return {
                     "rgw_id": rgw_id,
+                    "url_perf": "/perf_counters/rgw/" + str(rgw_id),
                     "rgw_metadata": to_sorted_array(rgw_metadata),
                     "rgw_status": to_sorted_array(rgw_status),
                 }
index 40a26551d4c6d4bc64a7d0d2ed02a24011e87cb1..60b34ad62c5056b1351ca4a8272fc9c1b2c78a6a 100644 (file)
@@ -67,7 +67,7 @@
                            <th>Open Sessions</th>
                        </thead>
                        <tr rv-each-mon="in_quorum" style="font-size:15px;height:80px">
-                           <td style="font-weight:bold">{mon.name}</td>
+                           <td style="font-weight:bold"><a rv-href="mon.url_perf">{mon.name}</a></td>
                            <td>{mon.rank}</td>
                            <td>{mon.public_addr}</td>
                            <td><span class="inlinesparkline" style="font-size:30px">{ mon.stats.num_sessions | sparkline_data }</span></td>
@@ -87,7 +87,7 @@
                    <th>Public Addr</th>
                </thead>
                <tr rv-each-mon="out_quorum" class="font-size:15px;height:80px">
-                   <td style="font-weight:bold">{mon.name}</td>
+                   <td style="font-weight:bold"><a rv-href="mon.url_perf">{mon.name}</a></td>
                    <td>{mon.rank}</td>
                    <td>{mon.public_addr}</td>
                </tr>
index b13ad17e1fd7ba0791ca12afa59f8ce1d11b940a..2c36613517f7faefe10e9284641d10ac03a9f060 100644 (file)
                     post_load();
                     setTimeout(refresh, 3000);
                 });
-            };
+           };
 
             // Wait 1s to load irrespective of normal frequency,
             // to promptly load our first delta
-            setTimeout(refresh, 1000);
+           setTimeout(refresh, 1000);
+                                   
         });
 </script>
 
 <section class="content-header">
     <h1>
         osd.{osd.osd}
+        <button class="pull-right btn btn-default"><a rv-href="url_perf">Performance Counters</a></button>
     </h1>
 </section>
 
 <section class="content">
-
+  
     <table>
         <tr>
             <td>
             <tbody>
             <tr rv-each-item="osd_list">
                 <td>{item.key}</td>
-                <td>{item.value}</td>
+                <td>{item.value}</td>          
             </tr>
             </tbody>
         </table>
diff --git a/src/pybind/mgr/dashboard/perf_counters.html b/src/pybind/mgr/dashboard/perf_counters.html
new file mode 100644 (file)
index 0000000..40638b6
--- /dev/null
@@ -0,0 +1,58 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+<script>
+        $(document).ready(function(){
+            // Pre-populated initial data at page load
+            var content_data = {{ content_data }};
+
+            rivets.bind($("div#content"), content_data);
+       
+            var refresh = function() {
+                $.get("{{ url_prefix }}/perf_counters/" + content_data.service_type  + "/" + content_data.service_id, function(data) {
+                    _.extend(content_data, data);
+                    setTimeout(refresh, 3000);
+                });
+            };
+        
+            setTimeout(refresh, 1000);
+        });
+</script>
+
+
+<section class="content-header">
+    <h1>
+        {service_type}.{service_id}
+    </h1>
+</section>
+
+<section class="content">
+<div class="box">
+    <div class="box-header">
+        <h3 class="box-title">Performance Counters</h3>
+    </div>
+    <div class="box-body">
+        <table class="table table-bordered">
+            <thead>
+            <tr>
+                <th>Name</th>
+                <th>Description</th>
+               <th>Value</th>
+            </tr>
+            </thead>
+            <tbody>
+            <tr rv-each-item="counters">
+                <td>{item.name}</td>
+                <td>{item.description}</td>
+               <td>{item.value | dimless} {item.unit}</td>
+            </tr>
+            </tbody>
+        </table>
+    </div>
+</div>
+
+</section>
+<!-- /.content -->
+
+{% endblock %}
index 986dc90da0796a27530e9883be8343a5d6783adc..3f224ac4c59cf1617d29ad03018a796c4a459ad0 100644 (file)
@@ -20,6 +20,7 @@
 </script>
 
 <section class="content-header">
+    <button class="pull-right btn btn-default"><a rv-href="url_perf">Performance Counters</a></button>
     <h1 rv-text="rgw_id"></h1>
 </section>
 
index 421d3389c3585edb09d8845208d6bda5f7ce2380..dcecac40943c9bfb7722df2bed720d71ca9bcf50 100644 (file)
             setTimeout(refresh, 5000);
 
             rivets.formatters.service_list = function(services) {
-                var strings = [];
+                var result = ""
                 $.each(services, function(i, svc) {
-                    strings.push(svc.type + "." + svc.id);
+                    result += "<a href={{url_prefix}}/perf_counters/" + svc.type + "/" + svc.id + ">" + svc.type + "." + svc.id + "</a>, " ;
                 });
-                return strings.join(", ");
+                result = result.slice(0, -2);
+                return result;
             };
 
             rivets.bind($("#content"), content_data);
@@ -55,8 +56,7 @@
                     <td>
                         {server.hostname}
                     </td>
-                    <td>
-                        {server.services | service_list}
+                    <td rv-html="server.services | service_list">
                     </td>
                     <td>
                         {server.ceph_version | short_version}
index ea72df830a05759a122943c5e3456939987705d3..60cc2202847ed960358351055521c4c4147ec1b4 100644 (file)
@@ -308,6 +308,21 @@ class MgrModule(ceph_module.BaseMgrModule):
         """
         return self._ceph_get(data_name)
 
+    def _stattype_to_str(self, stattype):
+        
+        typeonly = stattype & self.PERFCOUNTER_TYPE_MASK
+        if typeonly == 0:
+            return 'gauge'
+        if typeonly == self.PERFCOUNTER_LONGRUNAVG:
+            # this lie matches the DaemonState decoding: only val, no counts
+            return 'counter'
+        if typeonly == self.PERFCOUNTER_COUNTER:
+            return 'counter'
+        if typeonly == self.PERFCOUNTER_HISTOGRAM:
+            return 'histogram'
+        
+        return ''
+
     def get_server(self, hostname):
         """
         Called by the plugin to fetch metadata about a particular hostname from
index 5396d685175cfeefacaaa083aa361acdf340d4de..74aceeaad44eaeabd31f363e6029dbda7314ab00 100644 (file)
@@ -144,21 +144,6 @@ class Module(MgrModule):
         self.schema = OrderedDict()
         _global_instance['plugin'] = self
 
-    def _stattype_to_str(self, stattype):
-
-        typeonly = stattype & self.PERFCOUNTER_TYPE_MASK
-        if typeonly == 0:
-            return 'gauge'
-        if typeonly == self.PERFCOUNTER_LONGRUNAVG:
-            # this lie matches the DaemonState decoding: only val, no counts
-            return 'counter'
-        if typeonly == self.PERFCOUNTER_COUNTER:
-            return 'counter'
-        if typeonly == self.PERFCOUNTER_HISTOGRAM:
-            return 'histogram'
-
-        return ''
-
     def _setup_static_metrics(self):
         metrics = {}
         metrics['health_status'] = Metric(