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
Exemple #2
0
 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': [], }
Exemple #3
0
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))
Exemple #4
0
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': [], }
Exemple #6
0
    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], ]
Exemple #7
0
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()