+def _annotate_chain_stats(chain_stats, nodrop_marker='=>'):
+ """Transform a plain chain stats into an annotated one.
+
+ Example:
+ {
+ 0: {'packets': [2000054, 1999996, 1999996, 1999996],
+ 'lat_min_usec': 10,
+ 'lat_max_usec': 187,
+ 'lat_avg_usec': 45},
+ 1: {...},
+ 'total': {...}
+ }
+ should become:
+ {
+ 0: {'packets': [2000054, -58 (-0.034%), '=>', 1999996],
+ 'lat_min_usec': 10,
+ 'lat_max_usec': 187,
+ 'lat_avg_usec': 45},
+ 1: {...},
+ 'total': {...}
+ }
+
+ In the case of shared net, some columns in packets array can have ''
+ """
+ for stats in chain_stats.values():
+ packets = stats['packets']
+ count = len(packets)
+ if count > 1:
+ # keep the first counter
+ annotated_packets = [packets[0]]
+ # modify all remaining counters
+ prev_count = packets[0]
+ for index in range(1, count):
+ cur_count = packets[index]
+ if cur_count == '':
+ # an empty string indicates an unknown counter for a shared interface
+ # do not annotate those
+ annotated_value = ''
+ else:
+ drop = cur_count - prev_count
+ if drop:
+ dr = (drop * 100.0) / prev_count if prev_count else 0
+ annotated_value = '{:,} ({:.4f}%)'.format(drop, dr)
+ else:
+ # no drop
+ # if last column we display the value
+ annotated_value = cur_count if index == count - 1 else nodrop_marker
+ prev_count = cur_count
+ annotated_packets.append(annotated_value)
+
+ stats['packets'] = annotated_packets