Преглед изворни кода

实现宿主机top 10性能接口

James Iter пре 9 година
родитељ
комит
eb13382c72
4 измењених фајлова са 284 додато и 13 уклоњено
  1. 230 0
      api/host_performance.py
  2. 36 10
      api/performance.py
  3. 15 0
      api_route_table.py
  4. 3 3
      templates/dashboard.html

+ 230 - 0
api/host_performance.py

@@ -221,3 +221,233 @@ def r_disk_usage_io_last_seven_days(node_id, mountpoint):
                                 granularity='seven_days')
 
 
+@Utils.dumps2response
+def r_current_top_10():
+
+    # JimV 设计的 Hosts 容量为 100 个
+    volume = 100
+    limit = volume
+    length = 10
+    end_ts = ji.Common.ts() - 60
+    start_ts = end_ts - 60
+
+    # 避免落在时间边界上,导致过滤条件的范围落空
+    if start_ts % 60 == 0:
+        start_ts -= 1
+
+    ret = dict()
+    ret['state'] = ji.Common.exchange_state(20000)
+    ret['data'] = {
+        'cpu_load': list(),
+        'rw_bytes': list(),
+        'rw_req': list(),
+        'rt_bytes': list(),
+        'rt_packets': list()
+    }
+
+    filter_str = ';'.join([':'.join(['timestamp', 'gt', start_ts.__str__()]),
+                           ':'.join(['timestamp', 'lt', end_ts.__str__()])])
+
+    rows, _ = HostCPUMemory.get_by_filter(limit=limit, filter_str=filter_str)
+    rows.sort(key=lambda k: k['cpu_load'], reverse=True)
+
+    effective_range = length
+    if rows.__len__() < length:
+        effective_range = rows.__len__()
+
+    for i in range(effective_range):
+        if rows[i]['cpu_load'] == 0:
+            break
+
+        ret['data']['cpu_load'].append(rows[i])
+
+    rows, _ = HostDiskUsageIO.get_by_filter(limit=limit, filter_str=filter_str)
+    for i in range(rows.__len__()):
+        rows[i]['rw_bytes'] = rows[i]['rd_bytes'] + rows[i]['wr_bytes']
+        rows[i]['rw_req'] = rows[i]['rd_req'] + rows[i]['wr_req']
+
+    effective_range = length
+    if rows.__len__() < length:
+        effective_range = rows.__len__()
+
+    rows.sort(key=lambda k: k['rw_bytes'], reverse=True)
+
+    for i in range(effective_range):
+        if rows[i]['rw_req'] == 0:
+            break
+
+        ret['data']['rw_bytes'].append(rows[i])
+
+    rows.sort(key=lambda k: k['rw_req'], reverse=True)
+
+    for i in range(effective_range):
+        if rows[i]['rw_req'] == 0:
+            break
+
+        ret['data']['rw_req'].append(rows[i])
+
+    rows, _ = HostTraffic.get_by_filter(limit=limit, filter_str=filter_str)
+    for i in range(rows.__len__()):
+        rows[i]['rt_bytes'] = rows[i]['rx_bytes'] + rows[i]['tx_bytes']
+        rows[i]['rt_packets'] = rows[i]['rx_packets'] + rows[i]['tx_packets']
+
+    effective_range = length
+    if rows.__len__() < length:
+        effective_range = rows.__len__()
+
+    rows.sort(key=lambda k: k['rt_bytes'], reverse=True)
+
+    for i in range(effective_range):
+        if rows[i]['rt_packets'] == 0:
+            break
+
+        ret['data']['rt_bytes'].append(rows[i])
+
+    rows.sort(key=lambda k: k['rt_packets'], reverse=True)
+
+    for i in range(effective_range):
+        if rows[i]['rt_packets'] == 0:
+            break
+
+        ret['data']['rt_packets'].append(rows[i])
+
+    return ret
+
+
+@Utils.dumps2response
+def r_last_the_range_minutes_top_10(_range):
+
+    volume = 100
+    limit = volume * _range
+    length = 10
+    end_ts = ji.Common.ts() - 60
+    start_ts = end_ts - 60 * _range
+
+    # 避免落在时间边界上,导致过滤条件的范围落空
+    if start_ts % 60 == 0:
+        start_ts -= 1
+
+    ret = dict()
+    ret['state'] = ji.Common.exchange_state(20000)
+    ret['data'] = {
+        'cpu_load': list(),
+        'rw_bytes': list(),
+        'rw_req': list(),
+        'rt_bytes': list(),
+        'rt_packets': list()
+    }
+
+    filter_str = ';'.join([':'.join(['timestamp', 'gt', start_ts.__str__()]),
+                           ':'.join(['timestamp', 'lt', end_ts.__str__()])])
+
+    # cpu 负载
+    hosts_node_id_mapping = dict()
+    rows, _ = HostCPUMemory.get_by_filter(limit=limit, filter_str=filter_str)
+    for row in rows:
+        if row['node_id'] not in hosts_node_id_mapping:
+            hosts_node_id_mapping[row['node_id']] = {'cpu_load': 0, 'count': 0}
+
+        hosts_node_id_mapping[row['node_id']]['cpu_load'] += row['cpu_load']
+        hosts_node_id_mapping[row['node_id']]['count'] += 1.0
+
+    rows = list()
+    for k, v in hosts_node_id_mapping.items():
+
+        # 忽略除数为 0 的情况
+        if v['cpu_load'] == 0:
+            continue
+
+        rows.append({'node_id': k, 'cpu_load': v['cpu_load'] / v['count']})
+
+    effective_range = length
+    if rows.__len__() < length:
+        effective_range = rows.__len__()
+
+    rows.sort(key=lambda _k: _k['cpu_load'], reverse=True)
+
+    ret['data']['cpu_load'] = rows[0:effective_range]
+
+    # 磁盘使用统计
+    hosts_node_id_mapping.clear()
+    rows, _ = HostDiskUsageIO.get_by_filter(limit=limit, filter_str=filter_str)
+    for row in rows:
+        disk_uuid = '_'.join([row['node_id'].__str__(), row['mountpoint']])
+        if disk_uuid not in hosts_node_id_mapping:
+            hosts_node_id_mapping[disk_uuid] = {'rw_bytes': 0, 'rw_req': 0}
+
+        hosts_node_id_mapping[disk_uuid]['rw_bytes'] += row['rd_bytes'] + row['wr_bytes']
+        hosts_node_id_mapping[disk_uuid]['rw_req'] += row['rd_req'] + row['wr_req']
+
+    rows = list()
+    for k, v in hosts_node_id_mapping.items():
+
+        # 过滤掉无操作的数据
+        if v['rw_req'] == 0:
+            continue
+
+        rows.append({'disk_uuid': k, 'rw_bytes': v['rw_bytes'] * 60 * _range, 'rw_req': v['rw_req'] * 60 * _range})
+
+    effective_range = length
+    if rows.__len__() < length:
+        effective_range = rows.__len__()
+
+    rows.sort(key=lambda _k: _k['rw_bytes'], reverse=True)
+    ret['data']['rw_bytes'] = rows[0:effective_range]
+
+    rows.sort(key=lambda _k: _k['rw_req'], reverse=True)
+    ret['data']['rw_req'] = rows[0:effective_range]
+
+    # 网络流量
+    hosts_node_id_mapping.clear()
+    rows, _ = HostTraffic.get_by_filter(limit=limit, filter_str=filter_str)
+    for row in rows:
+        nic_uuid = '_'.join([row['node_id'].__str__(), row['name']])
+        if nic_uuid not in hosts_node_id_mapping:
+            hosts_node_id_mapping[nic_uuid] = {'rt_bytes': 0, 'rt_packets': 0}
+
+        hosts_node_id_mapping[nic_uuid]['rt_bytes'] += row['rx_bytes'] + row['tx_bytes']
+        hosts_node_id_mapping[nic_uuid]['rt_packets'] += row['rx_packets'] + row['tx_packets']
+
+    rows = list()
+    for k, v in hosts_node_id_mapping.items():
+
+        # 过滤掉无流量的数据
+        if v['rt_packets'] == 0:
+            continue
+
+        rows.append({'nic_uuid': k, 'rt_bytes': v['rt_bytes'] * 60 * _range,
+                     'rt_packets': v['rt_packets'] * 60 * _range})
+
+    effective_range = length
+    if rows.__len__() < length:
+        effective_range = rows.__len__()
+
+    rows.sort(key=lambda _k: _k['rt_bytes'], reverse=True)
+    ret['data']['rt_bytes'] = rows[0:effective_range]
+
+    rows.sort(key=lambda _k: _k['rt_packets'], reverse=True)
+    ret['data']['rt_packets'] = rows[0:effective_range]
+
+    return ret
+
+
+@Utils.dumps2response
+def r_last_10_minutes_top_10():
+    return r_last_the_range_minutes_top_10(_range=10)
+
+
+@Utils.dumps2response
+def r_last_hour_top_10():
+    return r_last_the_range_minutes_top_10(_range=60)
+
+
+@Utils.dumps2response
+def r_last_six_hours_top_10():
+    return r_last_the_range_minutes_top_10(_range=60 * 6)
+
+
+@Utils.dumps2response
+def r_last_day_top_10():
+    return r_last_the_range_minutes_top_10(_range=60 * 24)
+
+

+ 36 - 10
api/performance.py

@@ -208,6 +208,7 @@ def r_current_top_10():
     # JimV 设计的 Guests 容量为 4000 个
     volume = 4000
     limit = volume
+    length = 10
     end_ts = ji.Common.ts() - 60
     start_ts = end_ts - 60
 
@@ -231,7 +232,11 @@ def r_current_top_10():
     rows, _ = CPUMemory.get_by_filter(limit=limit, filter_str=filter_str)
     rows.sort(key=lambda k: k['cpu_load'], reverse=True)
 
-    for i in range(10):
+    effective_range = length
+    if rows.__len__() < length:
+        effective_range = rows.__len__()
+
+    for i in range(effective_range):
         if rows[i]['cpu_load'] == 0:
             break
 
@@ -242,9 +247,13 @@ def r_current_top_10():
         rows[i]['rw_bytes'] = rows[i]['rd_bytes'] + rows[i]['wr_bytes']
         rows[i]['rw_req'] = rows[i]['rd_req'] + rows[i]['wr_req']
 
+    effective_range = length
+    if rows.__len__() < length:
+        effective_range = rows.__len__()
+
     rows.sort(key=lambda k: k['rw_bytes'], reverse=True)
 
-    for i in range(10):
+    for i in range(effective_range):
         if rows[i]['rw_req'] == 0:
             break
 
@@ -252,7 +261,7 @@ def r_current_top_10():
 
     rows.sort(key=lambda k: k['rw_req'], reverse=True)
 
-    for i in range(10):
+    for i in range(effective_range):
         if rows[i]['rw_req'] == 0:
             break
 
@@ -263,9 +272,13 @@ def r_current_top_10():
         rows[i]['rt_bytes'] = rows[i]['rx_bytes'] + rows[i]['tx_bytes']
         rows[i]['rt_packets'] = rows[i]['rx_packets'] + rows[i]['tx_packets']
 
+    effective_range = length
+    if rows.__len__() < length:
+        effective_range = rows.__len__()
+
     rows.sort(key=lambda k: k['rt_bytes'], reverse=True)
 
-    for i in range(10):
+    for i in range(effective_range):
         if rows[i]['rt_packets'] == 0:
             break
 
@@ -273,7 +286,7 @@ def r_current_top_10():
 
     rows.sort(key=lambda k: k['rt_packets'], reverse=True)
 
-    for i in range(10):
+    for i in range(effective_range):
         if rows[i]['rt_packets'] == 0:
             break
 
@@ -287,6 +300,7 @@ def r_last_the_range_minutes_top_10(_range):
 
     volume = 4000
     limit = volume * _range
+    length = 10
     end_ts = ji.Common.ts() - 60
     start_ts = end_ts - 60 * _range
 
@@ -326,9 +340,13 @@ def r_last_the_range_minutes_top_10(_range):
 
         rows.append({'guest_uuid': k, 'cpu_load': v['cpu_load'] / v['count']})
 
+    effective_range = length
+    if rows.__len__() < length:
+        effective_range = rows.__len__()
+
     rows.sort(key=lambda _k: _k['cpu_load'], reverse=True)
 
-    ret['data']['cpu_load'] = rows[0:10]
+    ret['data']['cpu_load'] = rows[0:effective_range]
 
     # 磁盘使用统计
     guests_uuid_mapping.clear()
@@ -349,11 +367,15 @@ def r_last_the_range_minutes_top_10(_range):
 
         rows.append({'disk_uuid': k, 'rw_bytes': v['rw_bytes'] * 60 * _range, 'rw_req': v['rw_req'] * 60 * _range})
 
+    effective_range = length
+    if rows.__len__() < length:
+        effective_range = rows.__len__()
+
     rows.sort(key=lambda _k: _k['rw_bytes'], reverse=True)
-    ret['data']['rw_bytes'] = rows[0:10]
+    ret['data']['rw_bytes'] = rows[0:effective_range]
 
     rows.sort(key=lambda _k: _k['rw_req'], reverse=True)
-    ret['data']['rw_req'] = rows[0:10]
+    ret['data']['rw_req'] = rows[0:effective_range]
 
     # 网络流量
     guests_uuid_mapping.clear()
@@ -375,11 +397,15 @@ def r_last_the_range_minutes_top_10(_range):
         rows.append({'guest_uuid': k, 'rt_bytes': v['rt_bytes'] * 60 * _range,
                      'rt_packets': v['rt_packets'] * 60 * _range})
 
+    effective_range = length
+    if rows.__len__() < length:
+        effective_range = rows.__len__()
+
     rows.sort(key=lambda _k: _k['rt_bytes'], reverse=True)
-    ret['data']['rt_bytes'] = rows[0:10]
+    ret['data']['rt_bytes'] = rows[0:effective_range]
 
     rows.sort(key=lambda _k: _k['rt_packets'], reverse=True)
-    ret['data']['rt_packets'] = rows[0:10]
+    ret['data']['rt_packets'] = rows[0:effective_range]
 
     return ret
 

+ 15 - 0
api_route_table.py

@@ -196,4 +196,19 @@ add_rule_api(host_performance.blueprint, '/disk_io/last_day/<node_id>/<mountpoin
 add_rule_api(host_performance.blueprint, '/disk_io/last_seven_days/<node_id>/<mountpoint>',
              api_func='host_performance.r_disk_usage_io_last_seven_days', methods=['GET'])
 
+add_rule_api(host_performance.blueprint, '/_current_top_10',
+             api_func='host_performance.r_current_top_10', methods=['GET'])
+
+add_rule_api(host_performance.blueprint, '/_last_10_minutes_top_10',
+             api_func='host_performance.r_last_10_minutes_top_10', methods=['GET'])
+
+add_rule_api(host_performance.blueprint, '/_last_hour_top_10',
+             api_func='host_performance.r_last_hour_top_10', methods=['GET'])
+
+add_rule_api(host_performance.blueprint, '/_last_six_hours_top_10',
+             api_func='host_performance.r_last_six_hours_top_10', methods=['GET'])
+
+add_rule_api(host_performance.blueprint, '/_last_day_top_10',
+             api_func='host_performance.r_last_day_top_10', methods=['GET'])
+
 

+ 3 - 3
templates/dashboard.html

@@ -142,7 +142,7 @@
                 </div>
                 <div class="col-md-4">
                     <div class="content-box">
-                        <h3 class="content-box-header bg-black-opacity-alt">
+                        <h3 class="content-box-header" style="background-color: #9e9e9e; opacity: 0.9; color: #fff;">
                             磁盘 IOPS
                         </h3>
                         <div class="content-box-wrapper" style="padding-top: 0;">
@@ -175,7 +175,7 @@
                 </div>
                 <div class="col-md-4">
                     <div class="content-box">
-                        <h3 class="content-box-header bg-black-opacity-alt">
+                        <h3 class="content-box-header" style="background-color: #9e9e9e; opacity: 0.9; color: #fff;">
                             磁盘吞吐量
                         </h3>
                         <div class="content-box-wrapper" style="padding-top: 0;">
@@ -219,7 +219,7 @@
             <div class="row">
                 <div class="col-md-4">
                     <div class="content-box">
-                        <h3 class="content-box-header bg-green">
+                        <h3 class="content-box-header bg-green" style="opacity: 0.72;">
                             网络流量
                         </h3>
                         <div class="content-box-wrapper" style="padding-top: 0;">