def post(self, request): jmxId = request.data.get('jmxId') jmxAlias = request.data.get('jmxAlias') numThreads = request.data.get('numThreads') rampTime = request.data.get('rampTime') loops = request.data.get('loops') scheduler = request.data.get('scheduler') duration = request.data.get('duration') if not duration: duration = "" try: jmx_path = Jmxs.objects.all().get(id=jmxId).jmx ModifyJMX(jmx_path).modify_thread_num(numThreads, rampTime, loops, scheduler, duration) thread_base_info = { "num_threads": numThreads, "ramp_time": rampTime, "loops": loops, "scheduler": scheduler, "duration": duration } Jmxs.objects.filter(id=jmxId).update( jmx_alias=jmxAlias, thread_base_info=json.dumps(thread_base_info)) return APIRsp() except: return APIRsp(code=400, msg="修改线程组属性异常")
def post(self, request): samplerId = request.data.get('samplerId') childId = request.data.get('childId') name = request.data.get('name') if not name: name = "响应断言" radioStr = request.data.get('radioStr') checkedFalseStr = request.data.get('checkedFalseStr') checkedOrStr = request.data.get('checkedOrStr') assert_content = request.data.get('assertContent') assert_str = radioStr + checkedFalseStr + checkedOrStr if len(assert_content ) == 1 and assert_content[0]['key'] == "" and not childId: return APIRsp(msg='断言参数为空,不创建响应断言') try: # 获取jmx的信息 jmxInfo = JmxThreadGroup.objects.all().filter(id=samplerId) jmx_path = jmxInfo[0].jmx sampler_xpath = json.loads(jmxInfo[0].child_info)['xpath'] if childId: child_info = json.loads( str(SamplersChildren.objects.get(id=childId).child_info)) child_xpath = child_info['xpath'] new_child_info = ModifyJMX(str(jmx_path)).add_rsp_assert( sampler_xpath, name, assert_str=assert_str, assert_content=assert_content, rsp_assert_xpath=child_xpath) SamplersChildren.objects.filter(id=childId).update( child_name=name, child_info=json.dumps(new_child_info)) else: child_info = ModifyJMX(str(jmx_path)).add_rsp_assert( sampler_xpath, name, assert_str=assert_str, assert_content=assert_content) s = SamplersChildren(sampler_id=samplerId, child_name=name, child_type='rsp_assert', child_info=json.dumps(child_info)) s.save() return APIRsp() except: return APIRsp(code=400, msg='创建响应断言失败,参数错误!')
def post(self, request): samplerId = request.data.get('samplerId') childId = request.data.get('childId') name = request.data.get('name') jsonPath = request.data.get('jsonPath') expectedValue = request.data.get('expectedValue') expectNull = request.data.get('expectNull') invert = request.data.get('invert') if not jsonPath or not name: return APIRsp(msg='存在参数为空,不创建JSON断言') try: # 获取jmx的信息 jmxInfo = JmxThreadGroup.objects.all().filter(id=samplerId) jmx_path = jmxInfo[0].jmx sampler_xpath = json.loads(jmxInfo[0].child_info)['xpath'] if childId: child_info = json.loads( str(SamplersChildren.objects.get(id=childId).child_info)) child_xpath = child_info['xpath'] new_child_info = ModifyJMX(str(jmx_path)).add_json_assert( sampler_xpath, name, jsonPath, expectedValue, expectNull, invert, json_aassert_xpath=child_xpath) SamplersChildren.objects.filter(id=childId).update( child_name=name, child_info=json.dumps(new_child_info)) else: child_info = ModifyJMX(str(jmx_path)).add_json_assert( sampler_xpath, name, jsonPath, expectedValue, expectNull, invert) s = SamplersChildren(sampler_id=samplerId, child_name=name, child_type='json_assert', child_info=json.dumps(child_info)) s.save() return APIRsp() except: return APIRsp(code=400, msg='创建Json断言失败,参数错误!')
def post(self, request): samplerId = request.data.get('samplerId') childId = request.data.get('childId') name = request.data.get('name') params = request.data.get('params') express = request.data.get('express') match_num = request.data.get('match_num') if not params or not express or not name: return APIRsp(msg='存在参数为空,不创建Json提取器') if not match_num: match_num = "" try: # 获取jmx的信息 jmxInfo = JmxThreadGroup.objects.all().filter(id=samplerId) jmx_path = jmxInfo[0].jmx sampler_xpath = json.loads(jmxInfo[0].child_info)['xpath'] if childId: child_info = json.loads( str(SamplersChildren.objects.get(id=childId).child_info)) child_xpath = child_info['xpath'] new_child_info = ModifyJMX(str(jmx_path)).add_json_extract( sampler_xpath, name, params, express, match_num, json_extract_xpath=child_xpath) SamplersChildren.objects.filter(id=childId).update( child_name=name, child_info=json.dumps(new_child_info)) else: child_info = ModifyJMX(str(jmx_path)).add_json_extract( sampler_xpath, name, params, express, match_num) s = SamplersChildren(sampler_id=samplerId, child_name=name, child_type='json_extract', child_info=json.dumps(child_info)) s.save() return APIRsp() except: return APIRsp(code=400, msg='创建Json提取器失败,参数错误!')
def post(self, request): samplerId = request.data.get('samplerId') childId = request.data.get('childId') name = request.data.get('name') to_JSR223_param = request.data.get('to_JSR223_param') express = request.data.get('express') if not express or not name: return APIRsp(msg='存在参数为空,不创建JSR223!') if not to_JSR223_param: to_JSR223_param = "" try: # 获取jmx的信息 jmxInfo = JmxThreadGroup.objects.all().filter(id=samplerId) jmx_path = jmxInfo[0].jmx sampler_xpath = json.loads(jmxInfo[0].child_info)['xpath'] if childId: child_info = json.loads( str(SamplersChildren.objects.get(id=childId).child_info)) child_xpath = child_info['xpath'] new_child_info = ModifyJMX(str(jmx_path)).add_JSR223( sampler_xpath, name, to_JSR223_param, express, JSR223_xpath=child_xpath) SamplersChildren.objects.filter(id=childId).update( child_name=name, child_info=json.dumps(new_child_info)) else: child_info = ModifyJMX(str(jmx_path)).add_JSR223( sampler_xpath, name, to_JSR223_param, express) s = SamplersChildren(sampler_id=samplerId, child_name=name, child_type='JSR223', child_info=json.dumps(child_info)) s.save() return APIRsp() except: return APIRsp(code=400, msg='创建JSR223,参数错误!')
def post(self, request): samplerId = request.data.get('samplerId') childId = request.data.get('childId') name = request.data.get('name') params = request.data.get('params') if not name: name = "HTTP信息头管理器" if len(params) == 1 and params[0]['key'] == "" and params[0][ 'value'] == "" and not childId: return APIRsp(msg='头参数为空,不创建头信息') try: # 获取jmx的信息 jmxInfo = JmxThreadGroup.objects.all().filter(id=samplerId) jmx_path = jmxInfo[0].jmx sampler_xpath = json.loads(jmxInfo[0].child_info)['xpath'] if childId: child_info = json.loads( str(SamplersChildren.objects.get(id=childId).child_info)) child_xpath = child_info['xpath'] new_child_info = ModifyJMX(str(jmx_path)).add_header( sampler_xpath, name, headers=params, header_xpath=child_xpath) SamplersChildren.objects.filter(id=childId).update( child_name=name, child_info=json.dumps(new_child_info)) else: child_info = ModifyJMX(str(jmx_path)).add_header( sampler_xpath, name, headers=params) s = SamplersChildren(sampler_id=samplerId, child_name=name, child_type='header', child_info=json.dumps(child_info)) s.save() return APIRsp() except: return APIRsp(code=400, msg='创建header失败,参数错误!')
def post(self, request): """ 修改csv信息 """ childId = request.data.get('childId') name = request.data.get('name') variableNames = request.data.get('variableNames') delimiter = request.data.get('delimiter') ignoreFirstLine = request.data.get('ignoreFirstLine') recycle = request.data.get('recycle') stopThread = request.data.get('stopThread') if childId and variableNames: csv_base_info = JmxThreadGroup.objects.get(id=childId) jmx_path = csv_base_info.jmx child_info = json.loads(csv_base_info.child_info) xpath = child_info['xpath'] threadType = str(csv_base_info.child_thread) csv_path = child_info['filename'] csv_info = ModifyJMX(str(jmx_path)).add_csv( name, csv_path, variableNames, ignoreFirstLine=ignoreFirstLine, delimiter=delimiter, recycle=recycle, stopThread=stopThread, accord=threadType, xpath=xpath) # 更新csv信息 JmxThreadGroup.objects.filter(id=childId).update( child_name=name, child_info=json.dumps(csv_info)) return APIRsp() else: return APIRsp(code=400, msg='修改失败,参数不完整', status=status.HTTP_400_BAD_REQUEST)
def run_task(taskid, task_flow_str, jmxs): """ 执行一个任务,并汇总生成的jtl文件,执行任务前会先插入一条任务的flow流水记录 :param cmds: 一个字段,key是jtl文件路径,value是jmx执行命令 :return: """ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "jmeter_platform.settings") django.setup() from jtls.models import JtlsSummary from tasks.models import TaskFlow, FlowTaskAggregateReport, RspResult, PngResult from jmxs.models import JmxThreadGroup, Jmxs from params.models import UsersParams try: cmds = [] save_path_dict = {} sampler_id_name_dict = {} temp_dir = settings.TEMP_URL + task_flow_str jtl = settings.JTL_URL + task_flow_str + '.jtl' pt = re.compile('{{(.*?)}}') logger.debug(f'创建临时目录{temp_dir}') os.makedirs(temp_dir) logger.debug('将jmx复制到临时目录下') for sjmx in jmxs: jmx = sjmx['jmx'] jmx_id = sjmx['id'] thread_base_info = Jmxs.objects.get(id=jmx_id).thread_base_info num_threads = json.loads(thread_base_info)['num_threads'] samplers_info = JmxThreadGroup.objects.values( 'id', 'child_info').filter(jmx_id=jmx_id, child_type="sampler") jmx_name = Tools.filename(jmx) shutil.copy(jmx, temp_dir) # 在这里查找替换变量{{}} temp_jmx = temp_dir + os.sep + jmx_name + '.temp.jmx' temp_temp_jmx = temp_dir + os.sep + jmx_name + '.jmx' # 替换全局变量参数 logger.debug('替换全局参数') with open(temp_jmx, 'w') as write: with open(temp_temp_jmx, 'r') as read: content = read.readlines() for line in content: param_name_list = re.findall(pt, line) for param_name in param_name_list: value = UsersParams.objects.get( param_name=param_name).param_value logger.debug(f'全局参数:{param_name}\n{value}') line = line.replace('{{%s}}' % param_name, str(value)) write.write(line) os.remove(temp_temp_jmx) ModifyJMX(temp_jmx).add_backendListener( influxdb_url=settings.INFLUXDB_URL, application_name=task_flow_str) for sampler in samplers_info: sampler_id = sampler['id'] sampler_info = json.loads(sampler['child_info']) sampler_xpath = sampler_info['xpath'] # 提取ID和实际名称的对于关系 sampler_id_name_dict[sampler_xpath.split('@testname="') [1].split('"]')[0]] = sampler_id # 创建保存取样器响应的目录 save_path = temp_dir + os.sep + str(sampler_id) os.makedirs(save_path) save_path_dict[sampler_id] = save_path if str(num_threads) == '1': # 线程是1时,保存错误和异常日志 ModifyJMX(temp_jmx).save_rsp_data(sampler_xpath, save_path) else: # 线程不为1时,只保存错误日志 ModifyJMX(temp_jmx).save_rsp_data(sampler_xpath, save_path, errorsonly=True) cmd = f"{settings.JMETER} -n -t {temp_jmx} -l {jtl}" cmds.append(cmd) logger.debug('开始执行jmx') for cmd in cmds: os.system(cmd) try: flow_id = TaskFlow.objects.values('id').get( randomstr=task_flow_str)['id'] js = JtlsSummary(task_id=taskid, flow_id=flow_id, jtl_url=jtl) js.save() logger.debug('jtl信息入库成功') except: logger.error('jtl信息入库失败') os.remove(jtl) raise logger.debug('将jtl文件转换为csv文件') summary_csv = settings.TEMP_URL + task_flow_str + os.sep + 'temp.csv' rt_png = settings.PIC_URL + f"{task_flow_str}_ResponseTimesOverTime.png" tps_png = settings.PIC_URL + f"{task_flow_str}_TransactionsPerSecond.png" to_csv_cmd = f'{settings.JMETER_PLUGINS_CMD} --generate-csv {summary_csv} --input-jtl {jtl} --plugin-type AggregateReport' to_rt_png = f'{settings.JMETER_PLUGINS_CMD} --generate-png {rt_png} --input-jtl {jtl} --plugin-type ResponseTimesOverTime' to_tps_png = f'{settings.JMETER_PLUGINS_CMD} --generate-png {tps_png} --input-jtl {jtl} --plugin-type TransactionsPerSecond' os.system(to_csv_cmd) os.system(to_rt_png) os.system(to_tps_png) if os.path.exists(summary_csv): logger.info('jtl转为csv成功') csv_info = Tools.read_csv_info(summary_csv) try: for idx, info in enumerate(csv_info): if idx == 0: continue try: sampler_id = sampler_id_name_dict[info[0]] except KeyError: sampler_id = -1 try: tps = str(float(info[10])) except: tps = '0/sec' csv_to_db = FlowTaskAggregateReport( task_id=taskid, flow_id=flow_id, sampler_id=sampler_id, label=Tools.filename(info[0]), samplers=info[1], average_req=info[2], median_req=info[3], line90_req=info[4], line95_req=info[5], line99_req=info[6], min_req=info[7], max_req=info[8], error_rate=info[9], tps=tps, recieved_per=str(float(info[11]))) csv_to_db.save() for sampler_id, save_path in save_path_dict.items(): count_rsp = Tools.count_rsp(save_path) for key, value in count_rsp.items(): rr = RspResult(sampler_id=sampler_id, flow_id=flow_id, response=key, count=value) rr.save() png = PngResult(flow_id=flow_id, rt_png_url=os.sep + rt_png, tps_png_url=os.sep + tps_png) png.save() # 更新流水任务的状态为3,完成状态 logger.debug('更新流水任务状态为完成状态') TaskFlow.objects.filter(randomstr=task_flow_str).update( task_status=3, end_time=datetime.now()) logger.debug('流水任务执行完成') except: logger.error('保存数据失败') raise else: logger.error('jtl转为csvs失败') raise except: # 更新流水任务的状态为2,运行异常 TaskFlow.objects.filter(randomstr=task_flow_str).update( task_status=2, end_time=datetime.now()) # 这里会自动打印异常信息 logger.exception(f'执行流水任务失败') finally: try: logger.debug('删除任务流水目录') shutil.rmtree(settings.TEMP_URL + task_flow_str) except: logger.debug('任务流水目录不存在')
def post(self, request): """ :param request: :param request: {'csv': ,'jmx': , 'user': 1} :return: """ data = {} # request.POST.get适用于form-data请求获取参数 csv = request.FILES.get('csv') name = request.POST.get('name') jmx_id = request.POST.get('jmxId') user = request.POST.get('userId') variableNames = request.POST.get('variableNames') delimiter = request.POST.get('delimiter') # mult-form-data会将json中的true或者false转换为字符串 ignoreFirstLine = request.POST.get('ignoreFirstLine') recycle = request.POST.get('recycle') stopThread = request.POST.get('stopThread') threadType = request.POST.get('threadType') if csv and jmx_id and user and variableNames and delimiter and ignoreFirstLine and recycle and stopThread and threadType: csv_name_ext = os.path.splitext(csv.name) csv_name = csv_name_ext[0] csv_ext = csv_name_ext[1] if csv_ext not in settings.CSV_ALLOWED_FILE_TYPE: return APIRsp(code=205, msg='无效的格式,请上传.csv格式的文件', status=status.HTTP_205_RESET_CONTENT) csvfile = csv_name + "." + Tools.random_str(9) + csv_ext path = settings.CSV_URL + csvfile with open(path, 'wb') as f: for i in csv.chunks(): f.write(i) data['csv'] = csvfile # csv不存在时,接口会报错 data['jmx'] = jmx_id # user不存在时,接口会报错 data['add_user'] = user obj = CsvSerializer(data=data) if obj.is_valid(): obj.save() jmx_path = Jmxs.objects.values('jmx').get(id=jmx_id)['jmx'] csv_info = ModifyJMX(jmx_path).add_csv( name, path, variableNames, ignoreFirstLine=Tools.strToBool(ignoreFirstLine), delimiter=delimiter, recycle=Tools.strToBool(recycle), stopThread=Tools.strToBool(stopThread), accord=threadType) # 保存csv信息 s = JmxThreadGroup(jmx_id=jmx_id, child_name=name, child_type='csv', child_info=json.dumps(csv_info), child_thread=threadType) s.save() return APIRsp() return APIRsp(code=500, msg='添加失败,校验未通过', status=status.HTTP_400_BAD_REQUEST) else: return APIRsp(code=400, msg='添加失败,参数不完整', status=status.HTTP_400_BAD_REQUEST)
def post(self, request): jmx_id = request.data.get('jmxId') # 修改的时候才需要传入childid信息 child_id = request.data.get('childId') thread_type = request.data.get('threadType') sampler_name = request.data.get('samplerName') method = request.data.get('method') url = request.data.get('url') param_type = request.data.get('paramType') params = request.data.get('params') jmx_path = Jmxs.objects.values('jmx').get(id=jmx_id)['jmx'] if not jmx_path: return APIRsp(code=400, msg='无效的jmxID!', status=status.HTTP_400_BAD_REQUEST) if child_id: # 修改已有sampler try: child_info = JmxThreadGroup.objects.values('child_info').get( id=child_id, child_type='sampler')['child_info'] child_xpath = json.loads(child_info)['xpath'] rst = ModifyJMX(jmx_path).add_sampler(sampler_name, url, method, accord=thread_type, param_type=param_type, params=params, xpath=child_xpath) JmxThreadGroup.objects.filter(id=child_id).update( child_name=sampler_name, child_info=json.dumps(rst), child_thread=thread_type) return APIRsp(msg='修改sampler成功!') except: return APIRsp(code=400, msg='修改sampler失败,sampler参数有误!', status=status.HTTP_400_BAD_REQUEST) else: try: # 新增sampler rst = ModifyJMX(jmx_path).add_sampler(sampler_name, url, method, accord=thread_type, param_type=param_type, params=params) # 保存sampler信息 s = JmxThreadGroup(jmx_id=jmx_id, child_name=sampler_name, child_info=json.dumps(rst), child_thread=thread_type) s.save() return APIRsp(msg='新增sampler成功!', data={'samplerId': s.id}) except: return APIRsp(code=400, msg='新增sapmler失败,sampler参数有误!', status=status.HTTP_400_BAD_REQUEST)
def post(self, request): data = {} jmx_name = request.data.get('jmxName') sampler_name = request.data.get('samplerName') method = request.data.get('method') url = request.data.get('url') param_type = request.data.get('paramType') params = request.data.get('params') user = request.data.get('addUser') if not sampler_name or not method or not url: return APIRsp(code=400, msg='创建jmx失败,接口名称、方法、url必传', status=status.HTTP_400_BAD_REQUEST) template_path = settings.JMX_URL + 'template.jmx' new_jmxpath = settings.JMX_URL + jmx_name + "." + Tools.random_str( 9) + '.jmx' shutil.copyfile(template_path, new_jmxpath) try: ModifyJMX(new_jmxpath).add_sampler(sampler_name, url, method, param_type=param_type, params=params) except: os.remove(new_jmxpath) return APIRsp(code=400, msg='创建jmx失败,参数错误!', status=status.HTTP_400_BAD_REQUEST) jmxinfo = ReadJmx(new_jmxpath).analysis_jmx(upload=False) if not jmxinfo: return APIRsp(code=400, msg='添加失败,jmx文件错误!', status=status.HTTP_400_BAD_REQUEST) sampler_info = jmxinfo[0][0] thread_info = jmxinfo[2] # jmx路径 data['jmx'] = new_jmxpath # jmx名称 data['jmx_alias'] = jmx_name # user的id不存在时,会校验失败 data['add_user'] = user # 线程组基础信息 data['thread_base_info'] = json.dumps(thread_info) obj = JmxsSerializer(data=data) # 校验数据格式 if obj.is_valid(): obj.save() jmx_id = obj.data['id'] if sampler_info: # 保存sampler信息 del sampler_info['children'] s = JmxThreadGroup(jmx_id=jmx_id, child_name=sampler_name, child_info=json.dumps(sampler_info), child_thread=sampler_info['thread_type']) s.save() return APIRsp(data={'samplerId': s.id}) # sampler的id os.remove(new_jmxpath) return APIRsp(code=400, msg='添加失败,参数校验未通过', status=status.HTTP_400_BAD_REQUEST)