Replace Pyasciigraph by termgraph for bar graphs in io.py
authorAntoine Busque <abusque@efficios.com>
Fri, 15 Jan 2016 21:53:10 +0000 (16:53 -0500)
committerAntoine Busque <abusque@efficios.com>
Thu, 11 Feb 2016 18:58:52 +0000 (13:58 -0500)
Signed-off-by: Antoine Busque <abusque@efficios.com>
lttnganalyses/cli/io.py

index 8b9cd90fc38b9844b2d9f7e8c0d4384ab4b569e9..413958c540ef641b368c9dd1044e0786bda69812 100644 (file)
@@ -27,7 +27,9 @@ import operator
 import statistics
 import sys
 from . import mi
+from . import termgraph
 from ..core import io
+from ..common import format_utils
 from .command import Command
 from ..linuxautomaton import common
 from ..ascii_graph import Pyasciigraph
@@ -584,166 +586,140 @@ class IoAnalysisCommand(Command):
             per_netif_send=per_netif_send_table,
         )
 
-    def _get_per_process_read_write_usage_datum(self, row):
-        if row.process.pid is None:
-            pid_str = 'unknown (tid=%d)' % (row.process.tid)
-        else:
-            pid_str = str(row.process.pid)
-
-        format_str = '{:>10} {:<25} {:>9} file {:>9} net {:>9} unknown'
-        output_str = format_str.format(
-            common.convert_size(row.size.value, padding_after=True),
-            '%s (%s)' % (row.process.name, pid_str),
-            common.convert_size(row.disk_size.value, padding_after=True),
-            common.convert_size(row.net_size.value, padding_after=True),
-            common.convert_size(row.unknown_size.value, padding_after=True))
+    def _print_per_proc_io(self, result_table, title):
+        header_format = '{:<25} {:<10} {:<10} {:<10}'
+        label_header = header_format.format(
+            'Process', 'Disk', 'Net', 'Unknown'
+        )
 
-        return (output_str, row.size.value)
+        def get_label(row):
+            label_format = '{:<25} {:>10} {:>10} {:>10}'
+            if row.process.pid is None:
+                pid_str = 'unknown (tid=%d)' % (row.process.tid)
+            else:
+                pid_str = str(row.process.pid)
 
-    def _get_per_process_block_read_write_usage_datum(self, row):
-        proc_name = row.process.name
+            label = label_format.format(
+                '%s (%s)' % (row.process.name, pid_str),
+                format_utils.format_size(row.disk_size.value),
+                format_utils.format_size(row.net_size.value),
+                format_utils.format_size(row.unknown_size.value)
+            )
 
-        if not proc_name:
-            proc_name = 'unknown'
+            return label
 
-        if row.process.pid is None:
-            pid_str = 'unknown (tid=%d)' % (row.process.tid)
-        else:
-            pid_str = str(row.process.pid)
+        graph = termgraph.BarGraph(
+            title='Per-process I/O ' + title,
+            label_header=label_header,
+            get_value=lambda row: row.size.value,
+            get_value_str=format_utils.format_size,
+            get_label=get_label,
+            data=result_table.rows
+        )
 
-        format_str = '{:>10} {:<22}'
-        output_str = format_str.format(
-            common.convert_size(row.size.value, padding_after=True),
-            '%s (pid=%s)' % (proc_name, pid_str))
+        graph.print_graph()
 
-        return (output_str, row.size.value)
+    def _print_per_proc_block_io(self, result_table, title):
+        def get_label(row):
+            proc_name = row.process.name
 
-    def _get_per_disk_count_usage_datum(self, row):
-        return (row.disk.name, row.count.value)
+            if not proc_name:
+                proc_name = 'unknown'
 
-    def _get_per_disk_rtps_usage_datum(self, row):
-        avg_latency = row.rtps.value / common.NSEC_PER_MSEC
-        avg_latency = round(avg_latency, 3)
+            if row.process.pid is None:
+                pid_str = 'unknown (tid={})'.format(row.process.tid)
+            else:
+                pid_str = str(row.process.pid)
 
-        return (row.disk.name, avg_latency)
+            return '{} (pid={})'.format(proc_name, pid_str)
 
-    def _get_per_netif_recv_send_usage_datum(self, row):
-        return ('%s %s' %
-                (common.convert_size(row.size.value), row.netif.name),
-                row.size.value)
+        graph = termgraph.BarGraph(
+            title='Block I/O ' + title,
+            label_header='Process',
+            get_value=lambda row: row.size.value,
+            get_value_str=format_utils.format_size,
+            get_label=get_label,
+            data=result_table.rows
+        )
 
-    def _get_per_file_read_write_usage_datum(self, row):
-        format_str = '{:>10} {} {}'
-        output_str = format_str.format(
-            common.convert_size(row.size.value, padding_after=True),
-            row.path.path, row.fd_owners.value)
+        graph.print_graph()
 
-        return (output_str, row.size.value)
+    def _print_per_disk_sector(self, result_table):
+        graph = termgraph.BarGraph(
+            title='Disk Requests Sector Count',
+            label_header='Disk',
+            unit='sectors',
+            get_value=lambda row: row.count.value,
+            get_label=lambda row: row.disk.name,
+            data=result_table.rows
+        )
 
-    def _print_usage_ascii_graph(self, result_table, get_datum_cb, graph_label,
-                                 graph_args=None):
-        graph = Pyasciigraph()
-        data = []
+        graph.print_graph()
 
-        if graph_args is None:
-            graph_args = {}
+    def _print_per_disk_request(self, result_table):
+        graph = termgraph.BarGraph(
+            title='Disk Request Count',
+            label_header='Disk',
+            unit='requests',
+            get_value=lambda row: row.count.value,
+            get_label=lambda row: row.disk.name,
+            data=result_table.rows
+        )
 
-        for row in result_table.rows:
-            datum = get_datum_cb(row)
-            data.append(datum)
+        graph.print_graph()
 
-        for line in graph.graph(graph_label, data, **graph_args):
-            print(line)
+    def _print_per_disk_rtps(self, result_table):
+        graph = termgraph.BarGraph(
+            title='Disk Request Average Latency',
+            label_header='Disk',
+            unit='ms',
+            get_value=lambda row: row.rtps.value / common.NSEC_PER_MSEC,
+            get_label=lambda row: row.disk.name,
+            data=result_table.rows
+        )
 
-    def _print_per_process_read(self, result_table):
-        label = 'Per-process I/O Read'
-        graph_args = {'with_value': False}
-        self._print_usage_ascii_graph(
-            result_table, self._get_per_process_read_write_usage_datum,
-            label, graph_args)
-
-    def _print_per_process_write(self, result_table):
-        label = 'Per-process I/O Write'
-        graph_args = {'with_value': False}
-        self._print_usage_ascii_graph(
-            result_table, self._get_per_process_read_write_usage_datum,
-            label, graph_args)
-
-    def _print_per_process_block_read(self, result_table):
-        label = 'Block I/O Read'
-        graph_args = {'with_value': False}
-        self._print_usage_ascii_graph(
-            result_table, self._get_per_process_block_read_write_usage_datum,
-            label, graph_args)
-
-    def _print_per_process_block_write(self, result_table):
-        label = 'Block I/O Write'
-        graph_args = {'with_value': False}
-        self._print_usage_ascii_graph(
-            result_table, self._get_per_process_block_read_write_usage_datum,
-            label, graph_args)
+        graph.print_graph()
 
-    def _print_per_disk_sector(self, result_table):
-        label = 'Disk requests sector count'
-        graph_args = {'unit': ' sectors'}
-        self._print_usage_ascii_graph(result_table,
-                                      self._get_per_disk_count_usage_datum,
-                                      label, graph_args)
+    def _print_per_netif_io(self, result_table, title):
+        graph = termgraph.BarGraph(
+            title='Network ' + title + ' Bytes',
+            label_header='Interface',
+            get_value=lambda row: row.size.value,
+            get_value_str=format_utils.format_size,
+            get_label=lambda row: row.netif.name,
+            data=result_table.rows
+        )
 
-    def _print_per_disk_request(self, result_table):
-        label = 'Disk request count'
-        graph_args = {'unit': ' requests'}
-        self._print_usage_ascii_graph(result_table,
-                                      self._get_per_disk_count_usage_datum,
-                                      label, graph_args)
+        graph.print_graph()
+
+    def _print_per_file_io(self, result_table, title):
+        # FIXME add option to show FD owners
+        # FIXME why are read and write values the same?
+        graph = termgraph.BarGraph(
+            title='Per-file I/O ' + title,
+            label_header='Path',
+            get_value=lambda row: row.size.value,
+            get_value_str=format_utils.format_size,
+            get_label=lambda row: row.path.path,
+            data=result_table.rows
+        )
 
-    def _print_per_disk_rtps(self, result_table):
-        label = 'Disk request average latency'
-        graph_args = {'unit': ' ms', 'sort': 2}
-        self._print_usage_ascii_graph(result_table,
-                                      self._get_per_disk_rtps_usage_datum,
-                                      label, graph_args)
-
-    def _print_per_netif_recv(self, result_table):
-        label = 'Network received bytes'
-        graph_args = {'with_value': False}
-        self._print_usage_ascii_graph(
-            result_table, self._get_per_netif_recv_send_usage_datum,
-            label, graph_args)
-
-    def _print_per_netif_send(self, result_table):
-        label = 'Network sent bytes'
-        graph_args = {'with_value': False}
-        self._print_usage_ascii_graph(
-            result_table, self._get_per_netif_recv_send_usage_datum,
-            label, graph_args)
-
-    def _print_per_file_read(self, result_table):
-        label = 'Files read'
-        graph_args = {'with_value': False, 'sort': 2}
-        self._print_usage_ascii_graph(
-            result_table, self._get_per_file_read_write_usage_datum,
-            label, graph_args)
-
-    def _print_per_file_write(self, result_table):
-        label = 'Files write'
-        graph_args = {'with_value': False, 'sort': 2}
-        self._print_usage_ascii_graph(
-            result_table, self._get_per_file_read_write_usage_datum,
-            label, graph_args)
+        graph.print_graph()
 
     def _print_usage(self, usage_tables):
-        self._print_per_process_read(usage_tables.per_proc_read)
-        self._print_per_process_write(usage_tables.per_proc_write)
-        self._print_per_file_read(usage_tables.per_file_read)
-        self._print_per_file_write(usage_tables.per_file_write)
-        self._print_per_process_block_read(usage_tables.per_proc_block_read)
-        self._print_per_process_block_write(usage_tables.per_proc_block_write)
+        self._print_per_proc_io(usage_tables.per_proc_read, 'Read')
+        self._print_per_proc_io(usage_tables.per_proc_write, 'Write')
+        self._print_per_file_io(usage_tables.per_file_read, 'Read')
+        self._print_per_file_io(usage_tables.per_file_write, 'Write')
+        self._print_per_proc_block_io(usage_tables.per_proc_block_read, 'Read')
+        self._print_per_proc_block_io(
+            usage_tables.per_proc_block_write, 'Write'
+        )
         self._print_per_disk_sector(usage_tables.per_disk_sector)
         self._print_per_disk_request(usage_tables.per_disk_request)
         self._print_per_disk_rtps(usage_tables.per_disk_rtps)
-        self._print_per_netif_recv(usage_tables.per_netif_recv)
-        self._print_per_netif_send(usage_tables.per_netif_send)
+        self._print_per_netif_io(usage_tables.per_netif_recv, 'Received')
+        self._print_per_netif_io(usage_tables.per_netif_send, 'Sent')
 
     def _fill_freq_result_table(self, duration_list, result_table):
         if not duration_list:
@@ -963,7 +939,7 @@ class IoAnalysisCommand(Command):
         if type(row.size) is mi.Empty:
             size = 'N/A'
         else:
-            size = common.convert_size(row.size.value)
+            size = format_utils.format_size(row.size.value)
 
         tid = row.process.tid
         proc_name = row.process.name
This page took 0.027496 seconds and 5 git commands to generate.