def calculate_proper_timeframe(low_value, high_value, start_time, end_time, aggregation, time_as_ts=False): start_time = str_to_timestamp(start_time) end_time = str_to_timestamp(end_time) interval = end_time - start_time start_shift = interval * (float(low_value) / 100.0) end_shift = interval * (float(high_value) / 100.0) end_time = start_time + end_shift start_time += start_shift real_interval = end_time - start_time seconds = real_interval / MAX_DOTS_ON_CHART if seconds > 1: seconds = int(seconds) else: seconds = 1 if aggregation == 'auto': aggregation = f'{seconds}s' if time_as_ts: return int(start_time), int(end_time), aggregation return (datetime.fromtimestamp( start_time, tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.000Z"), datetime.fromtimestamp( end_time, tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.000Z"), aggregation)
def calculate_proper_timeframe(build_id, test_name, lg_type, low_value, high_value, start_time, end_time, aggregation, time_as_ts=False): start_time = str_to_timestamp(start_time) end_time = str_to_timestamp(end_time) interval = end_time - start_time start_shift = interval * (float(low_value) / 100.0) end_shift = interval * (float(high_value) / 100.0) end_time = start_time + end_shift start_time += start_shift if time_as_ts: return int(start_time), int(end_time), aggregation t_format = "%Y-%m-%dT%H:%M:%S.000Z" start_time = datetime.fromtimestamp(start_time, tz=timezone.utc).strftime(t_format) end_time = datetime.fromtimestamp(end_time, tz=timezone.utc).strftime(t_format) if aggregation == 'auto': aggregation = calculate_auto_aggregation(build_id, test_name, lg_type, start_time, end_time) return start_time, end_time, aggregation
def get_test_details(project_id, build_id, test_name, lg_type): test = { "start_time": 0, "name": test_name, "environment": "", "type": "", "end_time": 0, "failures": 0, "total": 0, "thresholds_missed": 0, "throughput": 0, "vusers": 0, "duration": 0, "1xx": 0, "2xx": 0, "3xx": 0, "4xx": 0, "5xx": 0, "build_id": build_id, "lg_type": lg_type, "requests": [] } q_start_time = f"select time, active from {lg_type}_{project_id}..\"users\" " \ f"where build_id='{build_id}' order by time asc limit 1" q_end_time = f"select time, active from {lg_type}_{project_id}..\"users\" " \ f"where build_id='{build_id}' order by time desc limit 1" q_response_codes = f"select \"1xx\", \"2xx\", \"3xx\", \"4xx\", \"5xx\", \"ko\" as KO, " \ f"\"total\" as Total, \"throughput\" from comparison_{project_id}..api_comparison " \ f"where build_id='{build_id}' and request_name='All'" q_total_users = f"show tag values on comparison_{project_id} with key=\"users\" where build_id='{build_id}'" q_env = f"show tag values on comparison_{project_id} with key=\"env\" where build_id='{build_id}'" q_type = f"show tag values on comparison_{project_id} with key=\"test_type\" where build_id='{build_id}'" q_requests_name = f"show tag values on comparison_{project_id} with key=\"request_name\" " \ f"where build_id='{build_id}'" client = get_client(project_id) test["start_time"] = list(client.query(q_start_time)["users"])[0]["time"] test["end_time"] = list(client.query(q_end_time)["users"])[0]["time"] test["duration"] = round( str_to_timestamp(test["end_time"]) - str_to_timestamp(test["start_time"]), 1) test["vusers"] = list( client.query(q_total_users)["api_comparison"])[0]["value"] test["environment"] = list( client.query(q_env)["api_comparison"])[0]["value"] test["type"] = list(client.query(q_type)["api_comparison"])[0]["value"] test["requests"] = [ name["value"] for name in client.query(q_requests_name)["api_comparison"] ] response_data = list(client.query(q_response_codes)['api_comparison'])[0] test['total'] = response_data['Total'] test['failures'] = response_data['KO'] test['throughput'] = round(response_data['throughput'], 1) test['1xx'] = response_data['1xx'] test['2xx'] = response_data['2xx'] test['3xx'] = response_data['3xx'] test['4xx'] = response_data['4xx'] test['5xx'] = response_data['5xx'] return test
def get_hits(build_id, test_name, lg_type, start_time, end_time, aggregation, sampler, timestamps=None, users=None, scope=None): if not (timestamps and users): timestamps, users = get_backend_users(build_id, lg_type, start_time, end_time, aggregation) scope_addon = "" if scope and scope != 'All': scope_addon = f"and request_name='{scope}'" hits_query = f"select time, response_time from {lg_type}..{test_name} where " \ f"time>='{start_time}' and time<='{end_time}' and sampler_type='{sampler}' and" \ f" build_id='{build_id}' {scope_addon}" results = {"hits": {}} for _ in timestamps: results['hits'][_] = 0 res = get_client().query(hits_query)[test_name] for _ in res: timestamp = str_to_timestamp(_['time']) hit_time = datetime.fromtimestamp(timestamp - float(_["response_time"]) / 1000.0, tz=timezone.utc) if hit_time.strftime("%Y-%m-%dT%H:%M:%SZ") in results['hits']: results['hits'][hit_time.strftime("%Y-%m-%dT%H:%M:%SZ")] += 1 # aggregation of hits _tmp = [] if 'm' in aggregation: aggregation = f"{str(int(aggregation.replace('m', ''))*60)}s" _ts = None for _ in results['hits']: if len(_tmp) == 0: _ts = _ _tmp.append(results['hits'][_]) results['hits'][_] = None if (len(_tmp) % int(aggregation.replace('s', ''))) == 0: results['hits'][_ts] = float(sum(_tmp)) / int(aggregation.replace('s', '')) _tmp = [] _ts = None return timestamps, results, users
def get_tests_metadata(tests): tests_meta = APIReport.query.filter(APIReport.id.in_(tests)).order_by(APIReport.id.asc()).all() users_data = {} responses_data = {} errors_data = {} rps_data = {} labels = [] for each in tests_meta: ts = datetime.fromtimestamp(str_to_timestamp(each.start_time), tz=timezone.utc).strftime("%m-%d %H:%M:%S") labels.append(ts) users_data[ts] = each.vusers responses_data[ts] = each.pct95 errors_data[ts] = each.failures rps_data[ts] = each.throughput return labels, rps_data, errors_data, users_data, responses_data
def get_test_details(build_id, test_name, lg_type): test = { "start_time": 0, "name": test_name, "environment": "", "type": "", "end_time": 0, "failures": 0, "total": 0, "thresholds_missed": 0, "throughput": 0, "vusers": 0, "pct95": 0, "duration": 0, "1xx": 0, "2xx": 0, "3xx": 0, "4xx": 0, "5xx": 0, "build_id": build_id, "lg_type": lg_type, "requests": [] } q_start_time = f"select time, active from {lg_type}..\"users\" " \ f"where build_id='{build_id}' order by time asc limit 1" q_end_time = f"select time, active from {lg_type}..\"users\" " \ f"where build_id='{build_id}' order by time desc limit 1" q_response_codes = f"select sum(\"1xx\") as \"1xx\", sum(\"2xx\") as \"2xx\", sum(\"3xx\") as \"3xx\", " \ f"sum(\"4xx\") as \"4xx\", sum(\"5xx\") as \"5xx\", sum(\"ko\") as KO, " \ f"sum(\"total\") as Total, sum(throughput) as \"throughput\" " \ f"from comparison..api_comparison where build_id='{build_id}'" q_total_users = f"show tag values on comparison with key=\"users\" where build_id='{build_id}'" q_env = f"show tag values on comparison with key=\"env\" where build_id='{build_id}'" q_type = f"show tag values on comparison with key=\"test_type\" where build_id='{build_id}'" q_pct95 = f"select percentile(response_time, 95) from {lg_type}..{test_name} " \ f"where build_id='{build_id}' and status='OK'" q_requests_name = f"show tag values on comparison with key=\"request_name\" " \ f"where build_id='{build_id}'" client = get_client() test["start_time"] = list(client.query(q_start_time)["users"])[0]["time"] test["end_time"] = list(client.query(q_end_time)["users"])[0]["time"] test["duration"] = round( str_to_timestamp(test["end_time"]) - str_to_timestamp(test["start_time"]), 1) test["vusers"] = list( client.query(q_total_users)["api_comparison"])[0]["value"] test["environment"] = list( client.query(q_env)["api_comparison"])[0]["value"] test["type"] = list(client.query(q_type)["api_comparison"])[0]["value"] pct95 = list(client.query(q_pct95)[test_name]) test["pct95"] = pct95[0]["percentile"] if pct95 else 0 test["requests"] = [ name["value"] for name in client.query(q_requests_name)["api_comparison"] ] response_data = list(client.query(q_response_codes)['api_comparison'])[0] test['total'] = response_data['Total'] test['failures'] = response_data['KO'] test['throughput'] = round(response_data['throughput'], 1) test['1xx'] = response_data['1xx'] test['2xx'] = response_data['2xx'] test['3xx'] = response_data['3xx'] test['4xx'] = response_data['4xx'] test['5xx'] = response_data['5xx'] return test
def get(self): args = self._parser_get.parse_args(strict=False) project = Project.get_or_404(args["project_id"]) report = APIReport.query.filter( and_(APIReport.id == args['test_id'], APIReport.project_id == project.id)).first() start_time = str_to_timestamp(report.start_time) if report.end_time: current_time = str_to_timestamp(report.end_time) else: current_time = datetime.utcnow().timestamp() str_start_time = datetime.fromtimestamp( start_time, tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.000Z") str_current_time = datetime.fromtimestamp( current_time, tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.000Z") duration_till_now = current_time - start_time if duration_till_now < args['wait_till']: return {"message": "not enough results", "code": 0} ts_array, data, users = get_tps(report.build_id, report.name, report.lg_type, str_start_time, str_current_time, "1s", args["sampler"], scope=args["request"], status=args["status"]) users = list(users["users"].values()) _tmp = [] tps = list() usrs = list() errors = list() if 'm' in args["aggregation"]: ss = int(args["aggregation"].replace('m', '')) * 60 elif 's' in args["aggregation"]: ss = int(args["aggregation"].replace('s', '')) else: ss = 60 calculation_mapping = { 'max': max, 'min': min, 'mean': mean, 'sum': sum } calculation = args['calculation'] if args['calculation'] in list( calculation_mapping.keys()) else 'sum' for index, _ in enumerate(data["responses"].values()): if isinstance(_, int): _tmp.append(_) if len(_tmp) and (len(_tmp) % ss) == 0: tps.append(round(calculation_mapping[calculation](_tmp))) usrs.append(users[index]) _tmp = [] if _tmp: tps.append(round(calculation_mapping[calculation](_tmp))) usrs.append(users[-1]) _tmp = [] _, data, _ = get_errors(report.build_id, report.name, report.lg_type, str_start_time, str_current_time, args["aggregation"], args["sampler"], scope=args["request"]) for each in data['errors'].values(): if each: errors.append(each) total = int( get_response_time_per_test(report.build_id, report.name, report.lg_type, args["sampler"], args["request"], "total")) error_rate = float(sum(errors)) / float(total) * 100 try: max_tp, user_index = arrays.non_decreasing( tps[:-1], deviation=args["deviation"], val=True) max_users = args["u_aggr"] * round( usrs[user_index] / args["u_aggr"]) max_tp = tps[user_index] current_users = args["u_aggr"] * round( usrs[user_index + 1] / args["u_aggr"]) if current_users == max_users: current_users += args["u_aggr"] if current_users == 0: current_users = max_users + args["u_aggr"] if current_users < max_users: current_users = max_users + args["u_aggr"] except TypeError: return {"message": "not enough results", "code": 0} except IndexError: if error_rate > args["max_errors"]: return { "message": f"error rate reached 100% for {args['request']} transaction", "errors_rate": 100.0, "code": 1 } else: return {"message": "not enough results", "code": 0} response = { "ts": ts_array[-1], "max_users": max_users, "max_throughput": round(max_tp, 2), "current_users": current_users, "current_throughput": round(tps[user_index], 2), "errors_rate": round(error_rate, 2) } if args["u"]: user_array = args["u"] if max_users not in user_array: user_array.append(max_users) if current_users not in user_array: user_array.append(current_users) user_array.sort() user_array.reverse() uber_array = {} _, users = get_backend_users(report.build_id, report.lg_type, str_start_time, str_current_time, "1s") u = user_array.pop() start_time = _[0] end_time = _[-1] response["test_start"] = start_time response["test_end"] = end_time for key, value in users["users"].items(): if value > u and max_users >= u: _, data, _ = get_tps(report.build_id, report.name, report.lg_type, start_time, key, "1s", args["sampler"], scope=args["request"], status=args["status"]) tp = [ 0 if v is None else v for v in list(data['responses'].values())[:-1] ] array_size = len(tp) tp = calculation_mapping[calculation]( tp) if len(tp) != 0 else 0 if array_size != ss: coefficient = float(array_size / ss) else: coefficient = 1 tp = int(tp / coefficient) if round( tp, 2 ) > response["max_throughput"] and u != current_users: response["max_throughput"] = round(tp, 2) response["max_users"] = u current_users = u + args["u_aggr"] response["current_users"] = current_users _, data, _ = get_backend_requests(report.build_id, report.name, report.lg_type, start_time, key, "1s", args["sampler"], scope=args["request"], status=args["status"]) rt = [] started = False for v in list(data['response'].values())[:-1]: if v and v > 0: started = True if started and v and v > 0: rt.append(v) rt = self.part(rt, args["u_aggr"]) if rt else 0 uber_array[str(u)] = { "throughput": round(tp, 2), "response_time": round(rt, 2) } start_time = key u = user_array.pop() if str(response["max_users"]) not in list(uber_array.keys()): _, data, _ = get_backend_requests(report.build_id, report.name, report.lg_type, start_time, end_time, "1s", args["sampler"], scope=args["request"], status=args["status"]) rt = [] started = False for v in list(data['response'].values())[:-1]: if v and v > 0: started = True if started and v and v > 0: rt.append(v) rt = self.part(rt, args["u_aggr"]) if rt else 0 uber_array[str(max_users)] = { "throughput": response["max_throughput"], "response_time": round(rt, 2) } else: uber_array[str(response["max_users"] )]["throughput"] = response["max_throughput"] if str(current_users) not in list(uber_array.keys()): uber_array[str(current_users)] = { "throughput": response["current_throughput"], "response_time": uber_array.get( str(max_users), list(uber_array.values())[-1])["response_time"] } else: uber_array[str(current_users)]["throughput"] = response[ "current_throughput"] response["benchmark"] = uber_array if args["extended_output"]: response["details"] = {} response["tps"] = tps for index, value in enumerate(usrs): if not response["details"].get( value) or response["details"][value] > tps[index]: response["details"][value] = tps[index] if (arrays.non_decreasing(tps[:-1], deviation=args["deviation"]) and error_rate <= args["max_errors"] and response["current_throughput"] * (1 + args["max_deviation"]) >= response["max_throughput"]): response["message"] = "proceed" response["code"] = 0 return response else: response["message"] = "saturation" response["code"] = 1 return response