aboutsummaryrefslogtreecommitdiffstats
path: root/nfvbench/stats_collector.py
diff options
context:
space:
mode:
Diffstat (limited to 'nfvbench/stats_collector.py')
-rw-r--r--nfvbench/stats_collector.py145
1 files changed, 145 insertions, 0 deletions
diff --git a/nfvbench/stats_collector.py b/nfvbench/stats_collector.py
new file mode 100644
index 0000000..964d704
--- /dev/null
+++ b/nfvbench/stats_collector.py
@@ -0,0 +1,145 @@
+# Copyright 2016 Cisco Systems, Inc. All rights reserved.
+#
+# Licensed 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.
+
+
+import time
+
+
+class StatsCollector(object):
+ """Base class for all stats collector classes."""
+
+ def __init__(self, start_time):
+ self.start_time = start_time
+ self.stats = []
+
+ def get(self):
+ return self.stats
+
+ def peek(self):
+ return self.stats[-1]
+
+ @staticmethod
+ def _get_drop_percentage(drop_pkts, total_pkts):
+ return float(drop_pkts * 100) / total_pkts
+
+ @staticmethod
+ def _get_rx_pps(tx_pps, drop_percentage):
+ return (tx_pps * (100 - drop_percentage)) / 100
+
+ def _get_current_time_diff(self):
+ return int((time.time() - self.start_time) * 1000)
+
+
+class IntervalCollector(StatsCollector):
+ """Collects stats while traffic is running. Frequency is specified by 'interval_sec' setting."""
+
+ last_tx_pkts = 0
+ last_rx_pkts = 0
+ last_time = 0
+
+ def __init__(self, start_time):
+ StatsCollector.__init__(self, start_time)
+ self.notifier = None
+
+ def attach_notifier(self, notifier):
+ self.notifier = notifier
+
+ def add(self, stats):
+ if self.notifier:
+ current_stats = self.__compute_tx_rx_diff(stats)
+ self.notifier.send_interval_stats(**current_stats)
+
+ def reset(self):
+ # don't reset time!
+ self.last_rx_pkts = 0
+ self.last_tx_pkts = 0
+
+ def add_ndr_pdr(self, tag, stats):
+ if self.notifier:
+
+ current_time = self._get_current_time_diff()
+ rx_pps = self._get_rx_pps(stats['tx_pps'], stats['drop_percentage'])
+
+ self.last_tx_pkts = stats['tx_pps'] / 1000 * (current_time - self.last_time)
+ self.last_rx_pkts = rx_pps / 1000 * (current_time - self.last_time)
+ self.last_time = current_time
+
+ # 'drop_pct' key is an unfortunate name, since in iteration stats it means
+ # number of the packets. More suitable would be 'drop_percentage'.
+ # FDS frontend depends on this key
+ current_stats = {
+ '{}_pps'.format(tag): stats['tx_pps'],
+ 'tx_pps': stats['tx_pps'],
+ 'rx_pps': rx_pps,
+ 'drop_pct': stats['drop_percentage'],
+ 'time_ms': current_time
+ }
+
+ self.notifier.send_interval_stats(time_ms=current_stats['time_ms'],
+ tx_pps=current_stats['tx_pps'],
+ rx_pps=current_stats['rx_pps'],
+ drop_pct=current_stats['drop_pct'])
+ if tag == 'ndr':
+ self.notifier.send_ndr_found(stats['tx_pps'])
+ else:
+ self.notifier.send_pdr_found(stats['tx_pps'])
+
+ def __compute_tx_rx_diff(self, stats):
+ current_time = self._get_current_time_diff()
+ tx_diff = stats['overall']['tx']['total_pkts'] - self.last_tx_pkts
+ tx_pps = (tx_diff * 1000) / (current_time - self.last_time)
+ rx_diff = stats['overall']['rx']['total_pkts'] - self.last_rx_pkts
+ rx_pps = (rx_diff * 1000) / (current_time - self.last_time)
+
+ self.last_rx_pkts = stats['overall']['rx']['total_pkts']
+ self.last_tx_pkts = stats['overall']['tx']['total_pkts']
+ self.last_time = current_time
+
+ return {
+ 'tx_pps': tx_pps,
+ 'rx_pps': rx_pps,
+ 'drop_pct': max(0.0, (1 - (float(rx_pps) / tx_pps)) * 100),
+ 'time_ms': current_time
+ }
+
+
+class IterationCollector(StatsCollector):
+ """Collects stats after traffic is stopped. Frequency is specified by 'duration_sec' setting."""
+
+ def __init__(self, start_time):
+ StatsCollector.__init__(self, start_time)
+
+ def add(self, stats, tx_pps):
+ drop_percentage = self._get_drop_percentage(stats['overall']['rx']['dropped_pkts'],
+ stats['overall']['tx']['total_pkts'])
+
+ record = {
+ 'total_tx_pps': int(stats['total_tx_rate']),
+ 'tx_pps': tx_pps,
+ 'tx_pkts': stats['overall']['tx']['total_pkts'],
+ 'rx_pps': self._get_rx_pps(tx_pps, drop_percentage),
+ 'rx_pkts': stats['overall']['rx']['total_pkts'],
+ 'drop_pct': stats['overall']['rx']['dropped_pkts'],
+ 'drop_percentage': drop_percentage,
+ 'time_ms': int(time.time() * 1000)
+ }
+
+ if 'warning' in stats:
+ record['warning'] = stats['warning']
+
+ self.stats.append(record)
+
+ def add_ndr_pdr(self, tag, rate):
+ last_stats = self.peek()
+ last_stats['{}_pps'.format(tag)] = rate