1 # Copyright 2016 Cisco Systems, Inc. All rights reserved.
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
19 class StatsCollector(object):
20 """Base class for all stats collector classes."""
22 def __init__(self, start_time):
23 self.start_time = start_time
33 def _get_drop_percentage(drop_pkts, total_pkts):
34 return float(drop_pkts * 100) / total_pkts
37 def _get_rx_pps(tx_pps, drop_percentage):
38 return (tx_pps * (100 - drop_percentage)) / 100
40 def _get_current_time_diff(self):
41 return int((time.time() - self.start_time) * 1000)
44 class IntervalCollector(StatsCollector):
45 """Collects stats while traffic is running. Frequency is specified by 'interval_sec' setting."""
51 def __init__(self, start_time):
52 StatsCollector.__init__(self, start_time)
55 def attach_notifier(self, notifier):
56 self.notifier = notifier
60 current_stats = self.__compute_tx_rx_diff(stats)
61 self.notifier.send_interval_stats(**current_stats)
68 def add_ndr_pdr(self, tag, stats):
71 current_time = self._get_current_time_diff()
72 rx_pps = self._get_rx_pps(stats['tx_pps'], stats['drop_percentage'])
74 self.last_tx_pkts = stats['tx_pps'] / 1000 * (current_time - self.last_time)
75 self.last_rx_pkts = rx_pps / 1000 * (current_time - self.last_time)
76 self.last_time = current_time
78 # 'drop_pct' key is an unfortunate name, since in iteration stats it means
79 # number of the packets. More suitable would be 'drop_percentage'.
80 # FDS frontend depends on this key
82 '{}_pps'.format(tag): stats['tx_pps'],
83 'tx_pps': stats['tx_pps'],
85 'drop_pct': stats['drop_percentage'],
86 'time_ms': current_time
89 self.notifier.send_interval_stats(time_ms=current_stats['time_ms'],
90 tx_pps=current_stats['tx_pps'],
91 rx_pps=current_stats['rx_pps'],
92 drop_pct=current_stats['drop_pct'])
94 self.notifier.send_ndr_found(stats['tx_pps'])
96 self.notifier.send_pdr_found(stats['tx_pps'])
98 def __compute_tx_rx_diff(self, stats):
99 current_time = self._get_current_time_diff()
100 tx_diff = stats['overall']['tx']['total_pkts'] - self.last_tx_pkts
101 tx_pps = (tx_diff * 1000) / (current_time - self.last_time)
102 rx_diff = stats['overall']['rx']['total_pkts'] - self.last_rx_pkts
103 rx_pps = (rx_diff * 1000) / (current_time - self.last_time)
105 self.last_rx_pkts = stats['overall']['rx']['total_pkts']
106 self.last_tx_pkts = stats['overall']['tx']['total_pkts']
107 self.last_time = current_time
112 'drop_pct': max(0.0, (1 - (float(rx_pps) / tx_pps)) * 100),
113 'time_ms': current_time
117 class IterationCollector(StatsCollector):
118 """Collects stats after traffic is stopped. Frequency is specified by 'duration_sec' setting."""
120 def __init__(self, start_time):
121 StatsCollector.__init__(self, start_time)
123 def add(self, stats, tx_pps):
124 drop_percentage = self._get_drop_percentage(stats['overall']['rx']['dropped_pkts'],
125 stats['overall']['tx']['total_pkts'])
128 'total_tx_pps': int(stats['total_tx_rate']),
130 'tx_pkts': stats['overall']['tx']['total_pkts'],
131 'rx_pps': self._get_rx_pps(tx_pps, drop_percentage),
132 'rx_pkts': stats['overall']['rx']['total_pkts'],
133 'drop_pct': stats['overall']['rx']['dropped_pkts'],
134 'drop_percentage': drop_percentage,
135 'time_ms': int(time.time() * 1000)
138 if 'warning' in stats:
139 record['warning'] = stats['warning']
141 self.stats.append(record)
143 def add_ndr_pdr(self, tag, rate):
144 last_stats = self.peek()
145 last_stats['{}_pps'.format(tag)] = rate