def calc_expected_rps(fire, started_at=None): '''Calculate theoretical request per second sequinse. Args: fire: dict, current fire(job) options. Returns: result: list of tuples. ''' result = [] #try: # offset = int(fire['started_at']) #except TypeError: # exit_err('Can\'t parse fire *started_at* attribute, config malformed.') offset = fire.get('started_at', None) if not offset and started_at: offset = started_at else: exit_err('Can\'t parse fire *started_at* attribute, config malformed.') offset = int(offset) for schema in fire['load']: series = series_from_schema(schema, offset) result.extend(series) offset = series[-1][0] + 1 return result
def __init__(self, fire): #self.check = 0 self.first_epoach = 0.0 self.last_epoach = 0.0 self.parts = [100, 99, 98, 95, 90, 85, 80, 75, 50] self.resp = {} #__vals = [[]] * len(self.parts) #self.series = dict(zip([str(e) for e in self.parts], __vals)) #self.series['rps'] = [] self.series = { 'rps': [], '100': [], '99': [], '98': [], '95': [], '90': [], '85': [], '80': [], '75': [], '50': [], } self.codes_lst = [] self.codes_series = {} self.codes_tbl = {} self.errno_lst = [] self.errno_series = {} self.errno_tbl = {} try: self.time_periods = fire['time_periods'] except KeyError: exit_err('Can\'t parse *time_periods* fire attribute, it\'s ' + 'necessary!') for indx, bound in enumerate(self.time_periods): self.time_periods[indx] = bound_to_ms(str(bound), self.time_periods) self.time_periods.sort() self.boundaries = {k: {'num': 0, 'percentil': 0} for k in\ self.time_periods} self.responses_num = 0.0 self.http_codes_num = 0.0 self.reply_series = { 'name': 'replies', 'data': [], } self.resp_perc = [] self.total_tx = 0.0 self.total_rx = 0.0 self.tx_series = {'name': 'tx', 'data': [], } self.rx_series = {'name': 'rx', 'data': [], } self.rtt_fracts = ['con_ms', 'send_ms', 'proc_ms', 'resp_ms'] self.rtt_fracts_series = {} for part in self.rtt_fracts: self.rtt_fracts_series[part] = {'name': part, 'data': [], }
def get_fire(json_path='.fire_up.json'): '''Read JSON encoded file with fire dict inside. Args: json_path: file path Returns: fire: dict, describes fire(job) options. ''' try: with open(json_path, 'r') as fire_fh: return json.loads(fire_fh.read()) except IOError, e: exit_err('Could not read "%s": %s\n' % (json_path, e))
def get_calc_load_series(fire): '''Calculate theoretical request per second sequinse. Args: fire: dict, current fire(job) options. Returns: result: list of tuples. ''' result = [] try: offset = int(fire['started_at']) except TypeError: exit_err('Can\'t parse fire *started_at* attribute, config malformed.') for schema in fire['load']: __series = series_from_schema(schema, offset) result.extend(__series) offset = __series[-1][0] + 1 return result
def __init__(self, fire): self.first_epoach = None self.last_epoach = 0.0 self.def_percentiles = [100, 99, 98, 95, 90, 85, 80, 75, 50] self.percentiles_serieses = {} for p in self.def_percentiles: self.percentiles_serieses[str(p)] = [] self.responce_per_second_series = [] self.resp = {} self.codes_set = set() self.codes_series = {} self.codes_tbl = {} self.errno_set = set() self.errno_series = {} self.errno_tbl = {} try: #self.time_periods = fire['time_periods'] self.resp_time_vals = fire['time_periods'] except KeyError: exit_err('Can\'t parse *time_periods* fire attribute, it\'s ' + 'necessary!') # convert time bounds to milliseconds for idx, resp_time_val in enumerate(self.resp_time_vals): self.resp_time_vals[idx] = bound_to_ms(str(resp_time_val), self.resp_time_vals) self.resp_time_vals.sort() self.resp_by_times = {k: {'num': 0, 'percentil': 0} for k in\ self.resp_time_vals} self.responses_num = 0.0 self.http_codes_num = 0.0 self.total_tx = 0.0 self.total_rx = 0.0 self.tx_series = {'name': 'tx', 'data': [], } self.rx_series = {'name': 'rx', 'data': [], } self.rtt_fracts = ['con_ms', 'send_ms', 'proc_ms', 'resp_ms'] self.rtt_fracts_series = {} for part in self.rtt_fracts: self.rtt_fracts_series[part] = {'name': part, 'data': [], }
def add_resp(self, epoch, rtt, http_status, errno, req_byte, resp_byte, con_ms, send_ms, proc_ms, resp_ms): '''Process regular log line. Args: epoch: int, time stamp. rtt: int, request round trip time. http_status: int, responce HTTP status code. errno: str, errno code from TCP socket. req_byte: int, request size in bytes. resp_byte: int, responce size in bytes. con_ms: float, TCP connection establishing time in milliseconds. send_ms: float, request sending time in milliseconds. proc_ms: float, awaiting responce time in milliseconds. resp_ms: float, getting responce time in milliseconds. Returns: nothing, just update obj attributes ''' rtt_ms = rtt / 1000 self.responses_num += 1 periods = self.time_periods[:] periods.append(rtt_ms) periods.sort() indx = periods.index(rtt_ms) try: self.boundaries[periods[indx + 1]]['num'] += 1 except IndexError: exit_err('Buggy indx: %s\nperiods: %s in resp' % (indx, periods)) try: self.resp[epoch]['rtt'].append(rtt) except KeyError: self.resp[epoch] = { 'percentiles': [], 'rtt': [], 'rps': 0, 'codes': {}, 'errno': {}, } self.resp[epoch]['rtt'].append(rtt) if http_status != 0: # 0 mean transport layer error. self.http_codes_num += 1 # HTTP status codes processing for each req try: self.resp[epoch]['codes'][http_status] += 1 except KeyError: self.resp[epoch]['codes'][http_status] = 1 self.codes_lst.append(http_status) # for all test try: self.codes_tbl[http_status]['num'] += 1 except KeyError: self.codes_tbl[http_status] = {'num': 1} # Socket errno processing for each req try: self.resp[epoch]['errno'][errno] += 1 except KeyError: self.resp[epoch]['errno'][errno] = 1 self.errno_lst.append(errno) # for all test try: self.errno_tbl[errno]['num'] += 1 except KeyError: self.errno_tbl[errno] = {'num': 1} # Tx/Rx bytes processing for each req try: self.resp[epoch]['tx'] += req_byte self.resp[epoch]['rx'] += resp_byte except KeyError: self.resp[epoch]['tx'] = req_byte self.resp[epoch]['rx'] = resp_byte # rtt fractions for each req if not 'rtt_fract' in self.resp[epoch]: self.resp[epoch]['rtt_fract'] = {} for part in self.rtt_fracts: try: self.resp[epoch]['rtt_fract'][part].append(vars()[part]) except KeyError: self.resp[epoch]['rtt_fract'][part] = [vars()[part], ]
def get_fire(json_path='.fire_up.json'): '''Read JSON encoded file with fire dict inside. Args: json_path: file path Returns: fire: dict, describes fire(job) options. ''' try: with open(json_path, 'r') as fire_fh: return json.loads(fire_fh.read()) except IOError, e: exit_err('Could not read "%s": %s\n' % (json_path, e)) except JSONDecodeError, e: exit_err('Could not parse fire config file: %s\n%s' % (json_path, e)) def validate_bound(bound): '''Check conformity of bound short notation Args: bound: str with declare time bound in short notation Returns: bool, true if short notation is valid ''' trans_table = string.maketrans('', '') allowed = string.digits + 'sm' return not bound.translate(trans_table, allowed)
def add_resp(self, line, is_interactive=False): '''Process regular log line. Args: is_interactive: bool, is it running test stats or post facto proc. line: str - cvs contains fields: * epoch: int, time stamp. * rtt: int, request round trip time. * http_status: int, responce HTTP status code. * errno: str, errno code from TCP socket. * req_byte: int, request size in bytes. * resp_byte: int, responce size in bytes. * con_ms: float, TCP connection establishing time in milliseconds. * send_ms: float, request sending time in milliseconds. * proc_ms: float, awaiting responce time in milliseconds. * resp_ms: float, getting responce time in milliseconds. Returns: nothing, just update obj attributes ''' l_spltd = line.split() # in phantom v.14 line have from 11 to 12 fields, @see: # http://phantom-doc-ru.rtfd.org/en/latest/analyzing_result_data.html if len(l_spltd) == 12: epoch, tag, rtt, con_mcs, send_mcs, proc_mcs, resp_mcs, phantom_exec, \ req_byte, resp_byte, errno, http_status = l_spltd elif len(l_spltd) == 11: epoch, rtt, con_mcs, send_mcs, proc_mcs, resp_mcs, phantom_exec, \ req_byte, resp_byte, errno, http_status = l_spltd else: return None epoch = int(epoch.split('.')[0]) # cut out fractional part of epoach if epoch != self.last_epoach: self.last_epoach = epoch self.is_second_pass = True if self.first_epoach == None: self.first_epoach = epoch rtt_ms = int(rtt) / 1000 http_status = int(http_status) req_byte = int(req_byte) resp_byte = int(resp_byte) con_ms = float(con_mcs) / 1000 send_ms = float(send_mcs) / 1000 proc_ms = float(proc_mcs) / 1000 resp_ms = float(resp_mcs) / 1000 self.responses_num += 1 # find out, what time interval current RTT belong to resp_time_intervals = self.resp_time_vals[:] resp_time_intervals.append(rtt_ms) resp_time_intervals.sort() idx = resp_time_intervals.index(rtt_ms) # interval num of current RTT try: self.resp_by_times[resp_time_intervals[idx + 1]]['num'] += 1 except IndexError: # RTT contains phantom working costs, so total RTT # can be bigger than maximum of *time_periods*. if idx == len(resp_time_intervals) - 1: self.resp_by_times[self.resp_time_vals[-1]]['num'] += 1 else: exit_err('Buggy indx: %s\nperiods: %s in resp' % (idx, resp_time_intervals)) try: self.resp[epoch]['rtt'].append(rtt_ms) except KeyError: self.resp[epoch] = { 'percentiles': [], 'rtt': [], 'rps': 0, 'codes': {}, 'errno': {}, } self.resp[epoch]['rtt'].append(rtt_ms) if http_status != 0: # 0 mean transport layer error. self.http_codes_num += 1 # HTTP status codes processing for each req try: self.resp[epoch]['codes'][http_status] += 1 except KeyError: self.resp[epoch]['codes'][http_status] = 1 self.codes_set.update([http_status]) # for all test try: self.codes_tbl[http_status]['num'] += 1 except KeyError: self.codes_tbl[http_status] = {'num': 1} # Socket errno processing for each req try: self.resp[epoch]['errno'][errno] += 1 except KeyError: self.resp[epoch]['errno'][errno] = 1 self.errno_set.update([errno,]) # for all test try: self.errno_tbl[errno]['num'] += 1 except KeyError: self.errno_tbl[errno] = {'num': 1} # Tx/Rx bytes processing for each req try: self.resp[epoch]['tx'] += req_byte self.resp[epoch]['rx'] += resp_byte except KeyError: self.resp[epoch]['tx'] = req_byte self.resp[epoch]['rx'] = resp_byte # rtt fractions for each req if not 'rtt_fract' in self.resp[epoch]: self.resp[epoch]['rtt_fract'] = {} for part in self.rtt_fracts: try: self.resp[epoch]['rtt_fract'][part].append(vars()[part]) except KeyError: self.resp[epoch]['rtt_fract'][part] = [vars()[part], ] if is_interactive: self.sum_up()